Module math

math
Stability: stable — the method and constant names follow Rust's `f64`/`f32` inherent surface. The one remaining gap is that `f32` carries a SUBSET of `f64`'s methods: the inverse and hyperbolic trigonometry, `exp2`/`exp_m1`/`ln_1p` and `mul_add` are `f64`-only here. That is not a C limitation — `asinf`, `coshf`, `exp2f`, `expm1f`, `log1pf` and `fmaf` all exist in C99 and are already bound in `std/libc/math.yo`; this module simply has not wrapped them yet, and doing so is additive. — stable modules only change additively; this one may still change.

Floating-point mathematics — the Yo-level surface over libc/math.

f64 and f32 carry these as INHERENT methods and associated constants, so they read the way Rust's do:

import("std/math"); // registers the methods; the module exports no names

h := ((a * a) + (b * b)).sqrt();
deg := angle.to_degrees();
println(f64.PI.to_string());

Why this is not in the prelude

Every function here is a C call, and the prelude imports NOTHING and contains no c_include — it is the one module that cannot reach libc. std/string/rune.yo sets the precedent: it gives the primitive rune its character methods from an ordinary module. Importing this module anywhere in a program registers the impls for the whole program, exactly as importing std/string does for rune.

The unsafe(...) wrappers every C call needs live here once, so callers never need pragma(Pragma.AllowUnsafe) to compute a square root.

Constants are Yo literals, not libc's

M_PI and friends are C MACROS expanding to rvalues, which cannot be an inout receiver (issues/c-include-rvalue-macro-constant-cannot-be-addressed.md) and are not compile-time values to Yo. Spelling the constants as Yo literals makes them real comptime constants with no header dependency, and they are exact: each is the shortest decimal that round-trips to the same double.

INFINITY, NEG_INFINITY and NAN are here as of the v0.2.29 seed. They have no token of their own, so each is spelled as the thing that produces it: an OVERFLOWING literal (f64(1.0e400)) for the infinities, and ∞ - ∞ for the NaN. Two alternatives were tried and rejected — 0.0 / 0.0 is refused outright ("Division by zero in comptime float operation"), and x * y - x * y is fused into an FMA by -ffp-contract=on and evaluates to -inf. They had to wait for a seed because the v0.2.28 compiler emitted a non-finite float constant as the invalid C literal inf.0 (issues/fixed/comptime-float-infinity-emits-invalid-c.md), and std/ must build under the seed.

Stability

stable — the method and constant names follow Rust's f64/f32 inherent surface. The one remaining gap is that f32 carries a SUBSET of f64's methods: the inverse and hyperbolic trigonometry, exp2/exp_m1/ln_1p and mul_add are f64-only here. That is not a C limitation — asinf, coshf, exp2f, expm1f, log1pf and fmaf all exist in C99 and are already bound in std/libc/math.yo; this module simply has not wrapped them yet, and doing so is additive.