mirror of
				https://gitlab.com/artofrev/smallint.git
				synced 2025-10-31 06:51:12 -04:00 
			
		
		
		
	signed stuff - todo: test partialord / ord / add for SmallInt
This commit is contained in:
		
							parent
							
								
									cf9c8b0b78
								
							
						
					
					
						commit
						df10924284
					
				| @ -153,3 +153,26 @@ 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::try_from(i.abs()).unwrap(), | ||||
|             SmallIntType::Heap((r, s)) => { | ||||
|                 let size = usize::try_from(s.abs()).unwrap(); | ||||
|                 if size > 4 { | ||||
|                     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()); | ||||
|                     Self(SmallUintType::Heap((val.as_mut_ptr(), size))) | ||||
|                 } else if s >= 0 { | ||||
|                     Self(SmallUintType::Inline(u128::try_from(value).unwrap())) | ||||
|                 } else { | ||||
|                     Self(SmallUintType::Inline(u128::try_from(-value).unwrap())) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -19,6 +19,8 @@ mod error; | ||||
| pub use error::SmallIntError; | ||||
| 
 | ||||
| mod convert; | ||||
| mod ord; | ||||
| 
 | ||||
| mod logic; | ||||
| mod ops; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										96
									
								
								src/ops.rs
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								src/ops.rs
									
									
									
									
									
								
							| @ -1,14 +1,32 @@ | ||||
| use crate::smallint::SmallUintType; | ||||
| use crate::SmallUint; | ||||
| use crate::smallint::{SmallIntType, SmallUintType}; | ||||
| use crate::{SmallInt, SmallUint}; | ||||
| use core::mem::ManuallyDrop; | ||||
| use core::ops::{Add, Mul, Sub}; | ||||
| use core::ops::{Add, Mul, Neg, Sub}; | ||||
| 
 | ||||
| impl Neg for SmallInt { | ||||
|     type Output = Self; | ||||
| 
 | ||||
|     fn neg(self) -> Self::Output { | ||||
|         match self.0 { | ||||
|             SmallIntType::Inline(i) => SmallInt(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))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| macro_rules! basic_op { | ||||
|     ($imp:ident, $typ:ty, $fun:ident) => { | ||||
|     ($imp:ident, $lower:ident, $typ:ty, $fun:ident) => { | ||||
|         impl<'a, 'b> $imp<&'a $typ> for &'b $typ { | ||||
|             type Output = $typ; | ||||
| 
 | ||||
|             fn $fun(self, rhs: &$typ) -> Self::Output { | ||||
|             fn $lower(self, rhs: &$typ) -> Self::Output { | ||||
|                 $fun(self, rhs) | ||||
|             } | ||||
|         } | ||||
| @ -16,24 +34,24 @@ macro_rules! basic_op { | ||||
|         impl<'a> $imp<$typ> for &'a $typ { | ||||
|             type Output = $typ; | ||||
| 
 | ||||
|             fn $fun(self, rhs: $typ) -> Self::Output { | ||||
|                 self.$fun(&rhs) | ||||
|             fn $lower(self, rhs: $typ) -> Self::Output { | ||||
|                 self.$lower(&rhs) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl<'a> $imp<&'a $typ> for $typ { | ||||
|             type Output = $typ; | ||||
| 
 | ||||
|             fn $fun(self, rhs: &$typ) -> Self::Output { | ||||
|                 (&self).$fun(rhs) | ||||
|             fn $lower(self, rhs: &$typ) -> Self::Output { | ||||
|                 (&self).$lower(rhs) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl $imp<$typ> for $typ { | ||||
|             type Output = $typ; | ||||
| 
 | ||||
|             fn $fun(self, rhs: $typ) -> Self::Output { | ||||
|                 (&self).$fun(&rhs) | ||||
|             fn $lower(self, rhs: $typ) -> Self::Output { | ||||
|                 (&self).$lower(&rhs) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| @ -122,7 +140,57 @@ fn add(a: &SmallUint, b: &SmallUint) -> SmallUint { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| basic_op!(Add, SmallUint, add); | ||||
| basic_op!(Add, add, SmallUint, add); | ||||
| 
 | ||||
| fn add_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) => { | ||||
|             let s = SmallUint::from_smallint_unsigned(a.clone()); | ||||
|             let b = SmallUint::from_smallint_unsigned(b.clone()); | ||||
|             if b <= s { | ||||
|                 SmallInt::from(s - b) | ||||
|             } else { | ||||
|                 -SmallInt::from(b - s) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         x if (x.0 < 0 && x.1 >= 0) => { | ||||
|             let s = SmallUint::from_smallint_unsigned(a.clone()); | ||||
|             let b = SmallUint::from_smallint_unsigned(b.clone()); | ||||
|             if s <= b { | ||||
|                 SmallInt::from(b - s) | ||||
|             } else { | ||||
|                 -SmallInt::from(s - b) | ||||
|             } | ||||
|         } | ||||
|         (_, _) => { | ||||
|             panic!("This shouldn't happen. "); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| basic_op!(Add, add, SmallInt, add_signed); | ||||
| 
 | ||||
| fn sub_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec<u32> { | ||||
|     let b = slice1.len(); | ||||
| @ -207,7 +275,7 @@ fn sub(a: &SmallUint, b: &SmallUint) -> SmallUint { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| basic_op!(Sub, SmallUint, sub); | ||||
| basic_op!(Sub, sub, SmallUint, sub); | ||||
| 
 | ||||
| // Taken from https://github.com/rust-lang/rust/issues/85532#issuecomment-916309635. Credit to
 | ||||
| // AaronKutch.
 | ||||
| @ -392,4 +460,4 @@ fn mul(a: &SmallUint, b: &SmallUint) -> SmallUint { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| basic_op!(Mul, SmallUint, mul); | ||||
| basic_op!(Mul, mul, SmallUint, mul); | ||||
|  | ||||
							
								
								
									
										40
									
								
								src/ord.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/ord.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| use crate::smallint::SmallIntType; | ||||
| use crate::SmallInt; | ||||
| use crate::SmallUint; | ||||
| use std::cmp::Ordering; | ||||
| 
 | ||||
| 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, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Ord for SmallInt { | ||||
|     fn cmp(&self, other: &Self) -> Ordering { | ||||
|         self.partial_cmp(other).expect("This should not happen.") | ||||
|     } | ||||
| } | ||||
| @ -5,7 +5,7 @@ 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)] | ||||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub struct SmallUint(pub(crate) SmallUintType); | ||||
| 
 | ||||
| #[derive(Clone, PartialEq, Eq)] | ||||
| @ -14,7 +14,7 @@ pub enum SmallIntType { | ||||
|     Heap((*mut u32, isize)), | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, PartialEq, Eq)] | ||||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum SmallUintType { | ||||
|     Inline(u128), | ||||
|     Heap((*mut u32, usize)), | ||||
|  | ||||
							
								
								
									
										20
									
								
								src/tests.rs
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/tests.rs
									
									
									
									
									
								
							| @ -191,6 +191,26 @@ fn test_op_xor_u_u() { | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| #[cfg(feature = "num-bigint")] | ||||
| fn test_op_neg() { | ||||
|     let i = SmallInt::from(u128::MAX); | ||||
|     let q = -i; | ||||
|     assert_eq!(BigInt::from(&q), -BigInt::from(u128::MAX)); | ||||
| 
 | ||||
|     let i = SmallInt::from(i64::MIN); | ||||
|     let q = -i; | ||||
|     assert_eq!(BigInt::from(&q), -BigInt::from(i64::MIN)); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| #[cfg(feature = "num-bigint")] | ||||
| fn test_conversion_sign_drop() { | ||||
|     let si = SmallInt::from(i128::MIN + 1); | ||||
|     let i = SmallUint::from_smallint_unsigned(si); | ||||
|     assert_eq!(BigUint::from(&i), BigUint::from(-(i128::MIN + 1) as u128)) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| #[cfg(feature = "num-bigint")] | ||||
| fn test_bigint() { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user