1use std::borrow::Cow;
2use std::cmp;
3use std::cmp::Ordering::{self, Equal, Greater, Less};
4use std::iter::repeat;
5use std::mem;
6use traits;
7use traits::{One, Zero};
8
9use biguint::BigUint;
10
11use bigint::BigInt;
12use bigint::Sign;
13use bigint::Sign::{Minus, NoSign, Plus};
14
15use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit};
16
17#[inline]
21fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
22 *acc += DoubleBigDigit::from(a);
23 *acc += DoubleBigDigit::from(b);
24 let lo = *acc as BigDigit;
25 *acc >>= big_digit::BITS;
26 lo
27}
28
29#[inline]
31fn sbb(a: BigDigit, b: BigDigit, acc: &mut SignedDoubleBigDigit) -> BigDigit {
32 *acc += SignedDoubleBigDigit::from(a);
33 *acc -= SignedDoubleBigDigit::from(b);
34 let lo = *acc as BigDigit;
35 *acc >>= big_digit::BITS;
36 lo
37}
38
39#[inline]
40pub fn mac_with_carry(a: BigDigit, b: BigDigit, c: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
41 *acc += DoubleBigDigit::from(a);
42 *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c);
43 let lo = *acc as BigDigit;
44 *acc >>= big_digit::BITS;
45 lo
46}
47
48#[inline]
49pub fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
50 *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b);
51 let lo = *acc as BigDigit;
52 *acc >>= big_digit::BITS;
53 lo
54}
55
56#[inline]
63fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) {
64 debug_assert!(hi < divisor);
65
66 let lhs = big_digit::to_doublebigdigit(hi, lo);
67 let rhs = DoubleBigDigit::from(divisor);
68 ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit)
69}
70
71pub fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
72 let mut rem = 0;
73
74 for d in a.data.iter_mut().rev() {
75 let (q, r) = div_wide(rem, *d, b);
76 *d = q;
77 rem = r;
78 }
79
80 (a.normalized(), rem)
81}
82
83pub fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit {
84 let mut rem: DoubleBigDigit = 0;
85 for &digit in a.data.iter().rev() {
86 rem = (rem << big_digit::BITS) + DoubleBigDigit::from(digit);
87 rem %= DoubleBigDigit::from(b);
88 }
89
90 rem as BigDigit
91}
92
93#[inline]
95pub fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit {
96 debug_assert!(a.len() >= b.len());
97
98 let mut carry = 0;
99 let (a_lo, a_hi) = a.split_at_mut(b.len());
100
101 for (a, b) in a_lo.iter_mut().zip(b) {
102 *a = adc(*a, *b, &mut carry);
103 }
104
105 if carry != 0 {
106 for a in a_hi {
107 *a = adc(*a, 0, &mut carry);
108 if carry == 0 {
109 break;
110 }
111 }
112 }
113
114 carry as BigDigit
115}
116
117pub fn add2(a: &mut [BigDigit], b: &[BigDigit]) {
123 let carry = __add2(a, b);
124
125 debug_assert!(carry == 0);
126}
127
128pub fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
129 let mut borrow = 0;
130
131 let len = cmp::min(a.len(), b.len());
132 let (a_lo, a_hi) = a.split_at_mut(len);
133 let (b_lo, b_hi) = b.split_at(len);
134
135 for (a, b) in a_lo.iter_mut().zip(b_lo) {
136 *a = sbb(*a, *b, &mut borrow);
137 }
138
139 if borrow != 0 {
140 for a in a_hi {
141 *a = sbb(*a, 0, &mut borrow);
142 if borrow == 0 {
143 break;
144 }
145 }
146 }
147
148 assert!(
150 borrow == 0 && b_hi.iter().all(|x| *x == 0),
151 "Cannot subtract b from a because b is larger than a."
152 );
153}
154
155#[inline]
157pub fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit {
158 debug_assert!(b.len() == a.len());
159
160 let mut borrow = 0;
161
162 for (ai, bi) in a.iter().zip(b) {
163 *bi = sbb(*ai, *bi, &mut borrow);
164 }
165
166 borrow as BigDigit
167}
168
169pub fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) {
170 debug_assert!(b.len() >= a.len());
171
172 let len = cmp::min(a.len(), b.len());
173 let (a_lo, a_hi) = a.split_at(len);
174 let (b_lo, b_hi) = b.split_at_mut(len);
175
176 let borrow = __sub2rev(a_lo, b_lo);
177
178 assert!(a_hi.is_empty());
179
180 assert!(
182 borrow == 0 && b_hi.iter().all(|x| *x == 0),
183 "Cannot subtract b from a because b is larger than a."
184 );
185}
186
187pub fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) {
188 let a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
190 let b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
191
192 match cmp_slice(a, b) {
193 Greater => {
194 let mut a = a.to_vec();
195 sub2(&mut a, b);
196 (Plus, BigUint::new(a))
197 }
198 Less => {
199 let mut b = b.to_vec();
200 sub2(&mut b, a);
201 (Minus, BigUint::new(b))
202 }
203 _ => (NoSign, Zero::zero()),
204 }
205}
206
207pub fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) {
210 if c == 0 {
211 return;
212 }
213
214 let mut carry = 0;
215 let (a_lo, a_hi) = acc.split_at_mut(b.len());
216
217 for (a, &b) in a_lo.iter_mut().zip(b) {
218 *a = mac_with_carry(*a, b, c, &mut carry);
219 }
220
221 let mut a = a_hi.iter_mut();
222 while carry != 0 {
223 let a = a.next().expect("carry overflow during multiplication!");
224 *a = adc(*a, 0, &mut carry);
225 }
226}
227
228fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
231 let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) };
232
233 if x.len() <= 32 {
245 for (i, xi) in x.iter().enumerate() {
247 mac_digit(&mut acc[i..], y, *xi);
248 }
249 } else if x.len() <= 256 {
250 let b = x.len() / 2;
318 let (x0, x1) = x.split_at(b);
319 let (y0, y1) = y.split_at(b);
320
321 let len = x1.len() + y1.len() + 1;
326 let mut p = BigUint { data: vec![0; len] };
327
328 mac3(&mut p.data[..], x1, y1);
330
331 p.normalize();
333
334 add2(&mut acc[b..], &p.data[..]);
335 add2(&mut acc[b * 2..], &p.data[..]);
336
337 p.data.truncate(0);
339 p.data.extend(repeat(0).take(len));
340
341 mac3(&mut p.data[..], x0, y0);
343 p.normalize();
344
345 add2(&mut acc[..], &p.data[..]);
346 add2(&mut acc[b..], &p.data[..]);
347
348 let (j0_sign, j0) = sub_sign(x1, x0);
351 let (j1_sign, j1) = sub_sign(y1, y0);
352
353 match j0_sign * j1_sign {
354 Plus => {
355 p.data.truncate(0);
356 p.data.extend(repeat(0).take(len));
357
358 mac3(&mut p.data[..], &j0.data[..], &j1.data[..]);
359 p.normalize();
360
361 sub2(&mut acc[b..], &p.data[..]);
362 }
363 Minus => {
364 mac3(&mut acc[b..], &j0.data[..], &j1.data[..]);
365 }
366 NoSign => (),
367 }
368 } else {
369 let i = y.len() / 3 + 1;
378
379 let x0_len = cmp::min(x.len(), i);
380 let x1_len = cmp::min(x.len() - x0_len, i);
381
382 let y0_len = i;
383 let y1_len = cmp::min(y.len() - y0_len, i);
384
385 let x0 = BigInt::from_slice(Plus, &x[..x0_len]);
391 let x1 = BigInt::from_slice(Plus, &x[x0_len..x0_len + x1_len]);
392 let x2 = BigInt::from_slice(Plus, &x[x0_len + x1_len..]);
393
394 let y0 = BigInt::from_slice(Plus, &y[..y0_len]);
396 let y1 = BigInt::from_slice(Plus, &y[y0_len..y0_len + y1_len]);
397 let y2 = BigInt::from_slice(Plus, &y[y0_len + y1_len..]);
398
399 let p = &x0 + &x2;
425
426 let q = &y0 + &y2;
428
429 let p2 = &p - &x1;
431
432 let q2 = &q - &y1;
434
435 let r0 = &x0 * &y0;
437
438 let r4 = &x2 * &y2;
440
441 let r1 = (p + x1) * (q + y1);
443
444 let r2 = &p2 * &q2;
446
447 let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0);
449
450 let mut comp3: BigInt = (r3 - &r1) / 3;
470 let mut comp1: BigInt = (r1 - &r2) / 2;
471 let mut comp2: BigInt = r2 - &r0;
472 comp3 = (&comp2 - comp3) / 2 + &r4 * 2;
473 comp2 += &comp1 - &r4;
474 comp1 -= &comp3;
475
476 let result = r0
480 + (comp1 << (32 * i))
481 + (comp2 << (2 * 32 * i))
482 + (comp3 << (3 * 32 * i))
483 + (r4 << (4 * 32 * i));
484 let result_pos = result.to_biguint().unwrap();
485 add2(&mut acc[..], &result_pos.data);
486 }
487}
488
489pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
490 let len = x.len() + y.len() + 1;
491 let mut prod = BigUint { data: vec![0; len] };
492
493 mac3(&mut prod.data[..], x, y);
494 prod.normalized()
495}
496
497pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit {
498 let mut carry = 0;
499 for a in a.iter_mut() {
500 *a = mul_with_carry(*a, b, &mut carry);
501 }
502 carry as BigDigit
503}
504
505pub fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) {
506 if d.is_zero() {
507 panic!()
508 }
509 if u.is_zero() {
510 return (Zero::zero(), Zero::zero());
511 }
512
513 if d.data.len() == 1 {
514 if d.data == [1] {
515 return (u, Zero::zero());
516 }
517 let (div, rem) = div_rem_digit(u, d.data[0]);
518 d.data.clear();
520 d += rem;
521 return (div, d);
522 }
523
524 match u.cmp(&d) {
526 Less => return (Zero::zero(), u),
527 Equal => {
528 u.set_one();
529 return (u, Zero::zero());
530 }
531 Greater => {} }
533
534 let shift = d.data.last().unwrap().leading_zeros() as usize;
541 let (q, r) = if shift == 0 {
542 div_rem_core(u, &d)
544 } else {
545 div_rem_core(u << shift, &(d << shift))
546 };
547 (q, r >> shift)
549}
550
551pub fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
552 if d.is_zero() {
553 panic!()
554 }
555 if u.is_zero() {
556 return (Zero::zero(), Zero::zero());
557 }
558
559 if d.data.len() == 1 {
560 if d.data == [1] {
561 return (u.clone(), Zero::zero());
562 }
563
564 let (div, rem) = div_rem_digit(u.clone(), d.data[0]);
565 return (div, rem.into());
566 }
567
568 match u.cmp(d) {
570 Less => return (Zero::zero(), u.clone()),
571 Equal => return (One::one(), Zero::zero()),
572 Greater => {} }
574
575 let shift = d.data.last().unwrap().leading_zeros() as usize;
582
583 let (q, r) = if shift == 0 {
584 div_rem_core(u.clone(), d)
586 } else {
587 div_rem_core(u << shift, &(d << shift))
588 };
589 (q, r >> shift)
591}
592
593fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) {
603 let bn = *b.data.last().unwrap();
618 let q_len = a.data.len() - b.data.len() + 1;
619 let mut q = BigUint {
620 data: vec![0; q_len],
621 };
622
623 let mut tmp = BigUint {
628 data: Vec::with_capacity(2),
629 };
630
631 for j in (0..q_len).rev() {
632 let offset = j + b.data.len() - 1;
639 if offset >= a.data.len() {
640 continue;
641 }
642
643 let mut a0 = tmp;
645 a0.data.truncate(0);
646 a0.data.extend(a.data[offset..].iter().cloned());
647
648 let (mut q0, _) = div_rem_digit(a0, bn);
655 let mut prod = b * &q0;
656
657 while cmp_slice(&prod.data[..], &a.data[j..]) == Greater {
658 let one: BigUint = One::one();
659 q0 -= one;
660 prod -= b;
661 }
662
663 add2(&mut q.data[j..], &q0.data[..]);
664 sub2(&mut a.data[j..], &prod.data[..]);
665 a.normalize();
666
667 tmp = q0;
668 }
669
670 debug_assert!(a < *b);
671
672 (q.normalized(), a)
673}
674
675pub fn fls<T: traits::PrimInt>(v: T) -> usize {
678 mem::size_of::<T>() * 8 - v.leading_zeros() as usize
679}
680
681pub fn ilog2<T: traits::PrimInt>(v: T) -> usize {
682 fls(v) - 1
683}
684
685#[inline]
686pub fn biguint_shl(n: Cow<BigUint>, bits: usize) -> BigUint {
687 let n_unit = bits / big_digit::BITS;
688 let mut data = match n_unit {
689 0 => n.into_owned().data,
690 _ => {
691 let len = n_unit + n.data.len() + 1;
692 let mut data = Vec::with_capacity(len);
693 data.extend(repeat(0).take(n_unit));
694 data.extend(n.data.iter().cloned());
695 data
696 }
697 };
698
699 let n_bits = bits % big_digit::BITS;
700 if n_bits > 0 {
701 let mut carry = 0;
702 for elem in data[n_unit..].iter_mut() {
703 let new_carry = *elem >> (big_digit::BITS - n_bits);
704 *elem = (*elem << n_bits) | carry;
705 carry = new_carry;
706 }
707 if carry != 0 {
708 data.push(carry);
709 }
710 }
711
712 BigUint::new(data)
713}
714
715#[inline]
716pub fn biguint_shr(n: Cow<BigUint>, bits: usize) -> BigUint {
717 let n_unit = bits / big_digit::BITS;
718 if n_unit >= n.data.len() {
719 return Zero::zero();
720 }
721 let mut data = match n {
722 Cow::Borrowed(n) => n.data[n_unit..].to_vec(),
723 Cow::Owned(mut n) => {
724 n.data.drain(..n_unit);
725 n.data
726 }
727 };
728
729 let n_bits = bits % big_digit::BITS;
730 if n_bits > 0 {
731 let mut borrow = 0;
732 for elem in data.iter_mut().rev() {
733 let new_borrow = *elem << (big_digit::BITS - n_bits);
734 *elem = (*elem >> n_bits) | borrow;
735 borrow = new_borrow;
736 }
737 }
738
739 BigUint::new(data)
740}
741
742pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering {
743 debug_assert!(a.last() != Some(&0));
744 debug_assert!(b.last() != Some(&0));
745
746 let (a_len, b_len) = (a.len(), b.len());
747 if a_len < b_len {
748 return Less;
749 }
750 if a_len > b_len {
751 return Greater;
752 }
753
754 for (&ai, &bi) in a.iter().rev().zip(b.iter().rev()) {
755 if ai < bi {
756 return Less;
757 }
758 if ai > bi {
759 return Greater;
760 }
761 }
762 Equal
763}
764
765#[cfg(test)]
766mod algorithm_tests {
767 use big_digit::BigDigit;
768 use traits::Num;
769 use Sign::Plus;
770 use {BigInt, BigUint};
771
772 #[test]
773 fn test_sub_sign() {
774 use super::sub_sign;
775
776 fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt {
777 let (sign, val) = sub_sign(a, b);
778 BigInt::from_biguint(sign, val)
779 }
780
781 let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap();
782 let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap();
783 let a_i = BigInt::from_biguint(Plus, a.clone());
784 let b_i = BigInt::from_biguint(Plus, b.clone());
785
786 assert_eq!(sub_sign_i(&a.data[..], &b.data[..]), &a_i - &b_i);
787 assert_eq!(sub_sign_i(&b.data[..], &a.data[..]), &b_i - &a_i);
788 }
789}