diff --git a/src/bounded.rs b/src/bounded.rs index baff6f2..e421ef2 100644 --- a/src/bounded.rs +++ b/src/bounded.rs @@ -1,13 +1,38 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -/// Primitive types that have upper and lower bounds. +/// `Bounded` provides the inclusive minimum and maximum range limits +/// for a numeric type. +/// +/// Rust types have actual upper and lower representation limits that don't +/// follow the mathematical definitions. For example a Natural number goes +/// from one to infinity but a u8 can only really represent a number between +/// zero and two hundred and fifty five. This let's use set the minimum and +/// maximum values a Rust type can represent so we can use them in code easily. pub trait Bounded { /// The minimum value for this type. + /// + /// # Examples + /// ```rust + /// use sigils::Bounded; + /// + /// let min = ::MIN; + /// + /// assert_eq!(min, u8::MIN); + /// ``` const MIN: Self; /// The maximum value for this type. + /// + /// # Examples + /// ```rust + /// use sigils::Bounded; + /// + /// let max = ::MAX; + /// + /// assert_eq!(max, f64::MAX); + /// ``` const MAX: Self; } @@ -17,83 +42,20 @@ pub trait Bounded /// the Bounded trait easier. macro_rules! bounded_trait_impl { - ($T: ty, $minVal: expr, $maxVal: expr) => + ($($T:ty),*) => { - impl Bounded for $T - { - const MIN: $T = $minVal; - - const MAX: $T = $maxVal; - } + $( + impl Bounded for $T + { + const MIN: $T = <$T>::MIN; + const MAX: $T = <$T>::MAX; + } + )* } } // Implement the Bounded for all the primitive types. -bounded_trait_impl!(u8, 0u8, !0u8); -bounded_trait_impl!(u16, 0u16, !0u16); -bounded_trait_impl!(u32, 0u32, !0u32); -bounded_trait_impl!(u64, 0u64, !0u64); -bounded_trait_impl!(usize, 0usize, !0usize); - -bounded_trait_impl!(i8, (!0i8 ^ (!0u8 >> 1u8) as i8), - !(!0i8 ^ (!0u8 >> 1u8) as i8)); -bounded_trait_impl!(i16, (!0i16 ^ (!0u16 >> 1u16) as i16), - !(!0i16 ^ (!0u16 >> 1u16) as i16)); -bounded_trait_impl!(i32, (!0i32 ^ (!0u32 >> 1u32) as i32), - !(!0i32 ^ (!0u32 >> 1u32) as i32)); -bounded_trait_impl!(i64, (!0i64 ^ (!0u64 >> 1u64) as i64), - !(!0i64 ^ (!0u64 >> 1u64) as i64)); -bounded_trait_impl!(isize, (!0isize ^ (!0usize >> 1usize) as isize), - !(!0isize ^ (!0usize >> 1usize) as isize)); - -bounded_trait_impl!(f32, -3.40282347e+38f32, 3.40282347e+38f32); -bounded_trait_impl!(f64, -1.7976931348623157e+308f64, - 1.7976931348623157e+308f64); - - - -#[cfg(test)] -mod tests -{ - macro_rules! bounds_test - { - ($T: ident, $func_name: ident, $minVal: expr, $maxVal: expr) => - { - #[test] - fn $func_name() - { - assert_eq!($T::MIN, $minVal); - assert_eq!($T::MAX, $maxVal); - } - } - } - - bounds_test!(u8, min_max_u8, 0u8, !0u8); - bounds_test!(u16, min_max_u16, 0u16, !0u16); - bounds_test!(u32, min_max_u32, 0u32, !0u32); - bounds_test!(u64, min_max_u64, 0u64, !0u64); - bounds_test!(usize, min_max_usize, 0usize, !0usize); - - bounds_test!(i8, min_max_i8, - -1i8 << (((::std::mem::size_of::() as i8)*8i8)-1i8), - !(-1i8 << (((::std::mem::size_of::() as i8)*8i8)-1i8))); - bounds_test!(i16, min_max_i16, - -1i16 << (((::std::mem::size_of::() as i16)*8i16)-1i16), - !(-1i16 << (((::std::mem::size_of::() as i16)*8i16)-1i16))); - bounds_test!(i32, min_max_i32, - -1i32 << (((::std::mem::size_of::() as i32)*8i32)-1i32), - !(-1i32 << (((::std::mem::size_of::() as i32)*8i32)-1i32))); - bounds_test!(i64, min_max_i64, - -1i64 << (((::std::mem::size_of::() as i64)*8i64)-1i64), - !(-1i64 << (((::std::mem::size_of::() as i64)*8i64)-1i64))); - bounds_test!(isize, min_max_isize, - -1isize << (((::std::mem::size_of::() as isize)*8isize)-1isize), - !(-1isize << (((::std::mem::size_of::() as isize)*8isize)-1isize))); - - bounds_test!(f32, min_max_f32, - -3.40282347e+38f32, 3.40282347e+38f32); - bounds_test!(f64, min_max_f64, - -1.7976931348623157e+308f64, - 1.7976931348623157e+308f64); -} +bounded_trait_impl!(u8, u16, u32, u64, u128, usize); +bounded_trait_impl!(i8, i16, i32, i64, i128, isize); +bounded_trait_impl!(f32, f64); diff --git a/src/lib.rs b/src/lib.rs index 1553ce8..2d4eb80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,38 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -//! A mathematical library. -//! License: Proprietary +//! # Sigils //! +//! A high performance, 'no_std' mathematical library designed for use in +//! simulations and flight systems. //! +//! Sigils uses Rust's type system to strictly define a mathematical hierarchy +//! to ensure type-safe operations. + #![no_std] -extern crate core as std; -#[macro_use] -mod macros; - mod bounded; - -mod zero; -mod one; +//mod natural; mod number; +mod one; +mod zero; + + + +pub use self::bounded::Bounded; +//pub use self::natural::Natural; +pub use self::number::Number; +pub use self::one::One; +pub use self::zero::Zero; + + + +//#[macro_use] +//mod macros; +/* + mod whole; mod integer; mod real; @@ -28,11 +43,9 @@ mod trig; pub mod vector; pub mod matrix; pub mod quaternion; +*/ - - -pub use self::bounded::Bounded; -pub use self::zero::Zero; +/* pub use self::one::One; pub use self::number::{Number, FromNumber}; pub use self::whole::Whole; @@ -40,3 +53,4 @@ pub use self::integer::Integer; pub use self::real::Real; pub use self::constants::Constants; pub use self::trig::{Degree, Radian, Trig}; +*/ diff --git a/src/natural.rs b/src/natural.rs new file mode 100644 index 0000000..684e530 --- /dev/null +++ b/src/natural.rs @@ -0,0 +1,32 @@ +// 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 crate::number::Number; +use crate::one::One; + + + +/// A Natural number is a counting number from one to infinity. +/// 1, 2, 3, 4, 5, 6, ... +/// +/// Rust types that are in this category are: +/// u8, u16, u32, u64, u128, usize +pub trait Natural: Number + One + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign +{ + /// Performs division and returns both the quotient and remainder. + #[inline] + fn div_rem(self, rhs: Self) -> (Self, Self) + { + (self / rhs, self % rhs) + } +} diff --git a/src/number.rs b/src/number.rs index e2a9a4f..9b83d51 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,42 +1,35 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -use std::cmp::{PartialEq, PartialOrd}; -use std::fmt::{Debug, Display}; -use std::mem::size_of; -use std::ops::{Add, Sub, Mul, Div, Rem}; -use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use std::str::FromStr; - -use crate::bounded::Bounded; -use crate::zero::Zero; -use crate::one::One; +use core::cmp::{PartialEq, PartialOrd}; +use core::fmt::{Debug, Display}; -/// A trait that defines what is required to be considered -/// a number. -pub trait Number: Zero + One + Add + Sub + - Mul + Div + Rem + - AddAssign + SubAssign + MulAssign + - DivAssign + RemAssign + PartialEq + PartialOrd + - Copy + Clone + Debug + Display + +/// `Number` helps bridge the gap between the rust implementation and the pure +/// math definitions. +/// +/// `Number` has some basic Rust representation requirements. +/// +/// [`Sized`]: A `Number` has a known size at compile time. +/// [`Copy`] & [`Clone`]: A `Number` should be passed by value, not reference. +/// [`PartialEq`] & [`PartialOrd`]: Two instances of `Number` should be able to be compared. +/// [`Debug`] & [`Display`]: Easier to read output. +pub trait Number: Sized + Copy + Clone + + PartialEq + PartialOrd + + Debug + Display { - type StrRadixError; - - - - /// The smallest number that can be stored in this type. - //const MIN: Self; - - /// The largest number that can be stored in this type. - //const MAX: Self; - - - /// Returns the maximum of the two numbers. /// - /// ``` - /// use ::sigils::Number; + /// # Arguments + /// * `other` - Another value, of the same type, to compare. + /// + /// # Returns + /// The larger value of the two numbers. + /// + /// # Examples + /// ```rust + /// use sigils::Number; /// /// let x: f64; /// let y: f64; @@ -45,12 +38,23 @@ pub trait Number: Zero + One + Add + Sub + /// y = 2.0f64; /// assert_eq!(x.maximum(y), y); /// ``` - fn maximum(self, other: Self) -> Self; + #[inline] + fn maximum(self, other: Self) -> Self + { + if self >= other { self } else { other } + } /// Returns the minimum of the two numbers. /// - /// ``` - /// use ::sigils::Number; + /// # Arguments + /// * `other` - Another value, of the same type, to compare. + /// + /// # Returns + /// The smaller value of the two numbers. + /// + /// # Examples + /// ```rust + /// use sigils::Number; /// /// let x: i16; /// let y: i16; @@ -59,883 +63,29 @@ pub trait Number: Zero + One + Add + Sub + /// y = 55i16; /// assert_eq!(x.minimum(y), x); /// ``` - fn minimum(self, other: Self) -> Self; - - /// Create a number from a given string and base radix. - /// - ///``` - /// // Parse the hex value "FF" into an i32. - /// // Hex values have a radix (base) of 16. - /// use sigils::Number; - /// - /// let x: i32 = Number::from_str_radix("FF", 16u32).unwrap(); - /// # assert_eq!(x, 255i32); - ///``` - fn from_str_radix(src: &str, radix: u32) -> - Result; + #[inline] + fn minimum(self, other: Self) -> Self + { + if self <= other { self } else { other } + } } -/// A trait that defines converting something to a Number. -pub trait ToNumber + + + +/// A macro to make implementing the `Number` trait easier for all the +/// base types in Rust. +macro_rules! number_trait_impl { - /// Convert this to an u8. - /// None is returned if the conversion is not possible. - fn to_u8(&self) -> Option + ($($varType:ty),*) => { - let option: Option; - - option = self.to_u64(); - match option - { - Some(val) => - { - val.to_u8() - } - - None => - { - None - } - } - } - - /// Convert this to a u16. - /// None is returned if the conversion is not possible. - fn to_u16(&self) -> Option - { - let option: Option; - - option = self.to_u64(); - match option - { - Some(val) => - { - val.to_u16() - } - - None => - { - None - } - } - } - - /// Convert this to an u32. - /// None is returned if the conversion is not possible. - fn to_u32(&self) -> Option - { - let option: Option; - - option = self.to_u64(); - match option - { - Some(val) => - { - val.to_u32() - } - - None => - { - None - } - } - } - - /// Convert this to an u64. - /// None is returned if the conversion is not possible. - fn to_u64(&self) -> Option; - - /// Convert this to an usize. - /// None is returned if the conversion is not possible. - fn to_usize(&self) -> Option - { - let option: Option; - - option = self.to_u64(); - match option - { - Some(val) => - { - val.to_usize() - } - - None => - { - None - } - } - } - - - /// Convert this to an i8. - /// None is returned if the conversion is not possible. - fn to_i8(&self) -> Option - { - let option: Option; - - option = self.to_i64(); - match option - { - Some(val) => - { - val.to_i8() - } - - None => - { - None - } - } - } - - /// Convert this to an i16. - /// None is returned if the conversion is not possible. - fn to_i16(&self) -> Option - { - let option: Option; - - option = self.to_i64(); - match option - { - Some(val) => - { - val.to_i16() - } - - None => - { - None - } - } - } - - /// Convert this to an i32. - /// None is returned if the conversion is not possible. - fn to_i32(&self) -> Option - { - let option: Option; - - option = self.to_i64(); - match option - { - Some(val) => - { - val.to_i32() - } - - None => - { - None - } - } - } - - /// Convert this to an i64. - /// None is returned if the conversion is not possible. - fn to_i64(&self) -> Option; - - /// Convert this to an isize. - /// None is returned if the conversion is not possible. - fn to_isize(&self) -> Option - { - let option: Option; - - option = self.to_i64(); - match option - { - Some(val) => - { - val.to_isize() - } - - None => - { - None - } - } - } - - - /// Convert this to an f32. - /// None is returned if the conversion is not possible. - fn to_f32(&self) -> Option - { - let option: Option; - - option = self.to_f64(); - match option - { - Some(val) => - { - val.to_f32() - } - - None => - { - None - } - } - } - - /// Convert this to an f64. - /// None is returned if the conversion is not possible. - fn to_f64(&self) -> Option - { - let option: Option; - - option = self.to_i64(); - match option - { - Some(val) => - { - val.to_f64() - } - - None => - { - None - } - } + $( + impl Number for $varType {} + )* } } -/// A trait that defines convertung a Number to something else. -pub trait FromNumber : Sized -{ - /// Convert an i8 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_i8(number: i8) -> Option - { - FromNumber::from_i64(number as i64) - } - - /// Convert an i16 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_i16(number: i16) -> Option - { - FromNumber::from_i64(number as i64) - } - - /// Convert an i32 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_i32(number: i32) -> Option - { - FromNumber::from_i64(number as i64) - } - - /// Convert an i64 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_i64(number: i64) -> Option; - - /// Convert an isize to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_isize(number: isize) -> Option - { - FromNumber::from_i64(number as i64) - } - - - /// Convert an u8 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_u8(number: u8) -> Option - { - FromNumber::from_u64(number as u64) - } - - /// Convert an u16 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_u16(number: u16) -> Option - { - FromNumber::from_u64(number as u64) - } - - /// Convert an u32 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_u32(number: u32) -> Option - { - FromNumber::from_u64(number as u64) - } - - /// Convert an u64 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_u64(number: u64) -> Option; - - /// Convert an usize to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_usize(number: usize) -> Option - { - FromNumber::from_u64(number as u64) - } - - - /// Convert an f32 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_f32(number: f32) -> Option - { - FromNumber::from_f64(number as f64) - } - - /// Convert an f64 to an optional value of this type. - /// None is returned if the conversion is not possible. - fn from_f64(number: f64) -> Option - { - FromNumber::from_i64(number as i64) - } -} - - -// Create some macros to ease typing and reading. -macro_rules! convert_int_to_int -{ - ($srcType: ty, $dstType: ty, $val: expr) => - { - { - let num: i64; - let min_value: $dstType; - let max_value: $dstType; - - num = $val as i64; - min_value = Bounded::MIN; - max_value = Bounded::MAX; - - if (min_value as i64) <= num && num <= (max_value as i64) - { - Some($val as $dstType) - } - else - { - None - } - } - } -} - -macro_rules! convert_int_to_uint -{ - ($srcType: ty, $dstType: ty, $val: expr) => - { - { - let zero: $srcType; - let max_value: $dstType; - - zero = Zero::zero(); - max_value = Bounded::MAX; - - if zero <= $val && ($val as u64) <= (max_value as u64) - { - Some($val as $dstType) - } - else - { - None - } - } - } -} - -macro_rules! convert_uint_to_int -{ - ($dstType: ty, $val: expr) => - { - { - let max_value: $dstType; - - max_value = Bounded::MAX; - if ($val as u64) <= (max_value as u64) - { - Some($val as $dstType) - } - else - { - None - } - } - } -} - -macro_rules! convert_uint_to_uint -{ - ($srcType: ty, $dstType: ty, $val: expr) => - { - if size_of::<$srcType>() <= size_of::<$dstType>() - { - Some($val as $dstType) - } - else - { - let zero: $srcType; - let max_value: $dstType; - - zero = Zero::zero(); - max_value = Bounded::MAX; - - if zero <= $val && ($val as u64) <= (max_value as u64) - { - Some($val as $dstType) - } - else - { - None - } - } - } -} - -macro_rules! convert_float_to_float -{ - ($srcType: ty, $dstType: ty, $val: expr) => - { - if size_of::<$srcType>() <= size_of::<$dstType>() - { - Some($val as $dstType) - } - else - { - let num: f64; - let min_value: $srcType; - let max_value: $srcType; - - num = $val as f64; - min_value = Bounded::MIN; - max_value = Bounded::MAX; - - if (min_value as f64) <= num && num <= (max_value as f64) - { - Some($val as $dstType) - } - else - { - None - } - } - } -} - -macro_rules! int_to_number_impl -{ - ($traitName: ident for $($varType: ty)*) => - ($( - impl $traitName for $varType - { - fn to_u8(&self) -> Option - { - convert_int_to_uint!($varType, u8, *self) - } - - fn to_u16(&self) -> Option - { - convert_int_to_uint!($varType, u16, *self) - } - - fn to_u32(&self) -> Option - { - convert_int_to_uint!($varType, u32, *self) - } - - fn to_u64(&self) -> Option - { - convert_int_to_uint!($varType, u64, *self) - } - - fn to_usize(&self) -> Option - { - convert_int_to_uint!($varType, usize, *self) - } - - - fn to_i8(&self) -> Option - { - convert_int_to_int!($varType, i8, *self) - } - - fn to_i16(&self) -> Option - { - convert_int_to_int!($varType, i16, *self) - } - - fn to_i32(&self) -> Option - { - convert_int_to_int!($varType, i32, *self) - } - - fn to_i64(&self) -> Option - { - convert_int_to_int!($varType, i64, *self) - } - - fn to_isize(&self) -> Option - { - convert_int_to_int!($varType, isize, *self) - } - - - fn to_f32(&self) -> Option - { - Some(*self as f32) - } - - fn to_f64(&self) -> Option - { - Some(*self as f64) - } - } - )*) -} - -macro_rules! uint_to_number_impl -{ - ($traitName: ident for $($varType: ty)*) => - ($( - impl $traitName for $varType - { - fn to_u8(&self) -> Option - { - convert_uint_to_uint!($varType, u8, *self) - } - - fn to_u16(&self) -> Option - { - convert_uint_to_uint!($varType, u16, *self) - } - - fn to_u32(&self) -> Option - { - convert_uint_to_uint!($varType, u32, *self) - } - - fn to_u64(&self) -> Option - { - convert_uint_to_uint!($varType, u64, *self) - } - - fn to_usize(&self) -> Option - { - convert_uint_to_uint!($varType, usize, *self) - } - - - fn to_i8(&self) -> Option - { - convert_uint_to_int!(i8, *self) - } - - fn to_i16(&self) -> Option - { - convert_uint_to_int!(i16, *self) - } - - fn to_i32(&self) -> Option - { - convert_uint_to_int!(i32, *self) - } - - fn to_i64(&self) -> Option - { - convert_uint_to_int!(i64, *self) - } - - fn to_isize(&self) -> Option - { - convert_uint_to_int!(isize, *self) - } - - - fn to_f32(&self) -> Option - { - Some(*self as f32) - } - - fn to_f64(&self) -> Option - { - Some(*self as f64) - } - } - )*) -} - -macro_rules! float_to_number_impl -{ - ($traitName: ident for $($varType: ty)*) => - ($( - impl $traitName for $varType - { - fn to_u8(&self) -> Option - { - Some(*self as u8) - } - - fn to_u16(&self) -> Option - { - Some(*self as u16) - } - - fn to_u32(&self) -> Option - { - Some(*self as u32) - } - - fn to_u64(&self) -> Option - { - Some(*self as u64) - } - - fn to_usize(&self) -> Option - { - Some(*self as usize) - } - - - fn to_i8(&self) -> Option - { - Some(*self as i8) - } - - fn to_i16(&self) -> Option - { - Some(*self as i16) - } - - fn to_i32(&self) -> Option - { - Some(*self as i32) - } - - fn to_i64(&self) -> Option - { - Some(*self as i64) - } - - fn to_isize(&self) -> Option - { - Some(*self as isize) - } - - - fn to_f32(&self) -> Option - { - convert_float_to_float!($varType, f32, *self) - } - - fn to_f64(&self) -> Option - { - convert_float_to_float!($varType, f64, *self) - } - } - )*) -} - -macro_rules! from_number_impl -{ - ($varType: ty, $toTypeFunc: ident) => - { - impl FromNumber for $varType - { - fn from_u8(number: u8) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_u16(number: u16) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_u32(number: u32) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_u64(number: u64) -> Option<$varType> - { - number.$toTypeFunc() - } - - - fn from_i8(number: i8) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_i16(number: i16) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_i32(number: i32) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_i64(number: i64) -> Option<$varType> - { - number.$toTypeFunc() - } - - - fn from_f32(number: f32) -> Option<$varType> - { - number.$toTypeFunc() - } - - fn from_f64(number: f64) -> Option<$varType> - { - number.$toTypeFunc() - } - } - } -} - -/// A macro to make implementing the Number trait easier for all the -/// base integer types in rust. -macro_rules! int_number_trait_impl -{ - ($traitName: ident for $varType: ty, $min: expr, $max: expr) => - { - impl $traitName for $varType - { - type StrRadixError = ::std::num::ParseIntError; - - - - //const MIN: Self = $min; - //const MAX: Self = $max; - - - - fn maximum(self, other: Self) -> Self - { - if self >= other - { - self - } - else - { - other - } - } - - fn minimum(self, other: Self) -> Self - { - if self <= other - { - self - } - else - { - other - } - } - - fn from_str_radix(src: &str, radix: u32) -> - Result - { - <$varType>::from_str_radix(src, radix) - } - } - } -} - -/// A macro to make implementing the Number trait easier for all the -/// base float types in rust. -macro_rules! float_number_trait_impl -{ - ($traitName: ident for $varType: ty, $min: expr, $max: expr, - $minFunc: ident, $maxFunc: ident) => - { - impl $traitName for $varType - { - type StrRadixError = ::std::num::ParseFloatError; - - - - //const MIN: Self = $min; - //const MAX: Self = $max; - - - - fn maximum(self, other: Self) -> Self - { - unsafe - { - ::pact::math::$maxFunc(self, other) as Self - } - } - - fn minimum(self, other: Self) -> Self - { - unsafe - { - ::pact::math::$minFunc(self, other) as Self - } - } - - fn from_str_radix(src: &str, radix: u32) -> - Result - { - // TODO: Currently this will panic on a non base 10 radix. - // This is because the std library deprecated the - // from_str_radix function. Until a function can be - // written this will use the from_str function and - // panic for non base 10 requests. - assert!(radix == 10); - <$varType>::from_str(src) - } - } - } -} - - // Implement the Number trait for the types that are Numbers. -int_number_trait_impl!(Number for u8, 0u8, 255u8); -int_number_trait_impl!(Number for u16, 0u16, 65535u16); -int_number_trait_impl!(Number for u32, 0u32, 4294967295u32); -int_number_trait_impl!(Number for u64, 0u64, 18446744073709551615u64); -int_number_trait_impl!(Number for i8, -128i8, 127i8); -int_number_trait_impl!(Number for i16, -32768i16, 32767i16); -int_number_trait_impl!(Number for i32, -2147483648i32, 2147483647i32); -int_number_trait_impl!(Number for i64, -9223372036854775808i64, - 9223372036854775807i64); -float_number_trait_impl!(Number for f32, -3.40282347e+38f32, - 3.40282347e+38f32, - fminf, fmaxf); -float_number_trait_impl!(Number for f64, -1.7976931348623157e+308f64, - 1.7976931348623157e+308f64, - fmin, fmax); - -#[cfg(target_pointer_width = "16")] -int_number_trait_impl!(Number for usize, 0usize, 65535usize); -#[cfg(target_pointer_width = "32")] -int_number_trait_impl!(Number for usize, 0usize, 4294967295usize); -#[cfg(target_pointer_width = "64")] -int_number_trait_impl!(Number for usize, 0usize, 18446744073709551615usize); - -#[cfg(target_pointer_width = "16")] -int_number_trait_impl!(Number for isize, -32768isize, 32767isize); -#[cfg(target_pointer_width = "32")] -int_number_trait_impl!(Number for isize, -2147483648isize, 2147483647isize); -#[cfg(target_pointer_width = "64")] -int_number_trait_impl!(Number for isize, -9223372036854775808isize, - 9223372036854775807isize); - -// Implement the ToNumber and FromNumber traits for -// the types that are Numbers. The FromNumber trait needs -// to be defined after ToNumber since FromNumber uses -// ToNumber definitions. -uint_to_number_impl!(ToNumber for u8 u16 u32 u64 usize); -int_to_number_impl!(ToNumber for i8 i16 i32 i64 isize); -float_to_number_impl!(ToNumber for f32 f64); - -from_number_impl!(u8, to_u8); -from_number_impl!(u16, to_u16); -from_number_impl!(u32, to_u32); -from_number_impl!(u64, to_u64); -from_number_impl!(usize, to_usize); - -from_number_impl!(i8, to_i8); -from_number_impl!(i16, to_i16); -from_number_impl!(i32, to_i32); -from_number_impl!(i64, to_i64); -from_number_impl!(isize, to_isize); - -from_number_impl!(f32, to_f32); -from_number_impl!(f64, to_f64); +number_trait_impl!(u8, u16, u32, u64, u128, usize); +number_trait_impl!(i8, i16, i32, i64, i128, isize); +number_trait_impl!(f32, f64); diff --git a/src/one.rs b/src/one.rs index e9261c0..4b845dd 100644 --- a/src/one.rs +++ b/src/one.rs @@ -1,10 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -use std::ops::Mul; +use core::ops::{Mul, MulAssign}; -/// Defines a multiplicative identity element for `Self`. -pub trait One: Sized + Mul + + +/// Defines a multiplicative identity. +pub trait One: Sized + PartialEq + + Mul + MulAssign { /// Returns the multiplicative identity element of `Self`, `1`. /// @@ -14,44 +17,54 @@ pub trait One: Sized + Mul /// a * 1 = a ∀ a ∈ Self /// 1 * a = a ∀ a ∈ Self /// ``` + /// [Multiplicative Identity](https://en.wikipedia.org/wiki/1#In_mathematics) /// /// # Purity /// - /// This function should return the same result at all times regardless of - /// external mutable state, for example values stored in TLS or in - /// `static mut`s. + /// This function must be a pure mathematical constant. It should return + /// the same result at all times regardless of external mutable state, for + /// example values stored in Thread Local Storage(TLS) or in `static mut`s. fn one() -> Self; + + + /// Returns `true` if the value is the multiplicative identity. + /// + /// + /// # Examples + /// ```rust + /// use sigils::One; + /// + /// let x = 1u32; + /// assert!(x.is_one()); + /// + /// let y = 5f64; + /// assert!(!y.is_one()); + /// ``` + #[inline] + fn is_one(&self) -> bool + { + *self == Self::one() + } } macro_rules! one_impl { - ($varType: ty, $val: expr) => + ($($varType: ty),*) => { - impl One for $varType - { - fn one() -> $varType + $( + impl One for $varType { - $val + #[inline] + fn one() -> Self + { 1 as $varType } } - } + )* } } - - -one_impl!(u8, 1u8); -one_impl!(u16, 1u16); -one_impl!(u32, 1u32); -one_impl!(u64, 1u64); -one_impl!(usize, 1usize); - -one_impl!(i8, 1i8); -one_impl!(i16, 1i16); -one_impl!(i32, 1i32); -one_impl!(i64, 1i64); -one_impl!(isize, 1isize); - -one_impl!(f32, 1.0f32); -one_impl!(f64, 1.0f64); +// Implement the One trait for the basic rust types. +one_impl!(u8, u16, u32, u64, u128, usize); +one_impl!(i8, i16, i32, i64, i128, isize); +one_impl!(f32, f64); diff --git a/src/zero.rs b/src/zero.rs index 44ca527..9306c64 100644 --- a/src/zero.rs +++ b/src/zero.rs @@ -1,10 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 // Sealed with Magistamp. -use std::ops::Add; +use core::ops::{Add, AddAssign}; -/// Defines an additive identity element for `Self`. -pub trait Zero: Sized + Add + + +/// Defines an additive identity. +pub trait Zero: Sized + PartialEq + + Add + AddAssign { /// Returns the additive identity element of `Self`, `0`. /// @@ -14,44 +17,55 @@ pub trait Zero: Sized + Add /// a + 0 = a ∀ a ∈ Self /// 0 + a = a ∀ a ∈ Self /// ``` + /// [Additive Identity](https://en.wikipedia.org/wiki/Additive_identity) /// /// # Purity /// - /// This function should return the same result at all times regardless of - /// external mutable state, for example values stored in TLS or in - /// `static mut`s. + /// This function must be a pure mathematical constant. It should return + /// the same result at all times regardless of external mutable state, for + /// example values stored in Thread Local Storage(TLS) or in `static mut`s. fn zero() -> Self; -} - -macro_rules! zero_impl -{ - ($varType: ty, $val: expr) => + /// Returns `true` if the value is the additive identity. + /// + /// # Examples + /// ```rust + /// use sigils::Zero; + /// + /// let x = 0u32; + /// assert!(x.is_zero()); + /// + /// let y = 5u64; + /// assert!(!y.is_zero()); + /// ``` + #[inline] + fn is_zero(&self) -> bool { - impl Zero for $varType - { - fn zero() -> $varType - { - $val - } - } + *self == Self::zero() } } -zero_impl!(u8, 0u8); -zero_impl!(u16, 0u16); -zero_impl!(u32, 0u32); -zero_impl!(u64, 0u64); -zero_impl!(usize, 0usize); +/// A macro to make implementing the `Zero` trait easier for all the +/// base types in Rust. +macro_rules! zero_impl +{ + ($($varType: ty),*) => + { + $( + impl Zero for $varType + { + #[inline] + fn zero() -> Self + { 0 as $varType } + } + )* + } +} -zero_impl!(i8, 0i8); -zero_impl!(i16, 0i16); -zero_impl!(i32, 0i32); -zero_impl!(i64, 0i64); -zero_impl!(isize, 0isize); - -zero_impl!(f32, 0.0f32); -zero_impl!(f64, 0.0f64); +// Implement the Zero trait for the basic rust types. +zero_impl!(u8, u16, u32, u64, u128, usize); +zero_impl!(i8, i16, i32, i64, i128, isize); +zero_impl!(f32, f64);