Prechádzať zdrojové kódy

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 7 rokov pred
rodič
commit
e5ed503141
3 zmenil súbory, kde vykonal 94 pridanie a 2 odobranie
  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);
         }
     }
 }