about summary refs log tree commit diff stats
path: root/crates/core/src/numerics/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/core/src/numerics/mod.rs')
-rw-r--r--crates/core/src/numerics/mod.rs102
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);