12 KiB
12 KiB
std.math
Mathematical functions, constants, and utilities. Provides floating-point operations, trigonometry, integer arithmetic with overflow checking, and arbitrary-precision integers.
Quick Reference
| Category | Functions |
|---|---|
| Constants | e, pi, phi, tau, sqrt2, ln2, ln10 |
| Trig | sin, cos, tan, asin, acos, atan, atan2 |
| Hyperbolic | sinh, cosh, tanh, asinh, acosh, atanh |
| Exponential | exp, exp2, expm1, log, log2, log10, log1p |
| Powers/Roots | pow, powi, sqrt, cbrt, hypot |
| Rounding | floor, ceil, round, trunc |
| Float Tests | isNan, isInf, isFinite, isNormal, signbit |
| Integer Ops | add, sub, mul, divTrunc, divFloor, divCeil |
| Bit Ops | shl, shr, rotl, rotr, log2_int, isPowerOfTwo |
| Comparison | order, compare, clamp, sign |
Mathematical Constants
const std = @import("std");
const math = std.math;
// Fundamental constants
const euler = math.e; // 2.71828...
const pi_val = math.pi; // 3.14159...
const golden = math.phi; // 1.61803... (golden ratio)
const tau_val = math.tau; // 2 * pi
// Logarithmic constants
const log2_e = math.log2e; // log2(e)
const log10_e = math.log10e; // log10(e)
const ln_2 = math.ln2; // ln(2)
const ln_10 = math.ln10; // ln(10)
// Square root constants
const sqrt_2 = math.sqrt2; // sqrt(2)
const inv_sqrt2 = math.sqrt1_2; // 1/sqrt(2)
// Angle conversion
const rad_deg = math.rad_per_deg; // pi/180
const deg_rad = math.deg_per_rad; // 180/pi
Angle Conversion
// Convert between radians and degrees
const radians = std.math.degreesToRadians(@as(f32, 90.0)); // pi/2
const degrees = std.math.radiansToDegrees(@as(f32, std.math.pi)); // 180.0
// Works with vectors
const angles: @Vector(3, f32) = .{ 90.0, 180.0, 270.0 };
const rads = std.math.degreesToRadians(angles);
Trigonometric Functions
const x: f32 = std.math.pi / 4.0;
// Basic trig (use hardware instructions when available)
const sine = std.math.sin(x); // 0.7071...
const cosine = std.math.cos(x); // 0.7071...
const tangent = std.math.tan(x); // 1.0
// Inverse trig
const asin_val = std.math.asin(@as(f32, 0.5)); // pi/6
const acos_val = std.math.acos(@as(f32, 0.5)); // pi/3
const atan_val = std.math.atan(@as(f32, 1.0)); // pi/4
const atan2_val = std.math.atan2(@as(f32, 1.0), @as(f32, 1.0)); // pi/4
// Hyperbolic functions
const sinh_val = std.math.sinh(x);
const cosh_val = std.math.cosh(x);
const tanh_val = std.math.tanh(x);
const asinh_val = std.math.asinh(x);
const acosh_val = std.math.acosh(@as(f32, 2.0));
const atanh_val = std.math.atanh(@as(f32, 0.5));
Exponential and Logarithmic Functions
const x: f64 = 2.0;
// Exponential
const exp_val = std.math.exp(x); // e^x
const exp2_val = std.math.exp2(x); // 2^x
const expm1_val = std.math.expm1(x); // e^x - 1 (more precise near 0)
// Logarithms
const log_val = std.math.log(f64, std.math.e, x); // natural log
const log2_val = std.math.log2(x); // log base 2
const log10_val = std.math.log10(x); // log base 10
const log1p_val = std.math.log1p(x); // ln(1 + x) (more precise near 0)
// Integer logarithms (for integer types)
const log2_int_val = std.math.log2_int(u32, 8); // 3 (floor)
const log2_ceil = std.math.log2_int_ceil(u32, 9); // 4 (ceil)
const log10_int_val = std.math.log10_int(1000); // 3
Power and Root Functions
// Powers
const pow_val = std.math.pow(f64, 2.0, 3.0); // 2^3 = 8.0
const powi_val = try std.math.powi(i32, 2, 3); // checked integer power
// Roots
const sqrt_val = std.math.sqrt(@as(f64, 16.0)); // 4.0
const cbrt_val = std.math.cbrt(@as(f64, 27.0)); // 3.0
// Hypotenuse (sqrt(x^2 + y^2), avoids overflow)
const hyp = std.math.hypot(@as(f64, 3.0), @as(f64, 4.0)); // 5.0
Rounding Functions
const x: f32 = 2.7;
const floor_val = std.math.floor(x); // 2.0 (toward -inf)
const ceil_val = std.math.ceil(x); // 3.0 (toward +inf)
const trunc_val = std.math.trunc(x); // 2.0 (toward zero)
const round_val = std.math.round(x); // 3.0 (nearest, ties away from zero)
Floating-Point Classification
const x: f32 = 1.0;
const inf_val = std.math.inf(f32);
const nan_val = std.math.nan(f32);
// Classification tests
const is_nan = std.math.isNan(nan_val); // true
const is_inf = std.math.isInf(inf_val); // true
const is_pos_inf = std.math.isPositiveInf(inf_val); // true
const is_neg_inf = std.math.isNegativeInf(-inf_val); // true
const is_finite = std.math.isFinite(x); // true
const is_normal = std.math.isNormal(x); // true
// Sign operations
const has_neg_sign = std.math.signbit(-1.0); // true
const copied = std.math.copysign(@as(f32, 5.0), @as(f32, -1.0)); // -5.0
Float Properties
// Get float type properties
const mantissa_bits = std.math.floatMantissaBits(f32); // 23
const exponent_bits = std.math.floatExponentBits(f32); // 8
const eps = std.math.floatEps(f32); // ~1.19e-7
const min_val = std.math.floatMin(f32); // smallest positive normal
const max_val = std.math.floatMax(f32); // largest finite
const true_min = std.math.floatTrueMin(f32); // smallest positive (including subnormal)
// Special values
const inf_val = std.math.inf(f32); // positive infinity
const nan_val = std.math.nan(f32); // quiet NaN
const snan_val = std.math.snan(f32); // signaling NaN
Approximate Equality
const x: f32 = 1.0;
const y: f32 = 1.0 + std.math.floatEps(f32);
// Absolute tolerance (good for values near zero)
const abs_eq = std.math.approxEqAbs(f32, x, y, 1e-6);
// Relative tolerance (good for larger values)
const rel_eq = std.math.approxEqRel(f32, x, y, std.math.sqrt(std.math.floatEps(f32)));
Integer Arithmetic with Overflow Checking
// These return errors on overflow instead of wrapping
const sum = std.math.add(i32, 2147483647, 1) catch |err| {
// err is error.Overflow
return err;
};
const product = std.math.mul(i32, 1000000, 1000000) catch |err| {
return err; // Overflow for i32
};
const diff = std.math.sub(u32, 5, 10) catch |err| {
return err; // Overflow (underflow) for unsigned
};
// Negation with potential overflow
const negated = std.math.negate(@as(i8, -128)) catch |err| {
return err; // Can't represent 128 in i8
};
// Shift with overflow check
const shifted = std.math.shlExact(u8, 2, 7) catch |err| {
return err; // Overflow: 2 << 7 doesn't fit in u8
};
The shift amount has type std.math.Log2Int(T), so an out-of-range count such as 8 for u8 is rejected before shlExact can report value overflow.
Division Functions
// Division toward zero
const trunc_div = try std.math.divTrunc(i32, -7, 3); // -2
// Division toward negative infinity
const floor_div = try std.math.divFloor(i32, -7, 3); // -3
// Division toward positive infinity
const ceil_div = try std.math.divCeil(i32, 7, 3); // 3
// Exact division (error if remainder)
const exact = try std.math.divExact(i32, 10, 5); // 2
// std.math.divExact(i32, 10, 3) returns error.UnexpectedRemainder
// Modulo (always non-negative result)
const mod_val = try std.math.mod(i32, -5, 3); // 1
// Remainder (can be negative)
const rem_val = try std.math.rem(i32, -5, 3); // -2
Bit Operations
// Shift with truncation (no overflow, large shifts -> 0)
const shl_val = std.math.shl(u8, 0b11111111, 3); // 0b11111000
const shr_val = std.math.shr(u8, 0b11111111, 3); // 0b00011111
// Negative shift amounts reverse direction
const neg_shift = std.math.shl(u8, 0b11111111, -2); // 0b00111111
// Rotation (unsigned integers only)
const rotl_val = std.math.rotl(u8, 0b00000001, 4); // 0b00010000
const rotr_val = std.math.rotr(u8, 0b00010000, 4); // 0b00000001
// Power of two checks
const is_pow2 = std.math.isPowerOfTwo(@as(u32, 8)); // true
const floor_pow2 = std.math.floorPowerOfTwo(u32, 65); // 64
const ceil_pow2 = try std.math.ceilPowerOfTwo(u32, 65); // 128
Integer Type Utilities
// Get min/max values of integer type
const max_i32 = std.math.maxInt(i32); // 2147483647
const min_i32 = std.math.minInt(i32); // -2147483648
// Log2Int: type for bit indices
const Log2U32 = std.math.Log2Int(u32); // u5 (can hold 0-31)
// Smallest type fitting a range
const T = std.math.IntFittingRange(0, 100); // u7
const S = std.math.IntFittingRange(-50, 50); // i7
// Byte-aligned integer type
const ByteAligned = std.math.ByteAlignedInt(u5); // u8
Comparison and Ordering
// Get ordering between values
const ord = std.math.order(@as(i32, 5), @as(i32, 3)); // .gt
// ord is std.math.Order: .lt, .eq, or .gt
// Runtime comparison operator
const result = std.math.compare(@as(i32, 5), .gte, @as(i32, 3)); // true
// Clamp to range
const clamped = std.math.clamp(@as(i32, 15), @as(i32, 0), @as(i32, 10)); // 10
// Wrap to half-open interval [-r, r)
const wrapped = std.math.wrap(@as(i32, 270), @as(i32, 180)); // -90
Sign and Interpolation
// Get sign (-1, 0, or 1)
const s = std.math.sign(@as(i32, -42)); // -1
// Linear interpolation
const lerped = std.math.lerp(@as(f32, 0.0), @as(f32, 100.0), @as(f32, 0.25)); // 25.0
Type Casting
// Safe cast (returns null if doesn't fit)
const maybe: ?u8 = std.math.cast(u8, @as(i32, 300)); // null
// Lossy cast (clamps to representable range)
const clamped = std.math.lossyCast(u8, @as(i32, 300)); // 255
const from_float = std.math.lossyCast(i16, @as(f32, 70000.0)); // 32767
// Negate and cast to signed
const negated = try std.math.negateCast(@as(u32, 100)); // -100 as i32
Wide Multiplication
// Multiply without overflow (result is double width)
const wide = std.math.mulWide(u8, 200, 200); // 40000 as u16
Complex Numbers
const Complex = std.math.Complex;
const z1 = Complex(f32).init(3.0, 4.0); // 3 + 4i
const z2 = Complex(f32).init(1.0, 2.0); // 1 + 2i
// Arithmetic
const sum = z1.add(z2); // 4 + 6i
const diff = z1.sub(z2); // 2 + 2i
const prod = z1.mul(z2); // -5 + 10i
const quot = z1.div(z2);
// Operations
const conj = z1.conjugate(); // 3 - 4i
const neg = z1.neg(); // -3 - 4i
const recip = z1.reciprocal();
const mag = z1.magnitude(); // 5.0 (|z|)
// Multiply by i
const times_i = z1.mulbyi(); // -4 + 3i
// Complex math functions
const z_exp = std.math.complex.exp(z1);
const z_log = std.math.complex.log(z1);
const z_sin = std.math.complex.sin(z1);
const z_sqrt = std.math.complex.sqrt(z1);
Big Integers (Arbitrary Precision)
const big = std.math.big;
const Managed = big.int.Managed;
// Create big integers (requires allocator)
var a = try Managed.initSet(allocator, 12345678901234567890);
defer a.deinit();
var b = try Managed.initSet(allocator, 98765432109876543210);
defer b.deinit();
// Arithmetic
try a.add(&a, &b);
try a.mul(&a, &b);
var q = try Managed.init(allocator);
defer q.deinit();
var r = try Managed.init(allocator);
defer r.deinit();
try q.divTrunc(&r, &a, &b); // quotient in q, remainder in r
// Comparison
const ord = a.order(b); // .lt, .eq, or .gt
// Convert to primitive (if fits)
const val = a.toInt(i128) catch |err| {
// Value doesn't fit in i128
return err;
};
// Convert from string
var c = try Managed.init(allocator);
defer c.deinit();
try c.setString(10, "123456789012345678901234567890");
GCD and LCM
// Greatest common divisor
const gcd_val = std.math.gcd(@as(u32, 48), @as(u32, 18)); // 6
// Least common multiple
const lcm_val = std.math.lcm(@as(u32, 4), @as(u32, 6)); // 12
// lcm is not an error union; intermediate multiplication follows the selected
// integer overflow/safety behavior.
Gamma Functions
// Gamma function
const g = std.math.gamma(f64, 5.0); // 24.0 (= 4!)
// Log gamma (more numerically stable for large values)
const lg = std.math.lgamma(f64, 100.0);
Notes
- Floating-point support varies by function and target; check each signature rather than assuming every float width and
comptime_floatare accepted - Many functions support SIMD vectors:
sin(@Vector(4, f32){...}) - Integer helpers document their own error sets;
error.Overflowanderror.DivisionByZeroare common examples, not a universal pair - Hardware instructions used when available (
@sin,@cos,@sqrt, etc.) approxEqAbsfor values near zero,approxEqRelfor larger values- Complex number operations available in
std.math.complex - Big integers require allocator and are in
std.math.big.int