Support signed multiplication and division, for ECDSA.
This commit is contained in:
90
src/signed/mul.rs
Normal file
90
src/signed/mul.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
macro_rules! mul_impls
|
||||
{
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl MulAssign<$name> for $name {
|
||||
fn mul_assign(&mut self, rhs: $name) {
|
||||
self.mul_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MulAssign<&'a $name> for $name {
|
||||
fn mul_assign(&mut self, rhs: &$name) {
|
||||
self.value *= &rhs.value;
|
||||
self.negative = !self.value.is_zero() && (self.negative != rhs.negative);
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl
|
||||
{
|
||||
&self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl
|
||||
{
|
||||
&self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$name> for &'a $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl
|
||||
{
|
||||
self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Mul<&'a $name> for &'b $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl
|
||||
{
|
||||
let outval = &self.value * &rhs.value;
|
||||
let zero = outval.is_zero();
|
||||
$dbl {
|
||||
value: outval,
|
||||
negative: !zero && (self.negative != rhs.negative)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigmul_tests {
|
||||
($sname: ident, $name: ident, $lname: ident, $dbl: ident, $udbl: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigmul_tests!(body $sname, $name, $dbl, $udbl);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident, $dbl: ident, $udbl: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigmul_tests!(body $sname, $name, $dbl, $udbl);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $dbl: ident, $udbl: ident) => {
|
||||
let fname = build_test_path("sigmul", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let c = $dbl::new(*negc, $udbl::from_bytes(cbytes));
|
||||
assert_eq!(c, &a * &b, "base mul");
|
||||
a *= b;
|
||||
assert_eq!($sname::from(c), a, "in-place mul");
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user