Quellcode durchsuchen

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 vor 7 Jahren
Ursprung
Commit
e5ed503141
3 geänderte Dateien mit 94 neuen und 2 gelöschten Zeilen
  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);
         }
     }
 }