1use super::large_powers;
10use super::num::*;
11use super::small_powers::*;
12use alloc::vec::Vec;
13use core::{cmp, iter, mem};
14
15#[cfg(fast_arithmetic = "32")]
41pub type Limb = u32;
42
43#[cfg(fast_arithmetic = "32")]
44pub const POW5_LIMB: &[Limb] = &POW5_32;
45
46#[cfg(fast_arithmetic = "32")]
47pub const POW10_LIMB: &[Limb] = &POW10_32;
48
49#[cfg(fast_arithmetic = "32")]
50type Wide = u64;
51
52#[cfg(fast_arithmetic = "64")]
54pub type Limb = u64;
55
56#[cfg(fast_arithmetic = "64")]
57pub const POW5_LIMB: &[Limb] = &POW5_64;
58
59#[cfg(fast_arithmetic = "64")]
60pub const POW10_LIMB: &[Limb] = &POW10_64;
61
62#[cfg(fast_arithmetic = "64")]
63type Wide = u128;
64
65#[inline]
67pub(crate) fn as_limb<T: Integer>(t: T) -> Limb {
68 Limb::as_cast(t)
69}
70
71#[inline]
73fn as_wide<T: Integer>(t: T) -> Wide {
74 Wide::as_cast(t)
75}
76
77#[inline]
82#[cfg(fast_arithmetic = "32")]
83fn split_u64(x: u64) -> [Limb; 2] {
84 [as_limb(x), as_limb(x >> 32)]
85}
86
87#[inline]
89#[cfg(fast_arithmetic = "64")]
90fn split_u64(x: u64) -> [Limb; 1] {
91 [as_limb(x)]
92}
93
94#[inline]
101pub fn nonzero<T: Integer>(x: &[T], rindex: usize) -> bool {
102 let len = x.len();
103 let slc = &x[..len - rindex];
104 slc.iter().rev().any(|&x| x != T::ZERO)
105}
106
107#[inline]
109fn u64_to_hi64_1(r0: u64) -> (u64, bool) {
110 if true {
if !(r0 != 0) { ::core::panicking::panic("assertion failed: r0 != 0") };
};debug_assert!(r0 != 0);
111 let ls = r0.leading_zeros();
112 (r0 << ls, false)
113}
114
115#[inline]
117fn u64_to_hi64_2(r0: u64, r1: u64) -> (u64, bool) {
118 if true {
if !(r0 != 0) { ::core::panicking::panic("assertion failed: r0 != 0") };
};debug_assert!(r0 != 0);
119 let ls = r0.leading_zeros();
120 let rs = 64 - ls;
121 let v = match ls {
122 0 => r0,
123 _ => (r0 << ls) | (r1 >> rs),
124 };
125 let n = r1 << ls != 0;
126 (v, n)
127}
128
129trait Hi64<T>: AsRef<[T]> {
131 fn hi64_1(&self) -> (u64, bool);
133
134 fn hi64_2(&self) -> (u64, bool);
136
137 fn hi64_3(&self) -> (u64, bool);
139
140 #[inline]
142 fn hi64(&self) -> (u64, bool) {
143 match self.as_ref().len() {
144 0 => (0, false),
145 1 => self.hi64_1(),
146 2 => self.hi64_2(),
147 _ => self.hi64_3(),
148 }
149 }
150}
151
152impl Hi64<u32> for [u32] {
153 #[inline]
154 fn hi64_1(&self) -> (u64, bool) {
155 if true {
{
match (&self.len(), &1) {
(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!(self.len(), 1);
156 let r0 = self[0] as u64;
157 u64_to_hi64_1(r0)
158 }
159
160 #[inline]
161 fn hi64_2(&self) -> (u64, bool) {
162 if true {
{
match (&self.len(), &2) {
(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!(self.len(), 2);
163 let r0 = (self[1] as u64) << 32;
164 let r1 = self[0] as u64;
165 u64_to_hi64_1(r0 | r1)
166 }
167
168 #[inline]
169 fn hi64_3(&self) -> (u64, bool) {
170 if true {
if !(self.len() >= 3) {
::core::panicking::panic("assertion failed: self.len() >= 3")
};
};debug_assert!(self.len() >= 3);
171 let r0 = self[self.len() - 1] as u64;
172 let r1 = (self[self.len() - 2] as u64) << 32;
173 let r2 = self[self.len() - 3] as u64;
174 let (v, n) = u64_to_hi64_2(r0, r1 | r2);
175 (v, n || nonzero(self, 3))
176 }
177}
178
179impl Hi64<u64> for [u64] {
180 #[inline]
181 fn hi64_1(&self) -> (u64, bool) {
182 if true {
{
match (&self.len(), &1) {
(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!(self.len(), 1);
183 let r0 = self[0];
184 u64_to_hi64_1(r0)
185 }
186
187 #[inline]
188 fn hi64_2(&self) -> (u64, bool) {
189 if true {
if !(self.len() >= 2) {
::core::panicking::panic("assertion failed: self.len() >= 2")
};
};debug_assert!(self.len() >= 2);
190 let r0 = self[self.len() - 1];
191 let r1 = self[self.len() - 2];
192 let (v, n) = u64_to_hi64_2(r0, r1);
193 (v, n || nonzero(self, 2))
194 }
195
196 #[inline]
197 fn hi64_3(&self) -> (u64, bool) {
198 self.hi64_2()
199 }
200}
201
202mod scalar {
209 use super::*;
210
211 #[inline]
215 pub fn add(x: Limb, y: Limb) -> (Limb, bool) {
216 x.overflowing_add(y)
217 }
218
219 #[inline]
221 pub fn iadd(x: &mut Limb, y: Limb) -> bool {
222 let t = add(*x, y);
223 *x = t.0;
224 t.1
225 }
226
227 #[inline]
231 pub fn sub(x: Limb, y: Limb) -> (Limb, bool) {
232 x.overflowing_sub(y)
233 }
234
235 #[inline]
237 pub fn isub(x: &mut Limb, y: Limb) -> bool {
238 let t = sub(*x, y);
239 *x = t.0;
240 t.1
241 }
242
243 #[inline]
249 pub fn mul(x: Limb, y: Limb, carry: Limb) -> (Limb, Limb) {
250 let z: Wide = as_wide(x) * as_wide(y) + as_wide(carry);
254 let bits = mem::size_of::<Limb>() * 8;
255 (as_limb(z), as_limb(z >> bits))
256 }
257
258 #[inline]
260 pub fn imul(x: &mut Limb, y: Limb, carry: Limb) -> Limb {
261 let t = mul(*x, y, carry);
262 *x = t.0;
263 t.1
264 }
265} mod small {
273 use super::*;
274
275 #[inline]
282 pub fn iadd_impl(x: &mut Vec<Limb>, y: Limb, xstart: usize) {
283 if x.len() <= xstart {
284 x.push(y);
285 } else {
286 let mut carry = scalar::iadd(&mut x[xstart], y);
288
289 let mut size = xstart + 1;
291 while carry && size < x.len() {
292 carry = scalar::iadd(&mut x[size], 1);
293 size += 1;
294 }
295
296 if carry {
299 x.push(1);
300 }
301 }
302 }
303
304 #[inline]
306 pub fn iadd(x: &mut Vec<Limb>, y: Limb) {
307 iadd_impl(x, y, 0);
308 }
309
310 #[inline]
315 pub fn isub_impl(x: &mut Vec<Limb>, y: Limb, xstart: usize) {
316 if true {
if !(x.len() > xstart && (x[xstart] >= y || x.len() > xstart + 1)) {
::core::panicking::panic("assertion failed: x.len() > xstart && (x[xstart] >= y || x.len() > xstart + 1)")
};
};debug_assert!(x.len() > xstart && (x[xstart] >= y || x.len() > xstart + 1));
317
318 let mut carry = scalar::isub(&mut x[xstart], y);
320
321 let mut size = xstart + 1;
323 while carry && size < x.len() {
324 carry = scalar::isub(&mut x[size], 1);
325 size += 1;
326 }
327 normalize(x);
328 }
329
330 #[inline]
334 pub fn imul(x: &mut Vec<Limb>, y: Limb) {
335 let mut carry: Limb = 0;
337 for xi in &mut *x {
338 carry = scalar::imul(xi, y, carry);
339 }
340
341 if carry != 0 {
343 x.push(carry);
344 }
345 }
346
347 #[inline]
349 pub fn mul(x: &[Limb], y: Limb) -> Vec<Limb> {
350 let mut z = Vec::<Limb>::default();
351 z.extend_from_slice(x);
352 imul(&mut z, y);
353 z
354 }
355
356 pub fn imul_pow5(x: &mut Vec<Limb>, n: u32) {
389 use super::large::KARATSUBA_CUTOFF;
390
391 let small_powers = POW5_LIMB;
392 let large_powers = large_powers::POW5;
393
394 if n == 0 {
395 return;
399 }
400
401 let bit_length = 32 - n.leading_zeros() as usize;
405 if true {
if !(bit_length != 0 && bit_length <= large_powers.len()) {
::core::panicking::panic("assertion failed: bit_length != 0 && bit_length <= large_powers.len()")
};
};debug_assert!(bit_length != 0 && bit_length <= large_powers.len());
406 if x.len() + large_powers[bit_length - 1].len() < 2 * KARATSUBA_CUTOFF {
407 let step = small_powers.len() - 1;
412 let power = small_powers[step];
413 let mut n = n as usize;
414 while n >= step {
415 imul(x, power);
416 n -= step;
417 }
418
419 imul(x, small_powers[n]);
421 } else {
422 let mut idx: usize = 0;
428 let mut bit: usize = 1;
429 let mut n = n as usize;
430 while n != 0 {
431 if n & bit != 0 {
432 if true {
if !(idx < large_powers.len()) {
::core::panicking::panic("assertion failed: idx < large_powers.len()")
};
};debug_assert!(idx < large_powers.len());
433 large::imul(x, large_powers[idx]);
434 n ^= bit;
435 }
436 idx += 1;
437 bit <<= 1;
438 }
439 }
440 }
441
442 #[inline]
446 pub fn leading_zeros(x: &[Limb]) -> usize {
447 x.last().map_or(0, |x| x.leading_zeros() as usize)
448 }
449
450 #[inline]
452 pub fn bit_length(x: &[Limb]) -> usize {
453 let bits = mem::size_of::<Limb>() * 8;
454 let nlz = leading_zeros(x);
457 bits.checked_mul(x.len())
458 .map_or_else(usize::max_value, |v| v - nlz)
459 }
460
461 #[inline]
467 pub fn ishl_bits(x: &mut Vec<Limb>, n: usize) {
468 let bits = mem::size_of::<Limb>() * 8;
470 if true {
if !(n < bits) { ::core::panicking::panic("assertion failed: n < bits") };
};debug_assert!(n < bits);
471 if n == 0 {
472 return;
473 }
474
475 let rshift = bits - n;
481 let lshift = n;
482 let mut prev: Limb = 0;
483 for xi in &mut *x {
484 let tmp = *xi;
485 *xi <<= lshift;
486 *xi |= prev >> rshift;
487 prev = tmp;
488 }
489
490 let carry = prev >> rshift;
492 if carry != 0 {
493 x.push(carry);
494 }
495 }
496
497 #[inline]
501 pub fn ishl_limbs(x: &mut Vec<Limb>, n: usize) {
502 if true {
if !(n != 0) { ::core::panicking::panic("assertion failed: n != 0") };
};debug_assert!(n != 0);
503 if !x.is_empty() {
504 x.reserve(n);
505 x.splice(..0, iter::repeat(0).take(n));
506 }
507 }
508
509 #[inline]
511 pub fn ishl(x: &mut Vec<Limb>, n: usize) {
512 let bits = mem::size_of::<Limb>() * 8;
513 let rem = n % bits;
516 let div = n / bits;
517 ishl_bits(x, rem);
518 if div != 0 {
519 ishl_limbs(x, div);
520 }
521 }
522
523 #[inline]
527 pub fn normalize(x: &mut Vec<Limb>) {
528 while x.last() == Some(&0) {
531 x.pop();
532 }
533 }
534} mod large {
542 use super::*;
543
544 #[inline]
548 pub fn compare(x: &[Limb], y: &[Limb]) -> cmp::Ordering {
549 if x.len() > y.len() {
550 cmp::Ordering::Greater
551 } else if x.len() < y.len() {
552 cmp::Ordering::Less
553 } else {
554 let iter = x.iter().rev().zip(y.iter().rev());
555 for (&xi, &yi) in iter {
556 if xi > yi {
557 return cmp::Ordering::Greater;
558 } else if xi < yi {
559 return cmp::Ordering::Less;
560 }
561 }
562 cmp::Ordering::Equal
564 }
565 }
566
567 #[inline]
569 pub fn less(x: &[Limb], y: &[Limb]) -> bool {
570 compare(x, y) == cmp::Ordering::Less
571 }
572
573 #[inline]
575 pub fn greater_equal(x: &[Limb], y: &[Limb]) -> bool {
576 !less(x, y)
577 }
578
579 pub fn iadd_impl(x: &mut Vec<Limb>, y: &[Limb], xstart: usize) {
586 if y.len() > x.len() - xstart {
590 x.resize(y.len() + xstart, 0);
591 }
592
593 let mut carry = false;
595 for (xi, yi) in x[xstart..].iter_mut().zip(y.iter()) {
596 let mut tmp = scalar::iadd(xi, *yi);
600 if carry {
601 tmp |= scalar::iadd(xi, 1);
602 }
603 carry = tmp;
604 }
605
606 if carry {
608 small::iadd_impl(x, 1, y.len() + xstart);
609 }
610 }
611
612 #[inline]
614 pub fn iadd(x: &mut Vec<Limb>, y: &[Limb]) {
615 iadd_impl(x, y, 0);
616 }
617
618 #[inline]
620 pub fn add(x: &[Limb], y: &[Limb]) -> Vec<Limb> {
621 let mut z = Vec::<Limb>::default();
622 z.extend_from_slice(x);
623 iadd(&mut z, y);
624 z
625 }
626
627 pub fn isub(x: &mut Vec<Limb>, y: &[Limb]) {
631 if true {
if !greater_equal(x, y) {
::core::panicking::panic("assertion failed: greater_equal(x, y)")
};
};debug_assert!(greater_equal(x, y));
633
634 let mut carry = false;
636 for (xi, yi) in x.iter_mut().zip(y.iter()) {
637 let mut tmp = scalar::isub(xi, *yi);
641 if carry {
642 tmp |= scalar::isub(xi, 1);
643 }
644 carry = tmp;
645 }
646
647 if carry {
648 small::isub_impl(x, 1, y.len());
649 } else {
650 small::normalize(x);
651 }
652 }
653
654 pub const KARATSUBA_CUTOFF: usize = 32;
662
663 fn long_mul(x: &[Limb], y: &[Limb]) -> Vec<Limb> {
671 let mut z: Vec<Limb> = small::mul(x, y[0]);
676 z.resize(x.len() + y.len(), 0);
677
678 for (i, &yi) in y[1..].iter().enumerate() {
680 let zi: Vec<Limb> = small::mul(x, yi);
681 iadd_impl(&mut z, &zi, i + 1);
682 }
683
684 small::normalize(&mut z);
685
686 z
687 }
688
689 #[inline]
691 pub fn karatsuba_split(z: &[Limb], m: usize) -> (&[Limb], &[Limb]) {
692 (&z[..m], &z[m..])
693 }
694
695 fn karatsuba_mul(x: &[Limb], y: &[Limb]) -> Vec<Limb> {
699 if y.len() <= KARATSUBA_CUTOFF {
700 long_mul(x, y)
702 } else if x.len() < y.len() / 2 {
703 karatsuba_uneven_mul(x, y)
704 } else {
705 let m = y.len() / 2;
707 let (xl, xh) = karatsuba_split(x, m);
708 let (yl, yh) = karatsuba_split(y, m);
709 let sumx = add(xl, xh);
710 let sumy = add(yl, yh);
711 let z0 = karatsuba_mul(xl, yl);
712 let mut z1 = karatsuba_mul(&sumx, &sumy);
713 let z2 = karatsuba_mul(xh, yh);
714 isub(&mut z1, &z2);
716 isub(&mut z1, &z0);
717
718 let len = z0.len().max(m + z1.len()).max(2 * m + z2.len());
723 let mut result = z0;
724 result.reserve_exact(len - result.len());
725 iadd_impl(&mut result, &z1, m);
726 iadd_impl(&mut result, &z2, 2 * m);
727
728 result
729 }
730 }
731
732 fn karatsuba_uneven_mul(x: &[Limb], mut y: &[Limb]) -> Vec<Limb> {
736 let mut result = Vec::<Limb>::default();
737 result.resize(x.len() + y.len(), 0);
738
739 let mut start = 0;
743 while !y.is_empty() {
744 let m = x.len().min(y.len());
745 let (yl, yh) = karatsuba_split(y, m);
746 let prod = karatsuba_mul(x, yl);
747 iadd_impl(&mut result, &prod, start);
748 y = yh;
749 start += m;
750 }
751 small::normalize(&mut result);
752
753 result
754 }
755
756 #[inline]
758 fn karatsuba_mul_fwd(x: &[Limb], y: &[Limb]) -> Vec<Limb> {
759 if x.len() < y.len() {
760 karatsuba_mul(x, y)
761 } else {
762 karatsuba_mul(y, x)
763 }
764 }
765
766 #[inline]
768 pub fn imul(x: &mut Vec<Limb>, y: &[Limb]) {
769 if y.len() == 1 {
770 small::imul(x, y[0]);
771 } else {
772 *x = karatsuba_mul_fwd(x, y);
777 }
778 }
779} pub(crate) trait Math: Clone + Sized + Default {
790 fn data(&self) -> &Vec<Limb>;
794
795 fn data_mut(&mut self) -> &mut Vec<Limb>;
797
798 #[inline]
802 fn compare(&self, y: &Self) -> cmp::Ordering {
803 large::compare(self.data(), y.data())
804 }
805
806 #[inline]
810 fn hi64(&self) -> (u64, bool) {
811 self.data().as_slice().hi64()
812 }
813
814 #[inline]
818 fn bit_length(&self) -> usize {
819 small::bit_length(self.data())
820 }
821
822 #[inline]
826 fn from_u64(x: u64) -> Self {
827 let mut v = Self::default();
828 let slc = split_u64(x);
829 v.data_mut().extend_from_slice(&slc);
830 v.normalize();
831 v
832 }
833
834 #[inline]
838 fn normalize(&mut self) {
839 small::normalize(self.data_mut());
840 }
841
842 #[inline]
846 fn iadd_small(&mut self, y: Limb) {
847 small::iadd(self.data_mut(), y);
848 }
849
850 #[inline]
854 fn imul_small(&mut self, y: Limb) {
855 small::imul(self.data_mut(), y);
856 }
857
858 #[inline]
860 fn imul_pow2(&mut self, n: u32) {
861 self.ishl(n as usize);
862 }
863
864 #[inline]
866 fn imul_pow5(&mut self, n: u32) {
867 small::imul_pow5(self.data_mut(), n);
868 }
869
870 #[inline]
872 fn imul_pow10(&mut self, n: u32) {
873 self.imul_pow5(n);
874 self.imul_pow2(n);
875 }
876
877 #[inline]
881 fn ishl(&mut self, n: usize) {
882 small::ishl(self.data_mut(), n);
883 }
884}