From 2e04862fc131adb67f8a1f7c615ea1fbb27b6aac Mon Sep 17 00:00:00 2001 From: EvilMuffinHa Date: Sun, 7 Aug 2022 18:15:59 -0400 Subject: [PATCH] fixed clone + ord + eq, need to fix signed add --- src/ops.rs | 4 ++- src/ord.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++- src/smallint.rs | 37 +++++++++++++++++--- src/tests.rs | 82 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 201 insertions(+), 12 deletions(-) diff --git a/src/ops.rs b/src/ops.rs index 738047e..4c23c41 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -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 } } diff --git a/src/ord.rs b/src/ord.rs index 18fc508..f0b4e1d 100644 --- a/src/ord.rs +++ b/src/ord.rs @@ -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 { + 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 { let a_sign; diff --git a/src/smallint.rs b/src/smallint.rs index 0897f87..d600b5b 100644 --- a/src/smallint.rs +++ b/src/smallint.rs @@ -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 232 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 232 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))) + } + } + } +} diff --git a/src/tests.rs b/src/tests.rs index 5ffb10d..e33e382 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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;