diff --git a/src/cryptonum/mod.rs b/src/cryptonum/mod.rs index 5e3fd59..85664da 100644 --- a/src/cryptonum/mod.rs +++ b/src/cryptonum/mod.rs @@ -14,5 +14,5 @@ mod unsigned; // pub use self::extended_math::{modexp,modinv,extended_euclidean,egcd}; // pub use self::primes::{probably_prime}; -pub use self::signed::{Signed}; +pub use self::signed::{I512}; pub use self::unsigned::{U512,U1024,U2048,U3072,U4096,U7680,U8192,U15360}; diff --git a/src/cryptonum/signed.rs b/src/cryptonum/signed.rs index 2c64b28..ece8354 100644 --- a/src/cryptonum/signed.rs +++ b/src/cryptonum/signed.rs @@ -1,431 +1,443 @@ use cryptonum::traits::*; -use std::cmp::Ordering; -use std::fmt::{Debug,Error,Formatter}; -use std::ops::*; +use cryptonum::unsigned::*; -pub struct Signed { - positive: bool, - value: T +pub struct I512 { + negative: bool, + value: U512 } -impl Signed { - pub fn new(v: T) -> Signed { - Signed{ positive: true, value: v } - } - pub fn abs(&self) -> T - where T: Clone - { - self.value.clone() - } +//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() } +// } +//} - pub fn is_positive(&self) -> bool - where T: CryptoNumBase - { - self.positive && !self.value.is_zero() - } - - pub fn is_negative(&self) -> bool - where T: CryptoNumBase - { - !self.positive && !self.value.is_zero() - } - - pub fn negate(&mut self) - { - self.positive = !self.positive; - } -} - -impl CryptoNumBase for Signed { - 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)) - } - } -} +//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)) +// } +// } +//} diff --git a/src/cryptonum/traits.rs b/src/cryptonum/traits.rs index 9a16888..8e9e1d1 100644 --- a/src/cryptonum/traits.rs +++ b/src/cryptonum/traits.rs @@ -56,3 +56,18 @@ pub trait CryptoNumFastMod { /// Faster modulo through the use of the Barrett constant, above. fn fastmod(&self, &Self::BarrettMu) -> Self; } + +pub trait CryptoNumSigned { + /// The unsigned type that this type is related to. + type Unsigned; + + /// Generate a new signed number based on the given unsigned number. + fn new(x: Self::Unsigned) -> Self; + /// Get the absolute value of the signed number, turning it back into an + /// unsigned number. + fn abs(&self) -> Self::Unsigned; + /// Test if the number is negative. + fn is_negative(&self) -> bool; + /// Test if the number is positive. + fn is_positive(&self) -> bool; +}