roc/builtins/Float.roc

224 lines
6.7 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
##
2019-12-21 23:14:11 +03:00
## >>> 0.1
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> 1.0
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> 0.0
2019-09-26 15:11:30 +03:00
##
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.
##
2019-12-21 23:14:11 +03:00
## >>> 1_000_000.000_000_001
2019-09-26 15:11:30 +03:00
##
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
##
2019-12-21 23:14:11 +03:00
## >>> 0.1 + 0.2
2019-09-26 15:11:30 +03:00
##
## 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
##
2020-01-20 06:19:49 +03:00
## Like #Int, it's possible for #Float operations to overflow and underflow
## if they exceed the bounds of #Float.highest and #Float.lowest. When this happens:
##
## * In a development build, you'll get an assertion failure.
## * In an optimized build, you'll get [`Infinity` or `-Infinity`](https://en.wikipedia.org/wiki/IEEE_754-1985#Positive_and_negative_infinity).
##
## Although some languages treat have first-class representations for
## `-Infinity`, `Infinity`, and the special `NaN` ("not a number")
## floating-point values described in the IEEE-754, Roc does not.
## Instead, Roc treats all of these as errors. If any Float operation
## in a development build encounters one of these values, it will
## result in an assertion failure.
##
## Stll, it's possible that these values may accidentally arise in
## release builds. If this happens, they will behave according to the usual
## IEEE-754 rules: any operation involving `NaN` will output `NaN`,
## any operation involving `Infinity` or `-Infinity` will output either
## `Infinity`, `-Infinity`, or `NaN`, and `NaN` is defined to be not
## equal to itself - meaning `(x == x)` returns `False` if `x` is `NaN`.
##
## These are very error-prone values, so if you see an assertion fail in
## developent because of one of them, take it seriously - and try to fix
## the code so that it can't come up in a release!
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 ->
2019-12-24 01:17:04 +03:00
when num is
2019-12-05 05:34:37 +03:00
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?)
2020-01-20 06:19:49 +03:00
## Divide two #Float numbers.
2019-09-26 15:11:30 +03:00
##
## `a / b` is shorthand for `Float.div a b`.
##
2020-01-20 06:19:49 +03:00
## Division by zero is undefined in mathematics. As such, you should make
## sure never to pass zero as the denomaintor to this function!
##
## If zero does get passed as the denominator...
##
## * In a development build, you'll get an assertion failure.
## * In a release build, the function will return `Infinity`, `-Infinity`, or `NaN` depending on the arguments.
##
## To divide an #Int and a #Float, first convert the #Int to a #Float using one of the functions in this module.
##
2019-12-16 01:19:16 +03:00
## >>> 5.0 / 7.0
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## >>> Float.div 5 7
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## `Float.div` can be convenient in pipelines.
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## >>> Float.pi
## >>> |> Float.div 2.0
2019-12-05 05:34:37 +03:00
#div : Float, Float -> Result Float DivByZero
2019-12-19 05:45:00 +03:00
div = \numerator, denominator ->
2019-12-24 01:17:04 +03:00
when numerator is
2019-12-05 05:34:37 +03:00
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`.
##
2019-12-16 01:19:16 +03:00
## >>> 5.0 % 7.0
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## >>> Float.mod 5 7
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## `Float.mod` can be convenient in pipelines.
2019-09-26 15:11:30 +03:00
##
2019-12-16 01:19:16 +03:00
## >>> Float.pi
## >>> |> Float.mod 2.0
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-16 01:19:16 +03:00
#recip : Float -> Result Float [ DivByZero ]*
2019-12-05 05:34:37 +03:00
#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
##
2019-12-21 23:14:11 +03:00
## >>> Float.sqrt 4.0
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.sqrt 1.5
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.sqrt 0.0
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> 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 : Num.Num Float.FloatingPoint
2019-12-07 04:22:42 +03:00
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-21 23:14:11 +03:00
## >>> Float.highestInt
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.highestInt + 100 # Increasing may lose precision
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.highestInt - 100 # Decreasing is fine - but watch out for lowestLosslessInt!
2019-12-07 04:22:42 +03:00
#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-12-21 23:14:11 +03:00
## >>> Float.lowestIntVal
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.lowestIntVal - 100 # Decreasing may lose precision
2019-09-26 15:11:30 +03:00
##
2019-12-21 23:14:11 +03:00
## >>> Float.lowestIntVal + 100 # Increasing is fine - but watch out for highestInt!
2019-12-07 04:22:42 +03:00
#lowestInt : Float
lowestInt = 1.0