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.
This commit is contained in:
Sam Cappleman-Lynes 2017-06-29 08:41:46 +01:00
parent 784d26bbf8
commit e5ed503141
3 changed files with 94 additions and 2 deletions

View File

@ -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 { impl Add<BigDigit> for BigUint {
type Output = BigUint; type Output = BigUint;

View File

@ -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 // Forward everything to ref-ref, when reusing storage is not helpful
macro_rules! forward_all_binop_to_ref_ref { macro_rules! forward_all_binop_to_ref_ref {
(impl $imp:ident for $res:ty, $method:ident) => { (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); 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);
}
}

View File

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