1#![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)]
15pub(crate) enum AddAssignSliceAlignment {
16 RightOverlap {
19 count: usize,
20 },
21 RightDisjoint {
25 count: usize,
26 },
27 LeftOverlap {
31 count: usize,
32 },
33 LeftDisjoint {
38 count: usize,
39 },
40}
41
42impl AddAssignSliceAlignment {
43 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 pub fn from_lengths_and_icount(lhs: WithIntCount<usize>, rhs: WithIntCount<usize>) -> Self {
82 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 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 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 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 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 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 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 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 pub fn advance_by_n(&mut self, n: usize) {
234 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 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 pub fn from_slice(slice: &'a [R::Base]) -> Self {
303 Self {
304 shift: ShiftState::Zero,
305 digits: slice.iter().copied(),
306 }
307 }
308
309 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 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 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 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 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 pub fn peek_next(&self) -> Option<R::Base> {
366 self.clone().next()
367 }
368}
369
370)]
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 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 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)]
422pub(crate) struct BigDigitSplitter<R: RadixPowerOfTen> {
423 mask: R::Base,
424 shift: R::Base,
425}
426
427impl<R: RadixPowerOfTen> BigDigitSplitter<R> {
428 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 pub fn mask_high(n: usize) -> Self {
443 Self::mask_low((R::DIGITS - n) as u8)
444 }
445
446 pub fn split(&self, n: R::Base) -> (R::Base, R::Base) {
452 let lo = n % self.mask;
453 (n - lo, lo)
454 }
455
456 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)]
482pub(crate) struct WithIntCount<T> {
483 count: i32,
485 value: T,
487}
488
489#[cfg(test)]
490mod test {
491 use super::*;
492
493 include!("alignment.tests.rs");
494}