mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-04 00:51:38 -05:00
improve ops.rs, rename BigUint::from_smallint_unsigned to SmallInt::unsigned_abs, etc.
This commit is contained in:
parent
c392ba8633
commit
5bea89295d
|
@ -98,10 +98,10 @@ impl From<u128> for SmallInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SmallInt> for u128 {
|
||||
impl TryFrom<&SmallInt> for u128 {
|
||||
type Error = SmallIntError;
|
||||
|
||||
fn try_from(s: SmallInt) -> Result<Self, Self::Error> {
|
||||
fn try_from(s: &SmallInt) -> Result<Self, Self::Error> {
|
||||
match s.0 {
|
||||
SmallIntType::Inline(i) => {
|
||||
u128::try_from(i).map_err(|_| SmallIntError::ConversionError)
|
||||
|
@ -125,6 +125,14 @@ 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 {
|
||||
fn from(s: SmallUint) -> Self {
|
||||
match s.0 {
|
||||
|
@ -143,10 +151,10 @@ impl From<SmallUint> for SmallInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SmallInt> for SmallUint {
|
||||
impl TryFrom<&SmallInt> for SmallUint {
|
||||
type Error = SmallIntError;
|
||||
|
||||
fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &SmallInt) -> Result<Self, Self::Error> {
|
||||
match value.0 {
|
||||
SmallIntType::Inline(i) => Self::try_from(i),
|
||||
SmallIntType::Heap((r, s)) => {
|
||||
|
@ -165,11 +173,19 @@ impl TryFrom<SmallInt> for SmallUint {
|
|||
}
|
||||
}
|
||||
|
||||
impl SmallUint {
|
||||
/// Converts a `SmallInt` into a `SmallUint` and drops the sign instead of throwing an error.
|
||||
pub fn from_smallint_unsigned(value: SmallInt) -> Self {
|
||||
match value.0 {
|
||||
SmallIntType::Inline(i) => Self::from(i.unsigned_abs()),
|
||||
impl TryFrom<SmallInt> for SmallUint {
|
||||
type Error = SmallIntError;
|
||||
|
||||
fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
|
||||
Self::try_from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
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)) => {
|
||||
let size = s.unsigned_abs();
|
||||
if size > 4 {
|
||||
|
@ -177,11 +193,11 @@ impl SmallUint {
|
|||
let mut ret = vec![0; size];
|
||||
ret.clone_from_slice(slice);
|
||||
let mut val = ManuallyDrop::new(ret.into_boxed_slice());
|
||||
Self(SmallUintType::Heap((val.as_mut_ptr(), size)))
|
||||
SmallUint(SmallUintType::Heap((val.as_mut_ptr(), size)))
|
||||
} else if s >= 0 {
|
||||
Self(SmallUintType::Inline(u128::try_from(value).unwrap()))
|
||||
SmallUint(SmallUintType::Inline(u128::try_from(self).unwrap()))
|
||||
} else {
|
||||
Self(SmallUintType::Inline(u128::try_from(-value).unwrap()))
|
||||
SmallUint(SmallUintType::Inline(u128::try_from(-self).unwrap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
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::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
|
||||
impl Neg for SmallInt {
|
||||
type Output = Self;
|
||||
impl Neg for &SmallInt {
|
||||
type Output = SmallInt;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
fn neg(self) -> SmallInt {
|
||||
match self.0 {
|
||||
SmallIntType::Inline(i) => {
|
||||
if let Some(n) = i.checked_neg() {
|
||||
|
@ -30,6 +30,14 @@ impl Neg for SmallInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl Neg for SmallInt {
|
||||
type Output = SmallInt;
|
||||
|
||||
fn neg(self) -> SmallInt {
|
||||
(&self).neg()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! basic_op {
|
||||
($imp:ident, $lower:ident, $typ:ty, $fun:ident) => {
|
||||
impl<'a, 'b> $imp<&'a $typ> for &'b $typ {
|
||||
|
@ -178,17 +186,17 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
|||
|
||||
match (a_sign, b_sign) {
|
||||
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
+ SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
+ b.unsigned_abs(),
|
||||
),
|
||||
x if (x.0 < 0 && x.1 < 0) => -SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
+ SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
+ b.unsigned_abs(),
|
||||
),
|
||||
|
||||
x if (x.0 >= 0 && x.1 < 0) => {
|
||||
let s = SmallUint::from_smallint_unsigned(a.clone());
|
||||
let b = SmallUint::from_smallint_unsigned(b.clone());
|
||||
let s = a.unsigned_abs();
|
||||
let b = b.unsigned_abs();
|
||||
if b <= s {
|
||||
SmallInt::from(s - b)
|
||||
} else {
|
||||
|
@ -197,8 +205,8 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
|||
}
|
||||
|
||||
x if (x.0 < 0 && x.1 >= 0) => {
|
||||
let s = SmallUint::from_smallint_unsigned(a.clone());
|
||||
let b = SmallUint::from_smallint_unsigned(b.clone());
|
||||
let s = a.unsigned_abs();
|
||||
let b = b.unsigned_abs();
|
||||
if s <= b {
|
||||
SmallInt::from(b - s)
|
||||
} else {
|
||||
|
@ -552,22 +560,22 @@ fn mul_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
|||
|
||||
match (a_sign, b_sign) {
|
||||
x if (x.0 >= 0 && x.1 >= 0) => SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
* b.unsigned_abs(),
|
||||
),
|
||||
x if (x.0 < 0 && x.1 < 0) => SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
* b.unsigned_abs(),
|
||||
),
|
||||
|
||||
x if (x.0 >= 0 && x.1 < 0) => -SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
* b.unsigned_abs(),
|
||||
),
|
||||
|
||||
x if (x.0 < 0 && x.1 >= 0) => -SmallInt::from(
|
||||
SmallUint::from_smallint_unsigned(a.clone())
|
||||
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||
a.unsigned_abs()
|
||||
* b.unsigned_abs(),
|
||||
),
|
||||
|
||||
(_, _) => {
|
||||
|
|
126
src/ord.rs
126
src/ord.rs
|
@ -6,23 +6,12 @@ use std::cmp::Ordering;
|
|||
impl PartialEq for SmallUint {
|
||||
fn eq(&self, other: &SmallUint) -> bool {
|
||||
match (&self.0, &other.0) {
|
||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i.eq(j),
|
||||
(SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
|
||||
Ordering::Greater => false,
|
||||
Ordering::Less => false,
|
||||
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
|
||||
}
|
||||
},
|
||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i == j,
|
||||
(SmallUintType::Heap((p, s)), SmallUintType::Heap((q, t))) => {
|
||||
let slice1 = unsafe { core::slice::from_raw_parts(*p, *s) };
|
||||
let slice2 = unsafe { core::slice::from_raw_parts(*q, *t) };
|
||||
slice1 == slice2
|
||||
}
|
||||
(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
@ -32,57 +21,45 @@ impl Eq for SmallUint {}
|
|||
|
||||
impl PartialOrd for SmallUint {
|
||||
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) {
|
||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => Some(i.cmp(j)),
|
||||
(SmallUintType::Inline(_), SmallUintType::Heap((_, _))) => Some(Ordering::Less),
|
||||
(SmallUintType::Heap((_, _)), SmallUintType::Inline(_)) => Some(Ordering::Greater),
|
||||
(SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
|
||||
Ordering::Greater => Some(Ordering::Less),
|
||||
Ordering::Less => Some(Ordering::Greater),
|
||||
(SmallUintType::Inline(i), SmallUintType::Inline(j)) => i.cmp(j),
|
||||
(SmallUintType::Inline(_), SmallUintType::Heap((_, _))) => Ordering::Less,
|
||||
(SmallUintType::Heap((_, _)), SmallUintType::Inline(_)) => Ordering::Greater,
|
||||
(SmallUintType::Heap((p, s)), SmallUintType::Heap((q, t))) => match s.cmp(t) {
|
||||
Ordering::Equal => {
|
||||
let slice1 = unsafe { core::slice::from_raw_parts(*r, *s) };
|
||||
let slice2 = unsafe { core::slice::from_raw_parts(*i, *j) };
|
||||
let slice1 = unsafe { core::slice::from_raw_parts(*p, *s) };
|
||||
let slice2 = unsafe { core::slice::from_raw_parts(*q, *t) };
|
||||
for i in 0..*s {
|
||||
match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
|
||||
Ordering::Less => return Some(Ordering::Less),
|
||||
Ordering::Greater => return Some(Ordering::Greater),
|
||||
_ => {}
|
||||
Ordering::Equal => {}
|
||||
o => return o,
|
||||
}
|
||||
}
|
||||
Some(Ordering::Equal)
|
||||
Ordering::Equal
|
||||
}
|
||||
},
|
||||
o => o,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for SmallInt {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
fn eq(&self, other: &SmallInt) -> bool {
|
||||
match (&self.0, &other.0) {
|
||||
(SmallIntType::Inline(i), SmallIntType::Inline(j)) => i.eq(j),
|
||||
(SmallIntType::Heap((r, s)), SmallIntType::Heap((i, j))) => {
|
||||
if s.signum() != j.signum() {
|
||||
(SmallIntType::Inline(i), SmallIntType::Inline(j)) => i == j,
|
||||
(SmallIntType::Heap((p, s)), SmallIntType::Heap((q, t))) => {
|
||||
if s != t { // need to compare signs, at minimum
|
||||
return false;
|
||||
}
|
||||
|
||||
match j.cmp(s) {
|
||||
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
|
||||
}
|
||||
}
|
||||
let slice1 = unsafe { core::slice::from_raw_parts(*p, s.unsigned_abs()) };
|
||||
let slice2 = unsafe { core::slice::from_raw_parts(*q, t.unsigned_abs()) };
|
||||
slice1 == slice2
|
||||
}
|
||||
(_, _) => false,
|
||||
}
|
||||
|
@ -93,36 +70,27 @@ impl Eq for SmallInt {}
|
|||
|
||||
impl PartialOrd for SmallInt {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
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,
|
||||
}
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for SmallInt {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).expect("This should not happen.")
|
||||
let a_sign = match &self.0 {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ fn test_op_neg() {
|
|||
#[cfg(feature = "num-bigint")]
|
||||
fn test_conversion_sign_drop() {
|
||||
run_tests_i_1(
|
||||
|i| BigUint::from(&SmallUint::from_smallint_unsigned(i)),
|
||||
|i| BigUint::from(&SmallInt::unsigned_abs(&i)),
|
||||
|i| i.magnitude().clone()
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user