bigdecimal/bigdigit/
radix.rs

1//! Radix definitions
2//!
3//! Empty structs used to make generic algorithms over kind of radix
4//!
5#![allow(dead_code)]
6#![allow(non_camel_case_types)]
7
8use crate::*;
9use crate::stdlib::fmt;
10
11use num_traits::{WrappingAdd, WrappingSub, AsPrimitive};
12
13
14/// All the information needed to specify a bigdecimal's radix, and methods operating on integers
15pub trait RadixType: Copy + Clone + Default + fmt::Debug {
16    /// the inner type of values
17    type Base
18        : 'static
19        + Copy
20        + fmt::Debug
21        + num_integer::Integer
22        + num_traits::PrimInt
23        + num_traits::FromPrimitive
24        + num_traits::AsPrimitive<Self::BaseDouble>
25        + num_traits::Zero
26        + num_traits::One
27        + num_traits::WrappingSub
28        + num_traits::Pow<u8, Output = Self::Base>
29        + AddAssign
30        + From<bool>
31        + From<u8>;
32
33    /// double wide unsigned type (capable of storing product of two BigDigits)
34    type BaseDouble
35        : 'static
36        + Copy
37        + num_integer::Integer
38        + num_traits::PrimInt
39        + num_traits::FromPrimitive
40        + num_traits::AsPrimitive<Self::Base>
41        + num_traits::Zero
42        + num_traits::One
43        + num_traits::WrappingAdd
44        + num_traits::WrappingSub
45        + AddAssign
46        + From<u8>
47        + From<Self::Base>;
48
49    /// signed version of base (used for diffs)
50    type SignedBase
51        : 'static
52        + Copy
53        + num_integer::Integer
54        + num_traits::PrimInt
55        + num_traits::FromPrimitive
56        + num_traits::Zero
57        + num_traits::One
58        + num_traits::Signed;
59
60    /// Value of the RADIX
61    const RADIX: Self::BaseDouble;
62
63    /// Check contents of iterable contains values less than the radix
64    fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(i: I) -> bool {
65        i.into_iter().map(|&d| d.into()).all(|d| Self::BaseDouble::zero() <= d && d < Self::RADIX)
66    }
67
68    /// True if n is the maximum value for this radix (RADIX - 1)
69    fn max() -> Self::Base {
70        (Self::RADIX - One::one()).as_()
71    }
72
73    /// True if n is the maximum value for this radix (RADIX - 1)
74    fn is_max(n: Self::Base) -> bool {
75        n == Self::max()
76    }
77
78    /// Split single-width BigDigit base-type value into valid BigDigits for
79    /// this Radix
80    fn split_single(n: Self::Base) -> (Self::Base, Self::Base) {
81        let (hi, lo) = num_integer::div_rem(n.as_(), Self::RADIX);
82        return (hi.as_(), lo.as_());
83    }
84
85    /// Split double-wide value into valid BigDigit and overflow for this Radix
86    fn split_doublewide(n: Self::BaseDouble) -> (Self::BaseDouble, Self::Base) {
87        let (hi, lo) = num_integer::div_rem(n, Self::RADIX);
88        return (hi, lo.as_());
89    }
90
91    /// Split double-wide bigdigit into high and low bigdigits.
92    ///
93    /// This assumes n will fit in two bigdigits, which is not guaranteed.
94    /// Use split_doublewide.
95    ///
96    fn split_wide_digit(n: Self::BaseDouble) -> (Self::Base, Self::Base) {
97        let (hi, lo) = num_integer::div_rem(n, Self::RADIX);
98        if true {
    if !(hi < Self::RADIX) {
        ::core::panicking::panic("assertion failed: hi < Self::RADIX")
    };
};debug_assert!(hi < Self::RADIX);
99        return (hi.as_(), lo.as_());
100    }
101
102    /// Perform n + carry, returning sum and storing overflow back in carry
103    fn add_carry(n: Self::Base, carry: &mut Self::Base) -> Self::Base {
104        let (hi, lo) = Self::expanding_add(n, *carry);
105        *carry = hi;
106        lo
107    }
108
109    /// Perform n += carry, returning overflow in carry
110    fn addassign_carry(n: &mut Self::Base, carry: &mut Self::Base) {
111        let (hi, lo) = Self::expanding_add(*n, *carry);
112        *carry = hi;
113        *n = lo;
114    }
115
116    /// Perform n += a + carry, returning overflow in carry
117    fn addassign_with_carry(n: &mut Self::Base, a: Self::Base, carry: &mut Self::Base) {
118        let sum = n.as_() + a.as_() + carry.as_();
119        let (hi, lo) = Self::split_wide_digit(sum);
120        *carry = hi;
121        *n = lo;
122    }
123
124    /// Perform a + b, returning tuple of (high, low) digits
125    fn add_expand_doublewide(a: Self::Base, b: Self::BaseDouble) -> (Self::Base, Self::Base) {
126        let a: Self::BaseDouble = a.into();
127        Self::split_wide_digit(a + b)
128    }
129
130    /// Perform a + b, returning tuple of (high, low) digits
131    fn expanding_add(a: Self::Base, b: Self::Base) -> (Self::Base, Self::Base) {
132        let a: Self::BaseDouble = a.into();
133        let b: Self::BaseDouble = b.into();
134        Self::split_wide_digit(a + b)
135    }
136
137    /// Perform a * b, returning tuple of (high, low) digits
138    fn expanding_mul(a: Self::Base, b: Self::Base) -> (Self::Base, Self::Base) {
139        let a: Self::BaseDouble = a.into();
140        let b: Self::BaseDouble = b.into();
141        Self::split_wide_digit(a * b)
142    }
143
144    /// Perform a * b + c, returning tuple of (high, low) digits
145    fn fused_mul_add(a: Self::Base, b: Self::Base, c: Self::Base) -> (Self::Base, Self::Base) {
146        let a: Self::BaseDouble = a.into();
147        let b: Self::BaseDouble = b.into();
148        let c: Self::BaseDouble = c.into();
149        Self::split_wide_digit(a * b + c)
150    }
151
152    /// Perform a * b + c + d, returning tuple of (high, low) digits
153    fn carrying_mul_add(
154        a: Self::Base,
155        b: Self::Base,
156        c: Self::Base,
157        d: Self::Base,
158    ) -> (Self::Base, Self::Base) {
159        let a: Self::BaseDouble = a.into();
160        let b: Self::BaseDouble = b.into();
161        let c: Self::BaseDouble = c.into();
162        let d: Self::BaseDouble = d.into();
163        Self::split_wide_digit(a * b + c + d)
164    }
165
166    /// Perform c += a * b + carry, returning overflow in carry
167    fn carrying_mul_add_inplace(
168        a: Self::Base,
169        b: Self::Base,
170        c: &mut Self::Base,
171        carry: &mut Self::Base,
172    ) {
173        let a: Self::BaseDouble = a.into();
174        let b: Self::BaseDouble = b.into();
175        let (hi, lo) = Self::split_wide_digit(a * b + (*c).into() + (*carry).into());
176        *c = lo;
177        *carry = hi;
178    }
179
180    /// Add c into little-endian slice of digits, storing overflow in c
181    ///
182    /// Starts adding at index 0.
183    ///
184    fn add_carry_into_slice(dest: &mut [Self::Base], c: &mut Self::Base) {
185        Self::add_carry_into(dest.iter_mut(), c)
186    }
187
188    /// Iterate over digits in 'dest', adding the carry value until it becomes zero.
189    ///
190    /// If iterator runs out of digits while carry has a value (i.e. the sum overflows),
191    /// the carry value will not be zero.
192    ///
193    fn add_carry_into<'a, I: Iterator<Item=&'a mut Self::Base>>(dest: I, c: &mut Self::Base) {
194        for d in dest {
195            if c.is_zero() {
196                return;
197            }
198
199            let (overflow, sum) = Self::expanding_add(*c, *d);
200            *d = sum;
201            *c = overflow;
202        }
203    }
204
205    /// a = a * b + c, storing
206    fn mulassign_add_carry(
207        a: &mut Self::Base,
208        b: Self::Base,
209        carry: &mut Self::Base,
210    ) {
211        let (hi, lo) = Self::expanding_mul(*a, b);
212        *a = Self::add_carry(lo, carry);
213        *carry += hi;
214    }
215
216    /// return value of (lhs - rhs + carry - borrow)
217    fn sub_with_carry_borrow(
218        lhs: Self::Base,
219        rhs: Self::Base,
220        carry: &mut Self::Base,
221        borrow: &mut Self::Base,
222    ) -> Self::Base {
223        let mut result = Self::BaseDouble::from(lhs);
224        result = result
225                    .wrapping_sub(&Self::BaseDouble::from(rhs))
226                    .wrapping_add(&(*carry).as_())
227                    .wrapping_sub(&(*borrow).as_());
228
229        *borrow = Self::Base::from(result >= (Self::RADIX << 1));
230        result = result.wrapping_add(&(borrow.as_() * Self::RADIX));
231        if true {
    if !(result < (Self::RADIX << 1)) {
        ::core::panicking::panic("assertion failed: result < (Self::RADIX << 1)")
    };
};debug_assert!(result < (Self::RADIX << 1));
232
233        *carry = Self::Base::from(result >= Self::RADIX);
234        result = result - carry.as_() * Self::RADIX;
235
236        return result.as_();
237    }
238}
239
240/// Radix=*10* / storage=*u8*
241#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_10_u8 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_10_u8 {
    #[inline]
    fn clone(&self) -> RADIX_10_u8 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_10_u8 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_10_u8")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_10_u8 {
    #[inline]
    fn default() -> RADIX_10_u8 { RADIX_10_u8 {} }
}Default)]
242pub struct RADIX_10_u8;
243
244/// Radix=*10,000* storage=*i16*
245#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_10p4_i16 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_10p4_i16 {
    #[inline]
    fn clone(&self) -> RADIX_10p4_i16 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_10p4_i16 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_10p4_i16")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_10p4_i16 {
    #[inline]
    fn default() -> RADIX_10p4_i16 { RADIX_10p4_i16 {} }
}Default)]
246pub struct RADIX_10p4_i16;
247
248/// Radix=*1,000,000,000* storage=*u32*
249#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_10p9_u32 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_10p9_u32 {
    #[inline]
    fn clone(&self) -> RADIX_10p9_u32 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_10p9_u32 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_10p9_u32")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_10p9_u32 {
    #[inline]
    fn default() -> RADIX_10p9_u32 { RADIX_10p9_u32 {} }
}Default)]
250pub struct RADIX_10p9_u32;
251
252/// Radix=*10,000,000,000,000,000,000* storage=*u64*
253#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_10p19_u64 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_10p19_u64 {
    #[inline]
    fn clone(&self) -> RADIX_10p19_u64 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_10p19_u64 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_10p19_u64")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_10p19_u64 {
    #[inline]
    fn default() -> RADIX_10p19_u64 { RADIX_10p19_u64 {} }
}Default)]
254pub struct RADIX_10p19_u64;
255
256/// Radix = 2^<sup>32</sup>
257#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_u32 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_u32 {
    #[inline]
    fn clone(&self) -> RADIX_u32 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_u32 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_u32")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_u32 {
    #[inline]
    fn default() -> RADIX_u32 { RADIX_u32 {} }
}Default)]
258pub struct RADIX_u32;
259
260/// Radix = 2^<sup>64</sup>
261#[derive(#[automatically_derived]
impl ::core::marker::Copy for RADIX_u64 { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RADIX_u64 {
    #[inline]
    fn clone(&self) -> RADIX_u64 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RADIX_u64 {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RADIX_u64")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for RADIX_u64 {
    #[inline]
    fn default() -> RADIX_u64 { RADIX_u64 {} }
}Default)]
262pub struct RADIX_u64;
263
264
265pub(crate) trait RadixPowerOfTen: RadixType {
266    const DIGITS: usize;
267
268    /// convert number of digits to number of big-digits
269    fn divceil_digit_count(digit_count: usize) -> usize {
270        use num_integer::Integer;
271        Integer::div_ceil(&digit_count, &Self::DIGITS)
272    }
273
274    /// convert number of digits to number of big-digits
275    fn divmod_digit_count(digit_count: usize) -> (usize, usize) {
276        use num_integer::Integer;
277        Integer::div_rem(&digit_count, &Self::DIGITS)
278    }
279}
280
281impl RadixPowerOfTen for RADIX_10p19_u64 {
282    const DIGITS: usize = 19;
283}
284impl RadixPowerOfTen for RADIX_10p9_u32 {
285    const DIGITS: usize = 9;
286}
287impl RadixPowerOfTen for RADIX_10_u8 {
288    const DIGITS: usize = 1;
289}
290impl RadixPowerOfTen for RADIX_10p4_i16 {
291    const DIGITS: usize = 4;
292}
293
294impl RADIX_10p19_u64 {
295    /// Divide double-wide u64 by radix, storing the quotient in the low u64,
296    /// and returning the remainder
297    pub(crate) fn rotating_div_u64_radix(hi: u64, lo: &mut u64) -> <Self as RadixType>::Base {
298        use num_integer::div_rem;
299        type BaseDouble = <RADIX_10p19_u64 as RadixType>::BaseDouble;
300
301        let num = BaseDouble::from(*lo) + (BaseDouble::from(hi) << 64);
302        let (q, r) = div_rem(num, Self::RADIX);
303        *lo = q.as_();
304        r.as_()
305    }
306}
307
308#[cfg(test)]
309mod test_validate {
310    use super::*;
311
312    macro_rules! impl_case {
313        (valid $name:ident : $radix:ident ~ $values:expr) => {
314            #[test]
315            fn $name() {
316                assert!($radix::validate_digits($values.iter()));
317            }
318        };
319        (invalid $name:ident : $radix:ident ~ $values:expr) => {
320            #[test]
321            fn $name() {
322                assert!(!$radix::validate_digits($values.iter()));
323            }
324        };
325    }
326
327    impl_case!(valid case_valid: RADIX_10p4_i16 ~ [1, 2, 3, 4, 5, 600]);
328    impl_case!(invalid case_invalid_too_big: RADIX_10p4_i16 ~ [10000, 1, 2, 3, 4, 5, 600]);
329    impl_case!(invalid case_invalid_negative: RADIX_10p4_i16 ~ [1, 2, -3, 4, 5, 600]);
330    impl_case!(invalid case_invalid_leading_zeros: RADIX_10p4_i16 ~ [0, 1, 2, -3, 4, 5, 600]);
331    impl_case!(invalid case_p9_toobig: RADIX_10p9_u32 ~ [3330199352]);
332}
333
334impl RadixType for RADIX_u32 {
335    type Base = u32;
336    type BaseDouble = u64;
337    type SignedBase = i32;
338
339    const RADIX: Self::BaseDouble = 1u64 << 32;
340
341    // all u32 are valid in this radix
342    fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(_: I) -> bool {
343        true
344    }
345
346    fn expanding_add(a: u32, b: u32) -> (u32, u32) {
347        let (sum, overflow) = a.overflowing_add(b);
348        (u32::from(overflow), sum)
349    }
350}
351
352impl RadixType for RADIX_u64 {
353    type Base = u64;
354    type BaseDouble = u128;
355    type SignedBase = i64;
356
357    const RADIX: Self::BaseDouble = 1u128 << 64;
358
359    // all u64 are valid in this radix
360    fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(_: I) -> bool {
361        true
362    }
363
364    fn expanding_add(a: u64, b: u64) -> (u64, u64) {
365        let (sum, overflow) = a.overflowing_add(b);
366        (u64::from(overflow), sum)
367    }
368}
369
370impl RadixType for RADIX_10p4_i16 {
371    type Base = i16;
372    type BaseDouble = i32;
373    type SignedBase = i64;
374
375    const RADIX: Self::BaseDouble = 10_000;
376}
377
378impl RadixType for RADIX_10p9_u32 {
379    type Base = u32;
380    type BaseDouble = u64;
381    type SignedBase = i32;
382
383    const RADIX: Self::BaseDouble = 1_000_000_000;
384}
385
386impl RadixType for RADIX_10p19_u64 {
387    type Base = u64;
388    type BaseDouble = u128;
389    type SignedBase = i64;
390
391    const RADIX: Self::BaseDouble = 10_000_000_000_000_000_000;
392}
393
394impl RadixType for RADIX_10_u8 {
395    type Base = u8;
396    type BaseDouble = u8;
397    type SignedBase = i8;
398
399    const RADIX: Self::BaseDouble = 10;
400}
401
402#[cfg(test)]
403mod tests {
404    use super::*;
405
406    include!("radix.tests.rs");
407}