And, or, and xor.

This commit is contained in:
2018-03-25 20:14:25 -07:00
parent a595eb349d
commit d53cdb6c97
2 changed files with 266 additions and 1 deletions

View 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
}
}
}
}

View File

@@ -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)
}
}
} }