From e5ed5031414f7840ce4d71e6601dfff6678a7b65 Mon Sep 17 00:00:00 2001 From: Sam Cappleman-Lynes Date: Thu, 29 Jun 2017 08:41:46 +0100 Subject: [PATCH] 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. --- bigint/src/biguint.rs | 2 + bigint/src/macros.rs | 88 +++++++++++++++++++++++++++++++++++++ bigint/src/tests/biguint.rs | 6 ++- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 9064490..3063236 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -394,6 +394,8 @@ impl<'a> Add<&'a BigUint> for BigUint { } } +forward_all_scalar_binop_to_val_val!(impl Add for BigUint, add); + impl Add for BigUint { type Output = BigUint; diff --git a/bigint/src/macros.rs b/bigint/src/macros.rs index 39f45a4..c6ebf71 100644 --- a/bigint/src/macros.rs +++ b/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); + } +} diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs index 1c57d86..f3627fa 100644 --- a/bigint/src/tests/biguint.rs +++ b/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); } } }