← Back to AILP Home

Math — Compiler Builtins & Type:Math

The Nitpick math system has two layers:

  1. Compiler builtins — wired directly to LLVM intrinsics or libm; no import needed.
  2. Type:Math stdlib — richer functions available via use "std/math.npk".*.

Compiler Builtins

No import is required. These are available everywhere.

Constants

Function Value Notes
PI() π ≈ 3.14159265358979… IEEE 754 double precision
E() e ≈ 2.71828182845904… Euler's number
TAU() τ = 2π ≈ 6.28318530717958… Full turn; TAU() == 2.0 * PI()
SQRT2() √2 ≈ 1.41421356237309… Added v0.55.1
LN2() ln(2) ≈ 0.69314718055994… Added v0.55.1
LN10() ln(10) ≈ 2.30258509299404… Added v0.55.1
flt64:area = PI() * r * r;
flt64:half_turn = PI();
flt64:full_turn = TAU();

Arithmetic

Function Description
abs(x) Absolute value. For flt64: IEEE 754 fabs.
sqrt(x) Square root (x ≥ 0). NaN for x < 0.
pow(x, y) xʸ. Wraps llvm.pow.
exp(x)
exp2(x) 2ˣ (added v0.55.1)
flt64:r = sqrt(9.0);       // 3.0
flt64:p = pow(2.0, 10.0);  // 1024.0
flt64:e2 = exp2(8.0);      // 256.0

Logarithms

Function Description
log(x) / ln(x) Natural logarithm (base e)
log2(x) Base-2 logarithm
log10(x) Base-10 logarithm

Change-of-base identity: log2(x) == log(x) / log(2.0)

flt64:bits = log2(1024.0);   // 10.0
flt64:db   = log10(1000.0);  // 3.0

Rounding

Function Description
floor(x) Round toward −∞. floor(x) ≤ x always.
ceil(x) Round toward +∞. x ≤ ceil(x) always.
trunc(x) Round toward 0. trunc(x) == floor(x) for x ≥ 0.
round(x) Round to nearest, ties away from zero.
floor(3.7)   // 3.0
floor(-3.7)  // -4.0
ceil(3.2)    // 4.0
trunc(-3.9)  // -3.0
round(2.5)   // 3.0

Trigonometry

All angles are in radians.

Function Description
sin(x) Sine
cos(x) Cosine
tan(x) Tangent
asin(x) Inverse sine — domain [-1, 1], range [-π/2, π/2]
acos(x) Inverse cosine — domain [-1, 1], range [0, π]
atan(x) Inverse tangent — range (-π/2, π/2)
atan2(y, x) Four-quadrant arctangent. Returns angle of vector (x,y)

Key identities (verified): - sin(x)² + cos(x)² == 1.0 (within floating-point precision) - sin(-x) == -sin(x) (odd function) - cos(-x) == cos(x) (even function) - asin(x) + acos(x) == PI() / 2.0 for x ∈ [0, 1]

flt64:angle = atan2(3.0, 4.0);   // angle of the 3-4-5 triangle
flt64:deg_90_rad = PI() / 2.0;
flt64:s = sin(deg_90_rad);       // 1.0

SIMD Variants (v0.55.6)

The trig builtins are lifted to simd<flt64, N> types via lane-wise expansion:

simd<flt64, 4>:angles = { 0.0, 0.5, 1.0, 1.5 };
simd<flt64, 4>:sins   = sin(angles);  // lane-wise sin
simd<flt64, 4>:coss   = cos(angles);  // lane-wise cos
simd<flt64, 4>:exps   = exp(angles);  // lane-wise exp

Type:Math Stdlib

Import once at the top of your module:

use "std/math.npk".*;

Access via raw Math.function_name(...).

Classification

Function Signature Description
is_nan(x) bool(flt64:x) True if x is NaN
is_inf(x) bool(flt64:x) True if x is ±∞
is_finite(x) bool(flt64:x) True if x is neither NaN nor ±∞
flt64:bad = 0.0 / 0.0;
if (raw Math.is_nan(bad)) {
    drop println("caught NaN");
}

Value Functions

Function Signature Description
sign(x) flt64(flt64:x) −1.0, 0.0, or +1.0
clamp(x, lo, hi) flt64(flt64, flt64, flt64) Restrict to [lo, hi]
clamp_i64(x, lo, hi) int64(int64, int64, int64) Integer clamp
clamp_i32(x, lo, hi) int32(int32, int32, int32) int32 clamp
abs_i64(x) int64(int64:x) Integer absolute value
sign_i64(x) int64(int64:x) Integer sign: −1, 0, +1
min_i64(a, b) int64(int64, int64) Integer minimum
max_i64(a, b) int64(int64, int64) Integer maximum
min_i32(a, b) int32(int32, int32) int32 minimum
max_i32(a, b) int32(int32, int32) int32 maximum

Note: Scalar min()/max() compiler builtins require vector types. For scalar floats, use inline if (a < b) or the Math.min_i64/Math.max_i64 integer variants.

flt64:clamped = raw Math.clamp(x, 0.0, 1.0);
int64:sign    = raw Math.sign_i64(-42i64);   // -1

Interpolation

Function Signature Description
lerp(a, b, t) flt64(flt64, flt64, flt64) Linear interpolation. lerp(a, b, 0.0) == a, lerp(a, b, 1.0) == b.
inverse_lerp(a, b, v) flt64(flt64, flt64, flt64) Find t such that lerp(a, b, t) == v
map_range(v, in_lo, in_hi, out_lo, out_hi) flt64(×5) Remap from one range to another
smoothstep(e0, e1, x) flt64(flt64, flt64, flt64) Hermite cubic interpolation — smooth S-curve
smootherstep(e0, e1, x) flt64(flt64, flt64, flt64) Ken Perlin's quintic variant — zero first and second derivative at endpoints
// Remap a temperature [0°C, 100°C] to a display bar [0.0, 1.0]
flt64:t = raw Math.map_range(temp_c, 0.0, 100.0, 0.0, 1.0);

// GPU shader-style blend
flt64:fade = raw Math.smoothstep(0.0, 1.0, distance);

Angle Conversion

Function Description
deg_to_rad(d) Degrees → radians. d * PI() / 180.0
rad_to_deg(r) Radians → degrees. r * 180.0 / PI()
flt64:rad = raw Math.deg_to_rad(90.0);  // PI/2
flt64:deg = raw Math.rad_to_deg(PI());  // 180.0

Integer Math

Function Signature Description
gcd(a, b) int64(int64, int64) Greatest common divisor (Euclidean algorithm)
lcm(a, b) int64(int64, int64) Least common multiple. gcd(a,b) * lcm(a,b) == a * b
factorial(n) int64(int64:n) n! for n ∈ [0..20]. Saturates at INT64_MAX for n > 20.
fibonacci(n) int64(int64:n) Fib(n) for n ∈ [0..92]. Iterative, O(n).
is_prime(n) bool(int64:n) Primality test. False for n ≤ 1. Trial division up to √n.
pow_int(base, exp) int64(int64, int64) Exact integer exponentiation (exp ≥ 0). Overflow wraps.
int64:g = raw Math.gcd(48i64, 36i64);      // 12
int64:f = raw Math.factorial(10i64);        // 3628800
int64:fib = raw Math.fibonacci(20i64);      // 6765
bool:prime = raw Math.is_prime(97i64);      // true
int64:p = raw Math.pow_int(2i64, 16i64);    // 65536

libm Wrappers

These expose C libm functions. Requires a build that links -lm for test targets.

Function Signature Description
fmod_f64(x, y) flt64(flt64, flt64) Floating-point remainder (IEEE 754 fmod)
hypot_f64(x, y) flt64(flt64, flt64) √(x²+y²) without overflow
copysign_f64(mag, sgn) flt64(flt64, flt64) mag with sign of sgn
fma_f64(x, y, z) flt64(flt64, flt64, flt64) Fused multiply-add: x*y+z in one rounding
wrap(value, max_val) flt64(flt64, flt64) Wrap value into [0, max_val) via fmod

Multi-Type Math Overloads (v0.55.5)

Type:Math provides overloads for non-float types:

Type Functions
int64 abs_i64, sign_i64, min_i64, max_i64, clamp_i64
int32 abs_i32, sign_i32, min_i32, max_i32, clamp_i32
tbb32 abs_tbb32, sign_tbb32, min_tbb32, max_tbb32 (ERR-safe)
tbb64 abs_tbb64, sign_tbb64, min_tbb64, max_tbb64 (ERR-safe)

ERR propagation: All tbb math functions propagate the ERR sentinel. abs(ERR) == ERR.


Mathematical Identities

The following identities are formally verified (see verification/z3/math_properties.py):

sin(x)² + cos(x)²        == 1.0              [Pythagorean]
sin(a + b)                == sin(a)*cos(b) + cos(a)*sin(b)
exp(log(x))               == x                [x > 0]
log(a * b)                == log(a) + log(b)  [a, b > 0]
pow(a, m + n)             == pow(a, m) * pow(a, n)
sqrt(x)²                  == x                [x ≥ 0]
asin(x) + acos(x)         == PI() / 2.0       [x ∈ [0, 1]]
floor(x)                  <= x                [always]
abs(-x)                   == abs(x)
|a * b|                   == |a| * |b|
gcd(a, b) * lcm(a, b)     == a * b            [a, b > 0]
fibonacci(n+2)            == fibonacci(n+1) + fibonacci(n)
factorial(n+1)            == factorial(n) * (n+1)

Related