math
Numeric operations on floats and integers. math is a single-file module with no sub-modules, so import std::math; brings in the whole thing.
Naming follows C: cbrt, ln, sin, atan2. min and max are a single generic over any cmp::Ord type rather than a family of type-suffixed names. The transcendentals are f64-only, because libm is.
Operations that belong to one numeric type are methods of that type, not functions here: x.sqrt() and x.abs() on f32 and f64, and x.abs(), x.checked_abs() and x.clamp(lo, hi) on every numeric primitive. See primitives.
Two implementation tiers
This distinction shows up in behaviour, so it is worth stating plainly.
Transcendentals — sin, exp, pow, and friends — are thin wrappers over libm and inherit its platform behaviour: rounding mode, errno on domain errors, subnormal handling. Cryo does not re-derive those IEEE-754 corner cases.
Classification and the cheap operations — floor, round, copysign, mul_add, and the sqrt and abs float methods — are Cryo-owned compiler intrinsics lowered to LLVM float intrinsics. Same results as the libm functions of the same name, but no libm dependency and no errno.
Constants
const PI: f64 = 3.141592653589793;
const TAU: f64 = 6.283185307179586;
const E: f64 = 2.718281828459045;
const PHI: f64 = 1.618033988749895;
const SQRT_2: f64 = 1.4142135623730951;
const SQRT_3: f64 = 1.7320508075688772;
const LN_2: f64 = 0.6931471805599453;
const LN_10: f64 = 2.302585092994046;
const LOG2_E: f64 = 1.4426950408889634;
const LOG10_E: f64 = 0.4342944819032518;
const F64_EPSILON: f64 = 2.220446049250313e-16;
const F64_MAX: f64 = 1.7976931348623157e308;
const F64_MIN: f64 = -1.7976931348623157e308;
const F64_MIN_POSITIVE: f64 = 2.2250738585072014e-308;
const F32_EPSILON: f32 = 1.1920929e-7;
const F32_MAX: f32 = 3.4028235e38;
const F32_MIN: f32 = -3.4028235e38;
const F32_MIN_POSITIVE: f32 = 1.1754944e-38;
*_MIN is the most-negative finite value (equal to -*_MAX); *_MIN_POSITIVE is the smallest positive normal. infinity(), neg_infinity(), and nan() produce the non-finite values.
function infinity() -> f64;
function neg_infinity() -> f64;
function nan() -> f64;
Powers and roots
| Function | Notes |
|---|---|
powi | Integer exponent. |
hypot | sqrt(x² + y²) without intermediate overflow. |
mul_add | Fused a * b + c — one rounding, not two. |
Square root is the sqrt method of f32 and f64: x.sqrt().
function cbrt(value: f64) -> f64;
function pow(base: f64, exponent: f64) -> f64;
function powi(base: f64, exp: i64) -> f64;
function powi(base: f64, exp: i64) -> f64;base raised to an integer power via binary exponentiation (libm has no powi). Negative exp returns the reciprocal; powi(_, 0) == 1.0, including powi(0.0, 0) == 1.0.
function hypot(x: f64, y: f64) -> f64;
function hypot(x: f64, y: f64) -> f64;sqrt(x^2 + y^2) without spurious overflow/underflow: libm's hypot scales by the larger operand, so hypot(3e200, 4e200) == 5e200 (the naive sqrt(x*x + y*y) overflows to +inf there).
function mul_add(a: f64, b: f64, c: f64) -> f64;
function mul_add(a: f64, b: f64, c: f64) -> f64;Fused multiply-add: a * b + c computed with a single rounding (IEEE fma), more accurate than performing the multiply and add separately.
Exponentials and logarithms
expm1 and log1p compute exp(x) - 1 and ln(1 + x) accurately for small x, where the naive forms lose most of their significant digits. log(value, base) takes an arbitrary base.
function exp(value: f64) -> f64;
function exp2(value: f64) -> f64;
function expm1(value: f64) -> f64;
function expm1(value: f64) -> f64;exp(value) - 1, accurate for value near 0 (IEEE expm1).
function ln(value: f64) -> f64;
function log2(value: f64) -> f64;
function log10(value: f64) -> f64;
function log1p(value: f64) -> f64;
function log1p(value: f64) -> f64;ln(1 + value), accurate for value near 0 (IEEE log1p).
function log(value: f64, base: f64) -> f64;
function log(value: f64, base: f64) -> f64;Logarithm of value in an arbitrary base.
Trigonometry
function sin(value: f64) -> f64;
function cos(value: f64) -> f64;
function tan(value: f64) -> f64;
function asin(value: f64) -> f64;
function acos(value: f64) -> f64;
function atan(value: f64) -> f64;
function atan2(y: f64, x: f64) -> f64;
function sinh(value: f64) -> f64;
function cosh(value: f64) -> f64;
function tanh(value: f64) -> f64;
function to_radians(degrees: f64) -> f64;
function to_radians(degrees: f64) -> f64;Convert degrees to radians and back.
function to_degrees(radians: f64) -> f64;
Rounding and sign
fract is the fractional part and fmod the floating-point remainder. A float's absolute value is its abs method, which clears the sign bit, so (-0.0).abs() is 0.0 and a negative NaN comes back positive.
function floor(value: f64) -> f64;
function ceil(value: f64) -> f64;
function round(value: f64) -> f64;
function round(value: f64) -> f64;Round to the nearest integer, halfway cases away from zero (round(2.5) == 3.0, round(-2.5) == -3.0) - C round semantics, not the current-rounding-mode rint/nearbyint.
function trunc(value: f64) -> f64;
function fract(value: f64) -> f64;
function fract(value: f64) -> f64;Fractional part, with the sign of value (fract(-2.25) == -0.25).
function copysign(magnitude: f64, sign: f64) -> f64;
function copysign(magnitude: f64, sign: f64) -> f64;magnitude with the sign of sign (IEEE copysign).
function fmod(x: f64, y: f64) -> f64;
function fmod(x: f64, y: f64) -> f64;Floating-point remainder of x / y (IEEE fmod).
function signum(value: f64) -> f64;
function signum(value: f64) -> f64;+1.0 / -1.0 for non-zero values; preserves +0.0, -0.0, and NaN.
Comparison and clamping
min and max are generic over both floats and integers.
abs, checked_abs, and clamp are methods of each numeric primitive: x.abs(), x.clamp(lo, hi). checked_abs is the non-wrapping counterpart of abs: on a signed integer, the most-negative value has no positive counterpart in two's complement, so abs wraps to itself and checked_abs returns None. See the overflow contract for why there is no broader checked_* family.
function min<T>(a: T, b: T) -> T where T: cmp::Ord;
function min<T>(a: T, b: T) -> T where T: cmp::Ord;Smaller of a and b. NaN-transparent for the float types.
function max<T>(a: T, b: T) -> T where T: cmp::Ord;
function max<T>(a: T, b: T) -> T where T: cmp::Ord;Larger of a and b. NaN-transparent for the float types.
Classification
type enum FpCategory {
Nan;
Infinite;
Zero;
Subnormal;
Normal;
}
These are implemented over the IEEE-754 bit pattern in pure Cryo, not through libm — the C equivalents are macros rather than exported symbols.
function is_nan(value: f64) -> boolean;
function is_nan(value: f64) -> boolean;True if value is NaN (quiet or signaling).
function is_infinite(value: f64) -> boolean;
function is_infinite(value: f64) -> boolean;True if value is positive or negative infinity.
function is_finite(value: f64) -> boolean;
function is_finite(value: f64) -> boolean;True if value is finite - neither NaN nor infinite. Includes +/-0 and subnormals.
function is_normal(value: f64) -> boolean;
function is_normal(value: f64) -> boolean;True if value is a normal number: finite, nonzero, and not subnormal.
function is_sign_negative(value: f64) -> boolean;
function is_sign_negative(value: f64) -> boolean;True if value's IEEE-754 sign bit is set. Unlike the class tests this reports the raw sign bit, so it is true for -0.0 and negative NaNs too. A single bit read - no libm.
function classify(value: f64) -> FpCategory;
function classify(value: f64) -> FpCategory;Classify value into its IEEE-754 category.
Integer helpers
next_power_of_two rounds up; align_up / align_down round to a power-of-two boundary. The pointer-flavoured versions of the alignment helpers live in core::mem.
function gcd(a: u64, b: u64) -> u64;
function gcd(a: u64, b: u64) -> u64;Greatest common divisor (Euclid). gcd(0, 0) == 0.
function lcm(a: u64, b: u64) -> u64;
function lcm(a: u64, b: u64) -> u64;Least common multiple. lcm(_, 0) == 0.
function is_power_of_two(value: u64) -> boolean;
function is_power_of_two(value: u64) -> boolean;True if value is a power of two (zero is not).
function next_power_of_two(value: u64) -> u64;
function next_power_of_two(value: u64) -> u64;Smallest power of two >= value. next_power_of_two(0) == 1.
function align_up(value: u64, align: u64) -> u64;
function align_up(value: u64, align: u64) -> u64;Round value up to the next multiple of align. An align of 0 or 1 returns value unchanged. Used for memory/field layout where align is a power of two, but works for any non-zero alignment. Consolidates the align_up helper the compiler's type-layout pass hand-rolls.
function align_down(value: u64, align: u64) -> u64;
function align_down(value: u64, align: u64) -> u64;Round value down to the previous multiple of align. An align of 0 or 1 returns value unchanged.
const NAME: Type = value;At module level, a true compile-time constant, conventionally SCREAMING_SNAKE_CASE. (mut at module level declares mutable global state instead.)
const PI: f64 = 3.141592653589793;const TAU: f64 = 6.283185307179586;const E: f64 = 2.718281828459045;const PHI: f64 = 1.618033988749895;const SQRT_2: f64 = 1.4142135623730951;const SQRT_3: f64 = 1.7320508075688772;const LN_2: f64 = 0.6931471805599453;const LN_10: f64 = 2.302585092994046;const LOG2_E: f64 = 1.4426950408889634;const LOG10_E: f64 = 0.4342944819032518;const F64_EPSILON: f64 = 2.220446049250313e-16;const F64_MAX: f64 = 1.7976931348623157e308;const F64_MIN: f64 = -1.7976931348623157e308;const F64_MIN_POSITIVE: f64 = 2.2250738585072014e-308;const F32_EPSILON: f32 = 1.1920929e-7;const F32_MAX: f32 = 3.4028235e38;const F32_MIN: f32 = -3.4028235e38;const F32_MIN_POSITIVE: f32 = 1.1754944e-38;type struct Name { ... }
type enum Name { ... }
type trait Name { ... }
type union Name { ... }Begins a type declaration; the keyword that follows says which kind. On its own, type Name = Existing; declares an alias.
type enum Name {
Unit,
Payload(T),
Named { x: i32 },
}An algebraic data type. Variants may be bare or carry a tuple or struct payload, and a match on an enum must cover every variant. Name::Variant names a variant; methods are added with implement enum Name { ... }.
type enum FpCategory {
Nan;
Infinite;
Zero;
Subnormal;
Normal;
}IEEE-754 value categories, as returned by classify.
FpCategory::NanFpCategory::InfiniteFpCategory::ZeroFpCategory::SubnormalFpCategory::Normalimport a::b;
import a::b::{ X, Y };
import a::b as c;
import a::b::*;Brings a module, or selected items from it, into scope. One path per declaration: use the brace form for several items, as to alias, and * for everything public (prefer the brace form; wildcards invite name collisions).
function cbrt(value: f64) -> f64function ln(value: f64) -> f64function sin(value: f64) -> f64function atan2(y: f64, x: f64) -> f64function min<T>(a: T, b: T) -> T
where T: cmp::OrdSmaller of a and b. NaN-transparent for the float types.
function max<T>(a: T, b: T) -> T
where T: cmp::OrdLarger of a and b. NaN-transparent for the float types.
function exp(value: f64) -> f64function pow(base: f64, exponent: f64) -> f64function floor(value: f64) -> f64function round(value: f64) -> f64Round to the nearest integer, halfway cases away from zero (round(2.5) == 3.0, round(-2.5) == -3.0) - C round semantics, not the current-rounding-mode rint/nearbyint.
function copysign(magnitude: f64, sign: f64) -> f64magnitude with the sign of sign (IEEE copysign).
function mul_add(a: f64, b: f64, c: f64) -> f64Fused multiply-add: a * b + c computed with a single rounding (IEEE fma), more accurate than performing the multiply and add separately.
function infinity() -> f64function neg_infinity() -> f64function nan() -> f64function name<T>(param: Type) -> Ret { ... }Declares a function. Parameters are written name: Type and are never inferred; the return type follows -> and defaults to void. Declaration order does not matter: every signature is collected before any body is checked, so functions may call each other freely and recurse.
function infinity() -> f64function neg_infinity() -> f64function nan() -> f64function powi(base: f64, exp: i64) -> f64base raised to an integer power via binary exponentiation (libm has no powi). Negative exp returns the reciprocal; powi(_, 0) == 1.0, including powi(0.0, 0) == 1.0.
function hypot(x: f64, y: f64) -> f64sqrt(x^2 + y^2) without spurious overflow/underflow: libm's hypot scales by the larger operand, so hypot(3e200, 4e200) == 5e200 (the naive sqrt(x*x + y*y) overflows to +inf there).
function cbrt(value: f64) -> f64(parameter) value: f64function pow(base: f64, exponent: f64) -> f64(parameter) base: f64(parameter) exponent: f64function powi(base: f64, exp: i64) -> f64base raised to an integer power via binary exponentiation (libm has no powi). Negative exp returns the reciprocal; powi(_, 0) == 1.0, including powi(0.0, 0) == 1.0.
(parameter) exp: i64function hypot(x: f64, y: f64) -> f64sqrt(x^2 + y^2) without spurious overflow/underflow: libm's hypot scales by the larger operand, so hypot(3e200, 4e200) == 5e200 (the naive sqrt(x*x + y*y) overflows to +inf there).
(parameter) x: f64(parameter) y: f64function mul_add(a: f64, b: f64, c: f64) -> f64Fused multiply-add: a * b + c computed with a single rounding (IEEE fma), more accurate than performing the multiply and add separately.
(parameter) a: f64(parameter) b: f64(parameter) c: f64function exp(value: f64) -> f64function exp2(value: f64) -> f64function expm1(value: f64) -> f64exp(value) - 1, accurate for value near 0 (IEEE expm1).
function ln(value: f64) -> f64function log2(value: f64) -> f64function log10(value: f64) -> f64function log1p(value: f64) -> f64ln(1 + value), accurate for value near 0 (IEEE log1p).
function log(value: f64, base: f64) -> f64Logarithm of value in an arbitrary base.
function sin(value: f64) -> f64function cos(value: f64) -> f64function tan(value: f64) -> f64function asin(value: f64) -> f64function acos(value: f64) -> f64function atan(value: f64) -> f64function atan2(y: f64, x: f64) -> f64function sinh(value: f64) -> f64function cosh(value: f64) -> f64function tanh(value: f64) -> f64function to_radians(degrees: f64) -> f64Convert degrees to radians and back.
(parameter) degrees: f64function to_degrees(radians: f64) -> f64(parameter) radians: f64function fract(value: f64) -> f64Fractional part, with the sign of value (fract(-2.25) == -0.25).
function floor(value: f64) -> f64function ceil(value: f64) -> f64function round(value: f64) -> f64Round to the nearest integer, halfway cases away from zero (round(2.5) == 3.0, round(-2.5) == -3.0) - C round semantics, not the current-rounding-mode rint/nearbyint.
function trunc(value: f64) -> f64function fract(value: f64) -> f64Fractional part, with the sign of value (fract(-2.25) == -0.25).
function copysign(magnitude: f64, sign: f64) -> f64magnitude with the sign of sign (IEEE copysign).
(parameter) magnitude: f64(parameter) sign: f64function fmod(x: f64, y: f64) -> f64Floating-point remainder of x / y (IEEE fmod).
function signum(value: f64) -> f64+1.0 / -1.0 for non-zero values; preserves +0.0, -0.0, and NaN.
function clamp<T>(value: T, lo: T, hi: T) -> T
where T: OrdConstrain value to [lo, hi]. Panics if lo > hi; the caller gave a nonsense range.
Option::Nonefunction min<T>(a: T, b: T) -> T
where T: cmp::OrdSmaller of a and b. NaN-transparent for the float types.
type parameter Twhere T: Ord
(parameter) a: T(parameter) b: Twhere T: Ord + Clone, U: HashConstrains generic parameters to types that implement the listed traits, which is what makes those traits' methods callable on T. Bounds on one parameter join with +; parameters separate with ,. A where on a single method narrows the type's parameter for that method only.
function max<T>(a: T, b: T) -> T
where T: cmp::OrdLarger of a and b. NaN-transparent for the float types.
function is_nan(value: f64) -> booleanTrue if value is NaN (quiet or signaling).
function is_infinite(value: f64) -> booleanTrue if value is positive or negative infinity.
function is_finite(value: f64) -> booleanTrue if value is finite - neither NaN nor infinite. Includes +/-0 and subnormals.
function is_normal(value: f64) -> booleanTrue if value is a normal number: finite, nonzero, and not subnormal.
function is_sign_negative(value: f64) -> booleanTrue if value's IEEE-754 sign bit is set. Unlike the class tests this reports the raw sign bit, so it is true for -0.0 and negative NaNs too. A single bit read - no libm.
function classify(value: f64) -> FpCategoryClassify value into its IEEE-754 category.
type enum FpCategory {
Nan;
Infinite;
Zero;
Subnormal;
Normal;
}IEEE-754 value categories, as returned by classify.
function next_power_of_two(value: u64) -> u64Smallest power of two >= value. next_power_of_two(0) == 1.
function align_up(value: u64, align: u64) -> u64Round value up to the next multiple of align. An align of 0 or 1 returns value unchanged. Used for memory/field layout where align is a power of two, but works for any non-zero alignment. Consolidates the align_up helper the compiler's type-layout pass hand-rolls.
function align_down(value: u64, align: u64) -> u64Round value down to the previous multiple of align. An align of 0 or 1 returns value unchanged.
function gcd(a: u64, b: u64) -> u64Greatest common divisor (Euclid). gcd(0, 0) == 0.
(parameter) a: u64(parameter) b: u64function lcm(a: u64, b: u64) -> u64Least common multiple. lcm(_, 0) == 0.
function is_power_of_two(value: u64) -> booleanTrue if value is a power of two (zero is not).
(parameter) value: u64function next_power_of_two(value: u64) -> u64Smallest power of two >= value. next_power_of_two(0) == 1.
function align_up(value: u64, align: u64) -> u64Round value up to the next multiple of align. An align of 0 or 1 returns value unchanged. Used for memory/field layout where align is a power of two, but works for any non-zero alignment. Consolidates the align_up helper the compiler's type-layout pass hand-rolls.
(parameter) align: u64function align_down(value: u64, align: u64) -> u64Round value down to the previous multiple of align. An align of 0 or 1 returns value unchanged.