fixed clone + ord + eq, need to fix signed add

This commit is contained in:
EvilMuffinHa 2022-08-07 18:15:59 -04:00
parent df10924284
commit 2e04862fc1
4 changed files with 201 additions and 12 deletions

View File

@ -171,7 +171,9 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt {
if b <= s {
SmallInt::from(s - b)
} else {
-SmallInt::from(b - s)
let v = b - s;
let r = SmallInt::from(v);
-r
}
}

View File

@ -1,8 +1,96 @@
use crate::smallint::SmallIntType;
use crate::smallint::{SmallIntType, SmallUintType};
use crate::SmallInt;
use crate::SmallUint;
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
}
},
(_, _) => false,
}
}
}
impl Eq for SmallUint {}
impl PartialOrd for SmallUint {
fn partial_cmp(&self, other: &Self) -> Option<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),
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 Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
_ => {}
}
}
Some(Ordering::Equal)
}
},
}
}
}
impl PartialEq for SmallInt {
fn eq(&self, other: &Self) -> 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() {
return false;
}
match j.cmp(s) {
Ordering::Greater => false,
Ordering::Less => false,
Ordering::Equal => {
let us = usize::try_from(s.abs()).unwrap();
let uj = usize::try_from(j.abs()).unwrap();
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,
}
}
}
impl Eq for SmallInt {}
impl PartialOrd for SmallInt {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let a_sign;

View File

@ -1,20 +1,18 @@
use core::mem::ManuallyDrop;
/// An integer-like type that will store small integers up to `i128` inline. Larger integers are
/// represented as a slice to a sequence of base 2<sup>32</sup> digits represented as a `*mut u32`.
#[derive(Clone, PartialEq, Eq)]
pub struct SmallInt(pub(crate) SmallIntType);
/// An integer-like type that will store small integers up to `u128` inline. Larger integers are
/// represented as a slice to a sequence of base 2<sup>32</sup> digits represented as a `*mut u32`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SmallUint(pub(crate) SmallUintType);
#[derive(Clone, PartialEq, Eq)]
pub enum SmallIntType {
Inline(i128),
Heap((*mut u32, isize)),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum SmallUintType {
Inline(u128),
Heap((*mut u32, usize)),
@ -38,3 +36,34 @@ impl Drop for SmallUint {
}
}
}
impl Clone for SmallUint {
fn clone(&self) -> Self {
match self.0 {
SmallUintType::Inline(i) => Self(SmallUintType::Inline(i)),
SmallUintType::Heap((r, s)) => {
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());
SmallUint(SmallUintType::Heap((val.as_mut_ptr(), s)))
}
}
}
}
impl Clone for SmallInt {
fn clone(&self) -> Self {
match self.0 {
SmallIntType::Inline(i) => Self(SmallIntType::Inline(i)),
SmallIntType::Heap((r, s)) => {
let size = usize::try_from(s.abs()).unwrap();
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());
SmallInt(SmallIntType::Heap((val.as_mut_ptr(), s)))
}
}
}
}

View File

@ -34,7 +34,51 @@ conversion_tests!(i128, test_i128);
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_add_u_u() {
fn test_cmp_u() {
let i = SmallUint::from(30u32);
let k = SmallUint::from(50u32);
assert!(i < k);
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
assert!(i < k);
let i = SmallUint::from(&BigUint::new(vec![3, 9, 8, 3, 1]));
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
assert!(i < k);
}
#[test]
#[cfg(feature = "num-bigint")]
fn test_cmp_i() {
let i = SmallInt::from(30u32);
let k = SmallInt::from(50u32);
assert!(i < k);
let i = SmallInt::from(u128::MAX);
let k = SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
assert!(i < k);
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]));
assert!(i < k);
let i = SmallInt::from(30u32);
let k = -SmallInt::from(50u32);
assert!(k < i);
let i = SmallInt::from(u128::MAX);
let k = -SmallInt::from(&BigInt::new(Sign::Plus, vec![5, 4, 9, 3, 1, 81]));
assert!(k < i);
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]));
assert!(k < i);
}
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_add_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i + k;
@ -59,7 +103,33 @@ fn test_op_add_u_u() {
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_mul_u_u() {
fn test_op_add_i() {
let i = SmallInt::from(u128::MAX);
let k = -SmallInt::from(u128::MAX);
let q = i + k;
assert_eq!(BigInt::from(&q), BigInt::from(0));
let i = SmallInt::from(u128::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),
u128::MAX - 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 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])
- BigInt::new(Sign::Plus, vec![3, 9, 8, 3, 1])
);
}
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_mul_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i * k;
@ -84,7 +154,7 @@ fn test_op_mul_u_u() {
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_sub_u_u() {
fn test_op_sub_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i - k;
@ -109,7 +179,7 @@ fn test_op_sub_u_u() {
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_and_u_u() {
fn test_op_and_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i & k;
@ -137,7 +207,7 @@ fn test_op_and_u_u() {
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_or_u_u() {
fn test_op_or_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i | k;
@ -165,7 +235,7 @@ fn test_op_or_u_u() {
#[test]
#[cfg(feature = "num-bigint")]
fn test_op_xor_u_u() {
fn test_op_xor_u() {
let i = SmallUint::from(u128::MAX);
let k = SmallUint::from(u128::MAX);
let q = i ^ k;