And, or, and xor.
This commit is contained in:
50
src/cryptonum/complete_arith.rs
Normal file
50
src/cryptonum/complete_arith.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
macro_rules! derive_arithmetic_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, 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, 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, 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, other: &$type) -> $type {
|
||||
let mut res = self.clone();
|
||||
res.$asnfn(other);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
#[macro_use]
|
||||
mod conversions;
|
||||
#[macro_use]
|
||||
mod complete_arith;
|
||||
|
||||
use num::{BigUint,ToPrimitive,Zero};
|
||||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::*;
|
||||
|
||||
@@ -26,6 +30,58 @@ impl UCN {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand(&mut self, rhs: &UCN) {
|
||||
while self.contents.len() < rhs.contents.len() {
|
||||
self.contents.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for UCN {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(),fmt::Error> {
|
||||
for x in self.contents.iter().rev() {
|
||||
fmt.write_char(tochar_upper(x >> 60))?;
|
||||
fmt.write_char(tochar_upper(x >> 56))?;
|
||||
fmt.write_char(tochar_upper(x >> 52))?;
|
||||
fmt.write_char(tochar_upper(x >> 48))?;
|
||||
fmt.write_char(tochar_upper(x >> 44))?;
|
||||
fmt.write_char(tochar_upper(x >> 40))?;
|
||||
fmt.write_char(tochar_upper(x >> 36))?;
|
||||
fmt.write_char(tochar_upper(x >> 32))?;
|
||||
fmt.write_char(tochar_upper(x >> 28))?;
|
||||
fmt.write_char(tochar_upper(x >> 24))?;
|
||||
fmt.write_char(tochar_upper(x >> 20))?;
|
||||
fmt.write_char(tochar_upper(x >> 16))?;
|
||||
fmt.write_char(tochar_upper(x >> 12))?;
|
||||
fmt.write_char(tochar_upper(x >> 8))?;
|
||||
fmt.write_char(tochar_upper(x >> 4))?;
|
||||
fmt.write_char(tochar_upper(x >> 0))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn tochar_upper(x: u64) -> char {
|
||||
match (x as u8) & (0xF as u8) {
|
||||
0x0 => '0',
|
||||
0x1 => '1',
|
||||
0x2 => '2',
|
||||
0x3 => '3',
|
||||
0x4 => '4',
|
||||
0x5 => '5',
|
||||
0x6 => '6',
|
||||
0x7 => '7',
|
||||
0x8 => '8',
|
||||
0x9 => '9',
|
||||
0xA => 'A',
|
||||
0xB => 'B',
|
||||
0xC => 'C',
|
||||
0xD => 'D',
|
||||
0xE => 'E',
|
||||
0xF => 'F',
|
||||
_ => panic!("the world is broken")
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -132,6 +188,81 @@ impl Not for UCN {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Not for &'a UCN {
|
||||
type Output = UCN;
|
||||
|
||||
fn not(self) -> UCN {
|
||||
let res = self.clone();
|
||||
res.not()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BitOrAssign<&'a UCN> for UCN {
|
||||
fn bitor_assign(&mut self, rhs: &UCN) {
|
||||
self.expand(&rhs);
|
||||
{
|
||||
let mut iter_me = self.contents.iter_mut();
|
||||
let mut iter_tm = rhs.contents.iter();
|
||||
|
||||
loop {
|
||||
match (iter_me.next(), iter_tm.next()) {
|
||||
(Some(dest), Some(val)) =>
|
||||
*dest |= val,
|
||||
_ =>
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
self.clean();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BitXorAssign<&'a UCN> for UCN {
|
||||
fn bitxor_assign(&mut self, rhs: &UCN) {
|
||||
self.expand(&rhs);
|
||||
{
|
||||
let mut iter_me = self.contents.iter_mut();
|
||||
let mut iter_tm = rhs.contents.iter();
|
||||
|
||||
loop {
|
||||
match (iter_me.next(), iter_tm.next()) {
|
||||
(Some(dest), Some(val)) =>
|
||||
*dest ^= val,
|
||||
_ =>
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
self.clean();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BitAndAssign<&'a UCN> for UCN {
|
||||
fn bitand_assign(&mut self, rhs: &UCN) {
|
||||
if self.contents.len() > rhs.contents.len() {
|
||||
self.contents.resize(rhs.contents.len(), 0);
|
||||
}
|
||||
{
|
||||
let mut iter_me = self.contents.iter_mut();
|
||||
let mut iter_tm = rhs.contents.iter();
|
||||
|
||||
loop {
|
||||
match (iter_me.next(), iter_tm.next()) {
|
||||
(Some(dest), Some(val)) =>
|
||||
*dest &= val,
|
||||
_ =>
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
self.clean();
|
||||
}
|
||||
}
|
||||
|
||||
derive_arithmetic_operators!(UCN, BitOr, bitor, BitOrAssign, bitor_assign);
|
||||
derive_arithmetic_operators!(UCN, BitXor, bitxor, BitXorAssign, bitxor_assign);
|
||||
derive_arithmetic_operators!(UCN, BitAnd, bitand, BitAndAssign, bitand_assign);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Tests!
|
||||
@@ -232,7 +363,7 @@ mod test {
|
||||
|
||||
impl Arbitrary for UCN {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> UCN {
|
||||
let lenopts = [4,8,16,32,48,64,112,128,240];
|
||||
let lenopts = [4,8]; //,8,16,32,48,64,112,128,240];
|
||||
let mut len = *g.choose(&lenopts).unwrap();
|
||||
let mut contents = Vec::with_capacity(len);
|
||||
|
||||
@@ -260,4 +391,88 @@ mod test {
|
||||
x3 == x
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn or_associative(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
((&a | &b) | &c) == (&a | (&b | &c))
|
||||
}
|
||||
fn xor_associative(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
((&a ^ &b) ^ &c) == (&a ^ (&b ^ &c))
|
||||
}
|
||||
fn and_associative(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
((&a & &b) & &c) == (&a & (&b & &c))
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn or_commutative(a: UCN, b: UCN) -> bool {
|
||||
(&a | &b) == (&b | &a)
|
||||
}
|
||||
fn xor_commutative(a: UCN, b: UCN) -> bool {
|
||||
(&a ^ &b) == (&b ^ &a)
|
||||
}
|
||||
fn and_commutative(a: UCN, b: UCN) -> bool {
|
||||
(&a & &b) == (&b & &a)
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn or_identity(a: UCN) -> bool {
|
||||
(&a | &UCN{ contents: vec![] }) == a
|
||||
}
|
||||
fn xor_identity(a: UCN) -> bool {
|
||||
(&a ^ &UCN{ contents: vec![] }) == a
|
||||
}
|
||||
fn and_identity(a: UCN) -> bool {
|
||||
let mut contents = Vec::new();
|
||||
contents.resize(a.contents.len(), 0xFFFFFFFFFFFFFFFF);
|
||||
let effs = UCN{ contents: contents };
|
||||
(&a & &effs) == a
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn or_annihilator(a: UCN) -> bool {
|
||||
let mut contents = Vec::new();
|
||||
contents.resize(a.contents.len(), 0xFFFFFFFFFFFFFFFF);
|
||||
let effs = UCN{ contents: contents };
|
||||
(&a | &effs) == effs
|
||||
}
|
||||
fn and_annihilator(a: UCN) -> bool {
|
||||
let zero = UCN{ contents: vec![] };
|
||||
(&a & &zero) == zero
|
||||
}
|
||||
fn xor_inverse(a: UCN, b: UCN) -> bool {
|
||||
((&a ^ &b) ^ &b) == a
|
||||
}
|
||||
fn or_idempotent(a: UCN, b: UCN) -> bool {
|
||||
(&a | &b) == ((&a | &b) | &b)
|
||||
}
|
||||
fn and_idempotent(a: UCN, b: UCN) -> bool {
|
||||
(&a & &b) == ((&a & &b) & &b)
|
||||
}
|
||||
fn andor_absorbtion(a: UCN, b: UCN) -> bool {
|
||||
(&a & (&a | &b)) == a
|
||||
}
|
||||
fn orand_absorbtion(a: UCN, b: UCN) -> bool {
|
||||
(&a | (&a & &b)) == a
|
||||
}
|
||||
fn and_over_or_distribution(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
(&a & (&b | &c)) == ((&a & &b) | (&a & &c))
|
||||
}
|
||||
fn and_over_xor_distribution(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
(&a & (&b ^ &c)) == ((&a & &b) ^ (&a & &c))
|
||||
}
|
||||
fn or_over_and_distribution(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
(&a | (&b & &c)) == ((&a | &b) & (&a | &c))
|
||||
}
|
||||
fn demorgans(a: UCN, b: UCN) -> bool {
|
||||
let mut a2 = if a.contents.len() < b.contents.len() {a.clone()}
|
||||
else {b.clone()};
|
||||
let b2 = if a.contents.len() < b.contents.len() {b.clone()}
|
||||
else {a.clone()};
|
||||
expand_to_match(&mut a2, &b2);
|
||||
(!(&a2 | &b2)) == (!a2 & !b2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user