Cleaner (?) implementation of signed numbers.

This commit is contained in:
2018-03-11 21:18:54 -07:00
parent 10a46a7e81
commit 9594a40d32
2 changed files with 345 additions and 703 deletions

View File

@@ -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<Ordering> {
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<Self::BarrettMu> {
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: Gen>(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 { macro_rules! construct_unsigned {
($type: ident, $barrett: ident, $modname: ident, $count: expr) => { ($type: ident, $barrett: ident, $modname: ident, $count: expr) => {
#[derive(Clone)] #[derive(Clone)]
@@ -75,9 +365,12 @@ macro_rules! construct_unsigned {
} }
} }
opers2!($type,BitOrAssign,bitor_assign,BitOr,bitor,generic_bitor); generic_2arg!($type, BitOrAssign, bitor_assign, generic_bitor);
opers2!($type,BitAndAssign,bitand_assign,BitAnd,bitand,generic_bitand); generic_2arg!($type, BitAndAssign, bitand_assign, generic_bitand);
opers2!($type,BitXorAssign,bitxor_assign,BitXor,bitxor,generic_bitxor); 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, usize);
shifts!($type, u64); shifts!($type, u64);
@@ -89,19 +382,6 @@ macro_rules! construct_unsigned {
shifts!($type, u8); shifts!($type, u8);
shifts!($type, i8); 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(&copy, &rhs.contents,
&mut self.contents, &mut dead);
}
}
impl<'a> DivAssign<&'a $type> for $type { impl<'a> DivAssign<&'a $type> for $type {
fn div_assign(&mut self, rhs: &$type) { fn div_assign(&mut self, rhs: &$type) {
let mut dead = [0; $count]; 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(&copy, &rhs.contents,
&mut dead, &mut self.contents);
}
}
impl<'a> RemAssign<&'a $type> for $type { impl<'a> RemAssign<&'a $type> for $type {
fn rem_assign(&mut self, rhs: &$type) { fn rem_assign(&mut self, rhs: &$type) {
let mut dead = [0; $count]; let mut dead = [0; $count];
@@ -177,53 +400,14 @@ macro_rules! construct_unsigned {
} }
} }
impl Rem<$type> for $type { derive_operators!($type, BitOr, bitor, BitOrAssign, bitor_assign);
type Output = $type; derive_operators!($type, BitAnd, bitand, BitAndAssign, bitand_assign);
derive_operators!($type, BitXor, bitxor, BitXorAssign, bitxor_assign);
fn rem(self, rhs: $type) -> $type { derive_operators!($type, Add, add, AddAssign, add_assign);
let mut res = $type::zero(); derive_operators!($type, Sub, sub, SubAssign, sub_assign);
let mut dead = [0; $count]; derive_operators!($type, Mul, mul, MulAssign, mul_assign);
generic_div(&self.contents, &rhs.contents, derive_operators!($type, Div, div, DivAssign, div_assign);
&mut dead, &mut res.contents); derive_operators!($type, Rem, rem, RemAssign, rem_assign);
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
}
}
impl CryptoNumBase for $type { impl CryptoNumBase for $type {
fn zero() -> $type { fn zero() -> $type {
@@ -879,188 +1063,74 @@ macro_rules! shifts {
} }
} }
macro_rules! opers2 { macro_rules! generic_2arg {
($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => { ($type: ident, $asncl: ident, $asnfn: ident, $impl: ident) => {
impl $asncl for $type {
fn $asnfn(&mut self, other: $type) {
$impl(&mut self.contents, &other.contents);
}
}
impl<'a> $asncl<&'a $type> for $type { impl<'a> $asncl<&'a $type> for $type {
fn $asnfn(&mut self, other: &$type) { fn $asnfn(&mut self, other: &$type) {
$impl(&mut self.contents, &other.contents); $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 { macro_rules! generic_3arg {
($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => { ($type: ident, $asncl: ident, $asnfn: ident, $impl: ident) => {
impl $asncl for $type {
fn $asnfn(&mut self, other: $type) {
let copy = self.contents.clone();
$impl(&mut self.contents, &copy, &other.contents);
}
}
impl<'a> $asncl<&'a $type> for $type { impl<'a> $asncl<&'a $type> for $type {
fn $asnfn(&mut self, other: &$type) { fn $asnfn(&mut self, other: &$type) {
let copy = self.contents.clone(); let copy = self.contents.clone();
$impl(&mut self.contents, &copy, &other.contents); $impl(&mut self.contents, &copy, &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 { impl $cl for $type {
type Output = $type; type Output = $type;
fn $fn(self, rhs: $type) -> $type { fn $fn(self, other: $type) -> $type {
let mut copy = self.clone(); let mut res = self.clone();
$impl(&mut copy.contents, &self.contents, &rhs.contents); res.$asnfn(&other);
copy res
} }
} }
impl<'a> $cl<&'a $type> for $type { impl<'a> $cl<&'a $type> for $type {
type Output = $type; type Output = $type;
fn $fn(self, rhs: &$type) -> $type { fn $fn(self, other: &$type) -> $type {
let mut copy = self.clone(); let mut res = self.clone();
$impl(&mut copy.contents, &self.contents, &rhs.contents); res.$asnfn(other);
copy res
} }
} }
impl<'a> $cl<$type> for &'a $type { impl<'a> $cl<$type> for &'a $type {
type Output = $type; type Output = $type;
fn $fn(self, rhs: $type) -> $type { fn $fn(self, other: $type) -> $type {
let mut copy = self.clone(); let mut res = self.clone();
$impl(&mut copy.contents, &self.contents, &rhs.contents); res.$asnfn(&other);
copy res
} }
} }
impl<'a,'b> $cl<&'a $type> for &'b $type { impl<'a,'b> $cl<&'a $type> for &'b $type {
type Output = $type; type Output = $type;
fn $fn(self, rhs: &$type) -> $type { fn $fn(self, other: &$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<T> $cl for Signed<T>
where
T: Clone + Ord,
T: AddAssign + SubAssign + MulAssign + DivAssign,
{
type Output = Signed<T>;
fn $fn(self, rhs: Signed<T>) -> Signed<T>
{
let mut res = self.clone(); let mut res = self.clone();
res.$asn(rhs); res.$asnfn(other);
res
}
}
impl<'a,T> $cl<&'a Signed<T>> for Signed<T>
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<T>;
fn $fn(self, rhs: &'a Signed<T>) -> Signed<T>
{
let mut res = self.clone();
res.$asn(rhs);
res
}
}
impl<'a,T> $cl for &'a Signed<T>
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<T>;
fn $fn(self, rhs: &'a Signed<T>) -> Signed<T>
{
let mut res = self.clone();
res.$asn(rhs);
res
}
}
impl<'a,T> $cl<Signed<T>> for &'a Signed<T>
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<T>;
fn $fn(self, rhs: Signed<T>) -> Signed<T>
{
let mut res = self.clone();
res.$asn(rhs);
res res
} }
} }
} }
} }

View File

@@ -1,443 +1,15 @@
use cryptonum::core::*;
use cryptonum::traits::*; use cryptonum::traits::*;
use cryptonum::unsigned::*; use cryptonum::unsigned::*;
use std::cmp::Ordering;
use std::fmt::{Debug,Error,Formatter};
use std::ops::*;
pub struct I512 { construct_signed!(I512, U512, i512);
negative: bool, construct_signed!(I1024, U1024, i1024);
value: U512 construct_signed!(I2048, U2048, i2048);
} construct_signed!(I3072, U3072, i3072);
construct_signed!(I4096, U4096, i4096);
construct_signed!(I7680, U7680, i7680);
//use cryptonum::traits::*; construct_signed!(I8192, U8192, i8192);
//use std::cmp::Ordering; construct_signed!(I15360, U15360, i15360);
//use std::fmt::{Debug,Error,Formatter};
//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() }
// }
//}
//impl<'a,T: PartialEq> PartialEq<&'a Signed<T>> for Signed<T> {
// fn eq(&self, other: &&Signed<T>) -> bool {
// (self.positive == other.positive) && (self.value == other.value)
// }
//}
//
//impl<'a,T: PartialEq> PartialEq<Signed<T>> for &'a Signed<T> {
// fn eq(&self, other: &Signed<T>) -> bool {
// (self.positive == other.positive) && (self.value == other.value)
// }
//}
//
//impl<T: PartialEq> PartialEq for Signed<T> {
// fn eq(&self, other: &Signed<T>) -> bool {
// (self.positive == other.positive) && (self.value == other.value)
// }
//}
//
//impl<T: Eq> Eq for Signed<T> {}
//
//impl<T: Debug> Debug for Signed<T> {
// fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
// if self.positive {
// f.write_str("+")?;
// } else {
// f.write_str("-")?;
// }
// self.value.fmt(f)
// }
//}
//
//impl<T: Ord> Ord for Signed<T> {
// fn cmp(&self, other: &Signed<T>) -> 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<T: Ord> PartialOrd for Signed<T> {
// fn partial_cmp(&self, other: &Signed<T>) -> Option<Ordering>{
// Some(self.cmp(other))
// }
//}
//
////------------------------------------------------------------------------------
//
//impl<T: Clone> Neg for Signed<T> {
// type Output = Signed<T>;
//
// fn neg(self) -> Signed<T> {
// Signed {
// positive: !self.positive,
// value: self.value.clone()
// }
// }
//}
//
//impl<'a,T: Clone> Neg for &'a Signed<T> {
// type Output = Signed<T>;
//
// fn neg(self) -> Signed<T> {
// Signed {
// positive: !self.positive,
// value: self.value.clone()
// }
// }
//}
//
////------------------------------------------------------------------------------
//
//impl<T> AddAssign for Signed<T>
// where
// T: Clone + Ord,
// T: AddAssign + SubAssign,
//{
// fn add_assign(&mut self, other: Signed<T>) {
// 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<T>> for Signed<T>
// where
// T: Clone + Ord,
// T: AddAssign + SubAssign,
// 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)) {
// // 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<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();
// other2.positive = !other.positive;
// self.add_assign(other2);
// }
//}
//
//impl<'a,T> SubAssign<&'a Signed<T>> for Signed<T>
// where
// 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();
// other2.positive = !other.positive;
// self.add_assign(other2);
// }
//}
//
//math_operator!(Sub,sub,sub_assign);
//
////------------------------------------------------------------------------------
//
//impl<T> MulAssign for Signed<T>
// where
// T: MulAssign
//{
// fn mul_assign(&mut self, other: Signed<T>) {
// self.positive = !(self.positive ^ other.positive);
// self.value *= other.value;
// }
//}
//
//impl<'a,T> MulAssign<&'a Signed<T>> for Signed<T>
// where
// T: MulAssign + MulAssign<&'a T>
//{
// fn mul_assign(&mut self, other: &'a Signed<T>) {
// self.positive = !(self.positive ^ other.positive);
// self.value *= &other.value;
// }
//}
//
//math_operator!(Mul,mul,mul_assign);
//
////------------------------------------------------------------------------------
//
//impl<T> DivAssign for Signed<T>
// where
// T: DivAssign
//{
// fn div_assign(&mut self, other: Signed<T>) {
// self.positive = !(self.positive ^ other.positive);
// self.value /= other.value;
// }
//}
//
//impl<'a,T> DivAssign<&'a Signed<T>> for Signed<T>
// where
// T: DivAssign + DivAssign<&'a T>
//{
// fn div_assign(&mut self, other: &'a Signed<T>) {
// 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<T: Arbitrary + CryptoNumBase> Arbitrary for Signed<T> {
// fn arbitrary<G: Gen>(g: &mut G) -> Signed<T> {
// 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<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))
// }
// }
//}