This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.
Num
import std/numstd/num — arbitrary-precision decimal numbers, taint-sourced.
num.kz · 32 tors
std/num — arbitrary-precision decimal numbers, taint-sourced. · 31 more lines
std/num — arbitrary-precision decimal numbers, taint-sourced.
Koru has no numeric tower: bare literals are raw expression text handed to
the host. This module is the tower. A `num` is a CANONICAL decimal string
— `[-]d[.ddd]e[-]E`, one nonzero leading digit, no trailing zeros, zero is
`0e0` — so value-equivalence is string equality (`num:equiv` is the honest
form of that law: `314e0` ≡ `3.14e2` ≡ `0.314e3`).
Taint (the 330_089 mechanism applied to numbers — "tainted for real"):
<external!> issued by `ingest`/`ingest-owned` on outside text. Marks the
value as unvalidated input; nothing but `parse` may consume
it. `ingest-owned` additionally discharges <allocated!> —
the buffer becomes num-owned.
<exact!> issued by `parse`/`lit` and every op. A REAL obligation:
ops consume <!exact> linearly (each operand dies into the
result — `dup` is the lawful fork), `free` discharges by
deallocating, `render` swaps it to <allocated!> for print.
A bare `string` cannot reach `add` — it must pass the gate.
The marks are phantoms: zero runtime cost, all checking at compile time.
At runtime a num is just a []const u8 the module owns; every num-owned
buffer is allocator-freed exactly once, at consume time.
Arithmetic: mantissa is an arbitrary-precision integer (std.math.big), the
exponent is decimal. Exact for +,-,*,pow; `div`/`sqrt` take an explicit
significant-digit `prec` because a decimal expansion need not terminate.
Port source: isa-physics `plex/lib/symbolic/arbitrary_precision.py`
(sign + decimal-position + digit nibbles) and the ISAR QuantityKernel
MetricExpr exact-rational layer; the quantity/dimension half lives in
std/quantity.
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
string 4 states external!exact!allocated!// Boundary: mark outside text as <external!>.
//
// Mark outside text as unvalidated input. Copies into a num-owned buffer so
// `parse` may free it unconditionally at consume time.
~pub tor ingest { s: string } -> string<external!>// Mark outside text that arrives under an <allocated!> obligation — the
// buffer is consumed and becomes num-owned; the allocated obligation is
// discharged by taking ownership (the buffer is returned, marked external).
~pub tor ingest-owned { s: string<!allocated> } -> string<external!>// The gate: text -> canonical num (<exact!>).
//
// Parse and normalize external text. Consumes <external!>: on success the
// input buffer is freed. Malformed text lands on |bad with the offending
// buffer itself — ownership transfers to the receiver under <allocated!>,
// disposed via std/io:free.
~pub tor parse { s: string<!external> }
| exact string<exact!>
| bad string<std.io:allocated!>// Parse trusted in-program text — a literal. Same gate, no taint to consume.
// `bad` returns the offending slice.
~pub tor lit { expr: Expression }
| exact string<exact!>
| bad string// Arithmetic — linear: operands are consumed (<!exact>) into the result.
~pub tor add { a: string<!exact>, b: string<!exact> } -> string<exact!>~pub tor sub { a: string<!exact>, b: string<!exact> } -> string<exact!>~pub tor mul { a: string<!exact>, b: string<!exact> } -> string<exact!>// a / b to `prec` significant digits. Division by zero lands on |div-zero
// (operands are still consumed — the marks are discharged before the branch).
~pub tor div { a: string<!exact>, b: string<!exact>, prec: i64 }
| exact string<exact!>
| div-zero~pub tor neg { a: string<!exact> } -> string<exact!>~pub tor abs { a: string<!exact> } -> string<exact!>// a^n for n >= 0. A negative exponent is not a num op (it is div(1, pow))
// and lands on |neg-exp.
~pub tor pow { a: string<!exact>, n: i64 }
| exact string<exact!>
| neg-exp// sqrt(a^2 + b^2) to `prec` significant digits — quadrature addition. The
// sum of two squares cannot be negative, so there is no lawful failure arm:
// the op is total by construction.
~pub tor qadd { a: string<!exact>, b: string<!exact>, prec: i64 } -> string<exact!>// isqrt to `prec` significant digits. Negative input lands on |negative.
~pub tor sqrt { a: string<!exact>, prec: i64 }
| exact string<exact!>
| negative// Predicates and equivalents — borrowing: operands keep their <exact> mark.
//
// Total order: | lt | eq | gt. The equivalence law — canonical form makes
// value-equality and string-equality coincide, so | eq is *the* lawful eq.
~pub tor cmp { a: string<exact>, b: string<exact> }
| lt
| eq
| gt// equiv: the equivalence law. Canonical nums are string-equal iff equal.
~pub tor equiv { a: string<exact>, b: string<exact> }
| same
| diff// Linearity management
//
// Fork one num into two (the lawful copy — a num is a linear resource).
// Canonical zero check — borrows the operand.
~pub tor is-zero { n: string<exact> }
| zero
| nonzero~pub tor dup { n: string<!exact> } -> { a: string<exact!>, b: string<exact!> }// Discharge <exact!>: the buffer is freed, the number is gone.
~pub tor free { n: string<!exact> }// Discharge an <external!> obligation WITHOUT validating — the lawful way
// out when a sibling field already failed and this one never reaches parse.
~pub tor drop { s: string<!external> }// i64 -> canonical decimal. The bridge from host counters into the tower.
~pub tor from-int { i: i64 } -> string<exact!>// Swap <exact!> to <allocated!>: hands the canonical text out for printing
// or formatting. The buffer stays allocator-owned — discharge with
// `std/io:free` (the `allocated` state is io's vocabulary, issued qualified).
~pub tor render { n: string<!exact> } -> string<std.io:allocated!>~pub tor exp { a: string<!exact>, prec: i64 }
| exact string<exact!>
| overflow~pub tor ln { a: string<!exact>, prec: i64 }
| exact string<exact!>
| non-pos~pub tor sin { a: string<!exact>, prec: i64 }
| exact string<exact!>
| overflow~pub tor cos { a: string<!exact>, prec: i64 }
| exact string<exact!>
| overflow~pub tor atan { a: string<!exact>, prec: i64 } -> string<exact!>// a^e for real e: exp(e * ln a). a < 0 -> |neg-base (complex plane is out of
// scope); a == 0 -> e>0 gives exact 0, e<=0 lands on |non-pos.
~pub tor powf { a: string<!exact>, e: string<!exact>, prec: i64 }
| exact string<exact!>
| neg-base
| non-pos
| overflow~pub tor mod { a: string<!exact>, b: string<!exact> }
| exact string<exact!>
| div-zero// Significant-digit count of the mantissa (bc's length()). Borrows.
~pub tor length { a: string<exact> } -> i64// Digits after the decimal point (bc's scale()). Canonical form has no
// trailing zeros, so scale = max(0, -e). Borrows.
~pub tor scale { a: string<exact> } -> i64// Render an integral value in base 2..36 (bc's obase, honest about scope:
// non-integers refuse rather than emitting bc's digit-vector notation).
~pub tor to-base { a: string<!exact>, base: i64 }
| exact string<exact!>
| non-int
| bad-base// Parse digits in base 2..36 into an integer value (bc's ibase; lit-lane —
// the text is trusted, same contract as lit). Upper and lower case both
// accepted; '_' separators refused, a leading '-' negates.
~pub tor from-base { s: string, base: i64 }
| exact string<exact!>
| bad-digit
| bad-base