diff --git a/Cargo.toml b/Cargo.toml index 38f6727..75e0b8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ ark-ff-04 = { version = "0.4.0", package = "ark-ff", optional = true, default-fe bn-rs = { version = "0.2", optional = true, default-features = true } fastrlp = { version = "0.3", optional = true, default-features = false, features = ["alloc"] } num-bigint = { version = "0.4", optional = true, default-features = false } +num-integer = { version = "0.1", optional = true, default-features = false } num-traits = { version = "0.2.16", optional = true, default-features = false } parity-scale-codec = { version = "3", optional = true, features = [ "derive", @@ -100,6 +101,7 @@ std = [ "bytes?/std", "fastrlp?/std", "num-bigint?/std", + "num-integer?/std", "num-traits?/std", "parity-scale-codec?/std", "primitive-types?/std", @@ -125,6 +127,7 @@ ark-ff-04 = ["dep:ark-ff-04"] bn-rs = ["dep:bn-rs", "std"] fastrlp = ["dep:fastrlp", "alloc"] num-bigint = ["dep:num-bigint", "alloc"] +num-integer = ["dep:num-integer", "num-traits", "alloc"] num-traits = ["dep:num-traits", "alloc"] parity-scale-codec = ["dep:parity-scale-codec", "alloc"] primitive-types = ["dep:primitive-types"] diff --git a/src/support/mod.rs b/src/support/mod.rs index 242c65c..ddfd7f5 100644 --- a/src/support/mod.rs +++ b/src/support/mod.rs @@ -10,6 +10,7 @@ mod bn_rs; mod bytemuck; mod fastrlp; mod num_bigint; +mod num_integer; mod num_traits; pub mod postgres; mod primitive_types; diff --git a/src/support/num_integer.rs b/src/support/num_integer.rs new file mode 100644 index 0000000..d65cdd0 --- /dev/null +++ b/src/support/num_integer.rs @@ -0,0 +1,103 @@ +//! Support for the [`num-integer`](https://crates.io/crates/num-integer) crate. + +#![cfg(feature = "num-integer")] + +use crate::Uint; +use num_integer::{ExtendedGcd, Integer}; + +impl Integer for Uint { + #[inline] + #[must_use] + #[track_caller] + fn div_floor(&self, other: &Self) -> Self { + Self::wrapping_div(*self, *other) + } + + #[inline] + #[must_use] + #[track_caller] + fn mod_floor(&self, other: &Self) -> Self { + Self::wrapping_rem(*self, *other) + } + + #[inline] + #[must_use] + fn gcd(&self, other: &Self) -> Self { + ::gcd(*self, *other) + } + + #[inline] + #[must_use] + #[track_caller] + fn lcm(&self, other: &Self) -> Self { + ::lcm(*self, *other).unwrap() + } + + #[inline] + fn is_multiple_of(&self, other: &Self) -> bool { + if other.is_zero() { + return self.is_zero(); + } + *self % *other == Self::ZERO + } + + #[inline] + fn is_even(&self) -> bool { + !self.bit(0) + } + + #[inline] + fn is_odd(&self) -> bool { + self.bit(0) + } + + #[inline] + #[track_caller] + fn div_rem(&self, other: &Self) -> (Self, Self) { + ::div_rem(*self, *other) + } + + #[inline] + #[track_caller] + fn div_ceil(&self, other: &Self) -> Self { + ::div_ceil(*self, *other) + } + + #[inline] + #[track_caller] + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + // Same as `div_rem` for unsigned integers. + ::div_rem(*self, *other) + } + + #[inline] + fn extended_gcd(&self, other: &Self) -> ExtendedGcd { + let (gcd, x, y, _sign) = ::gcd_extended(*self, *other); + ExtendedGcd { gcd, x, y } + } + + #[inline] + fn dec(&mut self) { + *self -= Self::from(1); + } + + #[inline] + fn inc(&mut self) { + *self += Self::from(1); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_is_even() { + let mut a = Uint::<64, 1>::from(0u32); + for _ in 0..10 { + a.inc(); + assert_eq!(a.is_even(), a.to::() % 2 == 0); + assert_eq!(a.is_odd(), a.to::() % 2 != 0); + } + } +}