License
BSD-3-Clause
The decimal-column layer of ddn.df (ADR-2026-10-23-13/-14): exact fixed-point values stored as raw coefficients (int64 for precision <= 18, Int128 payload for 38), semantics from ddn.num.fixed_decimal - never a FLOAT64 detour. Casts to/from STRING and INT are exact (inexact throws); FLOAT64 only explicitly. Comparisons align scales internally; same-dtype add/subtract exact; overflow throws.
The decimal coefficient's storage: int64 for precision <= 18, a two-int64 payload for 38. The column's precision/scale live in the dtype metadata, not per value.
Builds one DECIMAL chunk from int64 coefficients at a fixed scale. Values are coefficient * 10^-scale; nulls are validity-0.
private DecimalCoeff[] _coeffsprivate ulong[] _validityprivate size_t _lengthprivate bool _anyNullprivate bool _sealedvoid append(DecimalCoeff v) @safe pure nothrowAppends one coefficient (the caller manages the scale).long parseDecimalCoeff(scope const(char)[] text, ubyte scale) @safeParses a decimal string into a coefficient at the given scale. Exact: trailing digits beyond `scale` that are nonzero throw.string renderDecimal(long coeff, ubyte scale) @safe pure nothrowRenders a coefficient at the given scale as decimal text.Series decimalFromString(string name, ubyte precision, ubyte scale,
Nullable!(string)[] values)Builds a DECIMAL Series from decimal strings, parsed exactly.long[2] alignScales(long a, ubyte aScale, long b, ubyte bScale) @safeAligns two coefficients to a common scale (the max), returning the aligned pair. The one with the smaller scale is scaled up.Series decimalFromCoeffs(string name, ubyte precision, ubyte scale,
Nullable!long[] coeffs)Builds a DECIMAL Series from raw int64 coefficients at a fixed precision/scale (values are `coefficient * 10^-scale`). The exact constructor for tests and benchmarks; `decimalFromString` parses dec...bool decimalEq(long a, ubyte aScale, long b, ubyte bScale) @safe pure nothrowValue-based equality of two coefficients at their own scales: the smaller scale aligns up; an alignment overflow means the values differ (one magnitude cannot be the other's). Exact - never a FLOAT...int decimalCmp(long a, ubyte aScale, long b, ubyte bScale) @safe pure nothrowThe value-based three-way comparison of two coefficients at their own scales (the total order sort and min/max ride): negative when `a < b`, zero when equal, positive when `a > b`. An alignment ove...size_t decimalHash(long coeff, ubyte scale) @safe pure nothrowThe canonical value hash: trailing zero digits divide out of the coefficient while the effective exponent drops, so equal values at different scales hash equal (`1.10` and `1.1`); zero hashes equal...Series decimalArith(string op)(Series a, Series b)Same-dtype exact addition/subtraction of DECIMAL columns: one checked step per slot (overflow throws before any result is exposed), nulls propagate, the dtype is unchanged. Multiply, divide and cro...Series decimalNegate(Series a)Exact negation: every valid slot negates with the `long.min` overflow check.ArrayData decimalSumSlot(Series s)The exact checked sum as a one-slot DECIMAL chunk: the chunk- ordered serial left fold with a per-step overflow check (the same association the INT64 sum keeps, plus exactness).Series decimalGroupAgg(string agg)(string outName, Series col,
size_t[][] groupRows)The per-group decimal aggregation over group row lists: sum (the checked row-order fold), min/max (coefficient compare - one scale per column), first/last (the first/last row when valid, else null)...Series decimalCastFrom(Series s, DataType target, bool strict)Casts a DECIMAL Series to its admitted targets: STRING renders exactly; the integer kinds keep exact values only (a nonzero fraction or an out-of-range quotient is a failure); FLOAT32/64 compute `c...Series decimalCastTo(Series s, DataType target, bool strict)Casts a flat Series into a DECIMAL column at the target's precision/scale: STRING parses exactly (inexact or malformed is a failure); the integer kinds multiply up with the overflow check; FLOAT32/...