The width family¶
decimal-scaled ships thirteen storage widths. They all have the same
API shape - the same methods, the same const generic SCALE, the same
Decimal trait impl - and differ only in the size of the backing
integer, which sets the range and the maximum usable scale.
| Type | Storage | MAX_SCALE |
Feature gate | Typical use |
|---|---|---|---|---|
D9 |
i32 |
9 | always on | embedded / register-sized ledgers |
D18 |
i64 |
18 | always on | interchange size; maps to SQL DECIMAL(18, s) |
D38 |
i128 |
38 | always on | the financial standard; satoshi-grade at SCALE = 12 |
D56 |
192-bit | 57 | d56 / wide |
half-width between D38 and D76 |
D76 |
256-bit | 76 | d76 / wide |
crypto ratios, statistical accumulation |
D114 |
384-bit | 115 | d114 / wide |
half-width between D76 and D153 |
D153 |
512-bit | 153 | d153 / wide |
wide-scientific / actuarial work |
D230 |
768-bit | 230 | d230 / wide |
half-width between D153 and D307 |
D307 |
1024-bit | 307 | d307 / wide |
deep arbitrary-precision determinism |
D461 |
1536-bit | 462 | d461 / x-wide |
half-width between D307 and D615 |
D615 |
2048-bit | 616 | d615 / x-wide |
extended-precision scientific / cryptography |
D923 |
3072-bit | 924 | d923 / xx-wide |
half-width between D615 and D1231 |
D1231 |
4096-bit | 1232 | d1231 / xx-wide |
widest shipped tier; arbitrary-precision research |
MAX_SCALE is the largest SCALE for which 10^SCALE fits the storage
integer. Using a larger SCALE is a compile-time error (the
multiplier() const overflows when the type is instantiated).
Choosing a width¶
The range at a given scale is roughly storage_max / 10^SCALE. Pick the
narrowest width whose range covers your values at the scale you need -
narrower storage is faster and smaller.
D9/D18- native integer storage, single-instruction add / sub / compare.D18atSCALE = 9covers ±9.2 × 10⁹ with nanosecond-grade fractional precision.D38- the default choice. AtSCALE = 12the range is roughly ±1.7 × 10²⁶ - far beyond global-GDP-scale money.D56/D76/D114/D153/D230/D307- the wide tier. Backed by an in-tree hand-rolled wide-integer module; no external big-integer dependency. Opt-in via the matching feature (d56,d76,d114,d153,d230,d307, or umbrellawide). Half-width siblings (D56 / D114 / D230) let you size storage to your precision budget without paying for an unnecessary power-of-two jump.D76atSCALE ≈ 70still leaves ~10⁵ integer headroom.D461/D615- the extra-wide tier. Gated behindx-wide(ord461/d615). Use for scientific or cryptographic work that needs more than the ~307-digit budget of D307 but doesn't want the full xx-wide compile cost.D923/D1231- the xx-wide tier. Gated behindxx-wide(ord923/d1231). The widest shipped tier; transcendentals at D1231<1231> approach a second per call, so it's research-grade precision rather than a hot-path target.
Scale aliases¶
Each width exposes curated …s<N> aliases for common scales:
use decimal_scaled::{D9s2, D18s9, D38s12};
# #[cfg(feature = "wide")]
use decimal_scaled::{D76s35, D153s75, D307s150};
D38 has the full D38s0 … D38s38. The other widths ship a
curated subset; the generic form D18::<7> is always available for any
in-range scale.
The Decimal trait¶
Every width implements Decimal, the width-generic surface:
use decimal_scaled::Decimal;
fn sum_all<D: Decimal + core::ops::Add<Output = D>>(xs: &[D]) -> D {
D::sum(xs.iter().copied())
}
Decimal carries the full uniform surface every width implements:
- Type info:
Storage,SCALE,MAX_SCALE. - Constants:
ZERO,ONE,MAX,MIN, plusmultiplier(). - Round-trip:
from_bits/to_bits/scale. - Arithmetic & bitwise operators (via supertrait bounds):
+-*/%-(unary) and the*Assignvariants;&|^!<<u32>>>u32. - Sign:
abs,signum,is_positive,is_negative. - Integer methods:
div_euclid,rem_euclid,div_floor,div_ceil,abs_diff,midpoint,mul_add; the float-shape predicatesis_nan/is_infinite/is_finite. - Pow:
pow,powi, and the four*_powoverflow variants. - Overflow variants: every
checked_*/wrapping_*/saturating_*/overflowing_*ofadd/sub/mul/div/rem/neg. - Integer conversion:
from_i32,to_int,to_int_with. - Float bridge (gated on
std):from_f64,from_f64_with,to_f64,to_f32. - Default reductions:
is_zero,is_one,is_normal,sum,product.
A few methods are deliberately not on the trait because their
signature varies per width or the trait can't represent them - see
the trait reference
for the full out-of-scope list (rescale<TARGET> needs a const-generic
method param; from_int takes a per-width source integer;
transcendentals are feature-gated).
Reach for Decimal when writing code that must work across widths;
otherwise the concrete type is the canonical surface.
Moving between widths¶
Widening is lossless and infallible (From); narrowing is fallible
(TryFrom). See conversions for the details.
# use decimal_scaled::{D18s2, D38s2};
let small: D18s2 = D18s2::from_bits(150);
let wide: D38s2 = small.into(); // lossless widen
let back: D18s2 = wide.try_into().unwrap(); // fallible narrow
Every adjacent pair in the comprehensive ladder
(D9 → D18 → D38 → D56 → D76 → D114 → D153 → D230 → D307 →
D461 → D615 → D923 → D1231) has a From / TryFrom pair plus
.widen() / .narrow() helper methods that step one rung
in either direction. Chain them to skip multiple rungs, or use
the From / TryFrom matrix directly to jump straight to any
narrower or wider tier.
# #[cfg(feature = "wide")] {
use decimal_scaled::{D38, D56, D114};
let a: D38<6> = D38::<6>::from_int(7);
let b: D56<6> = a.widen(); // one rung up
let c: D114<6> = b.widen().widen(); // two more rungs: D56 → D76 → D114
let _: D38<6> = c.try_into().unwrap(); // skip-jump back via TryFrom
# }
Wide-tier notes (D56 … D1231)¶
- Enable per width (
d56,d76,d114,d153,d230,d307,d461,d615,d923,d1231) or by umbrella (widefor D56–D230,x-wideadds D461–D615,xx-wideadds D923–D1231). - Storage is the in-tree hand-rolled wide-integer module
(
crate::wide_int); there is no external big-integer dependency. The wide-int type never appears in your code - you work throughfrom_bits/to_bitsand the normal arithmetic. - The full surface is shipped on the wide tier: cross-type
PartialEqagainst every primitive integer and float, the 0.5-ULP-correctly- rounded strict transcendentals (with mode-aware*_strict_withsiblings and AGM alternatesln_strict_agm/exp_strict_agm), arithmetic, conversions, formatting, rescaling, rounding, and the full overflow-variant family.