#[rustfmt::skip]
use crate::{
FloatConst,
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
};
#[doc = crate::_tags!(num)]
#[doc = crate::_doc_location!("num/dom")]
pub trait NumConst: PartialEq<Self::Num> {
type Num;
const NUM_IS_BIG: bool;
const NUM_IS_INT: bool;
const NUM_IS_FLOAT: bool;
const NUM_IS_FIXED: bool;
const NUM_IS_SIGNED: bool;
const NUM_IS_NICHE: bool;
const NUM_ZERO: Option<Self::Num>;
const NUM_ONE: Option<Self::Num>;
const NUM_TWO: Option<Self::Num>;
const NUM_THREE: Option<Self::Num>;
const NUM_NEG_ONE: Option<Self::Num>;
const NUM_MIN: Option<Self::Num>;
const NUM_MAX: Option<Self::Num>;
const NUM_MIN_POSITIVE: Option<Self::Num>;
const NUM_MAX_NEGATIVE: Option<Self::Num>;
const NUM_MIN_NORM: Option<Self::Num>;
const NUM_MAX_NORM: Option<Self::Num>;
const NUM_MAX_POWER_OF_TWO: Option<Self::Num>;
fn is_num_zero(&self) -> bool {
Self::NUM_ZERO.is_some_and(|n| self == &n)
}
fn is_num_one(&self) -> bool {
Self::NUM_ONE.is_some_and(|n| self == &n)
}
fn is_num_two(&self) -> bool {
Self::NUM_TWO.is_some_and(|n| self == &n)
}
fn is_num_three(&self) -> bool {
Self::NUM_THREE.is_some_and(|n| self == &n)
}
fn is_num_neg_one(&self) -> bool {
Self::NUM_NEG_ONE.is_some_and(|n| self == &n)
}
fn is_num_min(&self) -> bool {
Self::NUM_MIN.is_some_and(|n| self == &n)
}
fn is_num_max(&self) -> bool {
Self::NUM_MAX.is_some_and(|n| self == &n)
}
fn is_num_min_positive(&self) -> bool {
Self::NUM_MIN_POSITIVE.is_some_and(|n| self == &n)
}
fn is_num_max_negative(&self) -> bool {
Self::NUM_MAX_NEGATIVE.is_some_and(|n| self == &n)
}
fn is_num_min_norm(&self) -> bool {
Self::NUM_MIN_NORM.is_some_and(|n| self == &n)
}
fn is_num_max_norm(&self) -> bool {
Self::NUM_MAX_NORM.is_some_and(|n| self == &n)
}
fn is_num_max_power_of_two(&self) -> bool {
Self::NUM_MAX_POWER_OF_TWO.is_some_and(|n| self == &n)
}
}
macro_rules! impl_ext_num_const {
() => {
impl_ext_num_const![float: f32|u32, f64|u64];
impl_ext_num_const![int: i8|u8, i16|u16, i32|u32, i64|u64, i128|u128, isize|usize];
impl_ext_num_const![uint: u8|u8, u16|u16, u32|u32, u64|u64, u128|u128, usize|usize];
impl_ext_num_const![non0int: NonZeroI8|u8, NonZeroI16|u16, NonZeroI32|u32,
NonZeroI64|u64, NonZeroI128|u128, NonZeroIsize|usize];
impl_ext_num_const![non0uint: NonZeroU8|u8, NonZeroU16|u16, NonZeroU32|u32,
NonZeroU64|u64, NonZeroU128|u128, NonZeroUsize|usize];
};
($T:ty | $U:ty: $ZERO:expr, $ONE:expr, $TWO:expr, $THREE:expr,
$NEG_ONE:expr, $MIN_POS:expr, $MAX_NEG:expr, $MAX_POW2:expr, $MIN_NORM:expr, $MAX_NORM:expr,
$IS_BIG:literal, $IS_INT:literal, $IS_FLOAT:literal, $IS_FIXED:literal,
$IS_SIGNED:literal, $IS_NICHE:literal) => {
impl_ext_num_const![@$T|$U: $ZERO, $ONE, $TWO, $THREE,
$NEG_ONE, $MIN_POS, $MAX_NEG, $MAX_POW2, $MIN_NORM, $MAX_NORM,
$IS_BIG, $IS_INT, $IS_FLOAT, $IS_FIXED, $IS_SIGNED, $IS_NICHE];
};
(@$T:ty | $U:ty: $ZERO:expr, $ONE:expr, $TWO:expr, $THREE:expr,
$NEG_ONE:expr, $MIN_POS:expr, $MAX_NEG:expr, $MAX_POW2:expr, $MIN_NORM:expr, $MAX_NORM:expr,
$IS_BIG:literal, $IS_INT:literal, $IS_FLOAT:literal, $IS_FIXED:literal,
$IS_SIGNED:literal, $IS_NICHE:literal) => {
impl NumConst for $T {
type Num = $T;
const NUM_IS_BIG: bool = $IS_BIG;
const NUM_IS_INT: bool = $IS_INT;
const NUM_IS_FLOAT: bool = $IS_FLOAT;
const NUM_IS_FIXED: bool = $IS_FIXED;
const NUM_IS_SIGNED: bool = $IS_SIGNED;
const NUM_IS_NICHE: bool = $IS_NICHE;
const NUM_ZERO: Option<$T> = $ZERO;
const NUM_ONE: Option<$T> = $ONE;
const NUM_TWO: Option<$T> = $TWO;
const NUM_THREE: Option<$T> = $THREE;
const NUM_NEG_ONE: Option<$T> = $NEG_ONE;
const NUM_MIN: Option<$T> = Some(<$T>::MIN); const NUM_MAX: Option<$T> = Some(<$T>::MAX); const NUM_MIN_POSITIVE: Option<$T> = $MIN_POS;
const NUM_MAX_NEGATIVE: Option<$T> = $MAX_NEG;
const NUM_MIN_NORM: Option<$T> = $MIN_NORM;
const NUM_MAX_NORM: Option<$T> = $MAX_NORM;
const NUM_MAX_POWER_OF_TWO: Option<$T> = $MAX_POW2;
}
};
(float: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
Some(0.0), Some(1.0), Some(2.0), Some(3.0), Some(-1.0), Some(<$T>::MIN_POSITIVE), Some(-0.0), Some(<$T>::from_bits((<$T>::EXPONENT_BIAS as $U << 1) << (<$T>::SIGNIFICAND_BITS))),
Some(0.0), Some(1.0), false, false, true, false, true, false ];
)+};
(int: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
Some(0), Some(1), Some(2), Some(3), Some(-1), Some(1), Some(-1), Some(<$T>::MAX - (<$T>::MAX >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, true, false ];
)+};
(uint: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
Some(0), Some(1), Some(2), Some(3), None, Some(1), None, Some(<$T>::MAX ^ (<$T>::MAX >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, false, false ];
)+};
(non0int: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
<$T>::new(0), <$T>::new(1), <$T>::new(2), <$T>::new(3), <$T>::new(-1), <$T>::new(1), <$T>::new(-1), <$T>::new(<$T>::MAX.get() - (<$T>::MAX.get() >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, true, true ];
)+};
(non0uint: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
<$T>::new(0), <$T>::new(1), <$T>::new(2), <$T>::new(3), None, <$T>::new(1), None, <$T>::new(<$T>::MAX.get() ^ (<$T>::MAX.get() >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, false, true ];
)+};
(nonval_int: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
<$T>::new(0), <$T>::new(1), <$T>::new(2), <$T>::new(3), <$T>::new(-1), <$T>::new(1), <$T>::new(-1), <$T>::new(<$T>::MAX.get() - (<$T>::MAX.get() >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, true, true ];
)+};
(nonval_uint: $( $T:ty | $U:ty ),+) => { $(
impl_ext_num_const![$T|$U:
<$T>::new(0), <$T>::new(1), <$T>::new(2), <$T>::new(3), None, <$T>::new(1), None, <$T>::new(<$T>::MAX.get() ^ (<$T>::MAX.get() >> 1)), Some(<$T>::MIN), Some(<$T>::MAX), false, true, false, false, false, true ];
)+};
}
impl_ext_num_const![];
#[cfg(test)]
mod tests {
use super::{FloatConst, NonZeroI8, NonZeroU8, NumConst};
#[test]
fn float() {
assert_eq!(f32::NUM_ZERO, Some(0.0));
assert_eq!(f32::NUM_ONE, Some(1.0));
assert_eq!(f32::NUM_TWO, Some(2.0));
assert_eq!(f32::NUM_THREE, Some(3.0));
assert_eq!(f32::NUM_NEG_ONE, Some(-1.0));
assert_eq!(f32::NUM_MIN_POSITIVE, Some(f32::MIN_POSITIVE));
assert_eq!(f32::NUM_MAX_NEGATIVE, Some(-0.0));
assert_eq!(f32::NUM_MIN_NORM, Some(0.0));
assert_eq!(f32::NUM_MAX_NORM, Some(1.0));
let expected_bits = ((f32::EXPONENT_BIAS as u32) << 1) << f32::SIGNIFICAND_BITS;
let actual_bits = f32::NUM_MAX_POWER_OF_TWO.unwrap().to_bits();
assert_eq!(actual_bits, expected_bits);
let expected_bits = ((f64::EXPONENT_BIAS as u64) << 1) << f64::SIGNIFICAND_BITS;
let actual_bits = f64::NUM_MAX_POWER_OF_TWO.unwrap().to_bits();
assert_eq!(actual_bits, expected_bits);
}
#[test]
fn int() {
assert_eq!(i8::NUM_ZERO, Some(0));
assert_eq!(i8::NUM_ONE, Some(1));
assert_eq!(i8::NUM_TWO, Some(2));
assert_eq!(i8::NUM_THREE, Some(3));
assert_eq!(i8::NUM_NEG_ONE, Some(-1));
assert_eq!(i8::NUM_MIN_POSITIVE, Some(1));
assert_eq!(i8::NUM_MAX_NEGATIVE, Some(-1));
assert_eq!(i8::NUM_MIN_NORM, Some(i8::MIN));
assert_eq!(i8::NUM_MAX_NORM, Some(i8::MAX));
assert_eq!(i8::NUM_MAX_POWER_OF_TWO, Some(64));
}
#[test]
fn uint() {
assert_eq!(u8::NUM_ZERO, Some(0));
assert_eq!(u8::NUM_ONE, Some(1));
assert_eq!(u8::NUM_TWO, Some(2));
assert_eq!(u8::NUM_THREE, Some(3));
assert_eq!(u8::NUM_NEG_ONE, None);
assert_eq!(u8::NUM_MIN_POSITIVE, Some(1));
assert_eq!(u8::NUM_MAX_NEGATIVE, None);
assert_eq!(u8::NUM_MIN_NORM, Some(u8::MIN));
assert_eq!(u8::NUM_MAX_NORM, Some(u8::MAX));
assert_eq!(u8::NUM_MAX_POWER_OF_TWO, Some(128));
}
#[test]
fn non0int() {
assert_eq!(NonZeroI8::NUM_ZERO, None);
assert_eq!(NonZeroI8::NUM_ONE, NonZeroI8::new(1));
assert_eq!(NonZeroI8::NUM_TWO, NonZeroI8::new(2));
assert_eq!(NonZeroI8::NUM_THREE, NonZeroI8::new(3));
assert_eq!(NonZeroI8::NUM_NEG_ONE, NonZeroI8::new(-1));
assert_eq!(NonZeroI8::NUM_MIN_POSITIVE, NonZeroI8::new(1));
assert_eq!(NonZeroI8::NUM_MAX_NEGATIVE, NonZeroI8::new(-1));
assert_eq!(NonZeroI8::NUM_MIN_NORM, Some(NonZeroI8::MIN));
assert_eq!(NonZeroI8::NUM_MAX_NORM, Some(NonZeroI8::MAX));
assert_eq!(NonZeroI8::NUM_MAX_POWER_OF_TWO, NonZeroI8::new(64));
}
#[test]
fn non0uint() {
assert_eq!(NonZeroU8::NUM_ZERO, None);
assert_eq!(NonZeroU8::NUM_ONE, NonZeroU8::new(1));
assert_eq!(NonZeroU8::NUM_TWO, NonZeroU8::new(2));
assert_eq!(NonZeroU8::NUM_THREE, NonZeroU8::new(3));
assert_eq!(NonZeroU8::NUM_NEG_ONE, None);
assert_eq!(NonZeroU8::NUM_MIN_POSITIVE, NonZeroU8::new(1));
assert_eq!(NonZeroU8::NUM_MAX_NEGATIVE, None);
assert_eq!(NonZeroU8::NUM_MIN_NORM, Some(NonZeroU8::MIN));
assert_eq!(NonZeroU8::NUM_MAX_NORM, Some(NonZeroU8::MAX));
assert_eq!(NonZeroU8::NUM_MAX_POWER_OF_TWO, NonZeroU8::new(128));
}
}