Cleaner (?) implementation of signed numbers.
This commit is contained in:
@@ -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 {
|
||||
($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<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>
|
||||
{
|
||||
fn $fn(self, other: &$type) -> $type {
|
||||
let mut res = self.clone();
|
||||
res.$asn(rhs);
|
||||
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.$asnfn(other);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<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))
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user