diff --git a/src/natural.rs b/src/natural.rs index 684e530..dd75ca2 100644 --- a/src/natural.rs +++ b/src/natural.rs @@ -1,10 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -use core::mem::size_of; -use core::ops::{Add, Sub, Mul, Div, Rem}; -use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use core::str::FromStr; +use core::ops::{Add, AddAssign, Mul, MulAssign}; use crate::number::Number; use crate::one::One; @@ -18,15 +15,68 @@ use crate::one::One; /// u8, u16, u32, u64, u128, usize pub trait Natural: Number + One + Add + AddAssign + - Sub + SubAssign + Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign { + /// Attempts to subtract a number from itself. + /// + /// Since subtraction isn't closed under this set (1 - 2 = -1) the trait + /// doesn't enforce that Sub and SubAssign are implemented. This function, + /// however, allows for subtraction and handles the case where the result is + /// no longer within the `Natural` numbers domain. + /// + /// # Arguments + /// `rhs`: The number to subtract. + /// + /// # Returns + /// `None` if the subtraction would fall below 1. + /// `Some` if their is a valid result. + /// + /// # Examples + /// ```rust + /// use sigils::Natural; + /// + /// let x = 3u8 as Natural; + /// + /// assert_eq!(x.try_sub(2), Some(1)); + /// assert_eq!(x.try_sub(7), None); + /// ``` + fn try_sub(self, rhs: Self) -> Option; +/* + /// + fn try_div(self, rhs: Self) -> Option; + + /// + fn try_rem(self, rhs: Self) -> Option; + /// Performs division and returns both the quotient and remainder. #[inline] - fn div_rem(self, rhs: Self) -> (Self, Self) + fn try_div_rem(self, rhs: Self) -> Option<(Self, Self)> { - (self / rhs, self % rhs) + Some((self.try_div(rhs)?, self.try_rem(rhs)?)) + } +*/ +} + + + +/// A macro to make implementing the `Natural` trait easier for all the +/// base types in Rust. +macro_rules! natural_trait_impl +{ + ($($varType:ty),*) => + { + $( + impl Natural for $varType + { + #[inline] + fn try_sub(self, rhs: Self) -> Option + { + self.checked_sub(rhs).filter(|x| *x >= Self::one()) + } + } + )* } } + +// Implement the Number trait for the types that are Numbers. +natural_trait_impl!(u8, u16, u32, u64, u128, usize);