mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-04 17:11:38 -05:00
basic logic for smalluint
This commit is contained in:
parent
543b4ef459
commit
85babc5e11
|
@ -20,6 +20,7 @@ pub use error::SmallIntError;
|
||||||
|
|
||||||
mod convert;
|
mod convert;
|
||||||
mod ops;
|
mod ops;
|
||||||
|
mod logic;
|
||||||
|
|
||||||
mod bigint;
|
mod bigint;
|
||||||
|
|
||||||
|
|
219
src/logic.rs
Normal file
219
src/logic.rs
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
use crate::SmallUint;
|
||||||
|
use crate::smallint::SmallUintType;
|
||||||
|
use core::ops::{BitAnd, BitOr, BitXor};
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
|
macro_rules! basic_op {
|
||||||
|
($imp:ident, $typ:ty, $fun:ident) => {
|
||||||
|
|
||||||
|
impl<'a, 'b> $imp<&'a $typ> for &'b $typ {
|
||||||
|
|
||||||
|
type Output = $typ;
|
||||||
|
|
||||||
|
fn $fun(self, rhs: &$typ) -> Self::Output {
|
||||||
|
$fun(self, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> $imp<$typ> for &'a $typ {
|
||||||
|
|
||||||
|
type Output = $typ;
|
||||||
|
|
||||||
|
fn $fun(self, rhs: $typ) -> Self::Output {
|
||||||
|
self.$fun(&rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> $imp<&'a $typ> for $typ {
|
||||||
|
|
||||||
|
type Output = $typ;
|
||||||
|
|
||||||
|
fn $fun(self, rhs: &$typ) -> Self::Output {
|
||||||
|
(&self).$fun(rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl $imp<$typ> for $typ {
|
||||||
|
|
||||||
|
type Output = $typ;
|
||||||
|
|
||||||
|
fn $fun(self, rhs: $typ) -> Self::Output {
|
||||||
|
(&self).$fun(&rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bitand(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
|
match (&a.0, &b.0) {
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
|
||||||
|
SmallUint(SmallUintType::Inline(i & j))
|
||||||
|
},
|
||||||
|
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
|
||||||
|
let slice = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
let mut j = 0u128;
|
||||||
|
for i in 0..4 {
|
||||||
|
j <<= 32;
|
||||||
|
|
||||||
|
j |= slice[3 - i] as u128;
|
||||||
|
|
||||||
|
}
|
||||||
|
SmallUint(SmallUintType::Inline(i & j))
|
||||||
|
},
|
||||||
|
|
||||||
|
(&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
|
||||||
|
|
||||||
|
let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
|
||||||
|
|
||||||
|
let min = std::cmp::min(slice1.len(), slice2.len());
|
||||||
|
|
||||||
|
let mut res = Vec::with_capacity(min);
|
||||||
|
|
||||||
|
for l in 0..min {
|
||||||
|
res.push(slice1[l] & slice2[l]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while res.len() != 1 && res[res.len() - 1] == 0 {
|
||||||
|
res.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.len() <= 4 {
|
||||||
|
let mut r = 0u128;
|
||||||
|
for t in 0..res.len() {
|
||||||
|
r <<= 32;
|
||||||
|
r |= res[res.len() - 1 - t] as u128;
|
||||||
|
}
|
||||||
|
SmallUint(SmallUintType::Inline(r))
|
||||||
|
} else {
|
||||||
|
let mut slice = ManuallyDrop::new(res.into_boxed_slice());
|
||||||
|
SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_op!(BitAnd, SmallUint, bitand);
|
||||||
|
|
||||||
|
fn bitor(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
|
match (&a.0, &b.0) {
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
|
||||||
|
SmallUint(SmallUintType::Inline(i | j))
|
||||||
|
},
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
|
||||||
|
let slice = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
|
||||||
|
let mut retvec = slice.to_vec();
|
||||||
|
|
||||||
|
let mut v = i;
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
|
for r in 0..4 {
|
||||||
|
retvec[r] |= v as u32;
|
||||||
|
|
||||||
|
v >>= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||||
|
|
||||||
|
SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len())))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
(&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
|
||||||
|
|
||||||
|
let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
|
||||||
|
|
||||||
|
let m = std::cmp::min(slice1.len(), slice2.len());
|
||||||
|
|
||||||
|
let mut retvec;
|
||||||
|
if slice1.len() > slice2.len() {
|
||||||
|
retvec = slice1.to_vec();
|
||||||
|
} else {
|
||||||
|
retvec = slice2.to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in 0..m {
|
||||||
|
retvec[t] = slice1[t] | slice2[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut slice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||||
|
|
||||||
|
SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_op!(BitOr, SmallUint, bitor);
|
||||||
|
|
||||||
|
fn bitxor(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
|
match (&a.0, &b.0) {
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
|
||||||
|
SmallUint(SmallUintType::Inline(i ^ j))
|
||||||
|
}
|
||||||
|
(&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
|
||||||
|
let slice = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
|
||||||
|
let mut retvec = slice.to_vec();
|
||||||
|
|
||||||
|
let mut v = i;
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
|
for r in 0..4 {
|
||||||
|
retvec[r] ^= v as u32;
|
||||||
|
|
||||||
|
v >>= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||||
|
|
||||||
|
SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len())))
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
(&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
|
||||||
|
|
||||||
|
let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
|
||||||
|
|
||||||
|
let m = std::cmp::min(slice1.len(), slice2.len());
|
||||||
|
|
||||||
|
let mut res;
|
||||||
|
if slice1.len() > slice2.len() {
|
||||||
|
res = slice1.to_vec();
|
||||||
|
} else {
|
||||||
|
res = slice2.to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in 0..m {
|
||||||
|
res[t] = slice1[t] ^ slice2[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
while res.len() != 1 && res[res.len() - 1] == 0 {
|
||||||
|
res.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.len() <= 4 {
|
||||||
|
let mut r = 0u128;
|
||||||
|
for t in 0..res.len() {
|
||||||
|
r <<= 32;
|
||||||
|
r |= res[res.len() - 1 - t] as u128;
|
||||||
|
}
|
||||||
|
SmallUint(SmallUintType::Inline(r))
|
||||||
|
} else {
|
||||||
|
let mut slice = ManuallyDrop::new(res.into_boxed_slice());
|
||||||
|
SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_op!(BitXor, SmallUint, bitxor);
|
|
@ -430,6 +430,7 @@ fn mul(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
(&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
|
(&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
|
||||||
|
|
||||||
let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
|
let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
|
61
src/tests.rs
61
src/tests.rs
|
@ -93,6 +93,67 @@ fn test_op_sub_u_u() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "num-bigint")]
|
||||||
|
fn test_op_and_u_u() {
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let k = SmallUint::from(u128::MAX);
|
||||||
|
let q = i & k;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::from(u128::MAX) & BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let q = k & i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3]) & BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(&BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
let q = k & i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) & BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "num-bigint")]
|
||||||
|
fn test_op_or_u_u() {
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let k = SmallUint::from(u128::MAX);
|
||||||
|
let q = i | k;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::from(u128::MAX) | BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let q = k | i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) | BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(&BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
let q = k | i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) | BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "num-bigint")]
|
||||||
|
fn test_op_xor_u_u() {
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let k = SmallUint::from(u128::MAX);
|
||||||
|
let q = i ^ k;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::from(u128::MAX) ^ BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(u128::MAX);
|
||||||
|
let q = k ^ i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) ^ BigUint::from(u128::MAX));
|
||||||
|
|
||||||
|
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallUint::from(&BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
let q = k ^ i;
|
||||||
|
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) ^ BigUint::new(vec![3, 9, 8, 3, 1]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_bigint() {
|
fn test_bigint() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user