mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-22 14:32:44 -05:00
Compare commits
No commits in common. "5bea89295d7ef50bc70af79c782d8bda0fc82df1" and "234fce4b92ae0df4564c41f156fb174c7274a720" have entirely different histories.
5bea89295d
...
234fce4b92
|
@ -98,10 +98,10 @@ impl From<u128> for SmallInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&SmallInt> for u128 {
|
impl TryFrom<SmallInt> for u128 {
|
||||||
type Error = SmallIntError;
|
type Error = SmallIntError;
|
||||||
|
|
||||||
fn try_from(s: &SmallInt) -> Result<Self, Self::Error> {
|
fn try_from(s: SmallInt) -> Result<Self, Self::Error> {
|
||||||
match s.0 {
|
match s.0 {
|
||||||
SmallIntType::Inline(i) => {
|
SmallIntType::Inline(i) => {
|
||||||
u128::try_from(i).map_err(|_| SmallIntError::ConversionError)
|
u128::try_from(i).map_err(|_| SmallIntError::ConversionError)
|
||||||
|
@ -125,14 +125,6 @@ impl TryFrom<&SmallInt> for u128 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<SmallInt> for u128 {
|
|
||||||
type Error = SmallIntError;
|
|
||||||
|
|
||||||
fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
|
|
||||||
Self::try_from(&value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SmallUint> for SmallInt {
|
impl From<SmallUint> for SmallInt {
|
||||||
fn from(s: SmallUint) -> Self {
|
fn from(s: SmallUint) -> Self {
|
||||||
match s.0 {
|
match s.0 {
|
||||||
|
@ -151,10 +143,10 @@ impl From<SmallUint> for SmallInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&SmallInt> for SmallUint {
|
impl TryFrom<SmallInt> for SmallUint {
|
||||||
type Error = SmallIntError;
|
type Error = SmallIntError;
|
||||||
|
|
||||||
fn try_from(value: &SmallInt) -> Result<Self, Self::Error> {
|
fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
|
||||||
match value.0 {
|
match value.0 {
|
||||||
SmallIntType::Inline(i) => Self::try_from(i),
|
SmallIntType::Inline(i) => Self::try_from(i),
|
||||||
SmallIntType::Heap((r, s)) => {
|
SmallIntType::Heap((r, s)) => {
|
||||||
|
@ -173,19 +165,11 @@ impl TryFrom<&SmallInt> for SmallUint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<SmallInt> for SmallUint {
|
impl SmallUint {
|
||||||
type Error = SmallIntError;
|
/// Converts a `SmallInt` into a `SmallUint` and drops the sign instead of throwing an error.
|
||||||
|
pub fn from_smallint_unsigned(value: SmallInt) -> Self {
|
||||||
fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
|
match value.0 {
|
||||||
Self::try_from(&value)
|
SmallIntType::Inline(i) => Self::from(i.unsigned_abs()),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SmallInt {
|
|
||||||
/// Returns the absolute value of the `SmallInt` as a `SmallUint`.
|
|
||||||
pub fn unsigned_abs(&self) -> SmallUint {
|
|
||||||
match self.0 {
|
|
||||||
SmallIntType::Inline(i) => SmallUint::from(i.unsigned_abs()),
|
|
||||||
SmallIntType::Heap((r, s)) => {
|
SmallIntType::Heap((r, s)) => {
|
||||||
let size = s.unsigned_abs();
|
let size = s.unsigned_abs();
|
||||||
if size > 4 {
|
if size > 4 {
|
||||||
|
@ -193,11 +177,11 @@ impl SmallInt {
|
||||||
let mut ret = vec![0; size];
|
let mut ret = vec![0; size];
|
||||||
ret.clone_from_slice(slice);
|
ret.clone_from_slice(slice);
|
||||||
let mut val = ManuallyDrop::new(ret.into_boxed_slice());
|
let mut val = ManuallyDrop::new(ret.into_boxed_slice());
|
||||||
SmallUint(SmallUintType::Heap((val.as_mut_ptr(), size)))
|
Self(SmallUintType::Heap((val.as_mut_ptr(), size)))
|
||||||
} else if s >= 0 {
|
} else if s >= 0 {
|
||||||
SmallUint(SmallUintType::Inline(u128::try_from(self).unwrap()))
|
Self(SmallUintType::Inline(u128::try_from(value).unwrap()))
|
||||||
} else {
|
} else {
|
||||||
SmallUint(SmallUintType::Inline(u128::try_from(-self).unwrap()))
|
Self(SmallUintType::Inline(u128::try_from(-value).unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
134
src/logic.rs
134
src/logic.rs
|
@ -130,7 +130,7 @@ macro_rules! inline_heap_to_heap {
|
||||||
|
|
||||||
let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
|
let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
|
||||||
|
|
||||||
$typ($typ_inner::Heap((retslice.as_mut_ptr(), retslice.len().try_into().unwrap())))
|
$typ($typ_inner::Heap((retslice.as_mut_ptr(), retslice.len())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,31 +160,31 @@ macro_rules! heap_heap_create_res_longest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! return_heap_inner {
|
macro_rules! heap_heap_return_heap_inner {
|
||||||
($typ:ident, $typ_inner:ident; $res:ident) => {
|
($typ:ident, $typ_inner:ident; $res:ident) => {
|
||||||
let mut slice = ManuallyDrop::new($res);
|
let mut slice = ManuallyDrop::new($res);
|
||||||
$typ($typ_inner::Heap((slice.as_mut_ptr(), slice.len().try_into().unwrap())))
|
$typ($typ_inner::Heap((slice.as_mut_ptr(), slice.len().try_into().unwrap())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! return_heap_inner_neg {
|
macro_rules! heap_heap_return_heap_inner_neg {
|
||||||
($typ:ident, $typ_inner:ident; $res:ident) => {
|
($typ:ident, $typ_inner:ident; $res:ident) => {
|
||||||
let mut slice = ManuallyDrop::new($res);
|
let mut slice = ManuallyDrop::new($res);
|
||||||
$typ($typ_inner::Heap((slice.as_mut_ptr(), -isize::try_from(slice.len()).unwrap())))
|
$typ($typ_inner::Heap((slice.as_mut_ptr(), -isize::try_from(slice.len()).unwrap())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! return_heap {
|
macro_rules! heap_heap_return_heap {
|
||||||
($typ:ident, $typ_inner:ident; $res:ident) => {
|
($typ:ident, $typ_inner:ident; $res:ident) => {
|
||||||
let res = $res.into_boxed_slice();
|
let res = $res.into_boxed_slice();
|
||||||
return_heap_inner! { $typ, $typ_inner; res }
|
heap_heap_return_heap_inner! { $typ, $typ_inner; res }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! return_heap_neg {
|
macro_rules! heap_heap_return_heap_neg {
|
||||||
($typ:ident, $typ_inner:ident; $res:ident) => {
|
($typ:ident, $typ_inner:ident; $res:ident) => {
|
||||||
let res = $res.into_boxed_slice();
|
let res = $res.into_boxed_slice();
|
||||||
return_heap_inner_neg! { $typ, $typ_inner; res }
|
heap_heap_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;
|
i, j, p, q, s, t, slice, slice1, slice2, min, res;
|
||||||
{ inline_heap_to_heap! { bitor_assign, SmallUint, SmallUintType; i, slice } },
|
{ inline_heap_to_heap! { bitor_assign, SmallUint, SmallUintType; i, slice } },
|
||||||
{ heap_heap_create_res_longest! { bitor; slice1, slice2, min }},
|
{ heap_heap_create_res_longest! { bitor; slice1, slice2, min }},
|
||||||
{ return_heap! { SmallUint, SmallUintType; res } }
|
{ heap_heap_return_heap! { SmallUint, SmallUintType; res } }
|
||||||
}
|
}
|
||||||
|
|
||||||
logic_op! {
|
logic_op! {
|
||||||
|
@ -256,28 +256,6 @@ fn bitand_two_slices_mixed_sign(positive: &[u32], negative: &[u32]) -> Vec<u32>
|
||||||
sub2
|
sub2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitand_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec<u32> {
|
|
||||||
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<u32> {
|
|
||||||
// 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! {
|
logic_op! {
|
||||||
BitAnd, BitAndAssign, SmallInt, SmallIntType, bitand, bitand_assign;
|
BitAnd, BitAndAssign, SmallInt, SmallIntType, bitand, bitand_assign;
|
||||||
i, j, p, q, s, t;
|
i, j, p, q, s, t;
|
||||||
|
@ -300,7 +278,7 @@ logic_op! {
|
||||||
res[idx] &= inline as u32;
|
res[idx] &= inline as u32;
|
||||||
inline >>= 32;
|
inline >>= 32;
|
||||||
}
|
}
|
||||||
return_heap_inner! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap_inner! { SmallInt, SmallIntType; res }
|
||||||
},
|
},
|
||||||
(Ordering::Less, Ordering::Less) => {
|
(Ordering::Less, Ordering::Less) => {
|
||||||
let mut res = <Box<[u32]>>::from(slice);
|
let mut res = <Box<[u32]>>::from(slice);
|
||||||
|
@ -314,9 +292,9 @@ logic_op! {
|
||||||
|
|
||||||
if lo == 0 && j != 0 {
|
if lo == 0 && j != 0 {
|
||||||
let res2 = add_two_slices(&res, &[0, 0, 0, 0, 1]);
|
let res2 = add_two_slices(&res, &[0, 0, 0, 0, 1]);
|
||||||
return_heap_neg! { SmallInt, SmallIntType; res2 }
|
heap_heap_return_heap_neg! { SmallInt, SmallIntType; res2 }
|
||||||
} else {
|
} else {
|
||||||
return_heap_inner_neg! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap_inner_neg! { SmallInt, SmallIntType; res }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(_, Ordering::Equal) => unreachable!("0 must be inline"),
|
(_, Ordering::Equal) => unreachable!("0 must be inline"),
|
||||||
|
@ -331,16 +309,16 @@ logic_op! {
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut res = { heap_heap_create_res_shortest! { bitand; slice1, slice2, min } };
|
let mut res = { heap_heap_create_res_shortest! { bitand; slice1, slice2, min } };
|
||||||
// TODO: shrink if needed, sometimes to Inline
|
|
||||||
return_heap! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap! { SmallInt, SmallIntType; res }
|
||||||
},
|
},
|
||||||
(Ordering::Greater, Ordering::Less) => {
|
(Ordering::Greater, Ordering::Less) => {
|
||||||
let res = bitand_two_slices_mixed_sign(slice1, slice2);
|
let res = bitand_two_slices_mixed_sign(slice1, slice2);
|
||||||
return_heap! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap! { SmallInt, SmallIntType; res }
|
||||||
},
|
},
|
||||||
(Ordering::Less, Ordering::Greater) => {
|
(Ordering::Less, Ordering::Greater) => {
|
||||||
let res = bitand_two_slices_mixed_sign(slice2, slice1);
|
let res = bitand_two_slices_mixed_sign(slice2, slice1);
|
||||||
return_heap! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap! { SmallInt, SmallIntType; res }
|
||||||
},
|
},
|
||||||
(Ordering::Less, Ordering::Less) => {
|
(Ordering::Less, Ordering::Less) => {
|
||||||
// (-a) & (-b) = -(((a-1) | (b-1)) + 1)
|
// (-a) & (-b) = -(((a-1) | (b-1)) + 1)
|
||||||
|
@ -349,89 +327,9 @@ logic_op! {
|
||||||
let sub2 = sub_two_slices(slice2, &[1]);
|
let sub2 = sub_two_slices(slice2, &[1]);
|
||||||
let tmp = bitor_two_slices(&sub1, &sub2);
|
let tmp = bitor_two_slices(&sub1, &sub2);
|
||||||
let res = add_two_slices(&tmp, &[1]);
|
let res = add_two_slices(&tmp, &[1]);
|
||||||
return_heap_neg! { SmallInt, SmallIntType; res }
|
heap_heap_return_heap_neg! { SmallInt, SmallIntType; res }
|
||||||
},
|
},
|
||||||
(Ordering::Equal, _) | (_, Ordering::Equal) => unreachable!("0 must be inline"),
|
(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(<Box<[_]>>::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 = <Box<[u32]>>::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 = <Box<[u32]>>::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"),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
46
src/ops.rs
46
src/ops.rs
|
@ -4,10 +4,10 @@ use core::mem::ManuallyDrop;
|
||||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||||
|
|
||||||
impl Neg for &SmallInt {
|
impl Neg for SmallInt {
|
||||||
type Output = SmallInt;
|
type Output = Self;
|
||||||
|
|
||||||
fn neg(self) -> SmallInt {
|
fn neg(self) -> Self::Output {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
SmallIntType::Inline(i) => {
|
SmallIntType::Inline(i) => {
|
||||||
if let Some(n) = i.checked_neg() {
|
if let Some(n) = i.checked_neg() {
|
||||||
|
@ -30,14 +30,6 @@ impl Neg for &SmallInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Neg for SmallInt {
|
|
||||||
type Output = SmallInt;
|
|
||||||
|
|
||||||
fn neg(self) -> SmallInt {
|
|
||||||
(&self).neg()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! basic_op {
|
macro_rules! basic_op {
|
||||||
($imp:ident, $lower:ident, $typ:ty, $fun:ident) => {
|
($imp:ident, $lower:ident, $typ:ty, $fun:ident) => {
|
||||||
impl<'a, 'b> $imp<&'a $typ> for &'b $typ {
|
impl<'a, 'b> $imp<&'a $typ> for &'b $typ {
|
||||||
|
@ -186,17 +178,17 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
|
|
||||||
match (a_sign, b_sign) {
|
match (a_sign, b_sign) {
|
||||||
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
+ b.unsigned_abs(),
|
+ SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
x if (x.0 < 0 && x.1 < 0) => -SmallInt::from(
|
x if (x.0 < 0 && x.1 < 0) => -SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
+ b.unsigned_abs(),
|
+ SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
|
|
||||||
x if (x.0 >= 0 && x.1 < 0) => {
|
x if (x.0 >= 0 && x.1 < 0) => {
|
||||||
let s = a.unsigned_abs();
|
let s = SmallUint::from_smallint_unsigned(a.clone());
|
||||||
let b = b.unsigned_abs();
|
let b = SmallUint::from_smallint_unsigned(b.clone());
|
||||||
if b <= s {
|
if b <= s {
|
||||||
SmallInt::from(s - b)
|
SmallInt::from(s - b)
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,8 +197,8 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
}
|
}
|
||||||
|
|
||||||
x if (x.0 < 0 && x.1 >= 0) => {
|
x if (x.0 < 0 && x.1 >= 0) => {
|
||||||
let s = a.unsigned_abs();
|
let s = SmallUint::from_smallint_unsigned(a.clone());
|
||||||
let b = b.unsigned_abs();
|
let b = SmallUint::from_smallint_unsigned(b.clone());
|
||||||
if s <= b {
|
if s <= b {
|
||||||
SmallInt::from(b - s)
|
SmallInt::from(b - s)
|
||||||
} else {
|
} else {
|
||||||
|
@ -560,22 +552,22 @@ fn mul_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
|
|
||||||
match (a_sign, b_sign) {
|
match (a_sign, b_sign) {
|
||||||
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
* b.unsigned_abs(),
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
x if (x.0 < 0 && x.1 < 0) => SmallInt::from(
|
x if (x.0 < 0 && x.1 < 0) => SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
* b.unsigned_abs(),
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
|
|
||||||
x if (x.0 >= 0 && x.1 < 0) => -SmallInt::from(
|
x if (x.0 >= 0 && x.1 < 0) => -SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
* b.unsigned_abs(),
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
|
|
||||||
x if (x.0 < 0 && x.1 >= 0) => -SmallInt::from(
|
x if (x.0 < 0 && x.1 >= 0) => -SmallInt::from(
|
||||||
a.unsigned_abs()
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
* b.unsigned_abs(),
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
),
|
),
|
||||||
|
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
|
|
124
src/ord.rs
124
src/ord.rs
|
@ -6,12 +6,23 @@ use std::cmp::Ordering;
|
||||||
impl PartialEq for SmallUint {
|
impl PartialEq for SmallUint {
|
||||||
fn eq(&self, other: &SmallUint) -> bool {
|
fn eq(&self, other: &SmallUint) -> bool {
|
||||||
match (&self.0, &other.0) {
|
match (&self.0, &other.0) {
|
||||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i == j,
|
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i.eq(j),
|
||||||
(SmallUintType::Heap((p, s)), SmallUintType::Heap((q, t))) => {
|
(SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
|
||||||
let slice1 = unsafe { core::slice::from_raw_parts(*p, *s) };
|
Ordering::Greater => false,
|
||||||
let slice2 = unsafe { core::slice::from_raw_parts(*q, *t) };
|
Ordering::Less => false,
|
||||||
slice1 == slice2
|
Ordering::Equal => {
|
||||||
|
let slice1 = unsafe { core::slice::from_raw_parts(*r, *s) };
|
||||||
|
let slice2 = unsafe { core::slice::from_raw_parts(*i, *j) };
|
||||||
|
for i in 0..*s {
|
||||||
|
match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
|
||||||
|
Ordering::Less => return false,
|
||||||
|
Ordering::Greater => return false,
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
},
|
||||||
(_, _) => false,
|
(_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,45 +32,57 @@ impl Eq for SmallUint {}
|
||||||
|
|
||||||
impl PartialOrd for SmallUint {
|
impl PartialOrd for SmallUint {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for SmallUint {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
match (&self.0, &other.0) {
|
match (&self.0, &other.0) {
|
||||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i.cmp(j),
|
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => Some(i.cmp(j)),
|
||||||
(SmallUintType::Inline(_), SmallUintType::Heap((_, _))) => Ordering::Less,
|
(SmallUintType::Inline(_), SmallUintType::Heap((_, _))) => Some(Ordering::Less),
|
||||||
(SmallUintType::Heap((_, _)), SmallUintType::Inline(_)) => Ordering::Greater,
|
(SmallUintType::Heap((_, _)), SmallUintType::Inline(_)) => Some(Ordering::Greater),
|
||||||
(SmallUintType::Heap((p, s)), SmallUintType::Heap((q, t))) => match s.cmp(t) {
|
(SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
|
||||||
|
Ordering::Greater => Some(Ordering::Less),
|
||||||
|
Ordering::Less => Some(Ordering::Greater),
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
let slice1 = unsafe { core::slice::from_raw_parts(*p, *s) };
|
let slice1 = unsafe { core::slice::from_raw_parts(*r, *s) };
|
||||||
let slice2 = unsafe { core::slice::from_raw_parts(*q, *t) };
|
let slice2 = unsafe { core::slice::from_raw_parts(*i, *j) };
|
||||||
for i in 0..*s {
|
for i in 0..*s {
|
||||||
match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
|
match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
|
||||||
Ordering::Equal => {}
|
Ordering::Less => return Some(Ordering::Less),
|
||||||
o => return o,
|
Ordering::Greater => return Some(Ordering::Greater),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ordering::Equal
|
Some(Ordering::Equal)
|
||||||
}
|
|
||||||
o => o,
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for SmallInt {
|
impl PartialEq for SmallInt {
|
||||||
fn eq(&self, other: &SmallInt) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (&self.0, &other.0) {
|
match (&self.0, &other.0) {
|
||||||
(SmallIntType::Inline(i), SmallIntType::Inline(j)) => i == j,
|
(SmallIntType::Inline(i), SmallIntType::Inline(j)) => i.eq(j),
|
||||||
(SmallIntType::Heap((p, s)), SmallIntType::Heap((q, t))) => {
|
(SmallIntType::Heap((r, s)), SmallIntType::Heap((i, j))) => {
|
||||||
if s != t { // need to compare signs, at minimum
|
if s.signum() != j.signum() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
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 j.cmp(s) {
|
||||||
slice1 == slice2
|
Ordering::Greater => false,
|
||||||
|
Ordering::Less => false,
|
||||||
|
Ordering::Equal => {
|
||||||
|
let us = s.unsigned_abs();
|
||||||
|
let uj = j.unsigned_abs();
|
||||||
|
let slice1 = unsafe { core::slice::from_raw_parts(*r, us) };
|
||||||
|
let slice2 = unsafe { core::slice::from_raw_parts(*i, uj) };
|
||||||
|
for i in 0..*s {
|
||||||
|
match slice1[(s - 1 - i) as usize].cmp(&slice2[(s - 1 - i) as usize]) {
|
||||||
|
Ordering::Less => return false,
|
||||||
|
Ordering::Greater => return false,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(_, _) => false,
|
(_, _) => false,
|
||||||
}
|
}
|
||||||
|
@ -70,27 +93,36 @@ impl Eq for SmallInt {}
|
||||||
|
|
||||||
impl PartialOrd for SmallInt {
|
impl PartialOrd for SmallInt {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
let a_sign;
|
||||||
|
match &self.0 {
|
||||||
|
SmallIntType::Inline(i) => a_sign = i.signum() as i8,
|
||||||
|
SmallIntType::Heap((_, s)) => a_sign = s.signum() as i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
let b_sign;
|
||||||
|
match &other.0 {
|
||||||
|
SmallIntType::Inline(i) => b_sign = i.signum() as i8,
|
||||||
|
SmallIntType::Heap((_, s)) => b_sign = s.signum() as i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
match (a_sign, b_sign) {
|
||||||
|
x if (x.0 >= 0 && x.1 < 0) => Some(Ordering::Greater),
|
||||||
|
|
||||||
|
x if (x.0 < 0 && x.1 >= 0) => Some(Ordering::Less),
|
||||||
|
|
||||||
|
x if (x.0 >= 0 && x.1 >= 0) => SmallUint::from_smallint_unsigned(self.clone())
|
||||||
|
.partial_cmp(&SmallUint::from_smallint_unsigned(other.clone())),
|
||||||
|
|
||||||
|
x if (x.0 < 0 && x.1 < 0) => SmallUint::from_smallint_unsigned(other.clone())
|
||||||
|
.partial_cmp(&SmallUint::from_smallint_unsigned(self.clone())),
|
||||||
|
|
||||||
|
(_, _) => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for SmallInt {
|
impl Ord for SmallInt {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
let a_sign = match &self.0 {
|
self.partial_cmp(other).expect("This should not happen.")
|
||||||
SmallIntType::Inline(i) => i.cmp(&0),
|
|
||||||
SmallIntType::Heap((_, s)) => s.cmp(&0),
|
|
||||||
};
|
|
||||||
let b_sign = match &other.0 {
|
|
||||||
SmallIntType::Inline(j) => j.cmp(&0),
|
|
||||||
SmallIntType::Heap((_, t)) => t.cmp(&0),
|
|
||||||
};
|
|
||||||
match a_sign.cmp(&b_sign) {
|
|
||||||
Ordering::Equal => match a_sign {
|
|
||||||
Ordering::Less => other.unsigned_abs().cmp(&self.unsigned_abs()),
|
|
||||||
Ordering::Equal => Ordering::Equal,
|
|
||||||
Ordering::Greater => self.unsigned_abs().cmp(&other.unsigned_abs()),
|
|
||||||
},
|
|
||||||
o => o,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/tests.rs
11
src/tests.rs
|
@ -232,15 +232,6 @@ 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]
|
#[test]
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_op_xor_u() {
|
fn test_op_xor_u() {
|
||||||
|
@ -260,7 +251,7 @@ fn test_op_neg() {
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_conversion_sign_drop() {
|
fn test_conversion_sign_drop() {
|
||||||
run_tests_i_1(
|
run_tests_i_1(
|
||||||
|i| BigUint::from(&SmallInt::unsigned_abs(&i)),
|
|i| BigUint::from(&SmallUint::from_smallint_unsigned(i)),
|
||||||
|i| i.magnitude().clone()
|
|i| i.magnitude().clone()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user