Module math
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.