mirror of
				https://gitlab.com/artofrev/smallint.git
				synced 2025-10-30 22:41:12 -04: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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user