diff options
Diffstat (limited to 'crates/core/src/numerics/mod.rs')
-rw-r--r-- | crates/core/src/numerics/mod.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/crates/core/src/numerics/mod.rs b/crates/core/src/numerics/mod.rs new file mode 100644 index 0000000..9e3d782 --- /dev/null +++ b/crates/core/src/numerics/mod.rs @@ -0,0 +1,102 @@ +//! Number traits and utilities. + +use core::{ + mem, + ops::{ + Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, + SubAssign, + }, +}; + +pub mod rational; + +//NOTE: these should probably be broken up a bunch; they're only implemented +// this way because i didn't really need much else to implement +// rationals. ideally we should break them up on the lines of rings, +// groups, fields, unique factorization domains, principal ideal domains, +// ordered rings, etc. this would make further extensions to +// functionality in azimuth easier. + +/// Integer. +pub trait Integer: + Eq + + Ord + + Mul<Output = Self> + + Div<Output = Self> + + Add<Output = Self> + + Sub<Output = Self> + + Rem<Output = Self> + + MulAssign + + DivAssign + + AddAssign + + SubAssign + + RemAssign + + Sized + + Copy + + Clone +{ + //NOTE: `Neg` is neglected here as the primary purpose of this trait is + // to abstract over integers for the `Rational` type. as stated + // above, i'd like to adjust the way all of this works anyway for + // future extensions, but for now, we don't really need it. + + //NOTE: `Copy` is required for now as bignum support is not a requirement + // yet and this makes implementation simpler. + + /// Additive identity. + const ZERO: Self; + + /// Multiplicative identity. + const ONE: Self; + + /// Maximum attainable value. + const MAX: Self; + + /// Minimum attainable value. + const MIN: Self; + + /// Calculates the greatest common divisor of this number and another + fn gcd(&self, rhs: &Self) -> Self; +} + +/// Helper macro for the implementation of `Integer` +macro_rules! integer_impl { + ($type:ty, $zero:expr, $one:expr, $max:expr, $min:expr) => { + impl Integer for $type { + const ZERO: Self = $zero; + const ONE: Self = $one; + const MAX: Self = $max; + const MIN: Self = $min; + + #[inline] + fn gcd(&self, rhs: &Self) -> Self { + let mut m = *self; + let mut n = *rhs; + + if m < n { + mem::swap(&mut m, &mut n); + } + + while n != 0 { + let t = n; + n = m % n; + m = t; + } + + m + } + } + }; +} + +integer_impl!(i8, 0, 1, i8::MAX, i8::MIN); +integer_impl!(i16, 0, 1, i16::MAX, i16::MIN); +integer_impl!(i32, 0, 1, i32::MAX, i32::MIN); +integer_impl!(i64, 0, 1, i64::MAX, i64::MIN); +integer_impl!(i128, 0, 1, i128::MAX, i128::MIN); + +integer_impl!(u8, 0, 1, u8::MAX, u8::MIN); +integer_impl!(u16, 0, 1, u16::MAX, u16::MIN); +integer_impl!(u32, 0, 1, u32::MAX, u32::MIN); +integer_impl!(u64, 0, 1, u64::MAX, u64::MIN); +integer_impl!(u128, 0, 1, u128::MAX, u128::MIN); |