diff --git a/src/logic.rs b/src/logic.rs index 891cd75..0a7d746 100644 --- a/src/logic.rs +++ b/src/logic.rs @@ -130,7 +130,7 @@ macro_rules! inline_heap_to_heap { let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice()); - $typ($typ_inner::Heap((retslice.as_mut_ptr(), retslice.len()))) + $typ($typ_inner::Heap((retslice.as_mut_ptr(), retslice.len().try_into().unwrap()))) } } @@ -160,31 +160,31 @@ macro_rules! heap_heap_create_res_longest { } -macro_rules! heap_heap_return_heap_inner { +macro_rules! return_heap_inner { ($typ:ident, $typ_inner:ident; $res:ident) => { let mut slice = ManuallyDrop::new($res); $typ($typ_inner::Heap((slice.as_mut_ptr(), slice.len().try_into().unwrap()))) } } -macro_rules! heap_heap_return_heap_inner_neg { +macro_rules! return_heap_inner_neg { ($typ:ident, $typ_inner:ident; $res:ident) => { let mut slice = ManuallyDrop::new($res); $typ($typ_inner::Heap((slice.as_mut_ptr(), -isize::try_from(slice.len()).unwrap()))) } } -macro_rules! heap_heap_return_heap { +macro_rules! return_heap { ($typ:ident, $typ_inner:ident; $res:ident) => { let res = $res.into_boxed_slice(); - heap_heap_return_heap_inner! { $typ, $typ_inner; res } + return_heap_inner! { $typ, $typ_inner; res } } } -macro_rules! heap_heap_return_heap_neg { +macro_rules! return_heap_neg { ($typ:ident, $typ_inner:ident; $res:ident) => { let res = $res.into_boxed_slice(); - heap_heap_return_heap_inner_neg! { $typ, $typ_inner; res } + return_heap_inner_neg! { $typ, $typ_inner; res } } } @@ -221,7 +221,7 @@ logic_op! { i, j, p, q, s, t, slice, slice1, slice2, min, res; { inline_heap_to_heap! { bitor_assign, SmallUint, SmallUintType; i, slice } }, { heap_heap_create_res_longest! { bitor; slice1, slice2, min }}, - { heap_heap_return_heap! { SmallUint, SmallUintType; res } } + { return_heap! { SmallUint, SmallUintType; res } } } logic_op! { @@ -256,6 +256,28 @@ fn bitand_two_slices_mixed_sign(positive: &[u32], negative: &[u32]) -> Vec sub2 } +fn bitand_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec { + let mut result = if slice1.len() > slice2.len() { + slice1.to_vec() + } else { + slice2.to_vec() + }; + for l in 0..std::cmp::min(slice1.len(), slice2.len()) { + result[l] = slice1[l] | slice2[l]; + } + result +} + +fn bitor_two_slices_mixed_sign(positive: &[u32], negative: &[u32]) -> Vec { + // a | (-b) = (a & (b - 1)) + 1 - b + // 0 is not negative, so we can ignore it + let sub1 = sub_two_slices(negative, &[1]); + let or = bitand_two_slices(positive, &sub1); + let add = add_two_slices(&or, &[1]); + let sub2 = sub_two_slices(&add, negative); + sub2 +} + logic_op! { BitAnd, BitAndAssign, SmallInt, SmallIntType, bitand, bitand_assign; i, j, p, q, s, t; @@ -278,7 +300,7 @@ logic_op! { res[idx] &= inline as u32; inline >>= 32; } - heap_heap_return_heap_inner! { SmallInt, SmallIntType; res } + return_heap_inner! { SmallInt, SmallIntType; res } }, (Ordering::Less, Ordering::Less) => { let mut res = >::from(slice); @@ -292,9 +314,9 @@ logic_op! { if lo == 0 && j != 0 { let res2 = add_two_slices(&res, &[0, 0, 0, 0, 1]); - heap_heap_return_heap_neg! { SmallInt, SmallIntType; res2 } + return_heap_neg! { SmallInt, SmallIntType; res2 } } else { - heap_heap_return_heap_inner_neg! { SmallInt, SmallIntType; res } + return_heap_inner_neg! { SmallInt, SmallIntType; res } } }, (_, Ordering::Equal) => unreachable!("0 must be inline"), @@ -309,16 +331,16 @@ logic_op! { #[allow(unused_mut)] let mut res = { heap_heap_create_res_shortest! { bitand; slice1, slice2, min } }; - - heap_heap_return_heap! { SmallInt, SmallIntType; res } + // TODO: shrink if needed, sometimes to Inline + return_heap! { SmallInt, SmallIntType; res } }, (Ordering::Greater, Ordering::Less) => { let res = bitand_two_slices_mixed_sign(slice1, slice2); - heap_heap_return_heap! { SmallInt, SmallIntType; res } + return_heap! { SmallInt, SmallIntType; res } }, (Ordering::Less, Ordering::Greater) => { let res = bitand_two_slices_mixed_sign(slice2, slice1); - heap_heap_return_heap! { SmallInt, SmallIntType; res } + return_heap! { SmallInt, SmallIntType; res } }, (Ordering::Less, Ordering::Less) => { // (-a) & (-b) = -(((a-1) | (b-1)) + 1) @@ -327,9 +349,89 @@ logic_op! { let sub2 = sub_two_slices(slice2, &[1]); let tmp = bitor_two_slices(&sub1, &sub2); let res = add_two_slices(&tmp, &[1]); - heap_heap_return_heap_neg! { SmallInt, SmallIntType; res } + return_heap_neg! { SmallInt, SmallIntType; res } }, (Ordering::Equal, _) | (_, Ordering::Equal) => unreachable!("0 must be inline"), } } } + +// logic_op! { +// BitOr, BitOrAssign, SmallInt, SmallIntType, bitor, bitor_assign; +// i, j, p, q, s, t; +// { +// let slice = unsafe { core::slice::from_raw_parts(p, s.unsigned_abs()) }; +// match (i.cmp(&0), s.cmp(&0)) { +// (Ordering::Equal, _) => { +// let mut slice = ManuallyDrop::new(>::from(slice)); +// SmallInt(SmallIntType::Heap((slice.as_mut_ptr(), s))) +// }, +// (Ordering::Greater, Ordering::Greater) => { +// inline_heap_to_heap! { bitor_assign, SmallInt, SmallIntType; i, slice } +// }, +// (Ordering::Greater, Ordering::Less) => { +// let mut res = >::from(slice); +// let mut inline = i as u128; +// for idx in 0..4 { +// res[idx] = ((res[idx] as i32).wrapping_neg() | (inline as i32).wrapping_neg()).wrapping_neg() as u32; +// inline >>= 32; +// } +// return_heap_inner_neg! { SmallInt, SmallIntType; res } +// }, +// (Ordering::Less, Ordering::Greater) => { +// let j = { heap_to_inline! { i128; slice } }; +// SmallInt(SmallIntType::Inline(i | -j)) +// }, +// (Ordering::Less, Ordering::Less) => { +// let mut res = >::from(slice); +// let j = { heap_to_inline! { i128; slice } }; +// let lo = (i | j.wrapping_neg()).wrapping_neg(); +// let mut lo_remaining = lo; +// for idx in 0..4 { +// res[idx] = lo_remaining as u32; +// lo_remaining >>= 32; +// } +// +// if lo == 0 && j != 0 { +// let res2 = add_two_slices(&res, &[0, 0, 0, 0, 1]); +// return_heap_neg! { SmallInt, SmallIntType; res2 } +// } else { +// return_heap_inner_neg! { SmallInt, SmallIntType; res } +// } +// }, +// (_, Ordering::Equal) => unreachable!("0 must be inline"), +// } +// }, +// { +// let slice1 = unsafe { core::slice::from_raw_parts(p, s.unsigned_abs()) }; +// let slice2 = unsafe { core::slice::from_raw_parts(q, t.unsigned_abs()) }; +// match (s.cmp(&0), t.cmp(&0)) { +// (Ordering::Greater, Ordering::Greater) => { +// let min = std::cmp::min(slice1.len(), slice2.len()); +// +// #[allow(unused_mut)] +// let mut res = { heap_heap_create_res_longest! { bitor; slice1, slice2, min } }; +// +// return_heap! { SmallInt, SmallIntType; res } +// }, +// (Ordering::Greater, Ordering::Less) => { +// let res = bitor_two_slices_mixed_sign(slice1, slice2); +// return_heap! { SmallInt, SmallIntType; res } +// }, +// (Ordering::Less, Ordering::Greater) => { +// let res = bitor_two_slices_mixed_sign(slice2, slice1); +// return_heap! { SmallInt, SmallIntType; res } +// }, +// (Ordering::Less, Ordering::Less) => { +// // (-a) | (-b) = -(((a-1) & (b-1)) + 1) +// // 0 is not negative, so we can ignore it +// let sub1 = sub_two_slices(slice1, &[1]); +// let sub2 = sub_two_slices(slice2, &[1]); +// let tmp = bitand_two_slices(&sub1, &sub2); +// let res = add_two_slices(&tmp, &[1]); +// return_heap_neg! { SmallInt, SmallIntType; res } +// }, +// (Ordering::Equal, _) | (_, Ordering::Equal) => unreachable!("0 must be inline"), +// } +// } +// } diff --git a/src/tests.rs b/src/tests.rs index a49cb8d..8ce5168 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -232,6 +232,15 @@ fn test_op_or_u() { ); } +// #[test] +// #[cfg(feature = "num-bigint")] +// fn test_op_or_i() { +// run_tests_i_2( +// |i, k| BigInt::from(&(i | k)), +// |i, k| i | k, +// ); +// } + #[test] #[cfg(feature = "num-bigint")] fn test_op_xor_u() {