diff --git a/src/cryptonum/builder.rs b/src/cryptonum/builder.rs index ecbaae2..d846cfa 100644 --- a/src/cryptonum/builder.rs +++ b/src/cryptonum/builder.rs @@ -1,3 +1,293 @@ +macro_rules! construct_signed { + ($type: ident, $base: ident, $modname: ident) => { + pub struct $type { + negative: bool, + value: $base + } + + impl Clone for $type { + fn clone(&self) -> $type { + $type{ negative: self.negative, value: self.value.clone() } + } + } + + impl<'a> PartialEq<&'a $type> for $type { + fn eq(&self, other: &&$type) -> bool { + (self.negative == other.negative) && + (self.value == other.value) + } + } + + impl PartialEq for $type { + fn eq(&self, other: &$type) -> bool { + (self.negative == other.negative) && + (self.value == other.value) + } + } + + impl Eq for $type {} + + impl Debug for $type { + fn fmt(&self, f: &mut Formatter) -> Result<(),Error> { + if self.negative { + f.write_str("-")?; + } else { + f.write_str("+")?; + } + self.value.fmt(f) + } + } + + impl PartialOrd for $type { + fn partial_cmp(&self, other: &$type) -> Option { + Some(self.cmp(other)) + } + } + + impl Ord for $type { + fn cmp(&self, other: &$type) -> Ordering { + match (self.negative, other.negative) { + (true, true) => + self.value.cmp(&other.value).reverse(), + (true, false) => Ordering::Greater, + (false, true) => Ordering::Less, + (false, false) => + self.value.cmp(&other.value) + } + } + } + + impl CryptoNumBase for $type { + fn zero() -> $type { + $type{ negative: false, value: $base::zero() } + } + fn max_value() -> $type { + $type{ negative: false, value: $base::max_value() } + } + fn is_zero(&self) -> bool { + self.value.is_zero() + } + fn is_odd(&self) -> bool { + self.value.is_odd() + } + fn is_even(&self) -> bool { + self.value.is_even() + } + fn from_u8(x: u8) -> $type { + $type{ negative: false, value: $base::from_u8(x) } + } + fn to_u8(&self) -> u8 { + self.value.to_u8() + } + fn from_u16(x: u16) -> $type { + $type{ negative: false, value: $base::from_u16(x) } + } + fn to_u16(&self) -> u16 { + self.value.to_u16() + } + fn from_u32(x: u32) -> $type { + $type{ negative: false, value: $base::from_u32(x) } + } + fn to_u32(&self) -> u32 { + self.value.to_u32() + } + fn from_u64(x: u64) -> $type { + $type{ negative: false, value: $base::from_u64(x) } + } + fn to_u64(&self) -> u64 { + self.value.to_u64() + } + } + + impl CryptoNumFastMod for $type { + type BarrettMu = <$base as CryptoNumFastMod>::BarrettMu; + + fn barrett_mu(&self) -> Option { + if self.negative { + None + } else { + self.value.barrett_mu() + } + } + + fn fastmod(&self, mu: &Self::BarrettMu) -> $type { + let res = self.value.fastmod(mu); + $type{ negative: self.negative, value: res } + } + } + + impl CryptoNumSigned for $type { + type Unsigned = $base; + + fn new(v: $base) -> $type { + $type{ negative: false, value: v.clone() } + } + fn abs(&self) -> $base { + self.value.clone() + } + fn is_positive(&self) -> bool { + !self.negative + } + fn is_negative(&self) -> bool { + self.negative + } + } + + impl Neg for $type { + type Output = $type; + + fn neg(self) -> $type { + (&self).neg() + } + } + + impl<'a> Neg for &'a $type { + type Output = $type; + + fn neg(self) -> $type { + if self.value.is_zero() { + $type{ negative: false, value: self.value.clone() } + } else { + $type{ negative: !self.negative, value: self.value.clone() } + } + } + } + + impl<'a> AddAssign<&'a $type> for $type { + fn add_assign(&mut self, other: &$type) { + let signs_match = self.negative == other.negative; + let ordering = self.value.cmp(&other.value); + + match (signs_match, ordering) { + (true, _) => + // if the signs are the same, we maintain the sign and + // just increase the magnitude + self.value.add_assign(&other.value), + (false, Ordering::Equal) => { + // if the signs are different and the numbers are equal, + // we just set this to zero. However, we actually do the + // subtraction to make the timing roughly similar. + self.negative = false; + self.value.sub_assign(&other.value) + } + (false, Ordering::Less) => { + // if the signs are different and the first one is less + // than the second, then we flip the sign and subtract. + self.negative = !self.negative; + let mut other_copy = other.value.clone(); + other_copy.sub_assign(&self.value); + self.value = other_copy; + } + (false, Ordering::Greater) => { + // if the signs are different and the first one is + // greater than the second, then we leave the sign and + // subtract. + self.value.sub_assign(&other.value) + } + } + } + } + + impl<'a> SubAssign<&'a $type> for $type { + fn sub_assign(&mut self, other: &$type) { + // this is a bit inefficient, but a heck of a lot easier. + let mut other2 = other.clone(); + other2.negative = !other2.negative; + self.add_assign(&other2) + } + } + + impl<'a> MulAssign<&'a $type> for $type { + fn mul_assign(&mut self, other: &$type) { + self.negative = self.negative ^ other.negative; + self.value.mul_assign(&other.value); + } + } + + impl<'a> DivAssign<&'a $type> for $type { + fn div_assign(&mut self, other: &$type) { + self.negative = self.negative ^ other.negative; + self.value.div_assign(&other.value); + } + } + + impl<'a> RemAssign<&'a $type> for $type { + fn rem_assign(&mut self, other: &$type) { + self.value.rem_assign(&other.value); + } + } + + derive_operators!($type,Add,add,AddAssign,add_assign); + derive_operators!($type,Sub,sub,SubAssign,sub_assign); + derive_operators!($type,Mul,mul,MulAssign,mul_assign); + derive_operators!($type,Div,div,DivAssign,div_assign); + derive_operators!($type,Rem,rem,RemAssign,rem_assign); + + #[cfg(test)] + mod $modname { + use quickcheck::{Arbitrary,Gen}; + use super::*; + + impl Arbitrary for $type { + fn arbitrary(g: &mut G) -> $type { + let value = $base::arbitrary(g); + if value.is_zero() { + $type{ negative: false, value: value } + } else { + $type{ negative: g.gen_weighted_bool(2), value: value } + } + } + } + + quickcheck! { + fn double_negation(x: $type) -> bool { + (- (- &x)) == &x + } + fn add_identity(x: $type) -> bool { + (&x + $type::zero()) == &x + } + fn add_commutivity(x: $type, y: $type) -> bool { + (&x + &y) == (&y + &x) + } + fn add_associativity(a: $type, b: $type, c: $type) -> bool { + // we shift these to get away from rollover + let x = $type{ negative: a.negative, value: a.value >> 2 }; + let y = $type{ negative: b.negative, value: b.value >> 2 }; + let z = $type{ negative: c.negative, value: c.value >> 2 }; + (&x + (&y + &z)) == ((&x + &y) + &z) + } + fn sub_is_add_negation(x: $type, y: $type) -> bool { + (&x - &y) == (&x + (- &y)) + } + fn sub_destroys(x: $type) -> bool { + (&x - &x) == $type::zero() + } + fn mul_identity(x: $type) -> bool { + (&x * $type::from_u8(1)) == &x + } + fn mul_commutivity(x: $type, y: $type) -> bool { + (&x * &y) == (&y * &x) + } + fn mul_associativity(a: $type, b: $type, c: $type) -> bool { + // we shift these to get away from rollover + let s = (a.value.bit_size() / 2) - 2; + let x = $type{ negative: a.negative, value: a.value >> s }; + let y = $type{ negative: b.negative, value: b.value >> s }; + let z = $type{ negative: c.negative, value: c.value >> s }; + (&x * (&y * &z)) == ((&x * &y) * &z) + } + #[ignore] + fn div_identity(a: $type) -> bool { + &a / $type::from_u64(1) == a + } + fn div_self_is_one(a: $type) -> bool { + (&a / &a) == $type::from_u64(1) + } + } + } + } +} + macro_rules! construct_unsigned { ($type: ident, $barrett: ident, $modname: ident, $count: expr) => { #[derive(Clone)] @@ -75,9 +365,12 @@ macro_rules! construct_unsigned { } } - opers2!($type,BitOrAssign,bitor_assign,BitOr,bitor,generic_bitor); - opers2!($type,BitAndAssign,bitand_assign,BitAnd,bitand,generic_bitand); - opers2!($type,BitXorAssign,bitxor_assign,BitXor,bitxor,generic_bitxor); + generic_2arg!($type, BitOrAssign, bitor_assign, generic_bitor); + generic_2arg!($type, BitAndAssign, bitand_assign, generic_bitand); + generic_2arg!($type, BitXorAssign, bitxor_assign, generic_bitxor); + generic_2arg!($type, AddAssign, add_assign, generic_add); + generic_2arg!($type, SubAssign, sub_assign, generic_sub); + generic_3arg!($type, MulAssign, mul_assign, generic_mul); shifts!($type, usize); shifts!($type, u64); @@ -89,19 +382,6 @@ macro_rules! construct_unsigned { shifts!($type, u8); shifts!($type, i8); - opers2!($type,AddAssign,add_assign,Add,add,generic_add); - opers2!($type,SubAssign,sub_assign,Sub,sub,generic_sub); - opers3!($type,MulAssign,mul_assign,Mul,mul,generic_mul); - - impl DivAssign<$type> for $type { - fn div_assign(&mut self, rhs: $type) { - let mut dead = [0; $count]; - let copy = self.contents.clone(); - generic_div(©, &rhs.contents, - &mut self.contents, &mut dead); - } - } - impl<'a> DivAssign<&'a $type> for $type { fn div_assign(&mut self, rhs: &$type) { let mut dead = [0; $count]; @@ -111,63 +391,6 @@ macro_rules! construct_unsigned { } } - impl Div<$type> for $type { - type Output = $type; - - fn div(self, rhs: $type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut res.contents, &mut dead); - res - } - } - - impl<'a> Div<$type> for &'a $type { - type Output = $type; - - fn div(self, rhs: $type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut res.contents, &mut dead); - res - } - } - - impl<'a> Div<&'a $type> for $type { - type Output = $type; - - fn div(self, rhs: &$type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut res.contents, &mut dead); - res - } - } - - impl<'a,'b> Div<&'a $type> for &'b $type { - type Output = $type; - - fn div(self, rhs: &$type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut res.contents, &mut dead); - res - } - } - - impl RemAssign<$type> for $type { - fn rem_assign(&mut self, rhs: $type) { - let mut dead = [0; $count]; - let copy = self.contents.clone(); - generic_div(©, &rhs.contents, - &mut dead, &mut self.contents); - } - } - impl<'a> RemAssign<&'a $type> for $type { fn rem_assign(&mut self, rhs: &$type) { let mut dead = [0; $count]; @@ -177,53 +400,14 @@ macro_rules! construct_unsigned { } } - impl Rem<$type> for $type { - type Output = $type; - - fn rem(self, rhs: $type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut dead, &mut res.contents); - res - } - } - - impl<'a> Rem<$type> for &'a $type { - type Output = $type; - - fn rem(self, rhs: $type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut dead, &mut res.contents); - res - } - } - - impl<'a> Rem<&'a $type> for $type { - type Output = $type; - - fn rem(self, rhs: &$type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut dead, &mut res.contents); - res - } - } - - impl<'a,'b> Rem<&'a $type> for &'b $type { - type Output = $type; - - fn rem(self, rhs: &$type) -> $type { - let mut res = $type::zero(); - let mut dead = [0; $count]; - generic_div(&self.contents, &rhs.contents, - &mut dead, &mut res.contents); - res - } - } + derive_operators!($type, BitOr, bitor, BitOrAssign, bitor_assign); + derive_operators!($type, BitAnd, bitand, BitAndAssign, bitand_assign); + derive_operators!($type, BitXor, bitxor, BitXorAssign, bitxor_assign); + derive_operators!($type, Add, add, AddAssign, add_assign); + derive_operators!($type, Sub, sub, SubAssign, sub_assign); + derive_operators!($type, Mul, mul, MulAssign, mul_assign); + derive_operators!($type, Div, div, DivAssign, div_assign); + derive_operators!($type, Rem, rem, RemAssign, rem_assign); impl CryptoNumBase for $type { fn zero() -> $type { @@ -879,188 +1063,74 @@ macro_rules! shifts { } } -macro_rules! opers2 { - ($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => { - impl $asncl for $type { - fn $asnfn(&mut self, other: $type) { - $impl(&mut self.contents, &other.contents); - } - } - +macro_rules! generic_2arg { + ($type: ident, $asncl: ident, $asnfn: ident, $impl: ident) => { impl<'a> $asncl<&'a $type> for $type { fn $asnfn(&mut self, other: &$type) { $impl(&mut self.contents, &other.contents); } } - - impl $cl for $type { - type Output = $type; - - fn $fn(self, rhs: $type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &rhs.contents); - copy - } - } - - impl<'a> $cl<&'a $type> for $type { - type Output = $type; - - fn $fn(self, rhs: &$type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &rhs.contents); - copy - } - } - - impl<'a> $cl<$type> for &'a $type { - type Output = $type; - - fn $fn(self, rhs: $type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &rhs.contents); - copy - } - } - - impl<'a,'b> $cl<&'a $type> for &'b $type { - type Output = $type; - - fn $fn(self, rhs: &$type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &rhs.contents); - copy - } - } } } -macro_rules! opers3 { - ($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => { - impl $asncl for $type { - fn $asnfn(&mut self, other: $type) { - let copy = self.contents.clone(); - $impl(&mut self.contents, ©, &other.contents); - } - } - +macro_rules! generic_3arg { + ($type: ident, $asncl: ident, $asnfn: ident, $impl: ident) => { impl<'a> $asncl<&'a $type> for $type { fn $asnfn(&mut self, other: &$type) { let copy = self.contents.clone(); $impl(&mut self.contents, ©, &other.contents); } } + } +} + +macro_rules! derive_operators +{ + ($type: ident, $cl: ident, $fn: ident, $asncl: ident, $asnfn: ident) => { + impl $asncl for $type { + fn $asnfn(&mut self, other: $type) { + self.$asnfn(&other) + } + } impl $cl for $type { type Output = $type; - fn $fn(self, rhs: $type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &self.contents, &rhs.contents); - copy + fn $fn(self, other: $type) -> $type { + let mut res = self.clone(); + res.$asnfn(&other); + res } } impl<'a> $cl<&'a $type> for $type { type Output = $type; - fn $fn(self, rhs: &$type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &self.contents, &rhs.contents); - copy + fn $fn(self, other: &$type) -> $type { + let mut res = self.clone(); + res.$asnfn(other); + res } } impl<'a> $cl<$type> for &'a $type { type Output = $type; - fn $fn(self, rhs: $type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &self.contents, &rhs.contents); - copy + fn $fn(self, other: $type) -> $type { + let mut res = self.clone(); + res.$asnfn(&other); + res } } impl<'a,'b> $cl<&'a $type> for &'b $type { type Output = $type; - fn $fn(self, rhs: &$type) -> $type { - let mut copy = self.clone(); - $impl(&mut copy.contents, &self.contents, &rhs.contents); - copy - } - } - } -} - -macro_rules! math_operator { - ($cl: ident, $fn: ident, $asn: ident) => { - impl $cl for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - { - type Output = Signed; - - fn $fn(self, rhs: Signed) -> Signed - { + fn $fn(self, other: &$type) -> $type { let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl<&'a Signed> for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: &'a Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl for &'a Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: &'a Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl> for &'a Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); + res.$asnfn(other); res } } } } - - diff --git a/src/cryptonum/signed.rs b/src/cryptonum/signed.rs index ece8354..d8f6e2f 100644 --- a/src/cryptonum/signed.rs +++ b/src/cryptonum/signed.rs @@ -1,443 +1,15 @@ +use cryptonum::core::*; use cryptonum::traits::*; use cryptonum::unsigned::*; +use std::cmp::Ordering; +use std::fmt::{Debug,Error,Formatter}; +use std::ops::*; -pub struct I512 { - negative: bool, - value: U512 -} - - -//use cryptonum::traits::*; -//use std::cmp::Ordering; -//use std::fmt::{Debug,Error,Formatter}; -//use std::ops::*; -// -//pub struct Signed -// where T: Clone + CryptoNumBase + Sized -//{ -// positive: bool, -// value: T -//} -// -//impl Signed -// where T: Clone + CryptoNumBase + Sized -//{ -// pub fn new(v: T) -> Signed { -// Signed{ positive: true, value: v } -// } -// -// pub fn abs(&self) -> T -// { -// self.value.clone() -// } -// -// pub fn is_positive(&self) -> bool -// { -// self.positive && !self.value.is_zero() -// } -// -// pub fn is_negative(&self) -> bool -// { -// !self.positive && !self.value.is_zero() -// } -// -// pub fn negate(&mut self) -// { -// self.positive = !self.positive; -// } -//} -// -//impl CryptoNumBase for Signed -// where T: Clone + CryptoNumBase + Sized -//{ -// fn zero() -> Signed { -// Signed{ positive: true, value: T::zero() } -// } -// fn max_value() -> Signed { -// Signed{ positive: true, value: T::max_value() } -// } -// fn is_zero(&self) -> bool { -// self.value.is_zero() -// } -// fn is_odd(&self) -> bool { -// self.value.is_odd() -// } -// fn is_even(&self) -> bool { -// self.value.is_even() -// } -// fn from_u8(x: u8) -> Signed { -// Signed{ positive: true, value: T::from_u8(x) } -// } -// fn to_u8(&self) -> u8 { -// self.value.to_u8() -// } -// fn from_u16(x: u16) -> Signed { -// Signed{ positive: true, value: T::from_u16(x) } -// } -// fn to_u16(&self) -> u16 { -// self.value.to_u16() -// } -// fn from_u32(x: u32) -> Signed { -// Signed{ positive: true, value: T::from_u32(x) } -// } -// fn to_u32(&self) -> u32 { -// self.value.to_u32() -// } -// fn from_u64(x: u64) -> Signed { -// Signed{ positive: true, value: T::from_u64(x) } -// } -// fn to_u64(&self) -> u64 { -// self.value.to_u64() -// } -//} -// -//impl CryptoNumFastMod for Signed { -// type BarrettMu = T::BarrettMu; -// -// fn barrett_mu(&self) -> Option { -// if self.positive { -// self.value.barrett_mu() -// } else { -// None -// } -// } -// -// fn fastmod(&self, mu: &T::BarrettMu) -> Signed { -// Signed{ positive: self.positive, value: self.value.fastmod(&mu) } -// } -//} -// -//impl Clone for Signed { -// fn clone(&self) -> Signed { -// Signed{ positive: self.positive, value: self.value.clone() } -// } -//} - -//impl<'a,T: PartialEq> PartialEq<&'a Signed> for Signed { -// fn eq(&self, other: &&Signed) -> bool { -// (self.positive == other.positive) && (self.value == other.value) -// } -//} -// -//impl<'a,T: PartialEq> PartialEq> for &'a Signed { -// fn eq(&self, other: &Signed) -> bool { -// (self.positive == other.positive) && (self.value == other.value) -// } -//} -// -//impl PartialEq for Signed { -// fn eq(&self, other: &Signed) -> bool { -// (self.positive == other.positive) && (self.value == other.value) -// } -//} -// -//impl Eq for Signed {} -// -//impl Debug for Signed { -// fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { -// if self.positive { -// f.write_str("+")?; -// } else { -// f.write_str("-")?; -// } -// self.value.fmt(f) -// } -//} -// -//impl Ord for Signed { -// fn cmp(&self, other: &Signed) -> Ordering { -// match (self.positive, other.positive) { -// (true, true) => self.value.cmp(&other.value), -// (true, false) => Ordering::Greater, -// (false, true) => Ordering::Less, -// (false, false) => -// self.value.cmp(&other.value).reverse() -// } -// } -//} -// -//impl PartialOrd for Signed { -// fn partial_cmp(&self, other: &Signed) -> Option{ -// Some(self.cmp(other)) -// } -//} -// -////------------------------------------------------------------------------------ -// -//impl Neg for Signed { -// type Output = Signed; -// -// fn neg(self) -> Signed { -// Signed { -// positive: !self.positive, -// value: self.value.clone() -// } -// } -//} -// -//impl<'a,T: Clone> Neg for &'a Signed { -// type Output = Signed; -// -// fn neg(self) -> Signed { -// Signed { -// positive: !self.positive, -// value: self.value.clone() -// } -// } -//} -// -////------------------------------------------------------------------------------ -// -//impl AddAssign for Signed -// where -// T: Clone + Ord, -// T: AddAssign + SubAssign, -//{ -// fn add_assign(&mut self, other: Signed) { -// match (self.positive, other.positive, self.value.cmp(&other.value)) { -// // if the signs are the same, we maintain the sign and just increase -// // the magnitude -// (x, y, _) if x == y => -// self.value.add_assign(other.value), -// // if the signs are different and the numbers are equal, we just set -// // this to zero. However, we actually do the subtraction to make the -// // timing roughly similar. -// (_, _, Ordering::Equal) => { -// self.positive = true; -// self.value.sub_assign(other.value); -// } -// // if the signs are different and the first one is less than the -// // second, then we flip the sign and subtract. -// (_, _, Ordering::Less) => { -// self.positive = !self.positive; -// let temp = self.value.clone(); -// self.value = other.value.clone(); -// self.value.sub_assign(temp); -// } -// // if the signs are different and the first one is greater than the -// // second, then we leave the sign and subtract. -// (_, _, Ordering::Greater) => { -// self.value.sub_assign(other.value); -// } -// } -// } -//} -// -//impl<'a,T> AddAssign<&'a Signed> for Signed -// where -// T: Clone + Ord, -// T: AddAssign + SubAssign, -// T: AddAssign<&'a T> + SubAssign<&'a T> -//{ -// fn add_assign(&mut self, other: &'a Signed) { -// match (self.positive, other.positive, self.value.cmp(&other.value)) { -// // if the signs are the same, we maintain the sign and just increase -// // the magnitude -// (x, y, _) if x == y => -// self.value.add_assign(&other.value), -// // if the signs are different and the numbers are equal, we just set -// // this to zero. However, we actually do the subtraction to make the -// // timing roughly similar. -// (_, _, Ordering::Equal) => { -// self.positive = true; -// self.value.sub_assign(&other.value); -// } -// // if the signs are different and the first one is less than the -// // second, then we flip the sign and subtract. -// (_, _, Ordering::Less) => { -// self.positive = !self.positive; -// let temp = self.value.clone(); -// self.value = other.value.clone(); -// self.value.sub_assign(temp); -// } -// // if the signs are different and the first one is greater than the -// // second, then we leave the sign and subtract. -// (_, _, Ordering::Greater) => { -// self.value.sub_assign(&other.value); -// } -// } -// } -//} -// -//math_operator!(Add,add,add_assign); -// -////------------------------------------------------------------------------------ -// -//impl SubAssign for Signed -// where -// T: Clone + Ord, -// T: AddAssign + SubAssign, -//{ -// fn sub_assign(&mut self, other: Signed) { -// let mut other2 = other.clone(); -// other2.positive = !other.positive; -// self.add_assign(other2); -// } -//} -// -//impl<'a,T> SubAssign<&'a Signed> for Signed -// where -// T: Clone + Ord, -// T: AddAssign + SubAssign, -// T: AddAssign<&'a T> + SubAssign<&'a T> -//{ -// fn sub_assign(&mut self, other: &'a Signed) { -// let mut other2 = other.clone(); -// other2.positive = !other.positive; -// self.add_assign(other2); -// } -//} -// -//math_operator!(Sub,sub,sub_assign); -// -////------------------------------------------------------------------------------ -// -//impl MulAssign for Signed -// where -// T: MulAssign -//{ -// fn mul_assign(&mut self, other: Signed) { -// self.positive = !(self.positive ^ other.positive); -// self.value *= other.value; -// } -//} -// -//impl<'a,T> MulAssign<&'a Signed> for Signed -// where -// T: MulAssign + MulAssign<&'a T> -//{ -// fn mul_assign(&mut self, other: &'a Signed) { -// self.positive = !(self.positive ^ other.positive); -// self.value *= &other.value; -// } -//} -// -//math_operator!(Mul,mul,mul_assign); -// -////------------------------------------------------------------------------------ -// -//impl DivAssign for Signed -// where -// T: DivAssign -//{ -// fn div_assign(&mut self, other: Signed) { -// self.positive = !(self.positive ^ other.positive); -// self.value /= other.value; -// } -//} -// -//impl<'a,T> DivAssign<&'a Signed> for Signed -// where -// T: DivAssign + DivAssign<&'a T> -//{ -// fn div_assign(&mut self, other: &'a Signed) { -// self.positive = !(self.positive ^ other.positive); -// self.value /= &other.value; -// } -//} -// -//math_operator!(Div,div,div_assign); -// -////------------------------------------------------------------------------------ -// -//#[cfg(test)] -//mod tests { -// use cryptonum::unsigned::U512; -// use quickcheck::{Arbitrary,Gen}; -// use std::cmp::{max,min}; -// use super::*; -// -// impl Arbitrary for Signed { -// fn arbitrary(g: &mut G) -> Signed { -// let value = T::arbitrary(g); -// if value.is_zero() { -// Signed { -// positive: true, -// value: value -// } -// } else { -// Signed { -// positive: g.gen_weighted_bool(2), -// value: value -// } -// } -// } -// } -// -// quickcheck! { -// fn double_negation(x: Signed) -> bool { -// &x == (- (- &x)) -// } -// } -// -// quickcheck! { -// fn add_associates(x: Signed, y: Signed, z: Signed) -// -> bool -// { -// let mut a = x.clone(); -// let mut b = y.clone(); -// let mut c = z.clone(); -// -// // we shift these right because rollover makes for weird behavior -// a.value >>= 2; -// b.value >>= 2; -// c.value >>= 2; -// -// (&a + (&b + &c)) == ((&a + &b) + &c) -// } -// fn add_commutes(x: Signed, y: Signed) -> bool { -// (&x + &y) == (&y + &x) -// } -// fn add_identity(x: Signed) -> bool { -// let zero = Signed{ positive: true, value: U512::zero() }; -// (&x + &zero) == &x -// } -// } -// -// quickcheck! { -// fn sub_is_add_negation(x: Signed, y: Signed) -> bool { -// (&x - &y) == (&x + (- &y)) -// } -// } -// -// quickcheck! { -// fn mul_associates(x: Signed, y: Signed, z: Signed) -// -> bool -// { -// let mut a = x.clone(); -// let mut b = y.clone(); -// let mut c = z.clone(); -// -// // we shift these right because rollover makes for weird behavior -// a.value >>= 258; -// b.value >>= 258; -// c.value >>= 258; -// -// (&a * (&b * &c)) == ((&a * &b) * &c) -// } -// fn mul_commutes(x: Signed, y: Signed) -> bool { -// (&x * &y) == (&y * &x) -// } -// fn mul_identity(x: Signed) -> bool { -// let one = Signed{ positive: true, value: U512::from_u8(1) }; -// (&x * &one) == &x -// } -// } -// -// quickcheck! { -// fn add_mul_distribution(x:Signed,y:Signed,z:Signed) -// -> bool -// { -// let mut a = x.clone(); -// let mut b = y.clone(); -// let mut c = z.clone(); -// -// // we shift these right because rollover makes for weird behavior -// a.value >>= 258; -// b.value >>= 258; -// c.value >>= 258; -// -// (&a * (&b + &c)) == ((&a * &b) + (&a * &c)) -// } -// } -//} +construct_signed!(I512, U512, i512); +construct_signed!(I1024, U1024, i1024); +construct_signed!(I2048, U2048, i2048); +construct_signed!(I3072, U3072, i3072); +construct_signed!(I4096, U4096, i4096); +construct_signed!(I7680, U7680, i7680); +construct_signed!(I8192, U8192, i8192); +construct_signed!(I15360, U15360, i15360);