mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-22 14:32:44 -05:00
Compare commits
No commits in common. "021454c43876fb256ed91a96796bbf8d20dbcbb7" and "31ba185962aa984a38c86b010e9e6990834a09a5" have entirely different histories.
021454c438
...
31ba185962
128
src/lib.rs
128
src/lib.rs
|
@ -19,7 +19,6 @@ use num_bigint::BigUint;
|
||||||
use num_bigint::Sign;
|
use num_bigint::Sign;
|
||||||
|
|
||||||
use core::mem::ManuallyDrop;
|
use core::mem::ManuallyDrop;
|
||||||
use core::ops::Add;
|
|
||||||
|
|
||||||
/// An error that occurred when processing a `SmallInt`.
|
/// An error that occurred when processing a `SmallInt`.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -78,111 +77,6 @@ impl core::fmt::Debug for SmallUint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec<u32> {
|
|
||||||
|
|
||||||
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<SmallUint> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut slice = ManuallyDrop::new(<Box<[u32]>>::from(res));
|
|
||||||
|
|
||||||
Self(SmallUintType::Heap((slice.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];
|
|
||||||
|
|
||||||
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 {
|
impl Drop for SmallInt {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Self(SmallIntType::Heap((r, s))) = self {
|
if let Self(SmallIntType::Heap((r, s))) = self {
|
||||||
|
@ -428,10 +322,9 @@ impl From<&SmallUint> for BigUint {
|
||||||
mod conversion_tests {
|
mod conversion_tests {
|
||||||
|
|
||||||
use crate::SmallInt;
|
use crate::SmallInt;
|
||||||
use crate::SmallUint;
|
|
||||||
|
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
use num_bigint::{BigInt, Sign, BigUint};
|
use num_bigint::{BigInt, Sign};
|
||||||
|
|
||||||
macro_rules! conversion_tests {
|
macro_rules! conversion_tests {
|
||||||
($t:ty, $i:ident) => {
|
($t:ty, $i:ident) => {
|
||||||
|
@ -459,25 +352,6 @@ mod conversion_tests {
|
||||||
conversion_tests!(u128, test_u128);
|
conversion_tests!(u128, test_u128);
|
||||||
conversion_tests!(i128, test_i128);
|
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(u128::MAX);
|
|
||||||
let q = i + k;
|
|
||||||
assert_eq!(BigUint::from(&q), BigUint::from(u128::MAX) + u128::MAX);
|
|
||||||
|
|
||||||
let i = SmallUint::from(u128::MAX);
|
|
||||||
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
|
||||||
let q = i + k;
|
|
||||||
assert_eq!(BigUint::from(&q), BigUint::new(vec![5, 4, 9, 3, 1, 81]) + u128::MAX);
|
|
||||||
|
|
||||||
let i = SmallUint::from(&BigUint::new(vec![3, 9, 8]));
|
|
||||||
let k = SmallUint::from(&BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
|
||||||
let q = i + k;
|
|
||||||
assert_eq!(BigUint::from(&q), BigUint::new(vec![3, 9, 8]) + BigUint::new(vec![5, 4, 9, 3, 1, 81]));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "num-bigint")]
|
#[cfg(feature = "num-bigint")]
|
||||||
fn test_bigint() {
|
fn test_bigint() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user