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]
|
#[macro_use]
|
||||||
mod conversions;
|
mod conversions;
|
||||||
|
#[macro_use]
|
||||||
|
mod complete_arith;
|
||||||
|
|
||||||
use num::{BigUint,ToPrimitive,Zero};
|
use num::{BigUint,ToPrimitive,Zero};
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Write;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ops::*;
|
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!
|
// Tests!
|
||||||
@@ -232,7 +363,7 @@ mod test {
|
|||||||
|
|
||||||
impl Arbitrary for UCN {
|
impl Arbitrary for UCN {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> 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 len = *g.choose(&lenopts).unwrap();
|
||||||
let mut contents = Vec::with_capacity(len);
|
let mut contents = Vec::with_capacity(len);
|
||||||
|
|
||||||
@@ -260,4 +391,88 @@ mod test {
|
|||||||
x3 == x
|
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