A safe 54-bit signed integer for use cases where normal Int
isn't sufficient and 54-bit range will suffice.
A safe 54-bit signed integer.
A SafeInt
is either defined integer value from minValue
to maxValue
,
or undefined
.
minValue : SafeInt
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 -9007199254740991
maxValue : SafeInt
Maximum 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 9007199254740991
undefined : SafeInt
Undefined 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
--> Nothing
Operators ==
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
--> False
zero : SafeInt
Number 0
one : SafeInt
Number 1
two : SafeInt
Number 2
new : Basics.Int -> SafeInt
Same as fromInt
.
fromInt : Basics.Int -> SafeInt
Convert Int
to SafeInt
, rounding towards zero.
Return undefined
if argument is NaN
,
below minValue
or above maxValue
.
Note: Strange cases where argument is NaN
, -Infinity
, +Infinity
or
non-integer like 1234.5
are supported.
toInt : SafeInt -> Maybe Basics.Int
Convert SafeInt
to Maybe Int
.
Return Just value
if SafeInt
is defined,
and Nothing
if SafeInt
is undefined
.
Comparison 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 3
round : Basics.Float -> SafeInt
Convert 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 ]
ceiling : Basics.Float -> SafeInt
Convert Float
to SafeInt
, rounding towards positive infinity.
Return undefined
if argument is NaN
,
below minValue
or above maxValue
.
SafeInt.ceiling 3.8
|> SafeInt.toInt
--> Just 4
SafeInt.ceiling -3.8
|> SafeInt.toInt
--> Just -3
truncate : Basics.Float -> SafeInt
Convert Float
to SafeInt
, rounding towards zero.
Return undefined
if argument is NaN
,
below minValue
or above maxValue
.
SafeInt.truncate 3.8
|> SafeInt.toInt
--> Just 3
SafeInt.truncate -3.8
|> SafeInt.toInt
--> Just -3
floor : Basics.Float -> SafeInt
Convert Float
to SafeInt
, rounding towards negative infinity.
Return undefined
if argument is NaN
,
below minValue
or above maxValue
.
SafeInt.floor 3.8
|> SafeInt.toInt
--> Just 3
SafeInt.floor -3.8
|> SafeInt.toInt
--> Just -4
toFloat : SafeInt -> Maybe Basics.Float
Convert SafeInt
to Maybe Float
.
Return Just value
if SafeInt
is defined,
and Nothing
if SafeInt
is undefined
.
add : SafeInt -> SafeInt -> SafeInt
Addition.
Return undefined
if
-- `123 + 456`
SafeInt.add (SafeInt.new 123) (SafeInt.new 456)
|> SafeInt.toInt
--> Just 579
sub : SafeInt -> SafeInt -> SafeInt
Subtraction.
Return undefined
if
-- `456 - 123`
SafeInt.sub (SafeInt.new 456) (SafeInt.new 123)
|> SafeInt.toInt
--> Just 333
mul : SafeInt -> SafeInt -> SafeInt
Multiplication.
Return undefined
if
-- `123 * 456`
SafeInt.mul (SafeInt.new 123) (SafeInt.new 456)
|> SafeInt.toInt
--> Just 56088
pow : SafeInt -> SafeInt -> SafeInt
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 1099511627776
Note: 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 -3
Likewise 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 -1
The 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 1
All 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
--> Nothing
div : SafeInt -> SafeInt -> SafeInt
Integer 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 -13
mod : SafeInt -> SafeInt -> SafeInt
Remainder 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 66
quotient : SafeInt -> SafeInt -> SafeInt
Integer 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 -12
remainder : SafeInt -> SafeInt -> SafeInt
Remainder 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 -34
Functions 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 109951162777
divBy : SafeInt -> SafeInt -> SafeInt
Same as div
except with reversed arguments.
modBy : SafeInt -> SafeInt -> SafeInt
Same as mod
except with reversed arguments.
This is similar to Basics.modBy
.
quotientBy : SafeInt -> SafeInt -> SafeInt
Same as quotient
except with reversed arguments.
remainderBy : SafeInt -> SafeInt -> SafeInt
Same as remainder
except with reversed arguments.
This is similar to Basics.remainderBy
.
divMod : SafeInt -> SafeInt -> ( SafeInt, SafeInt )
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 )
quotRem : SafeInt -> SafeInt -> ( SafeInt, SafeInt )
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 )
divModBy : SafeInt -> SafeInt -> ( SafeInt, SafeInt )
Same as divMod
except with reversed arguments.
quotRemBy : SafeInt -> SafeInt -> ( SafeInt, SafeInt )
Same as quotRem
except with reversed arguments.
Operators ==
and /=
consider undefined
to be equal to itself and unequal to any defined value.
compare : Basics.Bool -> SafeInt -> SafeInt -> Basics.Order
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 ]
abs : SafeInt -> SafeInt
Absolute value.
Return undefined
if argument is undefined
.
SafeInt.abs (SafeInt.new 123)
|> SafeInt.toInt
--> Just 123
SafeInt.abs (SafeInt.new -123)
|> SafeInt.toInt
--> Just 123
negate : SafeInt -> SafeInt
Negation.
Return undefined
if argument is undefined
.
SafeInt.negate (SafeInt.new 123)
|> SafeInt.toInt
--> Just -123
SafeInt.negate (SafeInt.new -123)
|> SafeInt.toInt
--> Just 123
sign : SafeInt -> SafeInt
Sign.
1
if argument is positive-1
if argument is negative0
if argument is zeroundefined
if argument is undefined
SafeInt.sign (SafeInt.new 123)
|> SafeInt.toInt
--> Just 1
SafeInt.sign (SafeInt.new -123)
|> SafeInt.toInt
--> Just -1