[#2] Cleaned up the base traits.
I have switched to using the `core::` calling convention instead of using the `std::` by means of `extern crate core as std`. This makes it so that the library is easier to reason. The `Number` trait has been broken up now into `Number` and `Natural`. This was done to make it so that the pure mathematical types were separate from the Rust implementation types. I went and added better comments, including examples. The macros were tightened up so that the implementations took up less space. The FromNumber and ToNumber stuff will need to be reimplemented yet. Some of it seemed redundant with From and TryFrom traits now. It will be something to come back to and implement at the end.
This commit is contained in:
106
src/bounded.rs
106
src/bounded.rs
@ -1,13 +1,38 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Sealed with Magistamp.
|
// 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
|
pub trait Bounded
|
||||||
{
|
{
|
||||||
/// The minimum value for this type.
|
/// The minimum value for this type.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```rust
|
||||||
|
/// use sigils::Bounded;
|
||||||
|
///
|
||||||
|
/// let min = <u8 as Bounded>::MIN;
|
||||||
|
///
|
||||||
|
/// assert_eq!(min, u8::MIN);
|
||||||
|
/// ```
|
||||||
const MIN: Self;
|
const MIN: Self;
|
||||||
|
|
||||||
/// The maximum value for this type.
|
/// The maximum value for this type.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```rust
|
||||||
|
/// use sigils::Bounded;
|
||||||
|
///
|
||||||
|
/// let max = <f64 as Bounded>::MAX;
|
||||||
|
///
|
||||||
|
/// assert_eq!(max, f64::MAX);
|
||||||
|
/// ```
|
||||||
const MAX: Self;
|
const MAX: Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,83 +42,20 @@ pub trait Bounded
|
|||||||
/// the Bounded trait easier.
|
/// the Bounded trait easier.
|
||||||
macro_rules! bounded_trait_impl
|
macro_rules! bounded_trait_impl
|
||||||
{
|
{
|
||||||
($T: ty, $minVal: expr, $maxVal: expr) =>
|
($($T:ty),*) =>
|
||||||
{
|
{
|
||||||
|
$(
|
||||||
impl Bounded for $T
|
impl Bounded for $T
|
||||||
{
|
{
|
||||||
const MIN: $T = $minVal;
|
const MIN: $T = <$T>::MIN;
|
||||||
|
const MAX: $T = <$T>::MAX;
|
||||||
const MAX: $T = $maxVal;
|
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implement the Bounded for all the primitive types.
|
// Implement the Bounded for all the primitive types.
|
||||||
bounded_trait_impl!(u8, 0u8, !0u8);
|
bounded_trait_impl!(u8, u16, u32, u64, u128, usize);
|
||||||
bounded_trait_impl!(u16, 0u16, !0u16);
|
bounded_trait_impl!(i8, i16, i32, i64, i128, isize);
|
||||||
bounded_trait_impl!(u32, 0u32, !0u32);
|
bounded_trait_impl!(f32, f64);
|
||||||
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::<i8>() as i8)*8i8)-1i8),
|
|
||||||
!(-1i8 << (((::std::mem::size_of::<i8>() as i8)*8i8)-1i8)));
|
|
||||||
bounds_test!(i16, min_max_i16,
|
|
||||||
-1i16 << (((::std::mem::size_of::<i16>() as i16)*8i16)-1i16),
|
|
||||||
!(-1i16 << (((::std::mem::size_of::<i16>() as i16)*8i16)-1i16)));
|
|
||||||
bounds_test!(i32, min_max_i32,
|
|
||||||
-1i32 << (((::std::mem::size_of::<i32>() as i32)*8i32)-1i32),
|
|
||||||
!(-1i32 << (((::std::mem::size_of::<i32>() as i32)*8i32)-1i32)));
|
|
||||||
bounds_test!(i64, min_max_i64,
|
|
||||||
-1i64 << (((::std::mem::size_of::<i64>() as i64)*8i64)-1i64),
|
|
||||||
!(-1i64 << (((::std::mem::size_of::<i64>() as i64)*8i64)-1i64)));
|
|
||||||
bounds_test!(isize, min_max_isize,
|
|
||||||
-1isize << (((::std::mem::size_of::<isize>() as isize)*8isize)-1isize),
|
|
||||||
!(-1isize << (((::std::mem::size_of::<isize>() 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);
|
|
||||||
}
|
|
||||||
|
|||||||
40
src/lib.rs
40
src/lib.rs
@ -1,23 +1,38 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Sealed with Magistamp.
|
// Sealed with Magistamp.
|
||||||
|
|
||||||
//! A mathematical library.
|
//! # Sigils
|
||||||
//! License: Proprietary
|
|
||||||
//!
|
//!
|
||||||
|
//! 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]
|
#![no_std]
|
||||||
extern crate core as std;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod macros;
|
|
||||||
|
|
||||||
mod bounded;
|
mod bounded;
|
||||||
|
//mod natural;
|
||||||
mod zero;
|
|
||||||
mod one;
|
|
||||||
mod number;
|
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 whole;
|
||||||
mod integer;
|
mod integer;
|
||||||
mod real;
|
mod real;
|
||||||
@ -28,11 +43,9 @@ mod trig;
|
|||||||
pub mod vector;
|
pub mod vector;
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod quaternion;
|
pub mod quaternion;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
pub use self::bounded::Bounded;
|
|
||||||
pub use self::zero::Zero;
|
|
||||||
pub use self::one::One;
|
pub use self::one::One;
|
||||||
pub use self::number::{Number, FromNumber};
|
pub use self::number::{Number, FromNumber};
|
||||||
pub use self::whole::Whole;
|
pub use self::whole::Whole;
|
||||||
@ -40,3 +53,4 @@ pub use self::integer::Integer;
|
|||||||
pub use self::real::Real;
|
pub use self::real::Real;
|
||||||
pub use self::constants::Constants;
|
pub use self::constants::Constants;
|
||||||
pub use self::trig::{Degree, Radian, Trig};
|
pub use self::trig::{Degree, Radian, Trig};
|
||||||
|
*/
|
||||||
|
|||||||
32
src/natural.rs
Normal file
32
src/natural.rs
Normal file
@ -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<Output=Self> + AddAssign +
|
||||||
|
Sub<Output=Self> + SubAssign +
|
||||||
|
Mul<Output=Self> + MulAssign +
|
||||||
|
Div<Output=Self> + DivAssign +
|
||||||
|
Rem<Output=Self> + RemAssign
|
||||||
|
{
|
||||||
|
/// Performs division and returns both the quotient and remainder.
|
||||||
|
#[inline]
|
||||||
|
fn div_rem(self, rhs: Self) -> (Self, Self)
|
||||||
|
{
|
||||||
|
(self / rhs, self % rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
956
src/number.rs
956
src/number.rs
@ -1,42 +1,35 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Sealed with Magistamp.
|
// Sealed with Magistamp.
|
||||||
|
|
||||||
use std::cmp::{PartialEq, PartialOrd};
|
use core::cmp::{PartialEq, PartialOrd};
|
||||||
use std::fmt::{Debug, Display};
|
use core::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;
|
|
||||||
|
|
||||||
|
|
||||||
/// A trait that defines what is required to be considered
|
|
||||||
/// a number.
|
/// `Number` helps bridge the gap between the rust implementation and the pure
|
||||||
pub trait Number: Zero + One + Add<Output=Self> + Sub<Output=Self> +
|
/// math definitions.
|
||||||
Mul<Output=Self> + Div<Output=Self> + Rem<Output=Self> +
|
///
|
||||||
AddAssign<Self> + SubAssign<Self> + MulAssign<Self> +
|
/// `Number` has some basic Rust representation requirements.
|
||||||
DivAssign<Self> + RemAssign<Self> + PartialEq + PartialOrd +
|
///
|
||||||
Copy + Clone + Debug + Display
|
/// [`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.
|
/// Returns the maximum of the two numbers.
|
||||||
///
|
///
|
||||||
/// ```
|
/// # Arguments
|
||||||
/// use ::sigils::Number;
|
/// * `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 x: f64;
|
||||||
/// let y: f64;
|
/// let y: f64;
|
||||||
@ -45,12 +38,23 @@ pub trait Number: Zero + One + Add<Output=Self> + Sub<Output=Self> +
|
|||||||
/// y = 2.0f64;
|
/// y = 2.0f64;
|
||||||
/// assert_eq!(x.maximum(y), y);
|
/// 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.
|
/// Returns the minimum of the two numbers.
|
||||||
///
|
///
|
||||||
/// ```
|
/// # Arguments
|
||||||
/// use ::sigils::Number;
|
/// * `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 x: i16;
|
||||||
/// let y: i16;
|
/// let y: i16;
|
||||||
@ -59,883 +63,29 @@ pub trait Number: Zero + One + Add<Output=Self> + Sub<Output=Self> +
|
|||||||
/// y = 55i16;
|
/// y = 55i16;
|
||||||
/// assert_eq!(x.minimum(y), x);
|
/// assert_eq!(x.minimum(y), x);
|
||||||
/// ```
|
/// ```
|
||||||
fn minimum(self, other: Self) -> Self;
|
#[inline]
|
||||||
|
|
||||||
/// 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<Self, Self::StrRadixError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A trait that defines converting something to a Number.
|
|
||||||
pub trait ToNumber
|
|
||||||
{
|
|
||||||
/// Convert this to an u8.
|
|
||||||
/// None is returned if the conversion is not possible.
|
|
||||||
fn to_u8(&self) -> Option<u8>
|
|
||||||
{
|
|
||||||
let option: Option<u64>;
|
|
||||||
|
|
||||||
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<u16>
|
|
||||||
{
|
|
||||||
let option: Option<u64>;
|
|
||||||
|
|
||||||
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<u32>
|
|
||||||
{
|
|
||||||
let option: Option<u64>;
|
|
||||||
|
|
||||||
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<u64>;
|
|
||||||
|
|
||||||
/// Convert this to an usize.
|
|
||||||
/// None is returned if the conversion is not possible.
|
|
||||||
fn to_usize(&self) -> Option<usize>
|
|
||||||
{
|
|
||||||
let option: Option<u64>;
|
|
||||||
|
|
||||||
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<i8>
|
|
||||||
{
|
|
||||||
let option: Option<i64>;
|
|
||||||
|
|
||||||
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<i16>
|
|
||||||
{
|
|
||||||
let option: Option<i64>;
|
|
||||||
|
|
||||||
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<i32>
|
|
||||||
{
|
|
||||||
let option: Option<i64>;
|
|
||||||
|
|
||||||
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<i64>;
|
|
||||||
|
|
||||||
/// Convert this to an isize.
|
|
||||||
/// None is returned if the conversion is not possible.
|
|
||||||
fn to_isize(&self) -> Option<isize>
|
|
||||||
{
|
|
||||||
let option: Option<i64>;
|
|
||||||
|
|
||||||
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<f32>
|
|
||||||
{
|
|
||||||
let option: Option<f64>;
|
|
||||||
|
|
||||||
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<f64>
|
|
||||||
{
|
|
||||||
let option: Option<i64>;
|
|
||||||
|
|
||||||
option = self.to_i64();
|
|
||||||
match option
|
|
||||||
{
|
|
||||||
Some(val) =>
|
|
||||||
{
|
|
||||||
val.to_f64()
|
|
||||||
}
|
|
||||||
|
|
||||||
None =>
|
|
||||||
{
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>;
|
|
||||||
|
|
||||||
/// 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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>;
|
|
||||||
|
|
||||||
/// 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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<Self>
|
|
||||||
{
|
|
||||||
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<u8>
|
|
||||||
{
|
|
||||||
convert_int_to_uint!($varType, u8, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u16(&self) -> Option<u16>
|
|
||||||
{
|
|
||||||
convert_int_to_uint!($varType, u16, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u32(&self) -> Option<u32>
|
|
||||||
{
|
|
||||||
convert_int_to_uint!($varType, u32, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u64(&self) -> Option<u64>
|
|
||||||
{
|
|
||||||
convert_int_to_uint!($varType, u64, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_usize(&self) -> Option<usize>
|
|
||||||
{
|
|
||||||
convert_int_to_uint!($varType, usize, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_i8(&self) -> Option<i8>
|
|
||||||
{
|
|
||||||
convert_int_to_int!($varType, i8, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i16(&self) -> Option<i16>
|
|
||||||
{
|
|
||||||
convert_int_to_int!($varType, i16, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i32(&self) -> Option<i32>
|
|
||||||
{
|
|
||||||
convert_int_to_int!($varType, i32, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i64(&self) -> Option<i64>
|
|
||||||
{
|
|
||||||
convert_int_to_int!($varType, i64, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_isize(&self) -> Option<isize>
|
|
||||||
{
|
|
||||||
convert_int_to_int!($varType, isize, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_f32(&self) -> Option<f32>
|
|
||||||
{
|
|
||||||
Some(*self as f32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_f64(&self) -> Option<f64>
|
|
||||||
{
|
|
||||||
Some(*self as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! uint_to_number_impl
|
|
||||||
{
|
|
||||||
($traitName: ident for $($varType: ty)*) =>
|
|
||||||
($(
|
|
||||||
impl $traitName for $varType
|
|
||||||
{
|
|
||||||
fn to_u8(&self) -> Option<u8>
|
|
||||||
{
|
|
||||||
convert_uint_to_uint!($varType, u8, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u16(&self) -> Option<u16>
|
|
||||||
{
|
|
||||||
convert_uint_to_uint!($varType, u16, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u32(&self) -> Option<u32>
|
|
||||||
{
|
|
||||||
convert_uint_to_uint!($varType, u32, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u64(&self) -> Option<u64>
|
|
||||||
{
|
|
||||||
convert_uint_to_uint!($varType, u64, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_usize(&self) -> Option<usize>
|
|
||||||
{
|
|
||||||
convert_uint_to_uint!($varType, usize, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_i8(&self) -> Option<i8>
|
|
||||||
{
|
|
||||||
convert_uint_to_int!(i8, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i16(&self) -> Option<i16>
|
|
||||||
{
|
|
||||||
convert_uint_to_int!(i16, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i32(&self) -> Option<i32>
|
|
||||||
{
|
|
||||||
convert_uint_to_int!(i32, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i64(&self) -> Option<i64>
|
|
||||||
{
|
|
||||||
convert_uint_to_int!(i64, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_isize(&self) -> Option<isize>
|
|
||||||
{
|
|
||||||
convert_uint_to_int!(isize, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_f32(&self) -> Option<f32>
|
|
||||||
{
|
|
||||||
Some(*self as f32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_f64(&self) -> Option<f64>
|
|
||||||
{
|
|
||||||
Some(*self as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! float_to_number_impl
|
|
||||||
{
|
|
||||||
($traitName: ident for $($varType: ty)*) =>
|
|
||||||
($(
|
|
||||||
impl $traitName for $varType
|
|
||||||
{
|
|
||||||
fn to_u8(&self) -> Option<u8>
|
|
||||||
{
|
|
||||||
Some(*self as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u16(&self) -> Option<u16>
|
|
||||||
{
|
|
||||||
Some(*self as u16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u32(&self) -> Option<u32>
|
|
||||||
{
|
|
||||||
Some(*self as u32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_u64(&self) -> Option<u64>
|
|
||||||
{
|
|
||||||
Some(*self as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_usize(&self) -> Option<usize>
|
|
||||||
{
|
|
||||||
Some(*self as usize)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_i8(&self) -> Option<i8>
|
|
||||||
{
|
|
||||||
Some(*self as i8)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i16(&self) -> Option<i16>
|
|
||||||
{
|
|
||||||
Some(*self as i16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i32(&self) -> Option<i32>
|
|
||||||
{
|
|
||||||
Some(*self as i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_i64(&self) -> Option<i64>
|
|
||||||
{
|
|
||||||
Some(*self as i64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_isize(&self) -> Option<isize>
|
|
||||||
{
|
|
||||||
Some(*self as isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn to_f32(&self) -> Option<f32>
|
|
||||||
{
|
|
||||||
convert_float_to_float!($varType, f32, *self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_f64(&self) -> Option<f64>
|
|
||||||
{
|
|
||||||
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
|
fn minimum(self, other: Self) -> Self
|
||||||
{
|
{
|
||||||
if self <= other
|
if self <= other { self } else { other }
|
||||||
{
|
|
||||||
self
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
other
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_str_radix(src: &str, radix: u32) ->
|
|
||||||
Result<Self, ::std::num::ParseIntError>
|
|
||||||
|
|
||||||
|
/// A macro to make implementing the `Number` trait easier for all the
|
||||||
|
/// base types in Rust.
|
||||||
|
macro_rules! number_trait_impl
|
||||||
{
|
{
|
||||||
<$varType>::from_str_radix(src, radix)
|
($($varType:ty),*) =>
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 Number for $varType {}
|
||||||
{
|
)*
|
||||||
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<Self, ::std::num::ParseFloatError>
|
|
||||||
{
|
|
||||||
// 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.
|
// Implement the Number trait for the types that are Numbers.
|
||||||
int_number_trait_impl!(Number for u8, 0u8, 255u8);
|
number_trait_impl!(u8, u16, u32, u64, u128, usize);
|
||||||
int_number_trait_impl!(Number for u16, 0u16, 65535u16);
|
number_trait_impl!(i8, i16, i32, i64, i128, isize);
|
||||||
int_number_trait_impl!(Number for u32, 0u32, 4294967295u32);
|
number_trait_impl!(f32, f64);
|
||||||
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);
|
|
||||||
|
|||||||
67
src/one.rs
67
src/one.rs
@ -1,10 +1,13 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Sealed with Magistamp.
|
// Sealed with Magistamp.
|
||||||
|
|
||||||
use std::ops::Mul;
|
use core::ops::{Mul, MulAssign};
|
||||||
|
|
||||||
/// Defines a multiplicative identity element for `Self`.
|
|
||||||
pub trait One: Sized + Mul<Self, Output=Self>
|
|
||||||
|
/// Defines a multiplicative identity.
|
||||||
|
pub trait One: Sized + PartialEq +
|
||||||
|
Mul<Self, Output=Self> + MulAssign
|
||||||
{
|
{
|
||||||
/// Returns the multiplicative identity element of `Self`, `1`.
|
/// Returns the multiplicative identity element of `Self`, `1`.
|
||||||
///
|
///
|
||||||
@ -14,44 +17,54 @@ pub trait One: Sized + Mul<Self, Output=Self>
|
|||||||
/// a * 1 = a ∀ a ∈ Self
|
/// a * 1 = a ∀ a ∈ Self
|
||||||
/// 1 * a = a ∀ a ∈ Self
|
/// 1 * a = a ∀ a ∈ Self
|
||||||
/// ```
|
/// ```
|
||||||
|
/// [Multiplicative Identity](https://en.wikipedia.org/wiki/1#In_mathematics)
|
||||||
///
|
///
|
||||||
/// # Purity
|
/// # Purity
|
||||||
///
|
///
|
||||||
/// This function should return the same result at all times regardless of
|
/// This function must be a pure mathematical constant. It should return
|
||||||
/// external mutable state, for example values stored in TLS or in
|
/// the same result at all times regardless of external mutable state, for
|
||||||
/// `static mut`s.
|
/// example values stored in Thread Local Storage(TLS) or in `static mut`s.
|
||||||
fn one() -> Self;
|
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
|
macro_rules! one_impl
|
||||||
{
|
{
|
||||||
($varType: ty, $val: expr) =>
|
($($varType: ty),*) =>
|
||||||
{
|
{
|
||||||
|
$(
|
||||||
impl One for $varType
|
impl One for $varType
|
||||||
{
|
{
|
||||||
fn one() -> $varType
|
#[inline]
|
||||||
{
|
fn one() -> Self
|
||||||
$val
|
{ 1 as $varType }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implement the One trait for the basic rust types.
|
||||||
|
one_impl!(u8, u16, u32, u64, u128, usize);
|
||||||
one_impl!(u8, 1u8);
|
one_impl!(i8, i16, i32, i64, i128, isize);
|
||||||
one_impl!(u16, 1u16);
|
one_impl!(f32, f64);
|
||||||
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);
|
|
||||||
|
|||||||
68
src/zero.rs
68
src/zero.rs
@ -1,10 +1,13 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Sealed with Magistamp.
|
// Sealed with Magistamp.
|
||||||
|
|
||||||
use std::ops::Add;
|
use core::ops::{Add, AddAssign};
|
||||||
|
|
||||||
/// Defines an additive identity element for `Self`.
|
|
||||||
pub trait Zero: Sized + Add<Self, Output=Self>
|
|
||||||
|
/// Defines an additive identity.
|
||||||
|
pub trait Zero: Sized + PartialEq +
|
||||||
|
Add<Self, Output=Self> + AddAssign
|
||||||
{
|
{
|
||||||
/// Returns the additive identity element of `Self`, `0`.
|
/// Returns the additive identity element of `Self`, `0`.
|
||||||
///
|
///
|
||||||
@ -14,44 +17,55 @@ pub trait Zero: Sized + Add<Self, Output=Self>
|
|||||||
/// a + 0 = a ∀ a ∈ Self
|
/// a + 0 = a ∀ a ∈ Self
|
||||||
/// 0 + a = a ∀ a ∈ Self
|
/// 0 + a = a ∀ a ∈ Self
|
||||||
/// ```
|
/// ```
|
||||||
|
/// [Additive Identity](https://en.wikipedia.org/wiki/Additive_identity)
|
||||||
///
|
///
|
||||||
/// # Purity
|
/// # Purity
|
||||||
///
|
///
|
||||||
/// This function should return the same result at all times regardless of
|
/// This function must be a pure mathematical constant. It should return
|
||||||
/// external mutable state, for example values stored in TLS or in
|
/// the same result at all times regardless of external mutable state, for
|
||||||
/// `static mut`s.
|
/// example values stored in Thread Local Storage(TLS) or in `static mut`s.
|
||||||
fn zero() -> Self;
|
fn zero() -> Self;
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
{
|
||||||
|
*self == Self::zero()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// A macro to make implementing the `Zero` trait easier for all the
|
||||||
|
/// base types in Rust.
|
||||||
macro_rules! zero_impl
|
macro_rules! zero_impl
|
||||||
{
|
{
|
||||||
($varType: ty, $val: expr) =>
|
($($varType: ty),*) =>
|
||||||
{
|
{
|
||||||
|
$(
|
||||||
impl Zero for $varType
|
impl Zero for $varType
|
||||||
{
|
{
|
||||||
fn zero() -> $varType
|
#[inline]
|
||||||
{
|
fn zero() -> Self
|
||||||
$val
|
{ 0 as $varType }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implement the Zero trait for the basic rust types.
|
||||||
|
zero_impl!(u8, u16, u32, u64, u128, usize);
|
||||||
zero_impl!(u8, 0u8);
|
zero_impl!(i8, i16, i32, i64, i128, isize);
|
||||||
zero_impl!(u16, 0u16);
|
zero_impl!(f32, f64);
|
||||||
zero_impl!(u32, 0u32);
|
|
||||||
zero_impl!(u64, 0u64);
|
|
||||||
zero_impl!(usize, 0usize);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|||||||
Reference in New Issue
Block a user