# 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`).

```gizlang
import * as Decimal from "gizdb:decimal";
```

## Types

### `Dec`

```gizlang
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.

- `narrow`
- `wide`

### `DecRead`

```gizlang
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.

- `ok`
- `invalid`
- `overflow`

### `Parts`

```gizlang
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`: `i64`
- `wl`: `u64`
- `f1`: `u64`
- `f2`: `u64`
- `sticky`: `bool`
- `more`: `Vec<u64>`

## Functions

### `pow10`

```gizlang
function pow10(n: i64): i64
```

10^n for 0 <= n <= 18.

Effects: fail.

### `decOf`

```gizlang
function decOf(c: i64, s: i64): Dec
```

A coefficient that fits an i64 at scale `s`.

### `decOfInt`

```gizlang
function decOfInt(x: i64): Dec
```

The decimal of the integer X.

### `narrow`

```gizlang
function narrow(d: Dec): bool
```

Whether the coefficient is `c` alone.

### `decNegative`

```gizlang
function decNegative(d: Dec): bool
```

Whether D is below zero.

Effects: fail.

### `decZero`

```gizlang
function decZero(d: Dec): bool
```

Whether D is zero.

### `decScale`

```gizlang
function decScale(d: Dec): i64
```

The scale.

Effects: fail.

### `decCoef`

```gizlang
function decCoef(d: Dec): i64
```

The coefficient of a narrow value; the sign (1 or -1) of a wide one.

Effects: fail.

### `decShift`

```gizlang
function decShift(d: Dec, s: i64): Dec
```

The same coefficient at scale `s`: d × 10^(scale - s).

Effects: fail.

### `decWithin`

```gizlang
function decWithin(d: Dec): bool
```

Whether a value is within NUMERIC's limits: scale 16383 and 131072 digits before the point.

Effects: fail.

### `precisionOf`

```gizlang
function precisionOf(d: Dec): i64
```

Significant digits of the coefficient: what DECIMAL(p, s) checks against p.

Effects: fail.

### `decWords`

```gizlang
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`

```gizlang
function decOfWords(w: Vec<i64>, s: i64): Dec
```

The value of two's complement words (decWords) at scale `s`.

Effects: fail.

### `readDecimal`

```gizlang
function readDecimal(text: string): DecRead
```

The 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`

```gizlang
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`

```gizlang
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`

```gizlang
function decText(d: Dec): string
```

The decimal as text at its scale: -12.340, 0.05, 7.

Effects: fail.

### `trimmed`

```gizlang
function trimmed(d: Dec): Dec
```

The same value without trailing fractional zeros (2.50 → 2.5, 3.00 → 3).

Effects: fail.

### `decFloat`

```gizlang
function decFloat(d: Dec): f64
```

The nearest f64 (correctly rounded, through the digits); ±infinity past the f64 range.

Effects: fail.

### `rescale`

```gizlang
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`

```gizlang
function cut(d: Dec, s: i64, mode: string): Dec
```

Toward zero at scale `s` (s <= decScale(d)), or toward -∞ (`floor`) or +∞ (`ceil`).

Effects: fail.

### `decRound`

```gizlang
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`

```gizlang
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`

```gizlang
function fitsPrecision(d: Dec, p: i64): bool
```

Whether the value is in DECIMAL(p, s) once at scale s: at most p - s integer digits.

Effects: fail.

### `decSum`

```gizlang
function decSum(x: Dec, y: Dec): Dec
```

The exact sum past the limits too: a running total that PostgreSQL checks only at its end (decWithin).

Effects: fail.

### `decDifference`

```gizlang
function decDifference(x: Dec, y: Dec): Dec
```

x - y, exact past the limits too (decSum).

Effects: fail.

### `decAdd`

```gizlang
function decAdd(x: Dec, y: Dec): Option<Dec>
```

The exact sum; none past the limits.

Effects: fail.

### `decNeg`

```gizlang
function decNeg(x: Dec): Option<Dec>
```

-X, or none when it does not fit.

Effects: fail.

### `decSub`

```gizlang
function decSub(x: Dec, y: Dec): Option<Dec>
```

X - Y, or none when it does not fit.

Effects: fail.

### `decMul`

```gizlang
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`

```gizlang
function decProduct(x: Dec, y: Dec): Dec
```

The exact product at scale decScale(x) + decScale(y), past the limits too: a square inside variance, which
PostgreSQL keeps whole (decSum).

Effects: fail.

### `decDiv`

```gizlang
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`

```gizlang
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`

```gizlang
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`

```gizlang
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`

```gizlang
function decCompareSum(x: Dec, base: Dec, offset: Dec): i64
```

Compare x with base + offset without rounding the boundary.

Effects: fail.

### `decCompare`

```gizlang
function decCompare(x: Dec, y: Dec): i64
```

-1, 0 or 1, exactly.

Effects: fail.

### `decParts`

```gizlang
function decParts(d: Dec): Parts
```

D as a 128-bit whole part and two 19-digit fraction words, for a fast comparison (compareParts).

Effects: fail.

### `floatParts`

```gizlang
function floatParts(f: f64): Parts
```

The parts of a float with |f| < 2^127, exactly (from its bits, not its arithmetic).

Effects: fail.

### `compareParts`

```gizlang
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`

```gizlang
function decCompareFloat(d: Dec, y: f64): i64
```

A decimal against a finite float, exactly.

Effects: fail.

### `intOf`

```gizlang
function intOf(d: Dec): Option<i64>
```

The value as an i64 when it is whole and fits one.

Effects: fail.

### `truncInt`

```gizlang
function truncInt(d: Dec): i64
```

Toward zero as an i64, saturating (SQLite's CAST of a huge number).

Effects: fail.

### `unitOf`

```gizlang
function unitOf(s: i64): f64
```

10^s as a float: what a coefficient at scale s is divided by.

### `sqrtScale`

```gizlang
function sqrtScale(x: Dec): i64
```

PostgreSQL's sqrt scale for x: 16 significant digits from its base-10000 weight, at least its scale, at most
1000.

Effects: fail.

### `decSqrt`

```gizlang
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`

```gizlang
function decLn(x: Dec): Option<Dec>
```

ln(x) for x > 0 at PostgreSQL's scale.

Effects: fail.

### `decLog`

```gizlang
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`

```gizlang
function decExp(x: Dec): Option<Dec>
```

e^x at PostgreSQL's scale; none when it overflows.

Effects: fail.

### `decPow`

```gizlang
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`

```gizlang
const DEC_MAX_SCALE = 16383
```

The largest scale (PostgreSQL's NUMERIC_DSCALE_MAX).

### `DEC_MAX_WHOLE`

```gizlang
const DEC_MAX_WHOLE = 131072
```

The most digits before the point: (NUMERIC_WEIGHT_MAX + 1) base-10000 digits.

