فهرست منبع

Add scalar division to BigInt

Sam Cappleman-Lynes 7 سال پیش
والد
کامیت
9b0392d235
2فایلهای تغییر یافته به همراه93 افزوده شده و 0 حذف شده
  1. 40 0
      bigint/src/bigint.rs
  2. 53 0
      bigint/src/tests/bigint.rs

+ 40 - 0
bigint/src/bigint.rs

@@ -508,6 +508,26 @@ impl<'a, 'b> Div<&'b BigInt> for &'a BigInt {
     }
 }
 
+forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigInt, div);
+
+impl Div<BigDigit> for BigInt {
+    type Output = BigInt;
+
+    #[inline]
+    fn div(self, other: BigDigit) -> BigInt {
+        BigInt::from_biguint(self.sign, self.data / other)
+    }
+}
+
+impl Div<BigInt> for BigDigit {
+    type Output = BigInt;
+
+    #[inline]
+    fn div(self, other: BigInt) -> BigInt {
+        BigInt::from_biguint(other.sign, self / other.data)
+    }
+}
+
 forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem);
 
 impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
@@ -520,6 +540,26 @@ impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
     }
 }
 
+forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigInt, rem);
+
+impl Rem<BigDigit> for BigInt {
+    type Output = BigInt;
+
+    #[inline]
+    fn rem(self, other: BigDigit) -> BigInt {
+        BigInt::from_biguint(self.sign, self.data % other)
+    }
+}
+
+impl Rem<BigInt> for BigDigit {
+    type Output = BigInt;
+
+    #[inline]
+    fn rem(self, other: BigInt) -> BigInt {
+        BigInt::from_biguint(Plus, self % other.data)
+    }
+}
+
 impl Neg for BigInt {
     type Output = BigInt;
 

+ 53 - 0
bigint/src/tests/bigint.rs

@@ -832,6 +832,59 @@ fn test_div_rem() {
     }
 }
 
+#[test]
+fn test_scalar_div_rem() {
+    fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) {
+        let (q, r) = (a / b, a % b);
+        if !r.is_zero() {
+            assert_eq!(r.sign, a.sign);
+        }
+        assert!(r.abs() <= From::from(b));
+        assert!(*a == b * &q + &r);
+        assert!(q == *ans_q);
+        assert!(r == *ans_r);
+
+        let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone());
+        assert_op!(a / b == ans_q);
+        assert_op!(a % b == ans_r);
+    }
+
+    fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) {
+        check_sub(a, b, q, r);
+        check_sub(&a.neg(), b, &q.neg(), &r.neg());
+    }
+
+    for elm in MUL_TRIPLES.iter() {
+        let (a_vec, b_vec, c_vec) = *elm;
+        let a = BigInt::from_slice(Plus, a_vec);
+        let b = BigInt::from_slice(Plus, b_vec);
+        let c = BigInt::from_slice(Plus, c_vec);
+
+        if a_vec.len() == 1 && a_vec[0] != 0 {
+            let a = a_vec[0];
+            check(&c, a, &b, &Zero::zero());
+        }
+
+        if b_vec.len() == 1 && b_vec[0] != 0 {
+            let b = b_vec[0];
+            check(&c, b, &a, &Zero::zero());
+        }
+    }
+
+    for elm in DIV_REM_QUADRUPLES.iter() {
+        let (a_vec, b_vec, c_vec, d_vec) = *elm;
+        let a = BigInt::from_slice(Plus, a_vec);
+        let c = BigInt::from_slice(Plus, c_vec);
+        let d = BigInt::from_slice(Plus, d_vec);
+
+        if b_vec.len() == 1 && b_vec[0] != 0 {
+            let b = b_vec[0];
+            check(&a, b, &c, &d);
+        }
+    }
+
+}
+
 #[test]
 fn test_checked_add() {
     for elm in SUM_TRIPLES.iter() {