math
std/math — numbers.
Written in Kite, like the rest of the standard library. Nothing here needs compiler support, which is the test a standard library should have to pass.
absminmaxclamptruncfloorceilroundround_totrunc_tosqrtpowmax_intmin_intchecked_addwrapping_addhypotlerpsignpietauln2explnpowfcbrtsincostanatanatan2asinacosdegreesradians
abs
pub fn abs(x: float) -> float
min
pub fn min(a: float, b: float) -> float
max
pub fn max(a: float, b: float) -> float
clamp
pub fn clamp(x: float, low: float, high: float) -> float
trunc
pub fn trunc(x: float) -> float
Truncation towards zero, which is what an as int cast does. Casts are saturating on every backend, so a value out of range gives a number rather than killing the program.
floor
pub fn floor(x: float) -> float
Comparisons rather than t != x, which would be exact float equality and warn — rightly, since it is rarely what someone means.
ceil
pub fn ceil(x: float) -> float
round
pub fn round(x: float) -> float
Half away from zero, which is what most people mean by rounding.
round_to
pub fn round_to(x: float) -> int
A float as an int, rounded to nearest.
A bare x as int warns, and rightly: it truncates towards zero, which is almost never what code that measured something meant. Saying round_to is saying which rounding was intended, and is the escape hatch that makes keeping the warning worthwhile — without one, every program that has to produce an integer from a measurement has to ignore a warning to do it.
trunc_to
pub fn trunc_to(x: float) -> int
A float as an int, truncated towards zero — the cast, named.
Same purpose as [round_to]: the bare cast warns because it is usually a mistake, and a caller who means it says which rounding they meant.
sqrt
pub fn sqrt(x: float) -> float
The square root, by Newton's method.
Written in Kite rather than reached for from the host: a host call is a boundary two runtimes have to agree about, and this one converges to the same answer everywhere. Twenty iterations is far more than a float needs — the loop stops as soon as it stops moving.
pow
pub fn pow(base: float, exponent: int) -> float
base raised to a whole power. Negative powers give the reciprocal.
max_int
pub fn max_int() -> int
The largest int.
min_int
pub fn min_int() -> int
The smallest int. Written as a subtraction because 9223372036854775808 is not an int and so cannot be negated in source.
checked_add
pub fn checked_add(a: int, b: int) -> Option<int>
a + b, or nil when that does not fit.
The test is done by subtraction rather than by adding and looking at the result, because adding is what traps. max_int() - b is in range whenever b is positive, and min_int() - b is in range whenever b is negative, so neither side of the question can overflow while it is being asked.
wrapping_add
pub fn wrapping_add(a: int, b: int) -> int
a + b, wrapped into the range of an int — in every build.
On overflow the answer is a + b ∓ 2⁶⁴, and that is computed rather than discovered: with two positives too large, (a + min_int()) + (b + min_int()) is the same number and every step of it is in range, because min_int() is exactly -2⁶³ and shifting both operands down by it lands the sum in [min_int(), -2]. The negative case is the mirror image.
hypot
pub fn hypot(x: float, y: float) -> float
The length of the hypotenuse — the distance from the origin to (x, y).
lerp
pub fn lerp(a: float, b: float, t: float) -> float
A point t of the way from a to b.
sign
pub fn sign(x: float) -> int
-1, 0 or 1.
pi
pub fn pi() -> float
The ratio of a circle's circumference to its diameter, to the precision a float holds.
e
pub fn e() -> float
tau
pub fn tau() -> float
ln2
pub fn ln2() -> float
exp
pub fn exp(x: float) -> float
e raised to x.
Reduced by x = k·ln2 + r, so the series only ever sees |r| ≤ ln2/2 and the rest is a power of two. Without that a series for exp(20) would need hundreds of terms and lose most of its precision to cancellation.
ln
pub fn ln(x: float) -> float
The natural logarithm. Zero and negatives have none; both answer zero, which is the same choice sqrt makes above.
Reduced to a mantissa in [√½, √2) so the series argument stays under 0.172 in magnitude. The series is the one for atanh, which converges twice as fast here as the direct series for ln(1 + s).
powf
pub fn powf(base: float, exponent: float) -> float
base raised to a float power, by exp(exponent · ln base).
Only defined for a non-negative base: a negative one raised to a fractional power is not a real number, and raised to a whole one is [pow], which is exact where this would be approximate. Naming the two separately is what keeps a caller from getting an approximation of something exact.
cbrt
pub fn cbrt(x: float) -> float
The cube root, keeping the sign — unlike powf, which cannot.
sin
pub fn sin(x: float) -> float
cos
pub fn cos(x: float) -> float
tan
pub fn tan(x: float) -> float
atan
pub fn atan(x: float) -> float
The arctangent, in radians, in (-π/2, π/2).
Twice reduced. atan(x) = π/2 − atan(1/x) brings anything past 1 inside; the addition formula then brings anything past tan(π/12) down to 0.2679, where the series loses a decimal digit per two terms. Applying the series directly at x = 1 — where it is Leibniz's series for π/4 — would need thousands of terms.
atan2
pub fn atan2(y: float, x: float) -> float
The angle of the point (x, y) from the positive x axis, in (-π, π].
The quadrant comes from the signs, which is the whole reason this exists separately from atan(y / x): that division throws away which quadrant the point was in, and (-1, -1) and (1, 1) are not the same direction.
asin
pub fn asin(x: float) -> float
acos
pub fn acos(x: float) -> float
degrees
pub fn degrees(radians: float) -> float
radians
pub fn radians(degrees: float) -> float