Base implementation of signed numbers and EGCD, with tests.

This commit is contained in:
2018-10-15 19:16:25 -07:00
parent d43f0bcd42
commit 89e2dfc6ef
164 changed files with 560116 additions and 67 deletions

113
src/signed/add.rs Normal file
View File

@@ -0,0 +1,113 @@
macro_rules! add_impls
{
($name: ident, $bigger: ident, $ubigger: ident) => {
impl AddAssign<$name> for $name {
fn add_assign(&mut self, rhs: $name) {
self.add_assign(&rhs);
}
}
impl<'a> AddAssign<&'a $name> for $name {
fn add_assign(&mut self, rhs: &$name) {
if self.negative == rhs.negative {
unsafe_addition(&mut self.value.value, &rhs.value.value, true);
} else {
if self.value > rhs.value {
self.value -= rhs.value.clone();
} else {
self.value = rhs.value.clone() - self.value.clone();
self.negative = rhs.negative;
}
}
}
}
impl Add<$name> for $name {
type Output = $bigger;
fn add(self, rhs: $name) -> $bigger
{
&self + &rhs
}
}
impl<'a> Add<&'a $name> for $name {
type Output = $bigger;
fn add(self, rhs: &$name) -> $bigger
{
&self + rhs
}
}
impl<'a> Add<$name> for &'a $name {
type Output = $bigger;
fn add(self, rhs: $name) -> $bigger
{
self + &rhs
}
}
impl<'a,'b> Add<&'a $name> for &'b $name {
type Output = $bigger;
fn add(self, rhs: &$name) -> $bigger
{
if self.negative == rhs.negative {
$bigger{
negative: self.negative,
value: &self.value + &rhs.value
}
} else {
if self.value > rhs.value {
$bigger {
negative: self.negative,
value: $ubigger::from(&self.value - &rhs.value)
}
} else {
$bigger {
negative: rhs.negative,
value: $ubigger::from(&rhs.value - &self.value)
}
}
}
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigadd_tests {
($sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
fn $lname() {
generate_sigadd_tests!(body$sname, $name, $lname, $bigger, $ubigger);
}
};
(ignore $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigadd_tests!(body $sname, $name, $lname, $bigger, $ubigger);
}
};
(body $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
let fname = format!("testdata/sigadd/{}.tests", 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 = $bigger::new(*negc, $ubigger::from_bytes(cbytes));
assert_eq!(c, &a + &b, "base addition");
if c.value.value[c.value.value.len()-1] == 0 {
a += b;
assert_eq!($sname::from(c), a, "mutating addition");
}
});
};
}