Nevermind, let's try doing this in a less type-filled way.

This commit is contained in:
2018-03-11 18:08:25 -07:00
parent 667e32694e
commit 10a46a7e81
3 changed files with 453 additions and 426 deletions

View File

@@ -14,5 +14,5 @@ mod unsigned;
// pub use self::extended_math::{modexp,modinv,extended_euclidean,egcd}; // pub use self::extended_math::{modexp,modinv,extended_euclidean,egcd};
// pub use self::primes::{probably_prime}; // 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}; pub use self::unsigned::{U512,U1024,U2048,U3072,U4096,U7680,U8192,U15360};

View File

@@ -1,431 +1,443 @@
use cryptonum::traits::*; use cryptonum::traits::*;
use std::cmp::Ordering; use cryptonum::unsigned::*;
use std::fmt::{Debug,Error,Formatter};
use std::ops::*;
pub struct Signed<T: Sized> { pub struct I512 {
positive: bool, negative: bool,
value: T value: U512
} }
impl<T> Signed<T> {
pub fn new(v: T) -> Signed<T> {
Signed{ positive: true, value: v }
}
pub fn abs(&self) -> T //use cryptonum::traits::*;
where T: Clone //use std::cmp::Ordering;
{ //use std::fmt::{Debug,Error,Formatter};
self.value.clone() //use std::ops::*;
} //
//pub struct Signed<T: Sized>
// where T: Clone + CryptoNumBase + Sized
//{
// positive: bool,
// value: T
//}
//
//impl<T> Signed<T>
// where T: Clone + CryptoNumBase + Sized
//{
// pub fn new(v: T) -> Signed<T> {
// 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<T> CryptoNumBase for Signed<T>
// where T: Clone + CryptoNumBase + Sized
//{
// fn zero() -> Signed<T> {
// Signed{ positive: true, value: T::zero() }
// }
// fn max_value() -> Signed<T> {
// 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<T> {
// Signed{ positive: true, value: T::from_u8(x) }
// }
// fn to_u8(&self) -> u8 {
// self.value.to_u8()
// }
// fn from_u16(x: u16) -> Signed<T> {
// Signed{ positive: true, value: T::from_u16(x) }
// }
// fn to_u16(&self) -> u16 {
// self.value.to_u16()
// }
// fn from_u32(x: u32) -> Signed<T> {
// Signed{ positive: true, value: T::from_u32(x) }
// }
// fn to_u32(&self) -> u32 {
// self.value.to_u32()
// }
// fn from_u64(x: u64) -> Signed<T> {
// Signed{ positive: true, value: T::from_u64(x) }
// }
// fn to_u64(&self) -> u64 {
// self.value.to_u64()
// }
//}
//
//impl<T: CryptoNumFastMod> CryptoNumFastMod for Signed<T> {
// type BarrettMu = T::BarrettMu;
//
// fn barrett_mu(&self) -> Option<T::BarrettMu> {
// if self.positive {
// self.value.barrett_mu()
// } else {
// None
// }
// }
//
// fn fastmod(&self, mu: &T::BarrettMu) -> Signed<T> {
// Signed{ positive: self.positive, value: self.value.fastmod(&mu) }
// }
//}
//
//impl<T: Clone> Clone for Signed<T> {
// fn clone(&self) -> Signed<T> {
// Signed{ positive: self.positive, value: self.value.clone() }
// }
//}
pub fn is_positive(&self) -> bool //impl<'a,T: PartialEq> PartialEq<&'a Signed<T>> for Signed<T> {
where T: CryptoNumBase // fn eq(&self, other: &&Signed<T>) -> bool {
{ // (self.positive == other.positive) && (self.value == other.value)
self.positive && !self.value.is_zero() // }
} //}
//
pub fn is_negative(&self) -> bool //impl<'a,T: PartialEq> PartialEq<Signed<T>> for &'a Signed<T> {
where T: CryptoNumBase // fn eq(&self, other: &Signed<T>) -> bool {
{ // (self.positive == other.positive) && (self.value == other.value)
!self.positive && !self.value.is_zero() // }
} //}
//
pub fn negate(&mut self) //impl<T: PartialEq> PartialEq for Signed<T> {
{ // fn eq(&self, other: &Signed<T>) -> bool {
self.positive = !self.positive; // (self.positive == other.positive) && (self.value == other.value)
} // }
} //}
//
impl<T: CryptoNumBase> CryptoNumBase for Signed<T> { //impl<T: Eq> Eq for Signed<T> {}
fn zero() -> Signed<T> { //
Signed{ positive: true, value: T::zero() } //impl<T: Debug> Debug for Signed<T> {
} // fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
fn max_value() -> Signed<T> { // if self.positive {
Signed{ positive: true, value: T::max_value() } // f.write_str("+")?;
} // } else {
fn is_zero(&self) -> bool { // f.write_str("-")?;
self.value.is_zero() // }
} // self.value.fmt(f)
fn is_odd(&self) -> bool { // }
self.value.is_odd() //}
} //
fn is_even(&self) -> bool { //impl<T: Ord> Ord for Signed<T> {
self.value.is_even() // fn cmp(&self, other: &Signed<T>) -> Ordering {
} // match (self.positive, other.positive) {
fn from_u8(x: u8) -> Signed<T> { // (true, true) => self.value.cmp(&other.value),
Signed{ positive: true, value: T::from_u8(x) } // (true, false) => Ordering::Greater,
} // (false, true) => Ordering::Less,
fn to_u8(&self) -> u8 { // (false, false) =>
self.value.to_u8() // self.value.cmp(&other.value).reverse()
} // }
fn from_u16(x: u16) -> Signed<T> { // }
Signed{ positive: true, value: T::from_u16(x) } //}
} //
fn to_u16(&self) -> u16 { //impl<T: Ord> PartialOrd for Signed<T> {
self.value.to_u16() // fn partial_cmp(&self, other: &Signed<T>) -> Option<Ordering>{
} // Some(self.cmp(other))
fn from_u32(x: u32) -> Signed<T> { // }
Signed{ positive: true, value: T::from_u32(x) } //}
} //
fn to_u32(&self) -> u32 { ////------------------------------------------------------------------------------
self.value.to_u32() //
} //impl<T: Clone> Neg for Signed<T> {
fn from_u64(x: u64) -> Signed<T> { // type Output = Signed<T>;
Signed{ positive: true, value: T::from_u64(x) } //
} // fn neg(self) -> Signed<T> {
fn to_u64(&self) -> u64 { // Signed {
self.value.to_u64() // positive: !self.positive,
} // value: self.value.clone()
} // }
// }
impl<T: CryptoNumFastMod> CryptoNumFastMod for Signed<T> { //}
type BarrettMu = T::BarrettMu; //
//impl<'a,T: Clone> Neg for &'a Signed<T> {
fn barrett_mu(&self) -> Option<T::BarrettMu> { // type Output = Signed<T>;
if self.positive { //
self.value.barrett_mu() // fn neg(self) -> Signed<T> {
} else { // Signed {
None // positive: !self.positive,
} // value: self.value.clone()
} // }
// }
fn fastmod(&self, mu: &T::BarrettMu) -> Signed<T> { //}
Signed{ positive: self.positive, value: self.value.fastmod(&mu) } //
} ////------------------------------------------------------------------------------
} //
//impl<T> AddAssign for Signed<T>
impl<T: Clone> Clone for Signed<T> { // where
fn clone(&self) -> Signed<T> { // T: Clone + Ord,
Signed{ positive: self.positive, value: self.value.clone() } // T: AddAssign + SubAssign,
} //{
} // fn add_assign(&mut self, other: Signed<T>) {
// match (self.positive, other.positive, self.value.cmp(&other.value)) {
impl<'a,T: PartialEq> PartialEq<&'a Signed<T>> for Signed<T> { // // if the signs are the same, we maintain the sign and just increase
fn eq(&self, other: &&Signed<T>) -> bool { // // the magnitude
(self.positive == other.positive) && (self.value == other.value) // (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
impl<'a,T: PartialEq> PartialEq<Signed<T>> for &'a Signed<T> { // // timing roughly similar.
fn eq(&self, other: &Signed<T>) -> bool { // (_, _, Ordering::Equal) => {
(self.positive == other.positive) && (self.value == other.value) // self.positive = true;
} // self.value.sub_assign(other.value);
} // }
// // if the signs are different and the first one is less than the
impl<T: PartialEq> PartialEq for Signed<T> { // // second, then we flip the sign and subtract.
fn eq(&self, other: &Signed<T>) -> bool { // (_, _, Ordering::Less) => {
(self.positive == other.positive) && (self.value == other.value) // self.positive = !self.positive;
} // let temp = self.value.clone();
} // self.value = other.value.clone();
// self.value.sub_assign(temp);
impl<T: Eq> Eq for Signed<T> {} // }
// // if the signs are different and the first one is greater than the
impl<T: Debug> Debug for Signed<T> { // // second, then we leave the sign and subtract.
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { // (_, _, Ordering::Greater) => {
if self.positive { // self.value.sub_assign(other.value);
f.write_str("+")?; // }
} else { // }
f.write_str("-")?; // }
} //}
self.value.fmt(f) //
} //impl<'a,T> AddAssign<&'a Signed<T>> for Signed<T>
} // where
// T: Clone + Ord,
impl<T: Ord> Ord for Signed<T> { // T: AddAssign + SubAssign,
fn cmp(&self, other: &Signed<T>) -> Ordering { // T: AddAssign<&'a T> + SubAssign<&'a T>
match (self.positive, other.positive) { //{
(true, true) => self.value.cmp(&other.value), // fn add_assign(&mut self, other: &'a Signed<T>) {
(true, false) => Ordering::Greater, // match (self.positive, other.positive, self.value.cmp(&other.value)) {
(false, true) => Ordering::Less, // // if the signs are the same, we maintain the sign and just increase
(false, false) => // // the magnitude
self.value.cmp(&other.value).reverse() // (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.
impl<T: Ord> PartialOrd for Signed<T> { // (_, _, Ordering::Equal) => {
fn partial_cmp(&self, other: &Signed<T>) -> Option<Ordering>{ // self.positive = true;
Some(self.cmp(other)) // 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;
impl<T: Clone> Neg for Signed<T> { // let temp = self.value.clone();
type Output = Signed<T>; // self.value = other.value.clone();
// self.value.sub_assign(temp);
fn neg(self) -> Signed<T> { // }
Signed { // // if the signs are different and the first one is greater than the
positive: !self.positive, // // second, then we leave the sign and subtract.
value: self.value.clone() // (_, _, Ordering::Greater) => {
} // self.value.sub_assign(&other.value);
} // }
} // }
// }
impl<'a,T: Clone> Neg for &'a Signed<T> { //}
type Output = Signed<T>; //
//math_operator!(Add,add,add_assign);
fn neg(self) -> Signed<T> { //
Signed { ////------------------------------------------------------------------------------
positive: !self.positive, //
value: self.value.clone() //impl<T> SubAssign for Signed<T>
} // where
} // T: Clone + Ord,
} // T: AddAssign + SubAssign,
//{
//------------------------------------------------------------------------------ // fn sub_assign(&mut self, other: Signed<T>) {
// let mut other2 = other.clone();
impl<T> AddAssign for Signed<T> // other2.positive = !other.positive;
where // self.add_assign(other2);
T: Clone + Ord, // }
T: AddAssign + SubAssign, //}
{ //
fn add_assign(&mut self, other: Signed<T>) { //impl<'a,T> SubAssign<&'a Signed<T>> for Signed<T>
match (self.positive, other.positive, self.value.cmp(&other.value)) { // where
// if the signs are the same, we maintain the sign and just increase // T: Clone + Ord,
// the magnitude // T: AddAssign + SubAssign,
(x, y, _) if x == y => // T: AddAssign<&'a T> + SubAssign<&'a T>
self.value.add_assign(other.value), //{
// if the signs are different and the numbers are equal, we just set // fn sub_assign(&mut self, other: &'a Signed<T>) {
// this to zero. However, we actually do the subtraction to make the // let mut other2 = other.clone();
// timing roughly similar. // other2.positive = !other.positive;
(_, _, Ordering::Equal) => { // self.add_assign(other2);
self.positive = true; // }
self.value.sub_assign(other.value); //}
} //
// if the signs are different and the first one is less than the //math_operator!(Sub,sub,sub_assign);
// second, then we flip the sign and subtract. //
(_, _, Ordering::Less) => { ////------------------------------------------------------------------------------
self.positive = !self.positive; //
let temp = self.value.clone(); //impl<T> MulAssign for Signed<T>
self.value = other.value.clone(); // where
self.value.sub_assign(temp); // T: MulAssign
} //{
// if the signs are different and the first one is greater than the // fn mul_assign(&mut self, other: Signed<T>) {
// second, then we leave the sign and subtract. // self.positive = !(self.positive ^ other.positive);
(_, _, Ordering::Greater) => { // self.value *= other.value;
self.value.sub_assign(other.value); // }
} //}
} //
} //impl<'a,T> MulAssign<&'a Signed<T>> for Signed<T>
} // where
// T: MulAssign + MulAssign<&'a T>
impl<'a,T> AddAssign<&'a Signed<T>> for Signed<T> //{
where // fn mul_assign(&mut self, other: &'a Signed<T>) {
T: Clone + Ord, // self.positive = !(self.positive ^ other.positive);
T: AddAssign + SubAssign, // self.value *= &other.value;
T: AddAssign<&'a T> + SubAssign<&'a T> // }
{ //}
fn add_assign(&mut self, other: &'a Signed<T>) { //
match (self.positive, other.positive, self.value.cmp(&other.value)) { //math_operator!(Mul,mul,mul_assign);
// 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), //impl<T> DivAssign for Signed<T>
// if the signs are different and the numbers are equal, we just set // where
// this to zero. However, we actually do the subtraction to make the // T: DivAssign
// timing roughly similar. //{
(_, _, Ordering::Equal) => { // fn div_assign(&mut self, other: Signed<T>) {
self.positive = true; // self.positive = !(self.positive ^ other.positive);
self.value.sub_assign(&other.value); // self.value /= 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) => { //impl<'a,T> DivAssign<&'a Signed<T>> for Signed<T>
self.positive = !self.positive; // where
let temp = self.value.clone(); // T: DivAssign + DivAssign<&'a T>
self.value = other.value.clone(); //{
self.value.sub_assign(temp); // fn div_assign(&mut self, other: &'a Signed<T>) {
} // self.positive = !(self.positive ^ other.positive);
// if the signs are different and the first one is greater than the // self.value /= &other.value;
// second, then we leave the sign and subtract. // }
(_, _, Ordering::Greater) => { //}
self.value.sub_assign(&other.value); //
} //math_operator!(Div,div,div_assign);
} //
} ////------------------------------------------------------------------------------
} //
//#[cfg(test)]
math_operator!(Add,add,add_assign); //mod tests {
// use cryptonum::unsigned::U512;
//------------------------------------------------------------------------------ // use quickcheck::{Arbitrary,Gen};
// use std::cmp::{max,min};
impl<T> SubAssign for Signed<T> // use super::*;
where //
T: Clone + Ord, // impl<T: Arbitrary + CryptoNumBase> Arbitrary for Signed<T> {
T: AddAssign + SubAssign, // fn arbitrary<G: Gen>(g: &mut G) -> Signed<T> {
{ // let value = T::arbitrary(g);
fn sub_assign(&mut self, other: Signed<T>) { // if value.is_zero() {
let mut other2 = other.clone(); // Signed {
other2.positive = !other.positive; // positive: true,
self.add_assign(other2); // value: value
} // }
} // } else {
// Signed {
impl<'a,T> SubAssign<&'a Signed<T>> for Signed<T> // positive: g.gen_weighted_bool(2),
where // value: value
T: Clone + Ord, // }
T: AddAssign + SubAssign, // }
T: AddAssign<&'a T> + SubAssign<&'a T> // }
{ // }
fn sub_assign(&mut self, other: &'a Signed<T>) { //
let mut other2 = other.clone(); // quickcheck! {
other2.positive = !other.positive; // fn double_negation(x: Signed<U512>) -> bool {
self.add_assign(other2); // &x == (- (- &x))
} // }
} // }
//
math_operator!(Sub,sub,sub_assign); // quickcheck! {
// fn add_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
//------------------------------------------------------------------------------ // -> bool
// {
impl<T> MulAssign for Signed<T> // let mut a = x.clone();
where // let mut b = y.clone();
T: MulAssign // let mut c = z.clone();
{ //
fn mul_assign(&mut self, other: Signed<T>) { // // we shift these right because rollover makes for weird behavior
self.positive = !(self.positive ^ other.positive); // a.value >>= 2;
self.value *= other.value; // b.value >>= 2;
} // c.value >>= 2;
} //
// (&a + (&b + &c)) == ((&a + &b) + &c)
impl<'a,T> MulAssign<&'a Signed<T>> for Signed<T> // }
where // fn add_commutes(x: Signed<U512>, y: Signed<U512>) -> bool {
T: MulAssign + MulAssign<&'a T> // (&x + &y) == (&y + &x)
{ // }
fn mul_assign(&mut self, other: &'a Signed<T>) { // fn add_identity(x: Signed<U512>) -> bool {
self.positive = !(self.positive ^ other.positive); // let zero = Signed{ positive: true, value: U512::zero() };
self.value *= &other.value; // (&x + &zero) == &x
} // }
} // }
//
math_operator!(Mul,mul,mul_assign); // quickcheck! {
// fn sub_is_add_negation(x: Signed<U512>, y: Signed<U512>) -> bool {
//------------------------------------------------------------------------------ // (&x - &y) == (&x + (- &y))
// }
impl<T> DivAssign for Signed<T> // }
where //
T: DivAssign // quickcheck! {
{ // fn mul_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
fn div_assign(&mut self, other: Signed<T>) { // -> bool
self.positive = !(self.positive ^ other.positive); // {
self.value /= other.value; // let mut a = x.clone();
} // let mut b = y.clone();
} // let mut c = z.clone();
//
impl<'a,T> DivAssign<&'a Signed<T>> for Signed<T> // // we shift these right because rollover makes for weird behavior
where // a.value >>= 258;
T: DivAssign + DivAssign<&'a T> // b.value >>= 258;
{ // c.value >>= 258;
fn div_assign(&mut self, other: &'a Signed<T>) { //
self.positive = !(self.positive ^ other.positive); // (&a * (&b * &c)) == ((&a * &b) * &c)
self.value /= &other.value; // }
} // fn mul_commutes(x: Signed<U512>, y: Signed<U512>) -> bool {
} // (&x * &y) == (&y * &x)
// }
math_operator!(Div,div,div_assign); // fn mul_identity(x: Signed<U512>) -> bool {
// let one = Signed{ positive: true, value: U512::from_u8(1) };
//------------------------------------------------------------------------------ // (&x * &one) == &x
// }
#[cfg(test)] // }
mod tests { //
use cryptonum::unsigned::U512; // quickcheck! {
use quickcheck::{Arbitrary,Gen}; // fn add_mul_distribution(x:Signed<U512>,y:Signed<U512>,z:Signed<U512>)
use std::cmp::{max,min}; // -> bool
use super::*; // {
// let mut a = x.clone();
impl<T: Arbitrary + CryptoNumBase> Arbitrary for Signed<T> { // let mut b = y.clone();
fn arbitrary<G: Gen>(g: &mut G) -> Signed<T> { // let mut c = z.clone();
let value = T::arbitrary(g); //
if value.is_zero() { // // we shift these right because rollover makes for weird behavior
Signed { // a.value >>= 258;
positive: true, // b.value >>= 258;
value: value // c.value >>= 258;
} //
} else { // (&a * (&b + &c)) == ((&a * &b) + (&a * &c))
Signed { // }
positive: g.gen_weighted_bool(2), // }
value: value //}
}
}
}
}
quickcheck! {
fn double_negation(x: Signed<U512>) -> bool {
&x == (- (- &x))
}
}
quickcheck! {
fn add_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
-> 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<U512>, y: Signed<U512>) -> bool {
(&x + &y) == (&y + &x)
}
fn add_identity(x: Signed<U512>) -> bool {
let zero = Signed{ positive: true, value: U512::zero() };
(&x + &zero) == &x
}
}
quickcheck! {
fn sub_is_add_negation(x: Signed<U512>, y: Signed<U512>) -> bool {
(&x - &y) == (&x + (- &y))
}
}
quickcheck! {
fn mul_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
-> 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<U512>, y: Signed<U512>) -> bool {
(&x * &y) == (&y * &x)
}
fn mul_identity(x: Signed<U512>) -> bool {
let one = Signed{ positive: true, value: U512::from_u8(1) };
(&x * &one) == &x
}
}
quickcheck! {
fn add_mul_distribution(x:Signed<U512>,y:Signed<U512>,z:Signed<U512>)
-> 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))
}
}
}

View File

@@ -56,3 +56,18 @@ pub trait CryptoNumFastMod {
/// Faster modulo through the use of the Barrett constant, above. /// Faster modulo through the use of the Barrett constant, above.
fn fastmod(&self, &Self::BarrettMu) -> Self; 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;
}