Skip to main content

lean_decimal/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3
4mod display;
5mod from_str;
6mod ops;
7
8mod int128;
9// mod int64;
10// mod int32;
11
12use core::fmt::{Debug, Display};
13use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub, SubAssign};
14
15pub use from_str::ParseError;
16
17/// The 128-bit decimal type, with about 36 significant digits in base-10 and scale in [0, 36].
18pub type Dec128 = Decimal<u128>;
19
20/// The decimal type.
21///
22/// The `I` is the underlying integer type. It supports `u128` only by now,
23/// and will support `u64` and `u32` in next version.
24/// They have aliases [`Dec128`], `Dec64` and `Dec32` respectively.
25#[derive(Copy, Clone, Default)]
26#[repr(transparent)]
27pub struct Decimal<I: UnderlyingInt>(I);
28
29/// Underlying integer type.
30pub trait UnderlyingInt:
31    Sized
32    + Clone
33    + Copy
34    + Debug
35    + Display
36    + PartialEq
37    + Eq
38    + PartialOrd
39    + Ord
40    + Add<Output = Self>
41    + Sub<Output = Self>
42    + Div<Output = Self>
43    + Rem<Output = Self>
44    + Mul<Output = Self>
45    + Shl<u32, Output = Self>
46    + Shr<u32, Output = Self>
47    + BitOr<Output = Self>
48    + BitAnd<Output = Self>
49    + BitXor<Output = Self>
50    + AddAssign
51    + SubAssign
52{
53    const ZERO: Self;
54    const ONE: Self;
55    const TEN: Self;
56    const HUNDRED: Self;
57    const MAX_MATISSA: Self;
58    const MIN_UNDERINT: Self;
59
60    const BITS: u32;
61    const MAX_SCALE: u32;
62    const SCALE_BITS: u32 = (Self::MAX_SCALE * 2 - 1).ilog2();
63    const META_BITS: u32 = 1 + Self::SCALE_BITS;
64    const MATISSA_BITS: u32 = Self::BITS - Self::META_BITS;
65
66    type Signed: Display;
67
68    // to pack and unpack
69    fn to_signed(self, sign: u8) -> Self::Signed;
70    fn from_signed(s: Self::Signed) -> (Self, u8);
71
72    // to decode and encode the scale
73    fn as_u32(self) -> u32;
74    fn from_u32(n: u32) -> Self;
75
76    fn leading_zeros(self) -> u32;
77
78    // caller has made sure that no overflow
79    fn mul_exp(self, iexp: u32) -> Self;
80
81    // the implementation need to check if overflow
82    fn checked_mul_exp(self, iexp: u32) -> Option<Self>;
83
84    // caller has made sure that @iexp is in range
85    // remember to round the result
86    fn div_exp(self, iexp: u32) -> Self;
87
88    // caller has made sure that @iexp is in range
89    fn div_rem_exp(self, iexp: u32) -> (Self, Self);
90
91    // calculate `self * right` with sum of scales
92    fn mul_with_sum_scale(self, right: Self, sum_scale: u32) -> Option<(Self, u32)>;
93
94    // calculate `self / right` with scales
95    fn div_with_scales(self, d: Self, s_scale: u32, d_scale: u32) -> Option<(Self, u32)>;
96}
97
98impl<I: UnderlyingInt> Decimal<I> {
99    /// Zero.
100    pub const ZERO: Self = Self(I::ZERO);
101
102    /// The largest value. To be largest, the scale is 0, so this is an
103    /// integer, `2^b - 1`, where `b` is the mantissa bits, which is
104    /// 121, 58, 27 for [`Dec128`], `Dec64` and `Dec32` correspondingly.
105    pub const MAX: Self = Self(I::MAX_MATISSA);
106
107    /// The smallest value. It's the negative of [`Self::MAX`].
108    pub const MIN: Self = Self(I::MIN_UNDERINT);
109
110    // layout:
111    //   +-+-----+-------------+
112    //   |S|scale|  mantissa   |
113    //   +-+-----+-------------+
114    fn unpack(self) -> (u8, u32, I) {
115        let mantissa = self.0 & I::MAX_MATISSA;
116        let meta = (self.0 >> I::MATISSA_BITS).as_u32();
117        let scale = meta & ((1 << I::SCALE_BITS) - 1);
118        let sign = meta >> I::SCALE_BITS;
119        (sign as u8, scale, mantissa)
120    }
121
122    // the caller must make sure that the inputs are valid
123    fn pack(sign: u8, scale: u32, mantissa: I) -> Self {
124        debug_assert!(sign <= 1);
125        debug_assert!(scale <= I::MAX_SCALE);
126        debug_assert!(mantissa <= I::MAX_MATISSA);
127
128        let meta = ((sign as u32) << I::SCALE_BITS) | scale;
129        Self(I::from_u32(meta) << I::MATISSA_BITS | mantissa)
130    }
131
132    /// Deconstruct the decimal into signed mantissa and scale.
133    ///
134    /// # Examples:
135    ///
136    /// ```
137    /// use lean_decimal::Dec128;
138    /// use core::str::FromStr;
139    ///
140    /// let d = Dec128::from_str("3.14").unwrap();
141    /// assert_eq!(d.parts(), (314, 2));
142    /// ```
143    pub fn parts(self) -> (I::Signed, u32) {
144        let (sign, scale, man) = self.unpack();
145        (I::to_signed(man, sign), scale)
146    }
147
148    /// Construct a decimal from signed mantissa and scale.
149    ///
150    /// # Panic:
151    ///
152    /// Panic if the mantissa or scale is out of range. Use [`Self::try_from_parts`]
153    /// for the checked version.
154    ///
155    /// # Examples:
156    ///
157    /// ```
158    /// use lean_decimal::Dec128;
159    /// let d = Dec128::from_parts(314, 2);
160    /// assert_eq!(d.to_string(), "3.14");
161    /// ```
162    pub fn from_parts<S>(mantissa: S, scale: u32) -> Self
163    where
164        S: Into<I::Signed>,
165    {
166        Self::try_from_parts(mantissa, scale).expect("invalid decimal input parts")
167    }
168
169    /// Construct a decimal from signed mantissa and scale.
170    ///
171    /// Return `None` if the mantissa or scale is out of range.
172    ///
173    /// # Examples:
174    ///
175    /// ```
176    /// use lean_decimal::Dec128;
177    /// let d = Dec128::try_from_parts(314, 2).unwrap();
178    /// assert_eq!(d.to_string(), "3.14");
179    ///
180    /// let d = Dec128::try_from_parts(314, 99); // 99 is out of range
181    /// assert!(d.is_none());
182    /// ```
183    pub fn try_from_parts<S>(mantissa: S, scale: u32) -> Option<Self>
184    where
185        S: Into<I::Signed>,
186    {
187        if scale > I::MAX_SCALE {
188            return None;
189        }
190        let (man, sign) = I::from_signed(mantissa.into());
191        if man > I::MAX_MATISSA {
192            return None;
193        }
194        Some(Self::pack(sign, scale, man))
195    }
196
197    /// Return the underlying integer.
198    ///
199    /// You should not try to decode this integer yourself.
200    /// You should just hold this and load it later.
201    pub const fn underlying(self) -> I {
202        self.0
203    }
204
205    /// Load from underlying integer, which should only be got from [`Self::underlying`].
206    ///
207    /// # Panic:
208    ///
209    /// Panic if invalid. Use [`Self::try_from_underlying`] for checked version.
210    pub fn from_underlying(ui: I) -> Self {
211        Self::try_from_underlying(ui).expect("invalid underlying integer")
212    }
213
214    /// Load from underlying integer, which should only be got from [`Self::underlying`].
215    pub fn try_from_underlying(ui: I) -> Option<Self> {
216        let meta = (ui >> I::MATISSA_BITS).as_u32();
217        let scale = meta & ((1 << I::SCALE_BITS) - 1);
218        if scale > I::MAX_SCALE {
219            None
220        } else {
221            Some(Self(ui))
222        }
223    }
224
225    /// Load from underlying integer, which should only be got from [`Self::underlying`].
226    ///
227    /// SAFETY: It's safe if you make sure the integer was got from [`Self::underlying`].
228    pub const unsafe fn unchecked_from_underlying(ui: I) -> Self {
229        Self(ui)
230    }
231}
232
233macro_rules! convert_from_int {
234    ($decimal_int:ty, $decimal_signed:ty; $($from_int:ty),*) => {$(
235        impl From<$from_int> for Decimal<$decimal_int> {
236            fn from(value: $from_int) -> Self {
237                Self::from_parts(value as $decimal_signed, 0)
238            }
239        }
240    )*};
241}
242convert_from_int!(u128, i128; i8, u8, i16, u16, i32, u32, i64, u64);
243
244pub(crate) fn bits_to_digits(bits: u32) -> u32 {
245    bits * 1233 >> 12 // math!
246}