mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-04 17:11:38 -05:00
all basic arith ops done (we don't talk about div)
This commit is contained in:
parent
2e04862fc1
commit
f9eb2a1afa
|
@ -130,7 +130,14 @@ impl From<SmallUint> for SmallInt {
|
||||||
match s.0 {
|
match s.0 {
|
||||||
SmallUintType::Inline(i) => SmallInt::from(i),
|
SmallUintType::Inline(i) => SmallInt::from(i),
|
||||||
SmallUintType::Heap((r, s)) => {
|
SmallUintType::Heap((r, s)) => {
|
||||||
SmallInt(SmallIntType::Heap((r, isize::try_from(s).unwrap())))
|
let slice = unsafe { core::slice::from_raw_parts(r, s) };
|
||||||
|
let mut ret = vec![0; s];
|
||||||
|
ret.clone_from_slice(slice);
|
||||||
|
let mut val = ManuallyDrop::new(ret.into_boxed_slice());
|
||||||
|
SmallInt(SmallIntType::Heap((
|
||||||
|
val.as_mut_ptr(),
|
||||||
|
isize::try_from(s).unwrap(),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +152,11 @@ impl TryFrom<SmallInt> for SmallUint {
|
||||||
SmallIntType::Heap((r, s)) => {
|
SmallIntType::Heap((r, s)) => {
|
||||||
let size = usize::try_from(s).map_err(|_| SmallIntError::ConversionError)?;
|
let size = usize::try_from(s).map_err(|_| SmallIntError::ConversionError)?;
|
||||||
if size > 4 {
|
if size > 4 {
|
||||||
Ok(Self(SmallUintType::Heap((r, size))))
|
let slice = unsafe { core::slice::from_raw_parts(r, size) };
|
||||||
|
let mut ret = vec![0; size];
|
||||||
|
ret.clone_from_slice(slice);
|
||||||
|
let mut val = ManuallyDrop::new(ret.into_boxed_slice());
|
||||||
|
Ok(Self(SmallUintType::Heap((val.as_mut_ptr(), size))))
|
||||||
} else {
|
} else {
|
||||||
Ok(Self(SmallUintType::Inline(u128::try_from(value)?)))
|
Ok(Self(SmallUintType::Inline(u128::try_from(value)?)))
|
||||||
}
|
}
|
||||||
|
|
51
src/ops.rs
51
src/ops.rs
|
@ -171,9 +171,7 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
if b <= s {
|
if b <= s {
|
||||||
SmallInt::from(s - b)
|
SmallInt::from(s - b)
|
||||||
} else {
|
} else {
|
||||||
let v = b - s;
|
-SmallInt::from(b - s)
|
||||||
let r = SmallInt::from(v);
|
|
||||||
-r
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +277,12 @@ fn sub(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
|
|
||||||
basic_op!(Sub, sub, SmallUint, sub);
|
basic_op!(Sub, sub, SmallUint, sub);
|
||||||
|
|
||||||
|
fn sub_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
|
a + (-b.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_op!(Sub, sub, SmallInt, sub_signed);
|
||||||
|
|
||||||
// Taken from https://github.com/rust-lang/rust/issues/85532#issuecomment-916309635. Credit to
|
// Taken from https://github.com/rust-lang/rust/issues/85532#issuecomment-916309635. Credit to
|
||||||
// AaronKutch.
|
// AaronKutch.
|
||||||
const fn carrying_mul_u128(lhs: u128, rhs: u128, carry: u128) -> (u128, u128) {
|
const fn carrying_mul_u128(lhs: u128, rhs: u128, carry: u128) -> (u128, u128) {
|
||||||
|
@ -463,3 +467,44 @@ fn mul(a: &SmallUint, b: &SmallUint) -> SmallUint {
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_op!(Mul, mul, SmallUint, mul);
|
basic_op!(Mul, mul, SmallUint, mul);
|
||||||
|
|
||||||
|
fn mul_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
|
||||||
|
let a_sign;
|
||||||
|
match &a.0 {
|
||||||
|
SmallIntType::Inline(i) => a_sign = i.signum() as i8,
|
||||||
|
SmallIntType::Heap((_, s)) => a_sign = s.signum() as i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
let b_sign;
|
||||||
|
match &b.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) => SmallInt::from(
|
||||||
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
|
),
|
||||||
|
x if (x.0 < 0 && x.1 < 0) => SmallInt::from(
|
||||||
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
|
),
|
||||||
|
|
||||||
|
x if (x.0 >= 0 && x.1 < 0) => -SmallInt::from(
|
||||||
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
|
),
|
||||||
|
|
||||||
|
x if (x.0 < 0 && x.1 >= 0) => -SmallInt::from(
|
||||||
|
SmallUint::from_smallint_unsigned(a.clone())
|
||||||
|
* SmallUint::from_smallint_unsigned(b.clone()),
|
||||||
|
),
|
||||||
|
|
||||||
|
(_, _) => {
|
||||||
|
panic!("This shouldn't happen. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_op!(Mul, mul, SmallInt, mul_signed);
|
||||||
|
|
52
src/tests.rs
52
src/tests.rs
|
@ -152,6 +152,32 @@ fn test_op_mul_u() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "num-bigint")]
|
||||||
|
fn test_op_mul_i() {
|
||||||
|
let i = -SmallInt::from(u128::MAX);
|
||||||
|
let k = SmallInt::from(u128::MAX);
|
||||||
|
let q = i * k;
|
||||||
|
assert_eq!(BigInt::from(&q), -BigInt::from(u128::MAX) * u128::MAX);
|
||||||
|
|
||||||
|
let i = -SmallInt::from(u32::MAX);
|
||||||
|
let k = -SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let q = i * k;
|
||||||
|
assert_eq!(
|
||||||
|
BigInt::from(&q),
|
||||||
|
BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]) * u32::MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
let i = -SmallInt::from(&BigInt::new(Sign::Plus, vec![3, 9, 8, 3, 1]));
|
||||||
|
let k = SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let q = i * k;
|
||||||
|
assert_eq!(
|
||||||
|
BigInt::from(&q),
|
||||||
|
BigInt::new(Sign::Plus, vec![3, 9, 8, 3, 1])
|
||||||
|
* -BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_op_sub_u() {
|
fn test_op_sub_u() {
|
||||||
|
@ -177,6 +203,32 @@ fn test_op_sub_u() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "num-bigint")]
|
||||||
|
fn test_op_sub_i() {
|
||||||
|
let i = -SmallInt::from(u128::MAX);
|
||||||
|
let k = SmallInt::from(u128::MAX);
|
||||||
|
let q = i - k;
|
||||||
|
assert_eq!(BigInt::from(&q), -BigInt::from(u128::MAX) - u128::MAX);
|
||||||
|
|
||||||
|
let k = SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = -SmallInt::from(u128::MAX);
|
||||||
|
let q = k - i;
|
||||||
|
assert_eq!(
|
||||||
|
BigInt::from(&q),
|
||||||
|
BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]) + u128::MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
let k = -SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
|
||||||
|
let i = SmallInt::from(&BigInt::new(Sign::Plus, vec![3, 9, 8, 3, 1]));
|
||||||
|
let q = k - i;
|
||||||
|
assert_eq!(
|
||||||
|
BigInt::from(&q),
|
||||||
|
-(BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81])
|
||||||
|
+ BigInt::new(Sign::Plus, vec![3, 9, 8, 3, 1]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_op_and_u() {
|
fn test_op_and_u() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user