Skip to main content

decimal_scaled/
lib.rs

1//! Const-generic base-10 fixed-point decimal types for deterministic arithmetic.
2//!
3//! # Overview
4//!
5//! `decimal-scaled` provides `I128<const SCALE: u32>`, a fixed-point decimal
6//! type backed by `i128`. The stored integer encodes `actual_value * 10^SCALE`,
7//! so decimal literals like `1.1` round-trip exactly without any binary
8//! approximation. All core arithmetic is integer-only and produces identical
9//! bit-patterns on every platform.
10//!
11//! # Primary types
12//!
13//! - [`I128<SCALE>`] is the const-generic foundation. Every method is
14//!   implemented once and is available at any scale.
15//! - [`I128s12`] is the concrete alias `I128<12>`. At `SCALE = 12`, one LSB
16//!   equals `10^-12` model units and the representable range is roughly
17//!   +/-1.7e14 model units.
18//! - Scale aliases [`I128s0`] through [`I128s38`] cover every supported scale.
19//!   `SCALE = 39` is not supported because `10^39` overflows `i128`.
20//!
21//! # Equality and hashing
22//!
23//! Because each logical value has exactly one representation at a fixed scale,
24//! `Hash`, `Eq`, `PartialEq`, `PartialOrd`, and `Ord` are all derived from
25//! the underlying `i128`. Two `I128<S>` values compare equal if and only if
26//! their raw bit patterns are identical. This gives predictable behaviour when
27//! `I128` values are used as `HashMap` keys, unlike variable-scale decimal
28//! types where `1.10` and `1.1` may hash differently.
29//!
30//! # `num-traits` compatibility
31//!
32//! [`I128<SCALE>`] implements the standard `num-traits` 0.2 surface,
33//! including [`num_traits::Zero`], [`num_traits::One`], [`num_traits::Num`],
34//! [`num_traits::Bounded`], [`num_traits::Signed`],
35//! [`num_traits::FromPrimitive`], [`num_traits::ToPrimitive`], and the
36//! `Checked{Add,Sub,Mul,Div,Rem,Neg}` family. These impls are unconditional
37//! (not behind a feature flag) because generic numeric code in the wider
38//! ecosystem consumes this surface by default.
39//!
40//! # `no_std` support
41//!
42//! The crate compiles with `no_std + alloc` when default features are
43//! disabled. `alloc` is required for `Display::to_string` and
44//! `FromStr::from_str`. Targets without `alloc` are not supported.
45//!
46//! # Feature flags
47//!
48//! - `std` (default): enables the lossy implementations of transcendental
49//!   functions (trigonometry, logarithms, exponentials, square root, cube
50//!   root, float power) that delegate to platform `f64` intrinsics.
51//! - `alloc`: pulled in automatically; required for string formatting and
52//!   parsing.
53//! - `serde`: enables `serde_helpers` for serialisation and deserialisation.
54//! - `strict`: enables integer-only implementations of all transcendental
55//!   functions. When `strict` is active each function that would otherwise
56//!   route through `f64` is instead implemented using integer-only
57//!   algorithms. Explicit float-conversion methods (`to_f64_lossy`,
58//!   `from_f64_lossy`, etc.) remain available regardless; they are type
59//!   conversions, not mathematical operations. `strict` does not require
60//!   `std`; the integer transcendental implementations compile under
61//!   `no_std + alloc`.
62
63#![cfg_attr(not(feature = "std"), no_std)]
64#![allow(clippy::module_name_repetitions)]
65
66#[cfg(feature = "alloc")]
67extern crate alloc;
68
69mod arithmetic;
70mod bitwise;
71mod consts;
72mod conversions;
73mod core_type;
74mod display;
75mod i64f64_compat;
76#[cfg(any(feature = "std", not(feature = "strict")))]
77mod log_exp;
78mod mg_divide;
79mod num_traits_impls;
80mod overflow_variants;
81mod powers;
82#[cfg(feature = "serde")]
83pub mod serde_helpers;
84#[cfg(any(feature = "std", not(feature = "strict")))]
85mod trig;
86
87pub use consts::DecimalConsts;
88pub use conversions::DecimalConvertError;
89pub use core_type::{
90    I128, I128s0, I128s1, I128s2, I128s3, I128s4, I128s5, I128s6, I128s7, I128s8, I128s9, I128s10,
91    I128s11, I128s12, I128s13, I128s14, I128s15, I128s16, I128s17, I128s18, I128s19, I128s20,
92    I128s21, I128s22, I128s23, I128s24, I128s25, I128s26, I128s27, I128s28, I128s29, I128s30,
93    I128s31, I128s32, I128s33, I128s34, I128s35, I128s36, I128s37, I128s38, ParseDecimalError,
94};