Kite

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.

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