A safe 54-bit signed integer for use cases where normal Int isn't sufficient and 54-bit range will suffice.
Minimum possible defined value, - (2^53 - 1) = - 9 007 199 254 740 991.
Equal to Number.MIN_SAFE_INTEGER in JavaScript.
SafeInt.minValue
|> SafeInt.toInt
--> Just -9007199254740991Maximum possible defined value, 2^53 - 1 = 9 007 199 254 740 991.
Equal to Number.MAX_SAFE_INTEGER in JavaScript.
SafeInt.maxValue
|> SafeInt.toInt
--> Just 9007199254740991Undefined value.
Functions return undefined when result can't be represented using an integer
between minValue and maxValue.
For example division by zero or when result is above maxValue.
-- `1 / 0` is undefined
SafeInt.div SafeInt.one SafeInt.zero
|> SafeInt.toInt
--> Nothing
-- `2 ^ 55` is undefined
SafeInt.pow SafeInt.two (SafeInt.new 55)
|> SafeInt.toInt
--> NothingOperators == and /= consider undefined to be equal to itself and unequal to any defined value,
so to find out whether SafeInt is undefined or not,
you can just compare it to undefined.
SafeInt.div SafeInt.one SafeInt.zero
== SafeInt.undefined
--> True
SafeInt.div SafeInt.one SafeInt.one
== SafeInt.undefined
--> FalseComparison of Float to SafeInt conversion functions:
-3.8 -3.5 -3.2 ~ 3.2 3.5 3.8
---- ---- ---- ---- ---- ----
round -4 -3 -3 3 4 4
ceiling -3 -3 -3 4 4 4
truncate -3 -3 -3 3 3 3
floor -4 -4 -4 3 3 3Convert Float to SafeInt, rounding to nearest integer and half towards positive infinity.
Return undefined if argument is NaN,
below minValue or above maxValue.
[ 3.2, 3.5, 3.8 ]
|> List.map (SafeInt.round >> SafeInt.toInt)
--> [ Just 3, Just 4, Just 4 ]
[ -3.8, -3.5, -3.2 ]
|> List.map (SafeInt.round >> SafeInt.toInt)
--> [ Just -4, Just -3, Just -3 ]Power aka exponentiation, rounding towards zero.
Return undefined if
The table below shows the return values of pow a b near zero.
U denotes undefined and *0 denotes non-integer result rounded towards zero.
b: -2 -1 0 1 2
a -- -- -- -- --
--
-2 *0 *0 1 -2 4
-1 1 -1 1 -1 1
0 U U U 0 0
1 1 1 1 1 1
2 *0 *0 1 2 4-- `2 ^ 40`
SafeInt.pow SafeInt.two (SafeInt.new 40)
|> SafeInt.toInt
--> Just 1099511627776Note: Opinions differ on what the result of 0 ^ 0, NaN ^ 0 and 1 ^ NaN should be.
SafeInt takes the stance to return undefined when uncertain,
so all of these (using undefined instead of NaN) return undefined.
For more information see e.g. Zero to the power of zero🢅 and NaN § Function definition🢅.
SafeInt has four basic division functions:
div, mod, quotient and remainder.
Both div and quotient calculate integer division, the difference is in rounding:
div rounds the result towards negative infinity while quotient rounds towards zero.
The // operator is similar to quotient.
-- -10 divided by 3 is -3.333..., rounded to -4
SafeInt.div (SafeInt.new -10) (SafeInt.new 3)
|> SafeInt.toInt
--> Just -4
-- -10 divided by 3 is -3.333..., rounded to -3
SafeInt.quotient (SafeInt.new -10) (SafeInt.new 3)
|> SafeInt.toInt
--> Just -3Likewise both mod and remainder calculate remainder after integer division:
mod calculates remainder after div
and remainder calculates remainder after quotient.
-- -10 divided by 3 is -3.333..., rounded to -4
-- then remainder is -10 - (3 * -4) = 2
SafeInt.mod (SafeInt.new -10) (SafeInt.new 3)
|> SafeInt.toInt
--> Just 2
-- -10 divided by 3 is -3.333..., rounded to -3
-- then remainder is -10 - (3 * -3) = -1
SafeInt.remainder (SafeInt.new -10) (SafeInt.new 3)
|> SafeInt.toInt
--> Just -1The table below shows a comparison of div, mod, quotient and remainder,
with dividend from -7 to 7 and divisor either 3 or -3.
dividend: -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
-- -- -- -- -- -- -- -- -- -- -- -- -- -- --
divisor = 3
div -3 -2 -2 -2 -1 -1 -1 0 0 0 1 1 1 2 2
mod 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
quotient -2 -2 -1 -1 -1 0 0 0 0 0 1 1 1 2 2
remainder -1 0 -2 -1 0 -2 -1 0 1 2 0 1 2 0 1
divisor = -3
div 2 2 1 1 1 0 0 0 -1 -1 -1 -2 -2 -2 -3
mod -1 0 -2 -1 0 -2 -1 0 -2 -1 0 -2 -1 0 -2
quotient 2 2 1 1 1 0 0 0 0 0 -1 -1 -1 -2 -2
remainder -1 0 -2 -1 0 -2 -1 0 1 2 0 1 2 0 1All division functions return undefined if divisor is 0
or either argument is undefined.
-- `1 / 0` is undefined
SafeInt.div SafeInt.one SafeInt.zero
|> SafeInt.toInt
--> NothingInteger division, rounding towards negative infinity.
See Division Basics for more information about division functions.
SafeInt.div (SafeInt.new 1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just 12
SafeInt.div (SafeInt.new -1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just -13Remainder after div. This is also used for modular arithmetic🢅.
See Division Basics for more information about division functions.
SafeInt.mod (SafeInt.new 1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just 34
SafeInt.mod (SafeInt.new -1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just 66Integer division, rounding towards zero.
This is similar to // operator.
See Division Basics for more information about division functions.
SafeInt.quotient (SafeInt.new 1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just 12
SafeInt.quotient (SafeInt.new -1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just -12Remainder after quotient.
See Division Basics for more information about division functions.
SafeInt.remainder (SafeInt.new 1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just 34
SafeInt.remainder (SafeInt.new -1234) (SafeInt.new 100)
|> SafeInt.toInt
--> Just -34Functions divBy, modBy, quotientBy and remainderBy
are same as basic division functions, except with reversed arguments.
modBy is similar to Basics.modBy and remainderBy to Basics.remainderBy.
-- `2^40 / 10`
SafeInt.pow SafeInt.two (SafeInt.new 40)
|> SafeInt.divBy (SafeInt.new 10)
|> SafeInt.toInt
--> Just 109951162777Same as mod except with reversed arguments.
This is similar to Basics.modBy.
Same as quotient except with reversed arguments.
Same as remainder except with reversed arguments.
This is similar to Basics.remainderBy.
Combines div and mod into a single function.
divMod a b is same as ( div a b, mod a b ) except faster.
SafeInt.divMod (SafeInt.new 1234) (SafeInt.new 100)
|> Tuple.mapBoth SafeInt.toInt SafeInt.toInt
--> ( Just 12, Just 34 )
SafeInt.divMod (SafeInt.new -1234) (SafeInt.new 100)
|> Tuple.mapBoth SafeInt.toInt SafeInt.toInt
--> ( Just -13, Just 66 )Combines quotient and remainder into a single function.
quotRem a b is same as ( quotient a b, remainder a b ) except faster.
SafeInt.quotRem (SafeInt.new 1234) (SafeInt.new 100)
|> Tuple.mapBoth SafeInt.toInt SafeInt.toInt
--> ( Just 12, Just 34 )
SafeInt.quotRem (SafeInt.new -1234) (SafeInt.new 100)
|> Tuple.mapBoth SafeInt.toInt SafeInt.toInt
--> ( Just -12, Just -34 )Same as quotRem except with reversed arguments.
Operators == and /= consider undefined to be equal to itself and unequal to any defined value.
Compare two SafeInt:s.
First argument defines how undefined is handled:
True, undefined is equal to itself and smaller than any defined valueFalse, undefined is equal to itself and larger than any defined value[ SafeInt.new 34
, SafeInt.new 12
, SafeInt.undefined
, SafeInt.new 56
, SafeInt.undefined
]
|> List.sortWith (SafeInt.compare True)
|> List.map SafeInt.toInt
--> [ Nothing, Nothing, Just 12, Just 34, Just 56 ]
A safe 54-bit signed integer.
A
SafeIntis either defined integer value fromminValuetomaxValue, orundefined.