decimal-scaled 0.4.2

Const-generic base-10 fixed-point decimals (D9/D18/D38/D76/D153/D307) with integer-only transcendentals correctly rounded to within 0.5 ULP — exact at the type's last representable place. Deterministic across every platform; no_std-friendly.
Documentation

decimal-scaled

crates.io docs.rs MSRV License site CodSpeed OpenSSF Best Practices OpenSSF Scorecard cargo-audit

DocsBenchmarksAlgorithmsRoadmapAPI reference

Const-generic base-10 fixed-point decimals for Rust — bit-exact, ≤ 0.5 ULP correctly-rounded integer-only transcendentals, deterministic on every platform, no_std-friendly.


Install

[dependencies]

decimal-scaled = { version = "0.4", features = ["macros"] }

First use

use decimal_scaled::{d38, D38s12};

let price: D38s12 = "19.99".parse().unwrap();
let qty   = D38s12::from_int(3);
let total = price * qty;                       // 59.97 exactly

assert_eq!(total.to_string(), "59.97");
assert_eq!(total, d38!(59.97, scale 12));

// Transcendentals are correctly rounded to ≤ 0.5 ULP, integer-only,
// and bit-identical across platforms.
let sqrt2 = d38!(2, scale 12).sqrt_strict();

What it does

Every value is raw × 10^(-SCALE) for a compile-time SCALE. There is exactly one bit pattern per logical value — no normalisation, no per-value scale byte, no heap allocation. 0.1 + 0.2 == 0.3 is true, and so is hash(1.10) == hash(1.1) at the same scale.

Thirteen storage widths from D9 (32-bit, ~9 decimal digits) to D1232 (4096-bit, ~1232 decimal digits) share an identical API. Pick the narrowest width that covers your range.

The two guarantees nothing else on crates.io currently combines:

  1. ≤ 0.5 ULP correctness on every transcendentalln / exp / sin / cos / tan / sqrt / cbrt / powf / asin / acos / atan / atan2 / sinh / cosh / tanh / asinh / acosh / atanh / to_degrees / to_radians lands within half an ULP of the mathematically exact result, and the bit pattern is identical on every machine. The default strict path is integer-only and no_std-compatible.
  2. Caller-chosen rounding mode at every lossy operation. The default is HalfToEven (IEEE 754 default). Every lossy entry point (* / / / %, the rescale family, every strict transcendental) ships a *_with(mode) sibling that takes a RoundingMode: HalfToEven · HalfAwayFromZero · HalfTowardZero · Ceiling · Floor · Trunc. The crate-wide default is also selectable at compile time via the rounding-* Cargo features.

Documentation

In-depth guides live under docs/:

  • Getting started — constructing values, arithmetic, formatting, parsing.
  • The width familyD9 through D1232, scale aliases, the Decimal trait, picking a tier.
  • Conversions — integers, floats, cross-width widening / narrowing, the float bridge.
  • RoundingRoundingMode, the _with pairs, rescale, the compile-time rounding-* features.
  • Strict mode — integer-only *_strict transcendentals, the ≤ 0.5 ULP guarantee.
  • The d*! macros — compile-time decimal literals, scale inference, scientific / radix notation.
  • Cargo features — every feature flag with what it enables and the common configurations.
  • Benchmarks — head-to-head against bnum, ruint, rust_decimal, fixed, fastnum, dashu-float, bigdecimal, and the fast-vs-strict trade.
  • Algorithms — every kernel with its citation (Möller–Granlund, Brent, Knuth, Karatsuba, Burnikel–Ziegler, Mercator / Cody–Waite, …).
  • Roadmap — what's queued (signed SCALE, RNG surface, wide-tier perf catch-up, downstream adapter / ecosystem crates).
  • Changelog — release-by-release notes.
  • Contributing — algorithm-library tour, adding a per-(width, scale) override, performance gates, license-compatibility rules.

API reference: https://docs.rs/decimal-scaled/.


License

Licensed under either of:

at your option.

Copyright 2026 John Moxley. Third-party code attributions are listed in LICENSE-THIRD-PARTY.