mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-04 09:01:39 -05:00
refactor logic.rs and optimize ...Assign impls (&* instead of clone)
This commit is contained in:
parent
1fe105f58c
commit
45a3975d31
272
src/logic.rs
272
src/logic.rs
|
@ -40,201 +40,123 @@ macro_rules! basic_op {
|
|||
};
|
||||
}
|
||||
|
||||
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;
|
||||
macro_rules! logic_op {
|
||||
(
|
||||
$imp:ident, $imp_assign:ident, $typ:ident, $typ_inner:ident, $fun:ident, $fun_assign:ident;
|
||||
$i:ident, $j:ident, $r:ident, $s:ident, $slice:ident, $slice1:ident, $slice2:ident, $res:ident;
|
||||
$inline_heap:tt, $heap_heap:tt
|
||||
) => {
|
||||
fn $fun(a: &$typ, b: &$typ) -> $typ {
|
||||
match (&a.0, &b.0) {
|
||||
(&$typ_inner::Inline($i), &$typ_inner::Inline($j)) => {
|
||||
$typ($typ_inner::Inline($i.$fun($j)))
|
||||
}
|
||||
SmallUint(SmallUintType::Inline(r))
|
||||
} else {
|
||||
let mut slice = ManuallyDrop::new(res.into_boxed_slice());
|
||||
SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
|
||||
|
||||
(&$typ_inner::Inline($i), &$typ_inner::Heap(($r, $s)))
|
||||
| (&$typ_inner::Heap(($r, $s)), &$typ_inner::Inline($i)) => {
|
||||
let $slice = unsafe { core::slice::from_raw_parts($r, $s) };
|
||||
|
||||
$inline_heap
|
||||
}
|
||||
|
||||
(&$typ_inner::Heap(($r, $s)), &$typ_inner::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]);
|
||||
}
|
||||
|
||||
$heap_heap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
basic_op!($imp, $typ, $fun);
|
||||
|
||||
impl<'a> $imp_assign<&'a SmallUint> for $typ {
|
||||
fn $fun_assign(&mut self, rhs: &'a $typ) {
|
||||
*self = (&*self).$fun(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl $imp_assign<$typ> for $typ {
|
||||
fn $fun_assign(&mut self, rhs: $typ) {
|
||||
*self = (&*self).$fun(rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
basic_op!(BitAnd, SmallUint, bitand);
|
||||
macro_rules! inline_heap_to_heap {
|
||||
($op_assign:tt, $i:ident, $slice:ident) => {
|
||||
let mut retvec = $slice.to_vec();
|
||||
|
||||
impl<'a> BitAndAssign<&'a SmallUint> for SmallUint {
|
||||
fn bitand_assign(&mut self, rhs: &'a SmallUint) {
|
||||
*self = self.clone() & rhs;
|
||||
let mut v = $i;
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for r in 0..4 {
|
||||
retvec[r] $op_assign v as u32;
|
||||
|
||||
v >>= 32;
|
||||
}
|
||||
|
||||
let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||
|
||||
SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len())))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAndAssign<SmallUint> for SmallUint {
|
||||
fn bitand_assign(&mut self, rhs: SmallUint) {
|
||||
*self = self.clone() & rhs;
|
||||
}
|
||||
}
|
||||
|
||||
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())))
|
||||
macro_rules! heap_heap_to_any {
|
||||
($res:ident) => {
|
||||
while $res.len() != 1 && $res[$res.len() - 1] == 0 {
|
||||
$res.pop();
|
||||
}
|
||||
|
||||
(&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();
|
||||
if $res.len() <= 4 {
|
||||
let mut r = 0u128;
|
||||
for t in 0..$res.len() {
|
||||
r <<= 32;
|
||||
r |= $res[$res.len() - 1 - t] as u128;
|
||||
}
|
||||
|
||||
for t in 0..m {
|
||||
retvec[t] = slice1[t] | slice2[t];
|
||||
}
|
||||
|
||||
let mut slice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||
|
||||
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!(BitOr, SmallUint, bitor);
|
||||
logic_op! {
|
||||
BitAnd, BitAndAssign, SmallUint, SmallUintType, bitand, bitand_assign;
|
||||
i, j, r, s, slice, slice1, slice2, res;
|
||||
{
|
||||
let mut j = 0u128;
|
||||
for i in 0..4 {
|
||||
j <<= 32;
|
||||
j |= slice[3 - i] as u128;
|
||||
}
|
||||
SmallUint(SmallUintType::Inline(i & j))
|
||||
},
|
||||
{ heap_heap_to_any! { res } }
|
||||
}
|
||||
|
||||
impl<'a> BitOrAssign<&'a SmallUint> for SmallUint {
|
||||
fn bitor_assign(&mut self, rhs: &'a SmallUint) {
|
||||
*self = self.clone() | rhs;
|
||||
logic_op! {
|
||||
BitOr, BitOrAssign, SmallUint, SmallUintType, bitor, bitor_assign;
|
||||
i, j, r, s, slice, slice1, slice2, res;
|
||||
{ inline_heap_to_heap! { |=, i, slice } },
|
||||
{
|
||||
let mut slice = ManuallyDrop::new(res.into_boxed_slice());
|
||||
SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOrAssign<SmallUint> for SmallUint {
|
||||
fn bitor_assign(&mut self, rhs: SmallUint) {
|
||||
*self = self.clone() | rhs;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
impl<'a> BitXorAssign<&'a SmallUint> for SmallUint {
|
||||
fn bitxor_assign(&mut self, rhs: &'a SmallUint) {
|
||||
*self = self.clone() ^ rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl BitXorAssign<SmallUint> for SmallUint {
|
||||
fn bitxor_assign(&mut self, rhs: SmallUint) {
|
||||
*self = self.clone() ^ rhs;
|
||||
}
|
||||
logic_op! {
|
||||
BitXor, BitXorAssign, SmallUint, SmallUintType, bitxor, bitxor_assign;
|
||||
i, j, r, s, slice, slice1, slice2, res;
|
||||
{ inline_heap_to_heap! { |=, i, slice } },
|
||||
{ heap_heap_to_any! { res } }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user