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    pub fn new(iter: I) -> Self {
112        Self::from_shifter_and_iter(ShiftState::Zero, iter)
113    }
114
115    pub fn from_shifter_and_iter(shifter: ShiftState<R>, iter: I) -> Self {
116        Self {
117            shift: shifter,
118            digits: iter,
119        }
120    }
121
122    /// Return the internal 'mask' value
123    pub fn mask(&self) -> R::Base {
124        match self.shift {
125            ShiftState::Zero => Zero::zero(),
126            ShiftState::Shifted {
127                mask:
128                    BigDigitSplitter {
129                        mask,
130                        ..
131                    },
132                ..
133            } => mask,
134        }
135    }
136
137    /// Returns the value of the 'shift' with one subtracted
138    ///
139    /// Useful for adding nines to first result of `from_slice_starting_bottom`
140    ///
141    pub fn shift_minus_one(&self) -> R::Base {
142        match self {
143            BigDigitSplitterIter {
144                shift: ShiftState::Zero,
145                ..
146            } => R::max(),
147            BigDigitSplitterIter {
148                shift:
149                    ShiftState::Shifted {
150                        mask,
151                        ..
152                    },
153                ..
154            } => mask.shift - One::one(),
155        }
156    }
157
158    /// Copy all remaining digits into destination vector
159    pub fn extend_vector(self, dest: &mut BigDigitVec<R>) {
160        if let Self {
161            shift: ShiftState::Zero,
162            digits,
163            ..
164        } = self
165        {
166            dest.digits.extend(digits);
167        } else {
168            dest.digits.extend(self);
169        }
170    }
171
172    /// Copy all remaining digits into destination vector, adding carry
173    ///
174    /// Note: carry is not zeroed after being pushed into the vector
175    ///
176    pub(crate) fn extend_vector_adding_carry(
177        mut self,
178        mut carry: R::Base,
179        dest: &mut BigDigitVec<R>,
180    ) {
181        while !carry.is_zero() {
182            if let Some(mut next_digit) = self.next() {
183                R::addassign_carry(&mut next_digit, &mut carry);
184                dest.push_significant_digit(next_digit);
185            } else {
186                dest.push_significant_digit(carry);
187                return;
188            }
189        }
190        self.extend_vector(dest)
191    }
192
193    /// Extend vector with digits in self, adding carry and subtracting borrow
194    pub(crate) fn extend_vector_with_carry_borrow(
195        mut self,
196        carry: &mut R::Base,
197        borrow: &mut R::Base,
198        dest: &mut BigDigitVec<R>,
199    ) {
200        use num_traits::WrappingSub;
201
202        if borrow.is_zero() && carry.is_zero() {
203            return self.extend_vector(dest);
204        }
205
206        // the two cancel
207        if carry == borrow {
208            *borrow = Zero::zero();
209            *carry = Zero::zero();
210            return self.extend_vector(dest);
211        }
212
213        match self.next() {
214            Some(digit) => {
215                let d = R::sub_with_carry_borrow(digit, R::Base::zero(), carry, borrow);
216                dest.push_significant_digit(d);
217                // TODO: is there a cost to recursion?
218                self.extend_vector_with_carry_borrow(borrow, carry, dest);
219            }
220            None if carry == borrow => {}
221            None if carry > borrow => {
222                dest.push_significant_digit(carry.wrapping_sub(borrow));
223                *carry = Zero::zero();
224                *borrow = Zero::zero();
225            }
226            None => {
227                { ::core::panicking::unreachable_display(&"borrow underflow"); };unreachable!("borrow underflow");
228            }
229        }
230    }
231
232    /// skip n digits
233    pub fn advance_by_n(&mut self, n: usize) {
234        // naive loop implementation
235        for _ in 0..n {
236            if self.next().is_none() {
237                break;
238            }
239        }
240    }
241    fn on_next_digit(&mut self, digit: R::Base) -> R::Base {
242        if let ShiftState::Shifted {
243            ref mut prev,
244            ref mask,
245        } = self.shift
246        {
247            let (hi, mut lo) = mask.split_and_shift(digit);
248            lo += *prev;
249            *prev = hi;
250            lo
251        } else {
252            digit
253        }
254    }
255
256    fn on_last_digit(&mut self) -> Option<R::Base> {
257        match self.shift {
258            ShiftState::Shifted {
259                ref mut prev,
260                ..
261            } if !prev.is_zero() => {
262                let result = *prev;
263                *prev = Zero::zero();
264                Some(result)
265            }
266            _ => None,
267        }
268    }
269}
270
271impl<R, I> Iterator for BigDigitSplitterIter<R, I>
272where
273    R: RadixPowerOfTen,
274    I: Iterator<Item = R::Base>,
275{
276    type Item = R::Base;
277
278    fn next(&mut self) -> Option<Self::Item> {
279        self.digits
280            .next()
281            .map(|digit| self.on_next_digit(digit))
282            .or_else(|| self.on_last_digit())
283    }
284}
285
286type CopiedDigitSlice<'a, R> =
287    stdlib::iter::Copied<stdlib::slice::Iter<'a, <R as super::radix::RadixType>::Base>>;
288pub(crate) type BigDigitSliceSplitterIter<'a, R> = BigDigitSplitterIter<R, CopiedDigitSlice<'a, R>>;
289
290impl<'a, R: RadixPowerOfTen> BigDigitSliceSplitterIter<'a, R> {
291    /// Return the complimentary size to 'n'
292    fn comp_n(n: usize) -> usize {
293        if true {
    if !(n < R::DIGITS) {
        ::core::panicking::panic("assertion failed: n < R::DIGITS")
    };
};debug_assert!(n < R::DIGITS);
294        if n == 0 {
295            0
296        } else {
297            R::DIGITS - n
298        }
299    }
300
301    /// Build without shifting digits
302    pub fn from_slice(slice: &'a [R::Base]) -> Self {
303        Self {
304            shift: ShiftState::Zero,
305            digits: slice.iter().copied(),
306        }
307    }
308
309    /// Stream will behave as if adding n zeros to beginning of digits
310    ///
311    /// ```ignore
312    /// [987654321, ...] : n=3 => [654321000, xxxxxx987, ...]
313    /// ```
314    ///
315    pub(crate) fn from_slice_shifting_left(slice: &'a [R::Base], n: usize) -> Self {
316        Self::from_slice_starting_bottom(slice, Self::comp_n(n))
317    }
318
319    /// Stream will behave as if removing first n-digits from the slice
320    ///
321    /// ```ignore
322    /// [987654321, ...] : n=3 => [xxx987654, ...]
323    /// ```
324    ///
325    /// This is the second digit of `from_slice_starting_bottom`
326    ///
327    pub(crate) fn from_slice_shifting_right(slice: &'a [R::Base], n: usize) -> Self {
328        Self::from_slice_starting_top(slice, Self::comp_n(n))
329    }
330
331    /// First digit will be the bottom n digits shifted to top
332    ///
333    /// ```ignore
334    /// [987654321, ...] : n=3 => [321000000, xxx987654, ...]
335    /// ```
336    ///
337    pub(crate) fn from_slice_starting_bottom(slice: &'a [R::Base], n: usize) -> Self {
338        Self::from_shifter_and_iter(ShiftState::starting_with_bottom(n), slice.iter().copied())
339    }
340
341    /// First digit will be the highest n-digits shifted to bottom
342    ///
343    /// ```ignore
344    /// [987654321, ...] : n=3 => [xxxxxx987, ...]
345    /// ```
346    ///
347    /// This is the second digit of `from_slice_shifting_left`
348    /// The bottom digits will be lost.
349    ///
350    pub(crate) fn from_slice_starting_top(slice: &'a [R::Base], n: usize) -> Self {
351        let mut digits = slice.iter().copied();
352        let shifter = ShiftState::starting_with_top(n, &mut digits);
353        Self::from_shifter_and_iter(shifter, digits)
354    }
355
356    /// True if iterator has no more values
357    pub fn is_exhausted(&self) -> bool {
358        match self.shift {
359            ShiftState::Zero => self.digits.len() == 0,
360            _ => self.peek_next().is_none(),
361        }
362    }
363
364    /// Return the next bigdigit (if available) without advancing the internal value
365    pub fn peek_next(&self) -> Option<R::Base> {
366        self.clone().next()
367    }
368}
369
370/// Wrap shift-and-mask type with special-case for zero shift
371///
372#[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)]
373pub(crate) enum ShiftState<R: RadixPowerOfTen> {
374    Zero,
375    Shifted {
376        mask: BigDigitSplitter<R>,
377        prev: R::Base,
378    },
379}
380
381impl<R: RadixPowerOfTen> ShiftState<R> {
382    /// Start with the lower n digits of the first bigdigit, shifted up
383    ///
384    /// ```ignore
385    /// Self::starting_with_top([987654321, ...], 3) => [32100000, xxx987654, ...]
386    /// ```
387    /// 987654321, 3 =>
388    ///
389    fn starting_with_bottom(n: usize) -> Self {
390        if n == 0 {
391            Self::Zero
392        } else {
393            Self::Shifted {
394                mask: BigDigitSplitter::mask_low(n as u8),
395                prev: R::Base::zero(),
396            }
397        }
398    }
399
400    /// Start with high n digits of the first bigdigit
401    ///
402    /// ```ignore
403    /// Self::starting_with_top([987654321, ...], 3) => [xxxxxx987, ...]
404    /// ```
405    ///
406    fn starting_with_top<I: Iterator<Item = R::Base>>(n: usize, digits: &mut I) -> Self {
407        if n == 0 {
408            Self::Zero
409        } else {
410            let mask = BigDigitSplitter::mask_high(n);
411            let first_digit = digits.next().map(|d| d / mask.mask).unwrap_or(Zero::zero());
412            Self::Shifted {
413                mask: mask,
414                prev: first_digit,
415            }
416        }
417    }
418}
419
420/// Splits a bigdigit into pieces, used when aligning
421#[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)]
422pub(crate) struct BigDigitSplitter<R: RadixPowerOfTen> {
423    mask: R::Base,
424    shift: R::Base,
425}
426
427impl<R: RadixPowerOfTen> BigDigitSplitter<R> {
428    /// Build such that (X % mask) 'keeps' n digits of X
429    pub fn mask_low(n: u8) -> Self {
430        use crate::arithmetic::ten_to_the_t;
431
432        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);
433        let mask = ten_to_the_t(n);
434        let shift = ten_to_the_t(R::DIGITS as u8 - n);
435        Self {
436            shift,
437            mask,
438        }
439    }
440
441    /// Build such that (X / mask) 'keeps' n digits of X
442    pub fn mask_high(n: usize) -> Self {
443        Self::mask_low((R::DIGITS - n) as u8)
444    }
445
446    /// Split bigdigit into high and low digits
447    ///
448    /// BigDigitSplitter::mask_high(3).split(987654321) => (987000000, 000654321)
449    /// BigDigitSplitter::mask_low(3).split(987654321)  => (987654000, 000000321)
450    ///
451    pub fn split(&self, n: R::Base) -> (R::Base, R::Base) {
452        let lo = n % self.mask;
453        (n - lo, lo)
454    }
455
456    /// Split and shift such that the n "high" bits are on low
457    /// side of digit and low bits are at the high end
458    ///
459    /// BigDigitSplitter::mask_high(3).split_and_shift(987654321) => (000000987, 654321000)
460    /// BigDigitSplitter::mask_low(3).split_and_shift(987654321)  => (000987654, 321000000)
461    ///
462    pub fn split_and_shift(&self, n: R::Base) -> (R::Base, R::Base) {
463        let (hi, lo) = self.div_rem(n);
464        (hi, lo * self.shift)
465    }
466
467    pub fn div_rem(&self, n: R::Base) -> (R::Base, R::Base) {
468        n.div_rem(&self.mask)
469    }
470
471    pub fn div(&self, n: R::Base) -> R::Base {
472        n / self.mask
473    }
474}
475
476/// Wrap a container of bigidigts with a count of how
477/// many are integer
478///
479/// i.e. The digits are aligned with zero
480///
481#[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)]
482pub(crate) struct WithIntCount<T> {
483    /// number of big-digits in value to treat as integer
484    count: i32,
485    /// Slice of bigdigits
486    value: T,
487}
488
489#[cfg(test)]
490mod test {
491    use super::*;
492
493    include!("alignment.tests.rs");
494}