Преглед на файлове

Implement all variants of adding BigDigit to BigUint

Allow the addition to occur with either operand order, and with any combination
of owned and borrowed arguments.
Sam Cappleman-Lynes преди 8 години
родител
ревизия
e5ed503141
променени са 3 файла, в които са добавени 94 реда и са изтрити 2 реда
  1. 2 0
      bigint/src/biguint.rs
  2. 88 0
      bigint/src/macros.rs
  3. 4 2
      bigint/src/tests/biguint.rs

+ 2 - 0
bigint/src/biguint.rs

@@ -394,6 +394,8 @@ impl<'a> Add<&'a BigUint> for BigUint {
     }
 }
 
+forward_all_scalar_binop_to_val_val!(impl Add<BigDigit> for BigUint, add);
+
 impl Add<BigDigit> for BigUint {
     type Output = BigUint;
 

+ 88 - 0
bigint/src/macros.rs

@@ -105,6 +105,85 @@ macro_rules! forward_ref_ref_binop_commutative {
     }
 }
 
+macro_rules! forward_scalar_val_val_binop {
+    (impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => {
+        impl $imp<$res> for $scalar {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: $res) -> $res {
+                $imp::$method(other, self)
+            }
+        }
+    }
+}
+
+macro_rules! forward_scalar_val_ref_binop {
+    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
+        impl<'a> $imp<&'a $scalar> for $res {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: &$scalar) -> $res {
+                $imp::$method(self, *other)
+            }
+        }
+
+        impl<'a> $imp<$res> for &'a $scalar {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: $res) -> $res {
+                $imp::$method(other, *self)
+            }
+        }
+    }
+}
+
+macro_rules! forward_scalar_ref_val_binop {
+    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
+        impl<'a> $imp<$scalar> for &'a $res {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: $scalar) -> $res {
+                $imp::$method(self.clone(), other)
+            }
+        }
+
+        impl<'a> $imp<&'a $res> for $scalar {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: &$res) -> $res {
+                $imp::$method(other.clone(), self)
+            }
+        }
+    }
+}
+
+macro_rules! forward_scalar_ref_ref_binop {
+    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
+        impl<'a, 'b> $imp<&'b $scalar> for &'a $res {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: &$scalar) -> $res {
+                $imp::$method(self.clone(), *other)
+            }
+        }
+
+        impl<'a, 'b> $imp<&'a $res> for &'b $scalar {
+            type Output = $res;
+
+            #[inline]
+            fn $method(self, other: &$res) -> $res {
+                $imp::$method(other.clone(), *self)
+            }
+        }
+    }
+}
+
 // Forward everything to ref-ref, when reusing storage is not helpful
 macro_rules! forward_all_binop_to_ref_ref {
     (impl $imp:ident for $res:ty, $method:ident) => {
@@ -131,3 +210,12 @@ macro_rules! forward_all_binop_to_val_ref_commutative {
         forward_ref_ref_binop_commutative!(impl $imp for $res, $method);
     };
 }
+
+macro_rules! forward_all_scalar_binop_to_val_val {
+    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
+        forward_scalar_val_val_binop!(impl $imp<$scalar> for $res, $method);
+        forward_scalar_val_ref_binop!(impl $imp<$scalar> for $res, $method);
+        forward_scalar_ref_val_binop!(impl $imp<$scalar> for $res, $method);
+        forward_scalar_ref_ref_binop!(impl $imp<$scalar> for $res, $method);
+    }
+}

+ 4 - 2
bigint/src/tests/biguint.rs

@@ -699,13 +699,15 @@ fn test_scalar_add() {
       if a_vec.len() == 1 {
           let a = a_vec[0];
           let b = BigUint::from_slice(b_vec);
-          assert!(b + a == c);
+          assert_op!(a + b == c);
+          assert_op!(b + a == c);
       }
 
       if b_vec.len() == 1 {
           let a = BigUint::from_slice(a_vec);
           let b = b_vec[0];
-          assert!(a + b == c);
+          assert_op!(a + b == c);
+          assert_op!(b + a == c);
         }
     }
 }