bigdecimal/bigdigit/
digitvec.rs

1//! Digit vectors (and slices) of arbitrary radix and endianness
2
3use crate::*;
4
5use stdlib::marker::PhantomData;
6use stdlib::num::NonZeroU64;
7
8use super::radix::*;
9use super::endian::*;
10
11use crate::rounding::NonDigitRoundingData;
12
13
14/// Vector of integers, interpreted as bigdigits in an integer
15///
16/// Value of the integer is defined by the radix and endianness
17/// type parameters.
18///
19#[derive(#[automatically_derived]
impl<R: ::core::clone::Clone + RadixType, E: ::core::clone::Clone +
    Endianness> ::core::clone::Clone for DigitVec<R, E> where
    R::Base: ::core::clone::Clone {
    #[inline]
    fn clone(&self) -> DigitVec<R, E> {
        DigitVec {
            digits: ::core::clone::Clone::clone(&self.digits),
            _radix: ::core::clone::Clone::clone(&self._radix),
            _endian: ::core::clone::Clone::clone(&self._endian),
        }
    }
}Clone, #[automatically_derived]
impl<R: ::core::default::Default + RadixType, E: ::core::default::Default +
    Endianness> ::core::default::Default for DigitVec<R, E> where
    R::Base: ::core::default::Default {
    #[inline]
    fn default() -> DigitVec<R, E> {
        DigitVec {
            digits: ::core::default::Default::default(),
            _radix: ::core::default::Default::default(),
            _endian: ::core::default::Default::default(),
        }
    }
}Default)]
20pub(crate) struct DigitVec<R: RadixType, E: Endianness> {
21    pub digits: Vec<R::Base>,
22    _radix: PhantomData<R>,
23    _endian: PhantomData<E>,
24}
25
26#[allow(dead_code)]
27impl<R: RadixType, E: Endianness> DigitVec<R, E> {
28    /// Create new vector
29    pub fn new() -> Self {
30        Self::from_vec(Vec::new())
31    }
32
33    /// Create new vector with capacity
34    pub fn with_capacity(n: usize) -> Self {
35        Self::from_vec(Vec::with_capacity(n))
36    }
37
38    /// construct from vector of digits
39    pub fn from_vec(v: Vec<R::Base>) -> Self {
40        if true {
    if !R::validate_digits(v.iter()) {
        { ::std::rt::panic_fmt(format_args!("{0:?}", v)); }
    };
};debug_assert!(R::validate_digits(v.iter()), "{:?}", v);
41        Self {
42            digits: v,
43            _radix: PhantomData {},
44            _endian: PhantomData {},
45        }
46    }
47
48    /// allocate with n bigdigits and fill with zeros
49    pub fn from_zero_count(n: usize) -> Self {
50        Self::from_vec(::alloc::vec::from_elem(Zero::zero(), n)vec![Zero::zero(); n])
51    }
52
53    /// Number of bigdigits in the vector
54    pub fn len(&self) -> usize {
55        self.digits.len()
56    }
57
58    /// Remove all bigdigits
59    pub fn clear(&mut self) {
60        self.digits.clear()
61    }
62
63    /// Resize inner vector, filling new values with zero
64    pub fn resize(&mut self, n: usize) {
65        self.digits.resize(n, Zero::zero())
66    }
67
68    /// Shrink inner vectory to new size
69    pub fn truncate(&mut self, n: usize) {
70        self.digits.truncate(n);
71    }
72
73    /// construct digitvec with u128
74    pub(crate) fn from_u128(n: u128) -> Self {
75        let mut v = Self::new();
76        v.fill_with_u128(n);
77        v
78    }
79
80    /// create vector of bigdigits from u128
81    pub(crate) fn fill_with_u128(&mut self, n: u128) {
82        E::fill_vec_with_u128::<R>(&mut self.digits, n);
83    }
84
85    /// Remove 'n' insignificant from the vector
86    ///
87    /// BigEndian vectors truncate. LittleEndian vectors shift and truncate, and
88    /// remove significant zeros to reduce potential copy space
89    ///
90    /// If 'n' is larger than the vector, the vector is cleared.
91    ///
92    pub fn remove_insignificant_digits(&mut self, n: usize) {
93        if n == 0 {
94            return;
95        }
96        E::remove_insignificant_digits(&mut self.digits, n)
97    }
98
99    /// Borrow inner vectory as immutable digit-slice
100    pub fn as_digit_slice(&self) -> DigitSlice<'_, R, E> {
101        DigitSlice::from_slice(&self.digits[..])
102    }
103
104    /// Return slice skipping first n bigdigits
105    pub fn as_digit_slice_at(&self, n: usize) -> DigitSlice<'_, R, E> {
106        DigitSlice::from_slice(&self.digits[n..])
107    }
108
109    /// Borrow inner vectory as mutable digit-slice
110    pub fn as_digit_slice_mut(&mut self) -> DigitSliceMut<'_, R, E> {
111        DigitSliceMut::from_slice(&mut self.digits[..])
112    }
113
114    /// Split slice at 'pos' least-significant digits
115    pub fn split_le_at(
116        &self,
117        pos: usize
118    ) -> (DigitSlice<'_, R, E>, DigitSlice<'_, R, E>) {
119        let (lo, hi) = E::split_least_significant(&self.digits[..], pos);
120        (DigitSlice::from_slice(lo), DigitSlice::from_slice(hi))
121    }
122
123    /// Split slice at 'pos' least-significant digits
124    pub fn split_le_at_mut(
125        &mut self,
126        pos: usize,
127    ) -> (DigitSliceMut<'_, R, E>, DigitSliceMut<'_, R, E>) {
128        let (lo, hi) = E::split_least_significant_mut(&mut self.digits[..], pos);
129        (DigitSliceMut::from_slice(lo), DigitSliceMut::from_slice(hi))
130    }
131
132    /// Return the number of significant zeros in vector
133    pub fn count_significant_zeros(&self) -> usize {
134        E::count_significant_zeros(self.digits.as_slice())
135    }
136
137    /// true if empty or all zeros
138    pub fn is_all_zeros(&self) -> bool {
139        self.digits.iter().all(|&d| d.is_zero())
140    }
141
142    /// Return self, ignoring any significant zeros
143    pub fn least_n_are_zero(&self, n: usize) -> bool {
144        self.iter_le().take(n).all(Zero::is_zero)
145    }
146
147    /// Convert to inner vector
148    pub fn into_vec(self) -> Vec<R::Base> {
149        self.digits
150    }
151
152    /// Add bigdigit into this vector, starting from index of least significance
153    ///
154    /// Any "overflow" is pushed to most significant end of the vector
155    ///
156    pub fn add_value(&mut self, n: R::Base) {
157        self.add_value_at(0, n);
158    }
159
160    /// Add bigdigit into this vector (idexing from least-significant digit)
161    ///
162    /// TODO: Should vector resize if index is larger than size of vector?
163    ///
164    pub fn add_value_at(&mut self, idx: usize, n: R::Base) {
165        if true {
    if !(idx <= self.digits.len()) {
        ::core::panicking::panic("assertion failed: idx <= self.digits.len()")
    };
};debug_assert!(idx <= self.digits.len());
166
167        if n.is_zero() {
168            return;
169        }
170
171        let overflow = self.as_digit_slice_mut().add_value_at(idx, n);
172        if !overflow.is_zero() {
173            self.push_significant_digit(overflow);
174        }
175    }
176
177    /// Add bigdigit to the significant end of the vec
178    pub fn push_significant_digit(&mut self, n: R::Base) {
179        E::push_significant_digit(&mut self.digits, n);
180    }
181
182    /// remove significant zeros
183    pub fn remove_leading_zeros(&mut self) {
184        E::strip_significant_zeros(&mut self.digits)
185    }
186
187    #[cfg(rustc_1_75)]
188    pub fn iter_le(&self) -> impl LeBigDigitIterator<'_, &R::Base> {
189        E::iter_slice(&self.digits[..])
190    }
191
192    #[cfg(not(rustc_1_75))]
193    pub fn iter_le(&self) -> LittleEndianBigDigitIter<'_, &R::Base> {
194        E::iter_slice(&self.digits[..])
195    }
196
197    #[cfg(rustc_1_75)]
198    pub fn iter_le_mut(&mut self) -> impl LeBigDigitIterator<'_, &mut R::Base> {
199        E::iter_slice_mut(&mut self.digits[..])
200    }
201
202    #[cfg(not(rustc_1_75))]
203    pub fn iter_le_mut(&mut self) -> LittleEndianBigDigitIter<'_, &mut R::Base> {
204        E::iter_slice_mut(&mut self.digits[..])
205    }
206}
207
208impl<R: RadixPowerOfTen, E: Endianness> DigitVec<R, E> {
209    pub fn count_decimal_digits(&self) -> usize {
210        self.as_digit_slice().count_decimal_digits()
211    }
212}
213
214#[allow(dead_code)]
215impl<R: RadixType> DigitVec<R, LittleEndian> {
216    /// allocate with n bigdigits and fill with zeros
217    pub fn remove_significant_digits(&mut self) {
218        if let Some(idx) = self.digits.iter().rposition(|d| !d.is_zero()) {
219            self.digits.truncate(idx);
220        }
221    }
222}
223
224#[allow(dead_code)]
225impl<R: RadixType> DigitVec<R, BigEndian> {
226    pub fn remove_significant_digits(&mut self) {
227        if let Some(idx) = self.digits.iter().position(|d| !d.is_zero()) {
228            self.digits.copy_within(idx.., 0);
229            self.digits.truncate(self.len() - idx);
230        }
231    }
232}
233
234#[allow(dead_code)]
235impl<E: Endianness> DigitVec<RADIX_u64, E> {
236    /// multiply this vector by 'n'
237    fn mulassign_u64(&mut self, n: u64) {
238        let mut carry = 0u64;
239        for digit in self.iter_le_mut() {
240            RADIX_u64::mulassign_add_carry(digit, n, &mut carry);
241        }
242        if !carry.is_zero() {
243            E::push_significant_digit(&mut self.digits, carry);
244        }
245    }
246}
247
248#[allow(dead_code)]
249impl DigitVec<RADIX_u64, LittleEndian> {
250    /// Convert to signed big integer
251    pub fn into_bigint(self, sign: Sign) -> BigInt {
252        BigInt::from_biguint(sign, self.into())
253    }
254
255    /// Construct vector from iterator of base-10^{19} bigdigits
256    #[allow(dead_code)]
257    pub fn from_10p19_digits<I: Iterator<Item = u64>>(mut digits: I) -> Self {
258        type R2p64 = RADIX_u64;
259        type R10p19 = RADIX_10p19_u64;
260
261        let mut v = <[_]>::into_vec(::alloc::boxed::box_new([digits.next().unwrap_or(0)]))vec![digits.next().unwrap_or(0)];
262
263        if let Some(d) = digits.next() {
264            let mut carry = 0;
265            R2p64::carrying_mul_add_inplace(
266                d, R10p19::RADIX as u64, &mut v[0], &mut carry
267            );
268            if carry != 0 {
269                v.push(carry);
270            }
271        }
272
273        let mut d = match digits.next() {
274            Some(d) => d,
275            None => {
276                return Self::from_vec(v);
277            }
278        };
279
280        let mut shifter = BigUint::from(R10p19::RADIX * R10p19::RADIX);
281
282        loop {
283            v.push(0);
284
285            if d != 0 {
286                let mut carry = 0;
287                let mut dest_digits = v.iter_mut();
288                let mut shifter_digits = shifter.iter_u64_digits();
289
290                loop {
291                    match (dest_digits.next(), shifter_digits.next()) {
292                        (Some(p), Some(s)) => {
293                            R2p64::carrying_mul_add_inplace(d, s, p, &mut carry);
294                        }
295                        (None, Some(mut s)) => {
296                            loop {
297                                let (hi, lo) = R2p64::fused_mul_add(s, d, carry);
298                                v.push(lo);
299                                carry = hi;
300                                s = match shifter_digits.next() {
301                                    None => break,
302                                    Some(x) => x,
303                                };
304                            }
305                            break;
306                        }
307                        (Some(p), None) if carry != 0 => {
308                            R2p64::addassign_carry(p, &mut carry);
309                        }
310                        _ => {
311                            break;
312                        }
313                    }
314                }
315                if !carry.is_zero() {
316                    v.push(carry);
317                }
318            }
319
320            d = match digits.next() {
321                Some(d) => d,
322                None => {
323                    let zero_idx = v.iter().rposition(|&d| d != 0).unwrap_or(0);
324                    v.truncate(zero_idx + 1);
325                    return Self::from_vec(v);
326                }
327            };
328
329            shifter *= R10p19::RADIX as u64;
330        }
331    }
332}
333
334impl From<&num_bigint::BigUint> for DigitVec<RADIX_u64, LittleEndian> {
335    fn from(n: &num_bigint::BigUint) -> Self {
336        Self::from_vec(n.iter_u64_digits().collect())
337    }
338}
339
340impl From<DigitVec<RADIX_u64, LittleEndian>> for num_bigint::BigUint {
341    fn from(v: DigitVec<RADIX_u64, LittleEndian>) -> Self {
342        // TODO: Can we do this conversion in place?
343        let mut digits = Vec::with_capacity(v.len() * 2);
344        for d in v.digits.into_iter() {
345            digits.push(d as u32);
346            digits.push((d >> 32) as u32);
347        }
348        Self::new(digits)
349    }
350}
351
352impl From<&DigitVec<RADIX_u64, LittleEndian>> for num_bigint::BigUint {
353    fn from(v: &DigitVec<RADIX_u64, LittleEndian>) -> Self {
354        let mut digits = Vec::with_capacity(v.len() * 2);
355        for &d in v.digits.iter() {
356            digits.push(d as u32);
357            digits.push((d >> 32) as u32);
358        }
359        Self::new(digits)
360    }
361}
362
363impl DigitVec<RADIX_10p19_u64, LittleEndian> {
364    /// Convert a num biguint into DigitVec, using tmp as scratchpad
365    pub(crate) fn from_biguint_using_tmp(
366        n: &num_bigint::BigUint,
367        tmp: &mut Vec<u64>,
368    ) -> Self {
369        tmp.clear();
370        tmp.extend(n.iter_u64_digits());
371        let result = Self::from_2p64le_vec(tmp);
372        // clear tmp so any residual digits are not accessible
373        tmp.clear();
374        result
375    }
376
377    /// remove the bottom 'n' digits in the vector, returning the highest
378    pub fn shift_n_digits_returning_high(&mut self, n: usize) -> u8 {
379        use bigdigit::alignment::BigDigitSplitter;
380        type Splitter = BigDigitSplitter<RADIX_10p19_u64>;
381
382        if n == 0 {
383            return 0;
384        }
385
386        let (bd_count, d_count) = n.div_rem(&19);
387
388        if d_count == 0 {
389            // insig is top digit on previous bigdigit
390            let ret = self.digits[bd_count - 1] / (RADIX_10p19_u64::RADIX as u64 / 10);
391            self.digits.copy_within(bd_count.., 0);
392            self.digits.truncate(self.len() - bd_count);
393            return ret as u8;
394        }
395
396        let mask = Splitter::mask_low(d_count as u8);
397        let (d0, insig) = mask.div_rem(self.digits[bd_count]);
398        let ret = mask.div(insig * 10) as u8;
399
400        let mut prev = d0;
401
402        let mut j = 0;
403
404        loop {
405            if let Some(&d) = self.digits.get(bd_count + 1 + j) {
406                let (hi, lo) = mask.split_and_shift(d);
407                self.digits[j] = lo + prev;
408                prev = hi;
409
410                j += 1;
411            } else {
412                if prev != 0 {
413                    self.digits[j] = prev;
414                    j += 1;
415                }
416                self.digits.truncate(j);
417                return ret;
418            }
419        }
420    }
421
422    /// Convert a base-2^64 DigitVec to 10^19 DigitVec
423    fn from_2p64le_vec(src: &mut Vec<u64>) -> Self {
424        type R = RADIX_10p19_u64;
425
426        let mut result: Vec<u64>;
427        match src.split_last() {
428            None => {
429                return Self::default();
430            }
431            Some((&top_digit, &[])) => {
432                let result = if top_digit < R::RADIX as u64 {
433                    <[_]>::into_vec(::alloc::boxed::box_new([top_digit]))vec![top_digit]
434                } else {
435                    let (hi, lo) = top_digit.div_rem(&(R::RADIX as u64));
436                    <[_]>::into_vec(::alloc::boxed::box_new([lo, hi]))vec![lo, hi]
437                };
438                return Self::from_vec(result);
439            }
440            Some((&top_digit, digits)) => {
441                let bit_count = (64 * digits.len()) + (64 - top_digit.leading_zeros() as usize);
442                let base2p64_bigdigit_count = (bit_count as f64) / (LOG2_10 * R::DIGITS as f64);
443                result = Vec::with_capacity(base2p64_bigdigit_count.ceil() as usize);
444            }
445        }
446        while let Some(pos) = src.iter().rposition(|&d| d != 0) {
447            src.truncate(pos + 1);
448            let rem: u64 = src.iter_mut().rev().fold(0, |acc, d| {
449                R::rotating_div_u64_radix(acc, d)
450            });
451            result.push(rem);
452        }
453        Self::from_vec(result)
454    }
455
456    /// Convert to a num BigInt with given sign
457    pub fn into_bigint(self, sign: Sign) -> BigInt {
458        let uint = self.into_biguint();
459        BigInt::from_biguint(sign, uint)
460    }
461
462    /// Convert to BigUint
463    pub fn into_biguint(self) -> BigUint {
464        use num_integer::div_rem;
465        let radix = <RADIX_10p19_u64 as RadixType>::RADIX;
466
467        let mut digits = self.digits.into_iter();
468        let d0 = digits.next().unwrap_or(0);
469        let mut result = BigUint::from(d0);
470
471        let n = match digits.next() {
472            None => {
473                return result;
474            }
475            Some(n) => n,
476        };
477
478        let mut scale = BigUint::from(radix);
479        result += n * &scale;
480
481        for digit in digits {
482            scale *= radix;
483            match digit {
484                0 => {}
485                1 => {
486                    result += &scale;
487                }
488                n => {
489                    result += n * &scale;
490                }
491            }
492        }
493        return result;
494    }
495}
496
497impl From<DigitVec<RADIX_u32, LittleEndian>> for num_bigint::BigUint {
498    fn from(v: DigitVec<RADIX_u32, LittleEndian>) -> Self {
499        Self::new(v.digits)
500    }
501}
502
503
504impl From<DigitVec<RADIX_10p19_u64, LittleEndian>> for num_bigint::BigUint {
505    fn from(v: DigitVec<RADIX_10p19_u64, LittleEndian>) -> Self {
506        type R = RADIX_10p19_u64;
507        let radix = R::RADIX as u64;
508        match v.digits.as_slice() {
509            &[] => {
510                Self::zero()
511            }
512            &[d] => {
513                Self::from(d)
514            }
515            &[d0, d1] => {
516                let mut result = Self::from(d1);
517                result *= radix;
518                result += d0;
519                return result;
520            }
521            _ => {
522                let mut shifter = Self::one();
523                let mut digits = v.digits.iter().rev();
524
525                let mut result: Self = digits.next().copied().unwrap().into();
526
527                for &d in digits {
528                    shifter *= radix;
529                    result *= &shifter;
530                    result += d;
531                }
532                result
533            }
534        }
535    }
536}
537
538impl From<DigitSlice<'_, RADIX_u64, LittleEndian>> for DigitVec<RADIX_10p19_u64, LittleEndian> {
539    fn from(v: DigitSlice<'_, RADIX_u64, LittleEndian>) -> Self {
540        let mut src = Vec::from(v.digits);
541        Self::from_2p64le_vec(&mut src)
542    }
543}
544
545impl From<DigitVec<RADIX_10p19_u64, LittleEndian>> for DigitVec<RADIX_u64, LittleEndian> {
546    fn from(mut src: DigitVec<RADIX_10p19_u64, LittleEndian>) -> Self {
547        type R2p64 = RADIX_u64;
548
549        let radix = RADIX_10p19_u64::RADIX as u64;
550
551        match src.digits.len() {
552            0 | 1 => {
553                Self::from_vec(src.digits)
554            }
555            2 => {
556                let (hi, lo) = R2p64::expanding_mul(src.digits[1], radix);
557                let (sum, overflow) = src.digits[0].overflowing_add(lo);
558                src.digits[0] = sum;
559                src.digits[1] = hi + u64::from(overflow);
560                if src.digits[1] == 0 {
561                    src.digits.truncate(1);
562                }
563                Self::from_vec(src.digits)
564            }
565            _ => {
566                let mut result = ::alloc::vec::from_elem(0, src.len())vec![0; src.len()];
567                result[0] = src.digits[0];
568
569                let mut scaler = BigInt::from(radix);
570                let mut base10_digits = src.digits.iter().skip(1);
571                let mut base10_digit = base10_digits.next().copied().unwrap_or(0);
572                loop {
573                    for (i, base2_digit) in scaler.iter_u64_digits().enumerate() {
574                        let (hi, lo) = R2p64::expanding_mul(base10_digit, base2_digit);
575                        let (sum, overflow) = result[i].overflowing_add(lo);
576                        result[i] = sum;
577                        let mut j = i + 1;
578                        let (sum, overflow) = result[j].overflowing_add(hi + u64::from(overflow));
579                        result[j] = sum;
580                        let mut carry = u64::from(overflow);
581                        while carry != 0 {
582                            j += 1;
583                            let (sum, overflow) = result[j].overflowing_add(carry);
584                            result[j] = sum;
585                            carry = u64::from(overflow);
586                        }
587                    }
588
589                    match base10_digits.next() {
590                        None => break,
591                        Some(&d) => base10_digit = d,
592                    }
593                    scaler *= radix;
594                }
595                Self::from_vec(result)
596            }
597        }
598    }
599}
600
601/// Convert BigUint to base-10 digits
602impl From<&num_bigint::BigUint> for DigitVec<RADIX_10_u8, LittleEndian> {
603    fn from(n: &num_bigint::BigUint) -> Self {
604        Self::from_vec(n.to_radix_le(10))
605    }
606}
607
608#[cfg(test)]
609mod test_from_biguint_using_tmp {
610    use super::*;
611    use crate::bigdigit::radix::RADIX_10p19_u64;
612
613    macro_rules! impl_case {
614        ($name:ident: $input:literal => $result:expr) => {
615            #[test]
616            fn $name() {
617                let n: BigUint = $input.parse().unwrap();
618
619                let mut tmp = Vec::new();
620                let vec = DigitVec::from_biguint_using_tmp(&n, &mut tmp);
621                let expected: &[u64] = &$result;
622                assert_eq!(vec.digits.as_slice(), expected);
623            }
624        };
625    }
626
627    impl_case!(test_zero: "0" => []);
628    impl_case!(test_3888089293362626678: "3888089293362626678" => [3888089293362626678]);
629    impl_case!(test_10000000000000000000: "10000000000000000000" => [0, 1]);
630    impl_case!(test_141905914:
631        "1419059141115374799211309048234647259918822773497033524702964376392264024748829821875106774"
632        => [
633            4748829821875106774,
634            2470296437639226402,
635            2599188227734970335,
636            4799211309048234647,
637                141905914111537,
638        ]);
639}
640
641/// Vector of base-10 digits
642#[allow(dead_code)]
643impl DigitVec<RADIX_10_u8, LittleEndian> {
644    /// splits digits into `prec` significant digits, returning the lowest significant digit,
645    /// highest insignificant digit, and the remaining insignificant digits in little endian order
646    ///
647    pub fn get_rounding_digits_at_prec(
648        &self,
649        prec: NonZeroU64,
650    ) -> (u8, u8, DigitSlice<'_, RADIX_10_u8, LittleEndian>) {
651        let trimmed = self.digits.len().saturating_sub(prec.get() as usize);
652        if trimmed == 0 {
653            return (0, 0, DigitSlice::from_slice(&[]));
654        }
655
656        let (insig_digits, sig_digits) = self.digits.split_at(trimmed);
657        if true {
    match (&trimmed, &insig_digits.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(trimmed, insig_digits.len());
658        let (insig_digit, trailing_digits) = insig_digits.split_last().unwrap_or((&0, &[]));
659        (sig_digits[0], *insig_digit, DigitSlice::from_slice(trailing_digits))
660    }
661
662    /// Round the digits in this vec, returning slice of the digits
663    ///
664    /// Note: this changes the value of 'self', and should be considered as
665    /// just a buffer of bytes after rounding in place.
666    ///
667    pub fn round_at_prec_inplace(
668        &mut self,
669        prec: NonZeroU64,
670        rounding: NonDigitRoundingData,
671    ) -> (DigitSlice<'_, RADIX_10_u8, LittleEndian>, usize) {
672        // count number of insignificant digits to remove
673        let mut trimmed = self.digits.len().saturating_sub(prec.get() as usize);
674        if trimmed == 0 {
675            return (DigitSlice::from_slice(&self.digits), 0);
676        }
677
678        let (insig_digits, sig_digits) = self.digits.split_at_mut(trimmed);
679        if true {
    match (&trimmed, &insig_digits.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(trimmed, insig_digits.len());
680
681        let (&insig_digit, insig_digits) = insig_digits.split_last().unwrap_or((&0, &[]));
682        let trailing_zeros = insig_digits.iter().all(|&d| d == 0);
683        let round = rounding.round_pair((sig_digits[0], insig_digit), trailing_zeros);
684
685        if round != 10 {
686            sig_digits[0] = round;
687        } else {
688            match sig_digits.iter().position(|&d| d != 9) {
689                Some(idx) => {
690                    sig_digits[idx] += 1;
691                    fill_slice_with_zero(&mut sig_digits[..idx]);
692                }
693                None => {
694                    fill_slice_with_zero(sig_digits);
695                    *sig_digits.last_mut().unwrap() = 1;
696                    trimmed += 1;
697                }
698            }
699        }
700
701        if true {
    match (&(prec.get() as usize), &sig_digits.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(prec.get() as usize, sig_digits.len());
702        return (DigitSlice::from_slice(sig_digits), trimmed);
703    }
704}
705
706#[cfg(rustc_1_50)]
707#[allow(clippy::incompatible_msrv)]
708#[allow(dead_code)]
709fn fill_slice_with_zero<D: Zero + Clone>(s: &mut [D]) {
710    s.fill(Zero::zero());
711}
712
713#[cfg(not(rustc_1_50))]
714#[allow(dead_code)]
715fn fill_slice_with_zero<D: Zero + Clone>(s: &mut [D]) {
716    for r in s.iter_mut() {
717        *r = Zero::zero();
718    }
719}
720
721
722/// Immutable slice of digits
723///
724/// Operations on the bigdigit values are defined by the
725/// radix and endianness traits.
726///
727#[derive(#[automatically_derived]
impl<'a, R: ::core::clone::Clone + RadixType, E: ::core::clone::Clone +
    Endianness> ::core::clone::Clone for DigitSlice<'a, R, E> where
    R::Base: ::core::clone::Clone {
    #[inline]
    fn clone(&self) -> DigitSlice<'a, R, E> {
        DigitSlice {
            digits: ::core::clone::Clone::clone(&self.digits),
            _radix: ::core::clone::Clone::clone(&self._radix),
            _endian: ::core::clone::Clone::clone(&self._endian),
        }
    }
}Clone, #[automatically_derived]
impl<'a, R: ::core::marker::Copy + RadixType, E: ::core::marker::Copy +
    Endianness> ::core::marker::Copy for DigitSlice<'a, R, E> where
    R::Base: ::core::marker::Copy {
}Copy)]
728pub(crate) struct DigitSlice<'a, R: RadixType, E: Endianness> {
729    pub digits: &'a [R::Base],
730    _radix: PhantomData<R>,
731    _endian: PhantomData<E>,
732}
733
734#[allow(dead_code)]
735impl<'a, R: RadixType, E: Endianness> DigitSlice<'a, R, E> {
736    /// Wrap slice of numbers as a slice of big-digits with given radix
737    /// and endianness
738    ///
739    /// This does no validation, so the digits may be outside the bounds
740    /// of the radix and may have leading significant zeros.
741    ///
742    pub fn from_slice(d: &'a [R::Base]) -> Self {
743        Self {
744            digits: d,
745            _radix: PhantomData {},
746            _endian: PhantomData {},
747        }
748    }
749
750    /// Wrap slice of numbers, ignoring significant zeros
751    pub fn from_sig_slice(d: &'a [R::Base]) -> Self {
752        let (nonzero, _) = E::split_significant_zeros(d);
753        Self::from_slice(nonzero)
754    }
755
756    /// Number of bigdigits in slice
757    pub fn len(&self) -> usize {
758        self.digits.len()
759    }
760
761    /// Return self, ignoring any significant zeros
762    pub fn without_leading_zeros(&self) -> Self {
763        let (digits, _) = E::split_significant_zeros(self.digits);
764        Self::from_slice(digits)
765    }
766
767    /// Split splice into 'pos' least-significant bigdigits, and remaining
768    pub fn split_le_at(&'a self, pos: usize) -> (Self, Self) {
769        let (lo, hi) = E::split_least_significant(self.digits, pos);
770        (Self::from_slice(lo), Self::from_slice(hi))
771    }
772
773    /// Return the number of significant zeros
774    pub fn count_significant_zeros(&self) -> usize {
775        E::count_significant_zeros(self.digits)
776    }
777
778    /// true if empty or all zeros
779    pub fn is_all_zeros(&self) -> bool {
780        self.digits.iter().all(|&d| d.is_zero())
781    }
782
783    /// Return self, ignoring any significant zeros
784    pub fn least_n_are_zero(&self, n: usize) -> bool {
785        self.iter_le().take(n).all(Zero::is_zero)
786    }
787
788    #[cfg(rustc_1_75)]
789    pub fn iter_le(&self) -> impl LeBigDigitIterator<'_, &R::Base> {
790        E::iter_slice(self.digits)
791    }
792
793    #[cfg(not(rustc_1_75))]
794    pub fn iter_le(&self) -> LittleEndianBigDigitIter<'_, &R::Base> {
795        E::iter_slice(self.digits)
796    }
797}
798
799#[allow(dead_code)]
800impl<R: RadixType> DigitSlice<'_, R, LittleEndian> {
801    /// Return subslice of digits with the 'n' least significant bigdigits removed
802    pub fn trim_insignificant(&self, n: usize) -> Self {
803        Self::from_slice(&self.digits[n..])
804    }
805
806    pub fn find_least_significant_nonzero(&self) -> Option<usize> {
807        self.digits.iter().position(|&d| !d.is_zero())
808    }
809}
810
811#[allow(dead_code)]
812impl<'a, E: Endianness> From<&'a DigitVec<RADIX_u64, E>> for DigitSlice<'a, RADIX_u64, E> {
813    fn from(v: &'a DigitVec<RADIX_u64, E>) -> Self {
814        v.as_digit_slice()
815    }
816}
817
818impl<'a, R: RadixPowerOfTen, E: Endianness> DigitSlice<'a, R, E> {
819    pub fn count_decimal_digits(&self) -> usize {
820        use crate::arithmetic::decimal::count_digits_u64;
821
822        let (top_digit, trailing) = E::split_most_significant_digit(self.digits);
823        R::DIGITS * trailing.len()
824            + count_digits_u64(top_digit.to_u64().unwrap())
825    }
826}
827
828impl DigitSlice<'_, RADIX_10_u8, LittleEndian> {
829    /// fill digitvec with value contained in this digit-slice
830    #[allow(dead_code)]
831    pub fn fill_vec_u64(&self, dest: &mut DigitVec<RADIX_u64, LittleEndian>) {
832        let n = num_bigint::BigUint::from_radix_le(self.digits, 10).unwrap();
833        *dest = (&n).into();
834    }
835}
836
837/// Mutable slice of bigdigit values
838pub(crate) struct DigitSliceMut<'a, R: RadixType, E: Endianness> {
839    pub digits: &'a mut [R::Base],
840    _radix: PhantomData<R>,
841    _endian: PhantomData<E>,
842}
843
844#[allow(dead_code)]
845impl<'a, R: RadixType, E: Endianness> DigitSliceMut<'a, R, E> {
846    /// Construct from mutable slice of numbers
847    pub fn from_slice(v: &'a mut [R::Base]) -> Self {
848        Self {
849            digits: v,
850            _radix: PhantomData {},
851            _endian: PhantomData {},
852        }
853    }
854
855    /// Number of bigdigits in slice
856    pub fn len(&self) -> usize {
857        self.digits.len()
858    }
859
860    /// From digitvec, offset from the true index (independent of endianness)
861    pub fn from_vec_offset(v: &'a mut DigitVec<R, E>, offset: usize) -> Self {
862        Self::from_slice(&mut v.digits[offset..])
863    }
864
865    /// Cast to immutable slice
866    pub fn as_digit_slice(&'a self) -> DigitSlice<'a, R, E> {
867        DigitSlice::from_slice(self.digits)
868    }
869
870    /// Split, returning 'pos' little-endian
871    pub fn split_le_at(&'a self, pos: usize) -> (DigitSlice<'a, R, E>, DigitSlice<'a, R, E>) {
872        let (lo, hi) = E::split_least_significant(&self.digits[..], pos);
873        (DigitSlice::from_slice(lo), DigitSlice::from_slice(hi))
874    }
875
876    /// Split, returning 'pos' little-endian
877    pub fn split_le_at_mut(&'a mut self, pos: usize) -> (Self, Self) {
878        let (lo, hi) = E::split_least_significant_mut(self.digits, pos);
879        (Self::from_slice(lo), Self::from_slice(hi))
880    }
881
882    /// Add bigdigit 'n' into this slice, returning overflow
883    pub fn add_value_at(&mut self, idx: usize, mut n: R::Base) -> R::Base {
884        if n.is_zero() {
885            return n;
886        }
887        E::addassign_carry_into_slice_at::<R>(self.digits, &mut n, idx);
888        n
889    }
890
891    /// Add bigdigit into vector, storing overflow back in c
892    pub fn addassign_carry(&mut self, c: &mut R::Base) {
893        E::addassign_carry_into_slice_at::<R>(self.digits, c, 0);
894    }
895
896    #[cfg(rustc_1_75)]
897    pub fn iter_le(&self) -> impl LeBigDigitIterator<'_, &R::Base> {
898        E::iter_slice(self.digits)
899    }
900
901    #[cfg(not(rustc_1_75))]
902    pub fn iter_le(&self) -> LittleEndianBigDigitIter<'_, &R::Base> {
903        E::iter_slice(self.digits)
904    }
905
906    #[cfg(rustc_1_75)]
907    pub fn iter_le_mut(&mut self) -> impl LeBigDigitIterator<'_, &mut R::Base> {
908        E::iter_slice_mut(self.digits)
909    }
910
911    #[cfg(not(rustc_1_75))]
912    pub fn iter_le_mut(&mut self) -> LittleEndianBigDigitIter<'_, &mut R::Base> {
913        E::iter_slice_mut(self.digits)
914    }
915}
916
917#[allow(dead_code)]
918impl<R: RadixPowerOfTen, E: Endianness> DigitSliceMut<'_, R, E> {
919    pub fn count_decimal_digits(&self) -> usize {
920        self.as_digit_slice().count_decimal_digits()
921    }
922}
923
924
925impl<'a, R: RadixType, E: Endianness> From<&'a mut Vec<R::Base>> for DigitSliceMut<'a, R, E> {
926    fn from(digits: &'a mut Vec<R::Base>) -> Self {
927        Self::from_slice(&mut digits[..])
928    }
929}
930
931impl<R: RadixType, E: Endianness> fmt::Debug for DigitVec<R, E> {
932    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
933        f.write_fmt(format_args!("DigitVec({0}, {1:?})", E::NAME, self.digits))write!(f, "DigitVec({}, {:?})", E::NAME, self.digits)
934    }
935}
936
937impl<R: RadixType, E: Endianness> fmt::Debug for DigitSlice<'_, R, E> {
938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
939        f.write_fmt(format_args!("DigitSlice({0}, {1:?})", E::NAME, self.digits))write!(f, "DigitSlice({}, {:?})", E::NAME, self.digits)
940    }
941}
942
943impl<R: RadixType, E: Endianness> fmt::Debug for DigitSliceMut<'_, R, E> {
944    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
945        f.write_fmt(format_args!("DigitSliceMut({0}, {1:?})", E::NAME, self.digits))write!(f, "DigitSliceMut({}, {:?})", E::NAME, self.digits)
946    }
947}
948
949/// Add method to easily transform scaled DigitVec to scaled DigitSlice
950impl<R: RadixType, E: Endianness> crate::WithScale<DigitVec<R, E>> {
951    pub fn as_digit_slice(&self) -> crate::WithScale<DigitSlice<'_, R, E>> {
952        WithScale {
953            scale: self.scale,
954            value: self.value.as_digit_slice(),
955        }
956    }
957}