bigdecimal/bigdigit/
alignment.rs

1//! Splitting and shifting bigdigits for alignment
2//!
3#![allow(dead_code)]
4
5use crate::*;
6use super::radix::RadixPowerOfTen;
7use super::endian::LittleEndian;
8use crate::arithmetic::diff_usize;
9
10type BigDigitVec<R> = super::digitvec::DigitVec<R, LittleEndian>;
11
12/// The cases resulting from applying (lhs += rhs * offset)
13///
14#[derive(#[automatically_derived]
impl ::core::clone::Clone for AddAssignSliceAlignment {
    #[inline]
    fn clone(&self) -> AddAssignSliceAlignment {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AddAssignSliceAlignment { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for AddAssignSliceAlignment {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AddAssignSliceAlignment::RightOverlap { count: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "RightOverlap", "count", &__self_0),
            AddAssignSliceAlignment::RightDisjoint { count: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "RightDisjoint", "count", &__self_0),
            AddAssignSliceAlignment::LeftOverlap { count: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "LeftOverlap", "count", &__self_0),
            AddAssignSliceAlignment::LeftDisjoint { count: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "LeftDisjoint", "count", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::Eq for AddAssignSliceAlignment {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for AddAssignSliceAlignment {
    #[inline]
    fn eq(&self, other: &AddAssignSliceAlignment) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AddAssignSliceAlignment::RightOverlap { count: __self_0 },
                    AddAssignSliceAlignment::RightOverlap { count: __arg1_0 })
                    => __self_0 == __arg1_0,
                (AddAssignSliceAlignment::RightDisjoint { count: __self_0 },
                    AddAssignSliceAlignment::RightDisjoint { count: __arg1_0 })
                    => __self_0 == __arg1_0,
                (AddAssignSliceAlignment::LeftOverlap { count: __self_0 },
                    AddAssignSliceAlignment::LeftOverlap { count: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                (AddAssignSliceAlignment::LeftDisjoint { count: __self_0 },
                    AddAssignSliceAlignment::LeftDisjoint { count: __arg1_0 })
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
15pub(crate) enum AddAssignSliceAlignment {
16    ///  [rrrrrrrr]     |   [rrr]    |  [rrrrrrr]
17    ///      [lllllll]  | [lllllll]  |    [lllll]
18    RightOverlap {
19        count: usize,
20    },
21    ///  [rrrrr]
22    ///              [lllllll]
23    ///       ^count        ^0
24    RightDisjoint {
25        count: usize,
26    },
27    /// Left starts with the more significant digits
28    ///      [rrrrrrr]  | [rrrrrrr]
29    ///  [llllllll]     |   [lll]
30    LeftOverlap {
31        count: usize,
32    },
33    /// Disjoint, left more significant
34    ///              [rrrrrrr]
35    ///  [lllll]
36    ///       ^count        ^0
37    LeftDisjoint {
38        count: usize,
39    },
40}
41
42impl AddAssignSliceAlignment {
43    /// Determine relative alignment of digit-arrays of given length
44    /// and scale (exponent of the least significant digit)
45    pub fn from_lengths_and_scales(lhs: WithScale<usize>, rhs: WithScale<usize>) -> Self {
46        use cmp::Ordering::*;
47
48        match diff_usize(rhs.scale, lhs.scale) {
49            (Equal, _) => {
50                Self::RightOverlap {
51                    count: 0,
52                }
53            }
54            (Less, count) => {
55                if count < lhs.value {
56                    Self::RightOverlap {
57                        count,
58                    }
59                } else {
60                    Self::RightDisjoint {
61                        count,
62                    }
63                }
64            }
65            (Greater, count) => {
66                if count < rhs.value {
67                    Self::LeftOverlap {
68                        count,
69                    }
70                } else {
71                    Self::LeftDisjoint {
72                        count,
73                    }
74                }
75            }
76        }
77    }
78
79    /// Determine relative alignment of digit-arrays of given length
80    /// and number of integer bigdigits
81    pub fn from_lengths_and_icount(lhs: WithIntCount<usize>, rhs: WithIntCount<usize>) -> Self {
82        // position of least-significant digits
83        Self::from_lengths_and_scales(
84            WithScale {
85                scale: lhs.value as i64 - lhs.count as i64,
86                value: lhs.value,
87            },
88            WithScale {
89                scale: rhs.value as i64 - rhs.count as i64,
90                value: rhs.value,
91            },
92        )
93    }
94}
95
96#[derive(#[automatically_derived]
impl<R: ::core::marker::Copy, I: ::core::marker::Copy> ::core::marker::Copy
    for BigDigitSplitterIter<R, I> where R: RadixPowerOfTen,
    I: Iterator<Item = R::Base> {
}Copy, #[automatically_derived]
impl<R: ::core::clone::Clone, I: ::core::clone::Clone> ::core::clone::Clone
    for BigDigitSplitterIter<R, I> where R: RadixPowerOfTen,
    I: Iterator<Item = R::Base> {
    #[inline]
    fn clone(&self) -> BigDigitSplitterIter<R, I> {
        BigDigitSplitterIter {
            shift: ::core::clone::Clone::clone(&self.shift),
            digits: ::core::clone::Clone::clone(&self.digits),
        }
    }
}Clone, #[automatically_derived]
impl<R: ::core::fmt::Debug, I: ::core::fmt::Debug> ::core::fmt::Debug for
    BigDigitSplitterIter<R, I> where R: RadixPowerOfTen,
    I: Iterator<Item = R::Base> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "BigDigitSplitterIter", "shift", &self.shift, "digits",
            &&self.digits)
    }
}Debug)]
97pub(crate) struct BigDigitSplitterIter<R, I>
98where
99    R: RadixPowerOfTen,
100    I: Iterator<Item = R::Base>,
101{
102    shift: ShiftState<R>,
103    digits: I,
104}
105
106impl<R, I> BigDigitSplitterIter<R, I>
107where
108    R: RadixPowerOfTen,
109    I: Iterator<Item = R::Base>,
110{
111    /// Wrap iterator with on shifting
112    pub fn new(iter: I) -> Self {
113        Self::from_shifter_and_iter(ShiftState::Zero, iter)
114    }
115
116    /// Wrap iterator, shifting by shift-state
117    pub fn from_shifter_and_iter(shifter: ShiftState<R>, iter: I) -> Self {
118        Self {
119            shift: shifter,
120            digits: iter,
121        }
122    }
123
124    /// Return the internal 'mask' value
125    pub fn mask(&self) -> R::Base {
126        match self.shift {
127            ShiftState::Zero => Zero::zero(),
128            ShiftState::Shifted {
129                mask:
130                    BigDigitSplitter {
131                        mask,
132                        ..
133                    },
134                ..
135            } => mask,
136        }
137    }
138
139    /// Returns the value of the 'shift' with one subtracted
140    ///
141    /// Useful for adding nines to first result of `from_slice_starting_bottom`
142    ///
143    pub fn shift_minus_one(&self) -> R::Base {
144        match self {
145            BigDigitSplitterIter {
146                shift: ShiftState::Zero,
147                ..
148            } => R::max(),
149            BigDigitSplitterIter {
150                shift:
151                    ShiftState::Shifted {
152                        mask,
153                        ..
154                    },
155                ..
156            } => mask.shift - One::one(),
157        }
158    }
159
160    /// Copy all remaining digits into destination vector
161    pub fn extend_vector(self, dest: &mut BigDigitVec<R>) {
162        if let Self {
163            shift: ShiftState::Zero,
164            digits,
165            ..
166        } = self
167        {
168            dest.digits.extend(digits);
169        } else {
170            dest.digits.extend(self);
171        }
172    }
173
174    /// Copy all remaining digits into destination vector, adding carry
175    ///
176    /// Note: carry is not zeroed after being pushed into the vector
177    ///
178    pub(crate) fn extend_vector_adding_carry(
179        mut self,
180        mut carry: R::Base,
181        dest: &mut BigDigitVec<R>,
182    ) {
183        while !carry.is_zero() {
184            if let Some(mut next_digit) = self.next() {
185                R::addassign_carry(&mut next_digit, &mut carry);
186                dest.push_significant_digit(next_digit);
187            } else {
188                dest.push_significant_digit(carry);
189                return;
190            }
191        }
192        self.extend_vector(dest)
193    }
194
195    /// Extend vector with digits in self, adding carry and subtracting borrow
196    pub(crate) fn extend_vector_with_carry_borrow(
197        mut self,
198        carry: &mut R::Base,
199        borrow: &mut R::Base,
200        dest: &mut BigDigitVec<R>,
201    ) {
202        use num_traits::WrappingSub;
203
204        if borrow.is_zero() && carry.is_zero() {
205            return self.extend_vector(dest);
206        }
207
208        // the two cancel
209        if carry == borrow {
210            *borrow = Zero::zero();
211            *carry = Zero::zero();
212            return self.extend_vector(dest);
213        }
214
215        match self.next() {
216            Some(digit) => {
217                let d = R::sub_with_carry_borrow(digit, R::Base::zero(), carry, borrow);
218                dest.push_significant_digit(d);
219                // TODO: is there a cost to recursion?
220                self.extend_vector_with_carry_borrow(borrow, carry, dest);
221            }
222            None if carry == borrow => {}
223            None if carry > borrow => {
224                dest.push_significant_digit(carry.wrapping_sub(borrow));
225                *carry = Zero::zero();
226                *borrow = Zero::zero();
227            }
228            None => {
229                { ::core::panicking::unreachable_display(&"borrow underflow"); };unreachable!("borrow underflow");
230            }
231        }
232    }
233
234    /// skip n digits
235    pub fn advance_by_n(&mut self, n: usize) {
236        // naive loop implementation
237        for _ in 0..n {
238            if self.next().is_none() {
239                break;
240            }
241        }
242    }
243
244    /// called when there's further digits to iterate
245    fn on_next_digit(&mut self, digit: R::Base) -> R::Base {
246        if let ShiftState::Shifted {
247            ref mut prev,
248            ref mask,
249        } = self.shift
250        {
251            let (hi, mut lo) = mask.split_and_shift(digit);
252            lo += *prev;
253            *prev = hi;
254            lo
255        } else {
256            digit
257        }
258    }
259
260    /// called when internal iterator is exhausted, returning final
261    /// shifted digits
262    fn on_last_digit(&mut self) -> Option<R::Base> {
263        match self.shift {
264            ShiftState::Shifted {
265                ref mut prev,
266                ..
267            } if !prev.is_zero() => {
268                let result = *prev;
269                *prev = Zero::zero();
270                Some(result)
271            }
272            _ => None,
273        }
274    }
275}
276
277impl<R, I> Iterator for BigDigitSplitterIter<R, I>
278where
279    R: RadixPowerOfTen,
280    I: Iterator<Item = R::Base>,
281{
282    type Item = R::Base;
283
284    fn next(&mut self) -> Option<Self::Item> {
285        self.digits
286            .next()
287            .map(|digit| self.on_next_digit(digit))
288            .or_else(|| self.on_last_digit())
289    }
290}
291
292type CopiedDigitSlice<'a, R> =
293    stdlib::iter::Copied<stdlib::slice::Iter<'a, <R as super::radix::RadixType>::Base>>;
294pub(crate) type BigDigitSliceSplitterIter<'a, R> = BigDigitSplitterIter<R, CopiedDigitSlice<'a, R>>;
295
296impl<'a, R: RadixPowerOfTen> BigDigitSliceSplitterIter<'a, R> {
297    /// Return the complimentary size to 'n'
298    fn comp_n(n: usize) -> usize {
299        if true {
    if !(n < R::DIGITS) {
        ::core::panicking::panic("assertion failed: n < R::DIGITS")
    };
};debug_assert!(n < R::DIGITS);
300        if n == 0 {
301            0
302        } else {
303            R::DIGITS - n
304        }
305    }
306
307    /// Build without shifting digits
308    pub fn from_slice(slice: &'a [R::Base]) -> Self {
309        Self {
310            shift: ShiftState::Zero,
311            digits: slice.iter().copied(),
312        }
313    }
314
315    /// Stream will behave as if adding n zeros to beginning of digits
316    ///
317    /// ```ignore
318    /// [987654321, ...] : n=3 => [654321000, xxxxxx987, ...]
319    /// ```
320    ///
321    pub(crate) fn from_slice_shifting_left(slice: &'a [R::Base], n: usize) -> Self {
322        Self::from_slice_starting_bottom(slice, Self::comp_n(n))
323    }
324
325    /// Stream will behave as if removing first n-digits from the slice
326    ///
327    /// ```ignore
328    /// [987654321, ...] : n=3 => [xxx987654, ...]
329    /// ```
330    ///
331    /// This is the second digit of `from_slice_starting_bottom`
332    ///
333    pub(crate) fn from_slice_shifting_right(slice: &'a [R::Base], n: usize) -> Self {
334        Self::from_slice_starting_top(slice, Self::comp_n(n))
335    }
336
337    /// First digit will be the bottom n digits shifted to top
338    ///
339    /// ```ignore
340    /// [987654321, ...] : n=3 => [321000000, xxx987654, ...]
341    /// ```
342    ///
343    pub(crate) fn from_slice_starting_bottom(slice: &'a [R::Base], n: usize) -> Self {
344        Self::from_shifter_and_iter(ShiftState::starting_with_bottom(n), slice.iter().copied())
345    }
346
347    /// First digit will be the highest n-digits shifted to bottom
348    ///
349    /// ```ignore
350    /// [987654321, ...] : n=3 => [xxxxxx987, ...]
351    /// ```
352    ///
353    /// This is the second digit of `from_slice_shifting_left`
354    /// The bottom digits will be lost.
355    ///
356    pub(crate) fn from_slice_starting_top(slice: &'a [R::Base], n: usize) -> Self {
357        let mut digits = slice.iter().copied();
358        let shifter = ShiftState::starting_with_top(n, &mut digits);
359        Self::from_shifter_and_iter(shifter, digits)
360    }
361
362    /// True if iterator has no more values
363    pub fn is_exhausted(&self) -> bool {
364        match self.shift {
365            ShiftState::Zero => self.digits.len() == 0,
366            _ => self.peek_next().is_none(),
367        }
368    }
369
370    /// Return the next bigdigit (if available) without advancing the internal value
371    pub fn peek_next(&self) -> Option<R::Base> {
372        self.clone().next()
373    }
374}
375
376/// Wrap shift-and-mask type with special-case for zero shift
377///
378#[derive(#[automatically_derived]
impl<R: ::core::marker::Copy + RadixPowerOfTen> ::core::marker::Copy for
    ShiftState<R> where R::Base: ::core::marker::Copy {
}Copy, #[automatically_derived]
impl<R: ::core::clone::Clone + RadixPowerOfTen> ::core::clone::Clone for
    ShiftState<R> where R::Base: ::core::clone::Clone {
    #[inline]
    fn clone(&self) -> ShiftState<R> {
        match self {
            ShiftState::Zero => ShiftState::Zero,
            ShiftState::Shifted { mask: __self_0, prev: __self_1 } =>
                ShiftState::Shifted {
                    mask: ::core::clone::Clone::clone(__self_0),
                    prev: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone, #[automatically_derived]
impl<R: ::core::fmt::Debug + RadixPowerOfTen> ::core::fmt::Debug for
    ShiftState<R> where R::Base: ::core::fmt::Debug {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ShiftState::Zero => ::core::fmt::Formatter::write_str(f, "Zero"),
            ShiftState::Shifted { mask: __self_0, prev: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "Shifted", "mask", __self_0, "prev", &__self_1),
        }
    }
}Debug)]
379pub(crate) enum ShiftState<R: RadixPowerOfTen> {
380    Zero,
381    Shifted {
382        mask: BigDigitSplitter<R>,
383        prev: R::Base,
384    },
385}
386
387impl<R: RadixPowerOfTen> ShiftState<R> {
388    /// Start with the lower n digits of the first bigdigit, shifted up
389    ///
390    /// ```ignore
391    /// Self::starting_with_top([987654321, ...], 3) => [32100000, xxx987654, ...]
392    /// ```
393    /// 987654321, 3 =>
394    ///
395    fn starting_with_bottom(n: usize) -> Self {
396        if n == 0 {
397            Self::Zero
398        } else {
399            Self::Shifted {
400                mask: BigDigitSplitter::mask_low(n as u8),
401                prev: R::Base::zero(),
402            }
403        }
404    }
405
406    /// Start with high n digits of the first bigdigit
407    ///
408    /// ```ignore
409    /// Self::starting_with_top([987654321, ...], 3) => [xxxxxx987, ...]
410    /// ```
411    ///
412    fn starting_with_top<I: Iterator<Item = R::Base>>(n: usize, digits: &mut I) -> Self {
413        if n == 0 {
414            Self::Zero
415        } else {
416            let mask = BigDigitSplitter::mask_high(n);
417            let first_digit = digits.next().map(|d| d / mask.mask).unwrap_or(Zero::zero());
418            Self::Shifted {
419                mask: mask,
420                prev: first_digit,
421            }
422        }
423    }
424}
425
426/// Splits a bigdigit into pieces, used when aligning
427#[derive(#[automatically_derived]
impl<R: ::core::marker::Copy + RadixPowerOfTen> ::core::marker::Copy for
    BigDigitSplitter<R> where R::Base: ::core::marker::Copy,
    R::Base: ::core::marker::Copy {
}Copy, #[automatically_derived]
impl<R: ::core::clone::Clone + RadixPowerOfTen> ::core::clone::Clone for
    BigDigitSplitter<R> where R::Base: ::core::clone::Clone,
    R::Base: ::core::clone::Clone {
    #[inline]
    fn clone(&self) -> BigDigitSplitter<R> {
        BigDigitSplitter {
            mask: ::core::clone::Clone::clone(&self.mask),
            shift: ::core::clone::Clone::clone(&self.shift),
        }
    }
}Clone, #[automatically_derived]
impl<R: ::core::fmt::Debug + RadixPowerOfTen> ::core::fmt::Debug for
    BigDigitSplitter<R> where R::Base: ::core::fmt::Debug,
    R::Base: ::core::fmt::Debug {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "BigDigitSplitter", "mask", &self.mask, "shift", &&self.shift)
    }
}Debug)]
428pub(crate) struct BigDigitSplitter<R: RadixPowerOfTen> {
429    /// dividend to split a bigdigit into high and low digits
430    mask: R::Base,
431    /// multiplication shifts high bigdigit to correct place after split
432    shift: R::Base,
433}
434
435impl<R: RadixPowerOfTen> BigDigitSplitter<R> {
436    /// Build such that (X % mask) 'keeps' n digits of X
437    pub fn mask_low(n: u8) -> Self {
438        use crate::arithmetic::ten_to_the_t;
439
440        if true {
    if !((n as usize) < R::DIGITS) {
        ::core::panicking::panic("assertion failed: (n as usize) < R::DIGITS")
    };
};debug_assert!((n as usize) < R::DIGITS);
441        let mask = ten_to_the_t(n);
442        let shift = ten_to_the_t(R::DIGITS as u8 - n);
443        Self {
444            shift,
445            mask,
446        }
447    }
448
449    /// Build such that (X / mask) 'keeps' n digits of X
450    pub fn mask_high(n: usize) -> Self {
451        Self::mask_low((R::DIGITS - n) as u8)
452    }
453
454    /// Split bigdigit into high and low digits
455    ///
456    /// BigDigitSplitter::mask_high(3).split(987654321) => (987000000, 000654321)
457    /// BigDigitSplitter::mask_low(3).split(987654321)  => (987654000, 000000321)
458    ///
459    pub fn split(&self, n: R::Base) -> (R::Base, R::Base) {
460        let lo = n % self.mask;
461        (n - lo, lo)
462    }
463
464    /// Split and shift such that the n "high" bits are on low
465    /// side of digit and low bits are at the high end
466    ///
467    /// BigDigitSplitter::mask_high(3).split_and_shift(987654321) => (000000987, 654321000)
468    /// BigDigitSplitter::mask_low(3).split_and_shift(987654321)  => (000987654, 321000000)
469    ///
470    pub fn split_and_shift(&self, n: R::Base) -> (R::Base, R::Base) {
471        let (hi, lo) = self.div_rem(n);
472        (hi, lo * self.shift)
473    }
474
475    pub fn div_rem(&self, n: R::Base) -> (R::Base, R::Base) {
476        n.div_rem(&self.mask)
477    }
478
479    pub fn div(&self, n: R::Base) -> R::Base {
480        n / self.mask
481    }
482}
483
484/// Wrap a container of bigidigts with a count of how
485/// many are integer
486///
487/// i.e. The digits are aligned with zero
488///
489#[derive(#[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for WithIntCount<T> {
    #[inline]
    fn clone(&self) -> WithIntCount<T> {
        WithIntCount {
            count: ::core::clone::Clone::clone(&self.count),
            value: ::core::clone::Clone::clone(&self.value),
        }
    }
}Clone, #[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for WithIntCount<T> { }Copy, #[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for WithIntCount<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "WithIntCount",
            "count", &self.count, "value", &&self.value)
    }
}Debug, #[automatically_derived]
impl<T: ::core::default::Default> ::core::default::Default for WithIntCount<T>
    {
    #[inline]
    fn default() -> WithIntCount<T> {
        WithIntCount {
            count: ::core::default::Default::default(),
            value: ::core::default::Default::default(),
        }
    }
}Default)]
490pub(crate) struct WithIntCount<T> {
491    /// number of big-digits in value to treat as integer
492    count: i32,
493    /// Slice of bigdigits
494    value: T,
495}
496
497#[cfg(test)]
498#[allow(clippy::zero_prefixed_literal)]
499mod test {
500    use super::*;
501
502    include!("alignment.tests.rs");
503}