Math
Numeric helpers for Glide. Floating-point functions bind directly to the C math library (libm); the integer helpers and float min/max/clamp are pure Glide so they monomorphize cleanly. The page also exports the PI and E constants.
Import
import stdlib::math::*;
Linking against libm is automatic — there is no flag to pass.
Surface at a glance
| Group | Items |
|---|---|
| Constants | PI, E |
| Roots / powers / exp | sqrt, pow, exp |
| Rounding | floor, ceil, round, fabs |
| Trigonometry | sin, cos, tan, atan2 |
| Logarithms | log, log2, log10 |
| Integer helpers | min_int, max_int, abs_int, sign_int, clamp_int, ipow, gcd, lcm |
| Float helpers | min_f64, max_f64, clamp_f64 |
The 14 floating-point functions are thin extern fn bindings into libm; everything else is pure Glide. None of the math functions return !T/?T — there is nothing to unwrap. Float functions signal out-of-domain inputs with IEEE-754 NaN/inf (see IEEE semantics), and the integer helpers wrap or overflow silently on two's-complement targets rather than erroring.
Constants
| Name | Type | Value |
|---|---|---|
PI |
f64 |
3.141592653589793 |
E |
f64 |
2.718281828459045 |
pub const PI: f64 = 3.141592653589793;
pub const E: f64 = 2.718281828459045;
import stdlib::math::*;
fn main() -> i32 {
let area: f64 = PI * 2.0 * 2.0; // PI * r^2 with r = 2
let growth: f64 = E * E; // e^2
println!("area", area);
println!("growth", growth);
return 0;
}
Floating-point functions
These are extern fn bindings into libm. All take and return f64. They do not return !T/?T — out-of-domain inputs follow C/IEEE-754 semantics (e.g. sqrt of a negative returns NaN, log(0.0) returns -inf), so there is no error value to unwrap. See IEEE-754 NaN and inf for how those values behave downstream.
Roots, powers, exponentials
| Function | Signature | Description |
|---|---|---|
sqrt |
pub extern fn sqrt(x: f64) -> f64 |
Square root. Returns NaN for negative input. |
pow |
pub extern fn pow(x: f64, y: f64) -> f64 |
x^y as a float. For integer exponents prefer ipow. |
exp |
pub extern fn exp(x: f64) -> f64 |
e^x. |
import stdlib::math::*;
fn main() -> i32 {
let r: f64 = sqrt(9.0); // 3.0
let p: f64 = pow(2.0, 10.0); // 1024.0
let e2: f64 = exp(1.0); // E (≈ 2.71828)
println!("sqrt", r);
println!("pow", p);
println!("exp", e2);
return 0;
}
Rounding
| Function | Signature | Description |
|---|---|---|
floor |
pub extern fn floor(x: f64) -> f64 |
Round toward -∞. floor(-2.3) == -3.0. |
ceil |
pub extern fn ceil(x: f64) -> f64 |
Round toward +∞. ceil(-2.7) == -2.0. |
round |
pub extern fn round(x: f64) -> f64 |
Round to nearest, ties away from zero. round(2.5) == 3.0. |
fabs |
pub extern fn fabs(x: f64) -> f64 |
Absolute value (float). Use abs_int for ints. |
import stdlib::math::*;
fn main() -> i32 {
let f: f64 = floor(2.7); // 2.0
let c: f64 = ceil(2.1); // 3.0
let rn: f64 = round(2.5); // 3.0
let a: f64 = fabs(-1.5); // 1.5
println!("floor", f);
println!("ceil", c);
println!("round", rn);
println!("fabs", a);
return 0;
}
Trigonometry
Angles are in radians. Convert from degrees with deg * PI / 180.0.
| Function | Signature | Description |
|---|---|---|
sin |
pub extern fn sin(x: f64) -> f64 |
Sine. Argument in radians. |
cos |
pub extern fn cos(x: f64) -> f64 |
Cosine. Argument in radians. |
tan |
pub extern fn tan(x: f64) -> f64 |
Tangent. Argument in radians. |
atan2 |
pub extern fn atan2(y: f64, x: f64) -> f64 |
Two-argument arctangent: full-circle angle of point (x, y) in radians. |
import stdlib::math::*;
fn main() -> i32 {
let s: f64 = sin(PI / 2.0); // 1.0
let co: f64 = cos(PI); // -1.0
let t: f64 = tan(PI / 4.0); // 1.0
let ang: f64 = atan2(1.0, 0.0); // PI / 2 (point straight up)
println!("sin", s);
println!("cos", co);
println!("tan", t);
println!("atan2", ang);
return 0;
}
Logarithms
| Function | Signature | Description |
|---|---|---|
log |
pub extern fn log(x: f64) -> f64 |
Natural log (base e). Domain x > 0. |
log2 |
pub extern fn log2(x: f64) -> f64 |
Log base 2. |
log10 |
pub extern fn log10(x: f64) -> f64 |
Log base 10. |
import stdlib::math::*;
fn main() -> i32 {
let l: f64 = log(E); // 1.0
let l2: f64 = log2(8.0); // 3.0
let l10: f64 = log10(1000.0); // 3.0
println!("log", l);
println!("log2", l2);
println!("log10", l10);
return 0;
}
IEEE-754 NaN and inf
Because the float functions bind straight to libm, out-of-domain inputs produce IEEE-754 special values instead of raising an error. The important consequences:
sqrt(-1.0),log(-1.0),pow(-1.0, 0.5)→NaN.log(0.0)→-inf;pow(0.0, -1.0)→+inf.- A
NaNis unordered: every comparison against it (==,<,>) isfalse, includingnan == nan. Detect one with the self-inequality trickx != x. NaNpropagates through arithmetic and throughmin_f64/max_f64/clamp_f64(they are plain</>comparisons, so aNaNoperand can pass through unchanged).
import stdlib::math::*;
fn main() -> i32 {
let nan: f64 = sqrt(-1.0); // NaN
let neginf: f64 = log(0.0); // -inf
let is_nan: bool = nan != nan; // true — the canonical NaN test
println!("nan", nan);
println!("neginf", neginf);
println!("is_nan", is_nan);
println!("min-with-nan", min_f64(nan, 1.0)); // NaN propagates
return 0;
}
Integer helpers
Pure-Glide functions over i32. They never allocate and never fail; results are plain i32 (no !T).
| Function | Signature | Description |
|---|---|---|
min_int |
pub fn min_int(a: i32, b: i32) -> i32 |
Smaller of two ints. |
max_int |
pub fn max_int(a: i32, b: i32) -> i32 |
Larger of two ints. |
abs_int |
pub fn abs_int(a: i32) -> i32 |
Absolute value. abs_int(INT_MIN) overflows. |
sign_int |
pub fn sign_int(a: i32) -> i32 |
Sign: -1, 0, or +1. |
clamp_int |
pub fn clamp_int(x: i32, lo: i32, hi: i32) -> i32 |
Clamp into inclusive [lo, hi]. |
ipow |
pub fn ipow(a: i32, b: i32) -> i32 |
a^b for non-negative b, by repeated squaring (O(log b)). Wraps on overflow. |
gcd |
pub fn gcd(a: i32, b: i32) -> i32 |
Greatest common divisor (Euclidean). Always non-negative. |
lcm |
pub fn lcm(a: i32, b: i32) -> i32 |
Least common multiple. Returns 0 if either argument is 0. |
import stdlib::math::*;
fn main() -> i32 {
let mn: i32 = min_int(7, 3); // 3
let mx: i32 = max_int(7, 3); // 7
let av: i32 = abs_int(-5); // 5
let sg: i32 = sign_int(-9); // -1
let cl: i32 = clamp_int(15, 0, 10); // 10
let ip: i32 = ipow(2, 10); // 1024
let g: i32 = gcd(12, 18); // 6
let l: i32 = lcm(4, 6); // 12
println!("min_int", mn);
println!("max_int", mx);
println!("abs_int", av);
println!("sign_int", sg);
println!("clamp_int", cl);
println!("ipow", ip);
println!("gcd", g);
println!("lcm", l);
return 0;
}
gcd operates on absolute values, so gcd(-12, 8) == 4 and gcd(0, 0) == 0. lcm is computed as abs_int(a / gcd(a, b) * b) to limit overflow on the intermediate product.
Float helpers
Pure-Glide min/max/clamp over f64. NaN behaviour follows libc semantics — a NaN operand propagates.
| Function | Signature | Description |
|---|---|---|
min_f64 |
pub fn min_f64(a: f64, b: f64) -> f64 |
Smaller of two f64s. |
max_f64 |
pub fn max_f64(a: f64, b: f64) -> f64 |
Larger of two f64s. |
clamp_f64 |
pub fn clamp_f64(x: f64, lo: f64, hi: f64) -> f64 |
Clamp into [lo, hi]. See clamp_int caveats. |
import stdlib::math::*;
fn main() -> i32 {
let mn: f64 = min_f64(1.5, 2.5); // 1.5
let mx: f64 = max_f64(1.5, 2.5); // 2.5
let cl: f64 = clamp_f64(2.0, 0.0, 1.0); // 1.0
println!("min_f64", mn);
println!("max_f64", mx);
println!("clamp_f64", cl);
return 0;
}
Worked examples
Euclidean distance
sqrt plus a sum of squares gives the straight-line distance between two points — the building block for collision, nearest-neighbour, and physics code.
import stdlib::math::*;
fn distance(x1: f64, y1: f64, x2: f64, y2: f64) -> f64 {
let dx: f64 = x2 - x1;
let dy: f64 = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
fn main() -> i32 {
let d: f64 = distance(0.0, 0.0, 3.0, 4.0); // 5.0
println!("distance", d);
return 0;
}
Degrees and radians
Trig functions take radians. Wrap the conversion factor PI / 180.0 once so the call sites read cleanly.
import stdlib::math::*;
fn to_radians(deg: f64) -> f64 { return deg * PI / 180.0; }
fn to_degrees(rad: f64) -> f64 { return rad * 180.0 / PI; }
fn main() -> i32 {
let r: f64 = to_radians(90.0); // PI / 2
println!("sin90", sin(r)); // 1.0
println!("degrees", to_degrees(r)); // 90.0
return 0;
}
Reducing a fraction with gcd / lcm
Dividing numerator and denominator by their gcd reduces a fraction to lowest terms. lcm finds a common denominator. Both operate on absolute values and never allocate.
import stdlib::math::*;
fn main() -> i32 {
let num: i32 = 84;
let den: i32 = 126;
let g: i32 = gcd(num, den); // 42
println!("reduced", num / g, den / g); // 2 3
let l: i32 = lcm(lcm(4, 6), 8); // 24
println!("lcm", l);
// gcd uses magnitudes; the zero edge cases:
println!("gcd-neg", gcd(-12, 8)); // 4
println!("gcd-zero", gcd(0, 0)); // 0
println!("lcm-zero", lcm(0, 5)); // 0
return 0;
}
Clamping inputs, splitting sign and magnitude
clamp_int/clamp_f64 keep untrusted values inside a range; sign_int + abs_int split a signed value into direction and magnitude.
import stdlib::math::*;
fn main() -> i32 {
let vol: i32 = clamp_int(137, 0, 100); // 100 — slider saturates
let alpha: f64 = clamp_f64(1.4, 0.0, 1.0); // 1.0
let v: i32 = -42;
println!("dir", sign_int(v)); // -1
println!("mag", abs_int(v)); // 42
println!("vol", vol);
println!("alpha", alpha);
// clamp_int(x, lo, hi) is exactly max_int(lo, min_int(hi, x)):
println!("manual", max_int(0, min_int(100, 137))); // 100
return 0;
}
Exact integer powers — ipow vs pow
pow works in floating point and can drift off an exact integer; ipow stays in i32 (wrapping on overflow). Use ipow whenever both operands are integers and the result fits in i32.
import stdlib::math::*;
fn main() -> i32 {
let exact: i32 = ipow(10, 9); // 1000000000, exact
let approx: f64 = pow(10.0, 9.0); // may be 999999999.9999999...
let recovered: i32 = floor(approx + 0.5) as i32;
println!("ipow", exact);
println!("pow-recovered", recovered);
return 0;
}
See also
- `stdlib::random` — random number generation, often clamped with
clamp_int/clamp_f64. - The book's numeric-types chapter for
i32/f64literals, casts (as), and integer overflow semantics.