gizdb:decimal
Exact decimals, as PostgreSQL's NUMERIC: a value is C × 10^-s with a scale s of 0..16383 and at most 131072 digits before the point. A coefficient that fits an i64 (most values) is the narrow case: c and s, so columns and SIMD kernels work on c alone and a Dec stays 24 bytes (a wider Value made the decimal and integer sums 10-14% slower). A wider coefficient is the wide case: m[0] = s << 1 | sign, then |C| in base-10^9 limbs with the least significant first and no zero limb on top. Read a Dec through decScale, decCoef, decNegative and the limb helpers here. A value has one form at a scale, so === compares values of one scale. Every operation is exact, or rounds half away from zero at a scale it names, or reports overflow (none): nothing goes through binary floating point. ln, log, exp and power are correctly rounded at the scales PostgreSQL picks. Oracle's NUMBER keeps 40 digits by its own rule (numberArith, decNumber).
import * as Decimal from "gizdb:decimal";Types
Dec
type Dec = | { kind: "narrow"; c: i64; s: i32; } | { kind: "wide"; m: Vec<u64>; }An exact decimal: a 64-bit coefficient with its scale, or a wide sign-magnitude form for larger values.
narrowwide
DecRead
type DecRead = | { kind: "ok"; value: Dec; } | { kind: "invalid"; } | { kind: "overflow"; }What a text spells as a decimal: a value, not a number, or a number past the limits.
okinvalidoverflow
Parts
type Parts = { wh: i64; wl: u64; f1: u64; f2: u64; sticky: bool; more: Vec<u64>; }A finite number split as floor(v), 128-bit two's complement (wh its high word, wl its low bits), and its
fraction in 10^-38 units (f1 the first 19 digits, f2 the next 19), with sticky when digits remain below
those: what orders and compares integers, floats and decimals exactly together. A decimal's digits past those
are more, 19 a word with no zero word last (a float's are not kept: it orders before a decimal of the same first
38 fraction digits). A floor from 2^127 on passes every float the parts compare with: it saturates.
wh:i64wl:u64f1:u64f2:u64sticky:boolmore:Vec<u64>
Functions
pow10
function pow10(n: i64): i6410^n for 0 <= n <= 18.
Effects: fail.
decOf
function decOf(c: i64, s: i64): DecA coefficient that fits an i64 at scale s.
decOfInt
function decOfInt(x: i64): DecThe decimal of the integer X.
narrow
function narrow(d: Dec): boolWhether the coefficient is c alone.
decNegative
function decNegative(d: Dec): boolWhether D is below zero.
Effects: fail.
decZero
function decZero(d: Dec): boolWhether D is zero.
decScale
function decScale(d: Dec): i64The scale.
Effects: fail.
decCoef
function decCoef(d: Dec): i64The coefficient of a narrow value; the sign (1 or -1) of a wide one.
Effects: fail.
decShift
function decShift(d: Dec, s: i64): DecThe same coefficient at scale s: d × 10^(scale - s).
Effects: fail.
decWithin
function decWithin(d: Dec): boolWhether a value is within NUMERIC's limits: scale 16383 and 131072 digits before the point.
Effects: fail.
precisionOf
function precisionOf(d: Dec): i64Significant digits of the coefficient: what DECIMAL(p, s) checks against p.
Effects: fail.
decWords
function decWords(d: Dec): Vec<i64>The coefficient as 64-bit two's complement words, the least significant first: one word when it fits an i64.
Effects: fail.
decOfWords
function decOfWords(w: Vec<i64>, s: i64): DecThe value of two's complement words (decWords) at scale s.
Effects: fail.
readDecimal
function readDecimal(text: string): DecReadThe decimal a text spells, as PostgreSQL's numeric_in: [+-]digits[.digits][e[+-]digits], surrounding spaces allowed. Every digit stays; the scale is the digits after the point less the exponent, at least 0.
Effects: fail.
parseDecimal
function parseDecimal(text: string): Option<Dec>readDecimal's value, or none for a text that is not a number or a number past the limits.
Effects: fail.
decOfFloat
function decOfFloat(f: f64, scale: i64): Option<Dec>The decimal of a float at its shortest exact digits, then rounded to scale (-1: as many as those digits have);
none for NaN, infinities and what does not fit.
Effects: fail.
decText
function decText(d: Dec): stringThe decimal as text at its scale: -12.340, 0.05, 7.
Effects: fail.
trimmed
function trimmed(d: Dec): DecThe same value without trailing fractional zeros (2.50 → 2.5, 3.00 → 3).
Effects: fail.
decFloat
function decFloat(d: Dec): f64The nearest f64 (correctly rounded, through the digits); ±infinity past the f64 range.
Effects: fail.
rescale
function rescale(d: Dec, s: i64): Option<Dec>The value at scale s (0..16383): more digits are exact, fewer round half away from zero; none on overflow.
Effects: fail.
cut
function cut(d: Dec, s: i64, mode: string): DecToward zero at scale s (s <= decScale(d)), or toward -∞ (floor) or +∞ (ceil).
Effects: fail.
decRound
function decRound(d: Dec, scale: i64): Option<Dec>PostgreSQL's round(d, scale): half away from zero at scale; a negative scale rounds to a multiple of 10^-scale
at scale 0. None on overflow.
Effects: fail.
decTrunc
function decTrunc(d: Dec, scale: i64): Option<Dec>PostgreSQL's trunc(d, scale): toward zero at scale; a negative scale truncates to a multiple of 10^-scale at
scale 0.
Effects: fail.
fitsPrecision
function fitsPrecision(d: Dec, p: i64): boolWhether the value is in DECIMAL(p, s) once at scale s: at most p - s integer digits.
Effects: fail.
decSum
function decSum(x: Dec, y: Dec): DecThe exact sum past the limits too: a running total that PostgreSQL checks only at its end (decWithin).
Effects: fail.
decDifference
function decDifference(x: Dec, y: Dec): Decx - y, exact past the limits too (decSum).
Effects: fail.
decAdd
function decAdd(x: Dec, y: Dec): Option<Dec>The exact sum; none past the limits.
Effects: fail.
decNeg
function decNeg(x: Dec): Option<Dec>-X, or none when it does not fit.
Effects: fail.
decSub
function decSub(x: Dec, y: Dec): Option<Dec>X - Y, or none when it does not fit.
Effects: fail.
decMul
function decMul(x: Dec, y: Dec): Option<Dec>The exact product at scale decScale(x) + decScale(y), rounded half away at scale 16383 past it (as PostgreSQL's numeric_mul); none past the limits.
Effects: fail.
decProduct
function decProduct(x: Dec, y: Dec): DecThe exact product at scale decScale(x) + decScale(y), past the limits too: a square inside variance, which PostgreSQL keeps whole (decSum).
Effects: fail.
decDiv
function decDiv(x: Dec, y: Dec): Option<Dec>x / y as PostgreSQL's numeric division: at its select_div_scale, rounded half away. None for a zero divisor (the caller reports it) and on overflow.
Effects: fail.
decDivTrunc
function decDivTrunc(x: Dec, y: Dec): Option<Dec>trunc(x / y) exactly, at scale 0 (PostgreSQL's div). None for a zero divisor and on overflow.
Effects: fail.
decMod
function decMod(x: Dec, y: Dec): Option<Dec>x - y × trunc(x / y): the sign of x, as SQL's % and MOD, at the larger scale. None for a zero divisor.
Effects: fail.
numberArith
function numberArith(op: string, x: Dec, y: Dec): Option<Dec>x op y (+ - * / %) as Oracle's NUMBER computes it: the exact result, or a quotient of 41 significant digits (one past what NUMBER keeps, so its rounding is the exact quotient's), then numberFit. None for a zero divisor and on overflow.
Effects: fail.
decCompareSum
function decCompareSum(x: Dec, base: Dec, offset: Dec): i64Compare x with base + offset without rounding the boundary.
Effects: fail.
decCompare
function decCompare(x: Dec, y: Dec): i64-1, 0 or 1, exactly.
Effects: fail.
decParts
function decParts(d: Dec): PartsD as a 128-bit whole part and two 19-digit fraction words, for a fast comparison (compareParts).
Effects: fail.
floatParts
function floatParts(f: f64): PartsThe parts of a float with |f| < 2^127, exactly (from its bits, not its arithmetic).
Effects: fail.
compareParts
function compareParts(a: Parts, b: Parts): i64-1, 0 or 1 as A is less than, equal to or greater than B.
Effects: fail.
decCompareFloat
function decCompareFloat(d: Dec, y: f64): i64A decimal against a finite float, exactly.
Effects: fail.
intOf
function intOf(d: Dec): Option<i64>The value as an i64 when it is whole and fits one.
Effects: fail.
truncInt
function truncInt(d: Dec): i64Toward zero as an i64, saturating (SQLite's CAST of a huge number).
Effects: fail.
unitOf
function unitOf(s: i64): f6410^s as a float: what a coefficient at scale s is divided by.
sqrtScale
function sqrtScale(x: Dec): i64PostgreSQL's sqrt scale for x: 16 significant digits from its base-10000 weight, at least its scale, at most 1000.
Effects: fail.
decSqrt
function decSqrt(x: Dec, scale: i64): Option<Dec>The square root of x rounded half away at scale, as PostgreSQL's sqrt_var. None for a negative x.
Effects: fail.
decLn
function decLn(x: Dec): Option<Dec>ln(x) for x > 0 at PostgreSQL's scale.
Effects: fail.
decLog
function decLog(b: Dec, x: Dec): Option<Dec>The logarithm of x to base b, both > 0 and b not 1, at PostgreSQL's scale.
Effects: fail.
decExp
function decExp(x: Dec): Option<Dec>e^x at PostgreSQL's scale; none when it overflows.
Effects: fail.
decPow
function decPow(x: Dec, y: Dec): Option<Dec>x^y for finite x and y, where x is not negative or y is whole, and a zero x has y >= 0 (the caller reports the other cases), at PostgreSQL's scale (power_var); none when it overflows.
Effects: fail.
Constants
DEC_MAX_SCALE
const DEC_MAX_SCALE = 16383The largest scale (PostgreSQL's NUMERIC_DSCALE_MAX).
DEC_MAX_WHOLE
const DEC_MAX_WHOLE = 131072The most digits before the point: (NUMERIC_WEIGHT_MAX + 1) base-10000 digits.