From 2b09c240c49647b399da6ba63d2bc91aaa143de6 Mon Sep 17 00:00:00 2001 From: EvilMuffinHa Date: Thu, 4 Aug 2022 00:31:20 -0400 Subject: [PATCH] add for smalluint - currently doesn't work --- src/lib.rs | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cc8fa0c..091e8b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ use num_bigint::BigUint; use num_bigint::Sign; use core::mem::ManuallyDrop; +use core::ops::Add; /// An error that occurred when processing a `SmallInt`. #[derive(Debug, Clone, PartialEq, Eq)] @@ -77,6 +78,109 @@ impl core::fmt::Debug for SmallUint { } } +fn add_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec { + + let s = slice1.len(); + let j = slice2.len(); + + let larger = std::cmp::max(s, j); + let mut res = Vec::with_capacity(larger + 1); + let mut carry = false; + + for t in 0..larger { + + let value1 = if t < s { + slice1[t] + } else { + 0 + }; + + let value2 = if t < j { + slice2[t] + } else { + 0 + }; + + let (val, overflow) = value1.overflowing_add(value2); + let (cval, coverflow) = val.overflowing_add(carry as u32); + res.push(cval); + carry = overflow | coverflow; + + } + + if carry { + res.push(1); + } + while res[res.len() - 1] == 0 { + res.pop(); + } + res +} + +impl Add for SmallUint { + type Output = SmallUint; + + fn add(self, rhs: SmallUint) -> Self::Output { + match (&self.0, &rhs.0) { + (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { + match i.overflowing_add(j) { + (t, false) => Self(SmallUintType::Inline(t)), + (t, true) => { + + + let mut res = [0, 0, 0, 0, 1]; + + let mut v = t; + #[allow(clippy::needless_range_loop)] + for r in 0..4 { + res[r] = v as u32; + + v >>= 32; + } + + Self(SmallUintType::Heap((>::from(res).as_mut_ptr(), 5))) + + } + } + }, + (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) | (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) => { + let slice1 = unsafe { core::slice::from_raw_parts(r, s) }; + + let mut res = [0, 0, 0, 0, 1]; + + let mut v = i; + #[allow(clippy::needless_range_loop)] + for r in 0..4 { + res[r] = v as u32; + + v >>= 32; + } + let result = add_two_slices(slice1, &res[..]); + let size = result.len(); + + let mut slice = ManuallyDrop::new(result.into_boxed_slice()); + + Self(SmallUintType::Heap((slice.as_mut_ptr(), size))) + + + }, + (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => { + + let slice1 = unsafe { core::slice::from_raw_parts(r, s) }; + let slice2 = unsafe { core::slice::from_raw_parts(i, j) }; + + let res = add_two_slices(slice1, slice2); + let size = res.len(); + + let mut slice = ManuallyDrop::new(res.into_boxed_slice()); + + Self(SmallUintType::Heap((slice.as_mut_ptr(), size))) + + } + } + } +} + impl Drop for SmallInt { fn drop(&mut self) { if let Self(SmallIntType::Heap((r, s))) = self { @@ -322,9 +426,10 @@ impl From<&SmallUint> for BigUint { mod conversion_tests { use crate::SmallInt; + use crate::SmallUint; #[cfg(feature = "num-bigint")] - use num_bigint::{BigInt, Sign}; + use num_bigint::{BigInt, Sign, BigUint, }; macro_rules! conversion_tests { ($t:ty, $i:ident) => { @@ -352,6 +457,17 @@ mod conversion_tests { conversion_tests!(u128, test_u128); conversion_tests!(i128, test_i128); + #[test] + #[cfg(feature = "num-bigint")] + fn test_op_add_u_u() { + let i = SmallUint::from(u128::MAX); + let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 2, 1, 5])); + let q = i + k; + println!("{:?}", BigUint::from(&q)); + println!("{:?}", BigUint::new(vec![5, 4, 9, 3, 2, 1, 5]) + u128::MAX); + + } + #[test] #[cfg(feature = "num-bigint")] fn test_bigint() {