Releases: AlexandrosKyriakakis/zerodecimal
Releases · AlexandrosKyriakakis/zerodecimal
v0.0.2
What's Changed
- perf: benchmark comparison vs jokruger/dec128 by @AlexandrosKyriakakis in #1
- perf: implement the verified optimization roadmap (geomean −41% vs dec128) by @AlexandrosKyriakakis in #2
Full Changelog: v0.0.1...v0.0.2
v0.0.1
zerodecimal v0.0.1 — first release
Zero-allocation, panic-free, fixed-point decimals for latency-critical Go. No big.Int anywhere in the package, no GC pressure, and the fastest benchmark results of any Go decimal library we tested.
Highlights
- Strictly zero heap allocations on every operation — parse, arithmetic, comparison, rounding, conversions, and every
Unmarshal*/Scanpath, on success and error paths. Enforced by exacttesting.AllocsPerRungates in the default test suite (alloc_test.go).String/Marshal*allocate exactly their one return value. - Fastest in class (Apple M1 Pro,
benchstatover-count=10, committed inbenchmarks/):- −35.0% time geomean vs quagmt/udecimal (15.50ns → 10.07ns) — faster on 89 of 90 op×shape cells, one statistical tie
- −79.7% vs ericlagergren/decimal, −83.4% vs alpacadecimal, −89.6% vs shopspring/decimal
- PGO adds a further −7.5% geomean — see the README's PGO guide and
benchmarks/bench-pgo.txt
- Reciprocal division: rescaling, rounding, formatting, and division never use the hardware divider for powers of ten — precomputed Granlund–Montgomery–Warren magics (64-bit) and Möller–Granlund 2-by-1 reciprocal steps (128/256-bit), with all table constants generated and re-proven against
big.Int. - Panic-free error model: fallible operations return zero-allocation sentinel errors (
errors.Is-able);Must*twins panic for call sites with proven bounds.
What's in the box
- 24-byte value type:
value = ±coef / 10^prec, 128-bit coefficient, 0–19 fractional digits; domain ±(2¹²⁸−1)/10^prec (~39 significant digits) - Arithmetic:
Add,Sub,Mul,Div(adaptive precision — huge quotients degrade precision gracefully instead of failing),QuoRem,Mod,Sum,Avg,Min/Max - Rounding:
Round(half away from zero),RoundBank,RoundUp,RoundDown,RoundCeil,RoundFloor,Truncate,Floor,Ceil— all infallible - Parsing: zero-alloc
NewFromString/ParseBytes(+Truncvariants for lossy ingest), scientific notation, strict float constructors - Codecs: always-quoted JSON, text, compact binary (10/18 bytes),
database/sqlScan/Value,NullDecimal; implements Go 1.24+encoding.TextAppender/BinaryAppenderfor zero-alloc encoding - Small-value string cache:
String()/Value()are 0-alloc for −1000.00..+1000.00 at ≤2dp (opt out:-tags zerodecimal_nostrcache) - Build tags
zerodecimal_prec9/zerodecimal_prec12for reduced division precision (compile+vet verified; test suites assume the default 19)
How correctness is enforced
- Deterministic differential cross-check vs shopspring/decimal: ~112k pairs every test run, including proofs that every returned
ErrOverflowis genuine (crosscheck_test.go) - 23 differential fuzz targets vs shopspring and udecimal (
-tags fuzz), soak-tested; garbage inputs cannot panic the library - 40M+ case verification of the 128/256-bit primitives and reciprocal tables against
bits.Div64/big.Int - 98.6% coverage, race-clean, CI across Linux/macOS/Windows × two Go versions
Requirements & install
- Go 1.26+, zero runtime dependencies
go get github.com/AlexandrosKyriakakis/zerodecimal(while the repo is private: setGOPRIVATE=github.com/AlexandrosKyriakakis/zerodecimal)
Known limitations (deliberate)
- Not a drop-in shopspring replacement: arithmetic returns
(Decimal, error), rounding places areuint8(no negative places),"1."/".1"are rejected,Divtruncates at adaptive precision rather than rounding atDivisionPrecision - No
Pow,Sqrt,Ln, or trig yet — reserved for v2 - Binary format is not wire-compatible with udecimal (documented layout, version-guarded)
==is representation equality; useEqual/Cmpfor numeric comparison
Credits
Built standing on the shoulders of quagmt/udecimal (BSD-3-Clause — the 256÷128 division is adapted from it, with a latent-panic fix, and the fuzz corpus seeds it pioneered), ridiculousfish/libdivide, alpacadecimal (small-value cache design), shopspring/decimal (the correctness oracle), and Möller & Granlund / Granlund & Montgomery's division papers.
Full Changelog: https://github.com/AlexandrosKyriakakis/zerodecimal/commits/v0.0.1