Explorar el Código

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 hace 7 años
padre
commit
e5ed503141
Se han modificado 3 ficheros con 94 adiciones y 2 borrados
  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);
         }
     }
 }