Status: v0.1 (alpha)
Scope: deterministic, dependency-free primitives used across ZMath:
- Traits (
Real,Index) and helpers - Constants
- Utilities: closeness, ULP distance, clamp/lerp, near-zero
- Explicit casts (checked/saturating) between ints/floats
- Ranges and linspace
- Formatting (decimal/dozenal) for diagnostics only
The public surface is re-exported from src/root.zig:
pub const fmt = struct { pub const format = @import("fmt/format.zig"); };
pub const consts = @import("lib/consts.zig");
pub const traits = @import("lib/traits.zig");
pub const util = @import("lib/util.zig");
pub const cast = @import("lib/cast.zig");
pub const range = @import("lib/range.zig");(See repo tree and build.zig.)
pub const Real: type = f64;pub const Index: type = usize;pub inline fn epsilon(comptime T: type) T— IEEE machine epsilon forT∈{f16,f32,f64,f128}pub inline fn isFinite(x: anytype) boolpub inline fn sign(x: anytype) comptime_int
Invariants
epsilon(T) > 0and matches mantissa width for IEEE754.
Pure constants:
PI, TAU, E, SQRT2, INV_SQRT2, LN2, LN10, GOLDEN, EULER_GAMMA.
pub fn almostEqualAbs(x: Real, y: Real, atol: Real) boolpub fn almostEqualRel(x: Real, y: Real, rtol: Real, maxAbs: Real) boolpub fn isClose(x: Real, y: Real) boolpub fn ulpDistance(x: Real, y: Real) u64pub fn clamp(x: Real, lo: Real, hi: Real) Realpub fn clamp01(t: Real) Realpub fn lerp(a: Real, b: Real, t: Real) Realpub fn nearZero(x: Real) Real
Invariants
ulpDistance(x,x) == 0for finitex.
pub const CastError = error{ Overflow, NaNInput };
pub fn toIntSaturate(comptime Dst: type, x: anytype) Dst;
pub fn toIntChecked(comptime Dst: type, x: anytype) CastError!Dst;
pub fn toFloatChecked(x: anytype) CastError!Real;Behavior
toIntSaturate: clamps to[minInt(Dst), maxInt(Dst)]; non-finite floats clamp to bound by sign.toIntChecked:error.Overflowif out of range;error.NaNInputfor non-finite floats.toFloatChecked:error.NaNInputfor non-finite.
pub const Range: half-open[start,end)overIndexwith positivesteppub fn init(start: Index, end: Index, step: Index) Rangepub fn next(self: *Range) ?Index
pub const RangeInc: inclusive[start,end]with positivestepinit,nextas above
pub const Linspace:npoints fromatobinclusive inRealpub fn init(a: Real, b: Real, n: Index) Linspacepub fn next(self: *Linspace) ?Real
Invariants
RangeandRangeIncrequirestep > 0and do not overflow.Linspace.init(a,b,n)withn >= 2yields exactlynvalues;first == a,last == b.
pub const RadixPolicy = enum { decimal, dozenal }pub fn formatIntAlloc(a: std.mem.Allocator, x: i128, policy: RadixPolicy) ![]u8pub fn formatUIntAlloc(a: std.mem.Allocator, x: u128, policy: RadixPolicy) ![]u8pub fn formatFloatAlloc(a: std.mem.Allocator, x: f64, policy: RadixPolicy, frac_digits: usize) ![]u8
Rules
- Dozenal uses
Tfor 10,Efor 11; integers/fractions built arithmetically (no locale). - Non-finite floats render as
"NaN","+Inf","-Inf". - Formatting is for diagnostics only; kernels must not depend on it.
- No syscalls; no locale; only
fmt/*allocates. - Branch-stable algorithms across targets; suitable for WASM builds.
- Inline unit tests live in each module.
- E2E (
tests/e2e/stability.zig) and integration (tests/integration/consumers.zig) import the public surface. zig build test-allruns: root tests, per-file unit tests, integration, and e2e.
build.ziguses Zig 0.16-dev module APIs; examples are installed viaaddInstallArtifactsozig build examplescreateszig-out/binaries.- CI should run:
zig fmt --check,zig build test-all,zig build examples.
Pre-1.0: breaking → minor bump; post-1.0: strict SemVer with deprecations.