roc/builtins/Float.roc

201 lines
6.0 KiB
Plaintext
Raw Normal View History

2019-10-24 01:39:14 +03:00
interface Float
2019-12-05 05:34:37 +03:00
exposes [
Float,
fromNum,
round,
ceiling,
floor,
div,
mod,
recip,
sqrt,
2019-12-07 04:22:42 +03:00
highest,
lowest,
highestInt,
lowestInt,
2019-12-05 05:34:37 +03:00
sin,
cos,
tan,
asin,
acos,
atan
]
2019-10-24 01:39:14 +03:00
imports []
2019-09-26 15:11:30 +03:00
## Types
2019-12-03 02:29:35 +03:00
## A 64-bit floating-point number. All number literals with decimal points are #Float values.
2019-09-26 15:11:30 +03:00
##
## > 0.1
##
## > 1.0
##
## > 0.0
##
2019-12-03 02:29:35 +03:00
## If you like, you can put underscores in your #Float literals.
2019-09-26 15:11:30 +03:00
## They have no effect on the number's value, but can make things easier to read.
##
## > 1_000_000.000_000_001
##
2019-12-03 02:29:35 +03:00
## Unlike #Int values, #Float values are imprecise. A classic example of this imprecision:
2019-09-26 15:11:30 +03:00
##
## > 0.1 + 0.2
##
## Floating point values work this way because of some (very reasonable) hardware design decisions made in 1985, which are hardwired into all modern CPUs. The performance penalty for having things work any other way than this is severe, so Roc defaults to using the one with hardware support.
##
2019-12-03 02:29:35 +03:00
## It is possible to build fractional systems with different precision characteristics (for example, storing an #Int numerator and #Int denominator), but their basic arithmetic operations will be unavoidably slower than #Float.
2019-09-26 15:11:30 +03:00
##
2019-12-07 04:22:42 +03:00
## See #Float.highest and #Float.lowest for the highest and
2019-12-03 02:29:35 +03:00
## lowest values that can be held in a #Float.
2019-09-26 15:11:30 +03:00
##
## Note that although the IEEE-754 specification describes the values `Infinity`, `-Infinity`, `NaN`, and `-0.0`, Roc avoids these as follows:
##
2019-12-03 02:29:35 +03:00
## * #Float.sqrt returns #(Err InvalidSqrt) when it would otherwise return `NaN`.
## * Division operations return #(Err DivByZero) when they would otherwise return `Infinity` or `-Infinity`.
2019-09-26 15:11:30 +03:00
## * Operations that overflow crash (just like integers do) instead of returning `Infinity` or `-Infinity`.
2019-12-03 02:29:35 +03:00
## Under the hood, it is possible to have a zero #Float with a negative sign. However, this implementation detail intentionally conceealed. For equality purpose, `-0.0` is treated as equivalent to `0.0`, just like the spec prescribes. However, #Str.decimal always returns `0.0` when it would otherwise return `-0.0`, and both #Num.isPositive and #Num.isNegative return #False for all zero values. The only way to detect a zero with a negative sign is to convert it to #Bytes and inspect the bits directly.
2019-12-05 05:34:37 +03:00
#Float : Num FloatingPoint
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## Returned in an #Err by functions like #Float.div and #Float.mod when their arguments would
2019-11-03 22:23:09 +03:00
## result in division by zero. Division by zero is not allowed!
2019-12-05 05:34:37 +03:00
#FloatingPoint := FloatingPoint
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## Returned in an #Err by #Float.sqrt when given a negative number.
2019-12-05 05:34:37 +03:00
#InvalidSqrt := InvalidSqrt
2019-09-26 15:11:30 +03:00
## Conversions
2019-12-05 05:34:37 +03:00
#fromNum : Num * -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#round : Float -> Int
round = \num ->
case num when
0.0 -> 0
_ -> 1
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#ceiling : Float -> Int
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#floor : Float -> Int
2019-09-26 15:11:30 +03:00
## Trigonometry
2019-12-05 05:34:37 +03:00
#cos : Float -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#acos : Float -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#sin : Float -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#asin : Float -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#tan : Float -> Float
2019-09-26 15:11:30 +03:00
2019-12-05 05:34:37 +03:00
#atan : Float -> Float
2019-09-26 15:11:30 +03:00
## Other Calculations (arithmetic?)
2019-12-03 02:29:35 +03:00
## Divide two #Float numbers. Return `Err DivByZero` if the
2019-09-26 15:11:30 +03:00
## second number is zero, because division by zero is undefined in mathematics.
##
2019-12-03 02:29:35 +03:00
## (To divide an #Int and a #Float, first convert the #Int to a #Float using one of the functions in this module.)
2019-09-26 15:11:30 +03:00
##
## `a / b` is shorthand for `Float.div a b`.
##
## > 5.0 / 7.0
##
## > Float.div 5 7
##
## > 4.0 / -0.5
##
## > Float.div 4.0 -0.5
2019-12-05 05:34:37 +03:00
#div : Float, Float -> Result Float DivByZero
div = \numerator denominator ->
case numerator when
0.0 -> 0.0 # TODO return Result!
_ -> denominator
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## Perform modulo on two #Float numbers.
2019-09-26 15:11:30 +03:00
##
## Modulo is the same as remainder when working with positive numbers,
## but if either number is negative, then modulo works differently.
##
2019-10-22 03:13:28 +03:00
## Return `Err DivByZero` if the second number is zero, because division by zero is undefined in mathematics.
2019-09-26 15:11:30 +03:00
##
## `a % b` is shorthand for `Float.mod a b`.
##
## > 5.0 % 7.0
##
## > Float.mod 5 7
##
## > 4.0 % -0.5
##
## > Float.mod -8 -3
2019-12-05 05:34:37 +03:00
#mod : Float, Float -> Result Float DivByZero
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## Return the reciprocal of the #Float.
2019-12-05 05:34:37 +03:00
#recip : Float -> Result Float Num.DivByZero
#recip = \float ->
# 1.0 / float
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## Return an approximation of the absolute value of the square root of the #Float.
2019-09-26 15:11:30 +03:00
##
2019-12-03 02:29:35 +03:00
## Return #InvalidSqrt if given a negative number. The square root of a negative number is an irrational number, and #Float only supports rational numbers.
2019-09-26 15:11:30 +03:00
##
## > Float.sqrt 4.0
##
## > Float.sqrt 1.5
##
## > Float.sqrt 0.0
##
## > Float.sqrt -4.0
2019-12-05 05:34:37 +03:00
#sqrt : Float -> Result Float InvalidSqrt
2019-09-26 15:11:30 +03:00
## Constants
2019-10-22 03:13:28 +03:00
## An approximation of e, specifically 2.718281828459045.
2019-12-05 05:34:37 +03:00
#e : Float
2019-10-22 03:13:28 +03:00
e = 2.718281828459045
2019-09-26 15:11:30 +03:00
2019-10-22 03:13:28 +03:00
## An approximation of pi, specifically 3.141592653589793.
2019-12-05 05:34:37 +03:00
#pi : Float
2019-10-22 03:13:28 +03:00
pi = 3.141592653589793
2019-09-26 15:11:30 +03:00
## Limits
2019-12-03 02:29:35 +03:00
## The highest supported #Float value you can have, which is approximately 1.8 × 10^308.
2019-09-26 15:11:30 +03:00
##
## If you go higher than this, your running Roc code will crash - so be careful not to!
2019-12-07 04:22:42 +03:00
#highest : Float
highest = 1.0
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## The lowest supported #Float value you can have, which is approximately -1.8 × 10^308.
2019-09-26 15:11:30 +03:00
##
## If you go lower than this, your running Roc code will crash - so be careful not to!
2019-12-07 04:22:42 +03:00
#lowest : Float
lowest = 1.0
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## The highest integer that can be represented as a #Float without # losing precision.
2019-10-22 03:13:28 +03:00
## It is equal to 2^53, which is approximately 9 × 10^15.
2019-09-26 15:11:30 +03:00
##
## Some integers higher than this can be represented, but they may lose precision. For example:
##
2019-12-07 04:22:42 +03:00
## > Float.highestInt
2019-09-26 15:11:30 +03:00
##
2019-12-07 04:22:42 +03:00
## > Float.highestInt + 100 # Increasing may lose precision
2019-09-26 15:11:30 +03:00
##
2019-12-07 04:22:42 +03:00
## > Float.highestInt - 100 # Decreasing is fine - but watch out for lowestLosslessInt!
#highestInt : Float
highestInt = 1.0
2019-09-26 15:11:30 +03:00
2019-12-03 02:29:35 +03:00
## The lowest integer that can be represented as a #Float without losing precision.
2019-10-22 03:13:28 +03:00
## It is equal to -2^53, which is approximately -9 × 10^15.
2019-09-26 15:11:30 +03:00
##
## Some integers lower than this can be represented, but they may lose precision. For example:
##
2019-10-22 03:13:28 +03:00
## > Float.lowestIntVal
2019-09-26 15:11:30 +03:00
##
2019-10-22 03:13:28 +03:00
## > Float.lowestIntVal - 100 # Decreasing may lose precision
2019-09-26 15:11:30 +03:00
##
2019-12-07 04:22:42 +03:00
## > Float.lowestIntVal + 100 # Increasing is fine - but watch out for highestInt!
#lowestInt : Float
lowestInt = 1.0