diff --git a/src/logic.rs b/src/logic.rs index 55ecca3..d38a2a9 100644 --- a/src/logic.rs +++ b/src/logic.rs @@ -2,6 +2,7 @@ use crate::smallint::SmallUintType; use crate::SmallUint; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor}; +use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign}; macro_rules! basic_op { ($imp:ident, $typ:ty, $fun:ident) => { @@ -90,6 +91,18 @@ fn bitand(a: &SmallUint, b: &SmallUint) -> SmallUint { basic_op!(BitAnd, SmallUint, bitand); +impl<'a> BitAndAssign<&'a SmallUint> for SmallUint { + fn bitand_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() & rhs; + } +} + +impl BitAndAssign for SmallUint { + fn bitand_assign(&mut self, rhs: SmallUint) { + *self = self.clone() & rhs; + } +} + fn bitor(a: &SmallUint, b: &SmallUint) -> SmallUint { match (&a.0, &b.0) { (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { @@ -140,6 +153,18 @@ fn bitor(a: &SmallUint, b: &SmallUint) -> SmallUint { basic_op!(BitOr, SmallUint, bitor); +impl<'a> BitOrAssign<&'a SmallUint> for SmallUint { + fn bitor_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() | rhs; + } +} + +impl BitOrAssign for SmallUint { + fn bitor_assign(&mut self, rhs: SmallUint) { + *self = self.clone() | rhs; + } +} + fn bitxor(a: &SmallUint, b: &SmallUint) -> SmallUint { match (&a.0, &b.0) { (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { @@ -201,3 +226,15 @@ fn bitxor(a: &SmallUint, b: &SmallUint) -> SmallUint { } basic_op!(BitXor, SmallUint, bitxor); + +impl<'a> BitXorAssign<&'a SmallUint> for SmallUint { + fn bitxor_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() ^ rhs; + } +} + +impl BitXorAssign for SmallUint { + fn bitxor_assign(&mut self, rhs: SmallUint) { + *self = self.clone() ^ rhs; + } +} diff --git a/src/ops.rs b/src/ops.rs index be7e3d7..e9e8246 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -2,6 +2,7 @@ use crate::smallint::{SmallIntType, SmallUintType}; use crate::{SmallInt, SmallUint}; use core::mem::ManuallyDrop; use core::ops::{Add, Mul, Neg, Sub}; +use core::ops::{AddAssign, MulAssign, SubAssign}; impl Neg for SmallInt { type Output = Self; @@ -142,6 +143,18 @@ fn add(a: &SmallUint, b: &SmallUint) -> SmallUint { basic_op!(Add, add, SmallUint, add); +impl<'a> AddAssign<&'a SmallUint> for SmallUint { + fn add_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() + rhs; + } +} + +impl AddAssign for SmallUint { + fn add_assign(&mut self, rhs: SmallUint) { + *self = self.clone() + rhs; + } +} + fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt { let a_sign; match &a.0 { @@ -192,6 +205,18 @@ fn add_signed(a: &SmallInt, b: &SmallInt) -> SmallInt { basic_op!(Add, add, SmallInt, add_signed); +impl<'a> AddAssign<&'a SmallInt> for SmallInt { + fn add_assign(&mut self, rhs: &'a SmallInt) { + *self = self.clone() + rhs; + } +} + +impl AddAssign for SmallInt { + fn add_assign(&mut self, rhs: SmallInt) { + *self = self.clone() + rhs; + } +} + fn sub_two_slices(slice1: &[u32], slice2: &[u32]) -> Vec { let b = slice1.len(); let s = slice2.len(); @@ -277,12 +302,36 @@ fn sub(a: &SmallUint, b: &SmallUint) -> SmallUint { basic_op!(Sub, sub, SmallUint, sub); +impl<'a> SubAssign<&'a SmallUint> for SmallUint { + fn sub_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() - rhs; + } +} + +impl SubAssign for SmallUint { + fn sub_assign(&mut self, rhs: SmallUint) { + *self = self.clone() - rhs; + } +} + fn sub_signed(a: &SmallInt, b: &SmallInt) -> SmallInt { a + (-b.clone()) } basic_op!(Sub, sub, SmallInt, sub_signed); +impl<'a> SubAssign<&'a SmallInt> for SmallInt { + fn sub_assign(&mut self, rhs: &'a SmallInt) { + *self = self.clone() - rhs; + } +} + +impl SubAssign for SmallInt { + fn sub_assign(&mut self, rhs: SmallInt) { + *self = self.clone() - rhs; + } +} + // Taken from https://github.com/rust-lang/rust/issues/85532#issuecomment-916309635. Credit to // AaronKutch. const fn carrying_mul_u128(lhs: u128, rhs: u128, carry: u128) -> (u128, u128) { @@ -468,6 +517,18 @@ fn mul(a: &SmallUint, b: &SmallUint) -> SmallUint { basic_op!(Mul, mul, SmallUint, mul); +impl<'a> MulAssign<&'a SmallUint> for SmallUint { + fn mul_assign(&mut self, rhs: &'a SmallUint) { + *self = self.clone() * rhs; + } +} + +impl MulAssign for SmallUint { + fn mul_assign(&mut self, rhs: SmallUint) { + *self = self.clone() * rhs; + } +} + fn mul_signed(a: &SmallInt, b: &SmallInt) -> SmallInt { let a_sign; match &a.0 { @@ -508,3 +569,15 @@ fn mul_signed(a: &SmallInt, b: &SmallInt) -> SmallInt { } basic_op!(Mul, mul, SmallInt, mul_signed); + +impl<'a> MulAssign<&'a SmallInt> for SmallInt { + fn mul_assign(&mut self, rhs: &'a SmallInt) { + *self = self.clone() * rhs; + } +} + +impl MulAssign for SmallInt { + fn mul_assign(&mut self, rhs: SmallInt) { + *self = self.clone() * rhs; + } +} diff --git a/src/pretty.rs b/src/pretty.rs index 8f6be5b..5c122c7 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -6,31 +6,51 @@ use crate::smallint::{SmallIntType, SmallUintType}; #[cfg(feature = "num-bigint")] use num_bigint::{BigInt, BigUint}; -#[cfg(feature = "num-bigint")] impl core::fmt::Debug for SmallInt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", BigInt::from(self)) + match self.0 { + SmallIntType::Inline(i) => { + write!(f, "{}", i)?; + } + SmallIntType::Heap((r, s)) => { + #[cfg(feature = "num-bigint")] + write!(f, "{}", BigInt::from(self))?; + + #[cfg(not(feature = "num-bigint"))] + todo!(); + } + } + Ok(()) } } -#[cfg(feature = "num-bigint")] impl core::fmt::Debug for SmallUint { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", BigUint::from(self)) + match self.0 { + SmallUintType::Inline(i) => { + write!(f, "{}", i)?; + } + SmallUintType::Heap((r, s)) => { + #[cfg(feature = "num-bigint")] + write!(f, "{}", BigUint::from(self))?; + + #[cfg(not(feature = "num-bigint"))] + todo!(); + } + } + Ok(()) } } -#[cfg(feature = "num-bigint")] impl core::fmt::Display for SmallInt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", BigInt::from(self)) + write!(f, "{:?}", self) } } -#[cfg(feature = "num-bigint")] impl core::fmt::Display for SmallUint { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", BigUint::from(self)) + write!(f, "{:?}", self) } } diff --git a/src/smallint.rs b/src/smallint.rs index d600b5b..5266be0 100644 --- a/src/smallint.rs +++ b/src/smallint.rs @@ -1,3 +1,4 @@ +use core::hash::Hash; use core::mem::ManuallyDrop; /// An integer-like type that will store small integers up to `i128` inline. Larger integers are @@ -67,3 +68,28 @@ impl Clone for SmallInt { } } } + +impl Hash for SmallUint { + fn hash(&self, state: &mut H) { + match self.0 { + SmallUintType::Inline(i) => i.hash(state), + SmallUintType::Heap((r, s)) => { + let slice = unsafe { core::slice::from_raw_parts(r, s) }; + slice.hash(state); + } + } + } +} + +impl Hash for SmallInt { + fn hash(&self, state: &mut H) { + match self.0 { + SmallIntType::Inline(i) => i.hash(state), + SmallIntType::Heap((r, s)) => { + let size = usize::try_from(s.abs()).unwrap(); + let slice = unsafe { core::slice::from_raw_parts(r, size) }; + slice.hash(state); + } + } + } +}