use super::{
integer::AllIntegers,
rational::AllRationals, traits::{self, Number},
NoNumber,
};
pub type Numbers = AllNumbers<NoNumber>;
pub type N = Numbers;
pub type AllN<N> = AllNumbers<N>;
macro_rules! define_numbers {
(match_variants:
$self:ident,
$method:ident,
no_std: $($v:ident),+ $(,)?
) => {
match $self {
$( AllNumbers::$v(n) => n.$method(), )+
AllNumbers::Any(n) => n.$method(),
}
};
(match_variants_rewrap:
$self:ident,
$method:ident,
no_std: $($v:ident),+ $(,)?
) => {
match $self {
$( AllNumbers::$v(n) => n.$method().map(|n| AllNumbers::$v(n)), )+
AllNumbers::Any(n) => n.$method().map(|n| AllNumbers::Any(n)),
}
};
(build_variants:
no_std: $($v:ident, $t:ident),+ $(,)?
) => {
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
#[allow(clippy::derive_partial_eq_without_eq)]
pub enum AllNumbers<N: Number> {
$( $v($t),)+
Any(N)
}
impl<N: Number> Number for AllNumbers<N> {
type InnerRepr = Self;
type InnermostRepr = Self;
#[inline]
fn from_inner_repr(value: Self) -> $crate::all::NumeraResult<Self> { Ok(value) }
#[inline]
#[cfg(not(feature = "safe"))]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
unsafe fn from_inner_repr_unchecked(value: AllNumbers<N>) -> Self { value }
#[inline]
fn from_innermost_repr(value: Self) -> $crate::all::NumeraResult<Self> { Ok(value) }
#[inline]
#[cfg(not(feature = "safe"))]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
unsafe fn from_innermost_repr_unchecked(value: Self) -> Self { value }
#[inline]
fn into_inner_repr(self) -> Self::InnerRepr { self }
#[inline]
fn into_innermost_repr(self) -> Self::InnermostRepr { self }
}
impl<N: Number> traits::Bound for AllNumbers<N> {
fn is_lower_bounded(&self) -> bool {
define_numbers! { match_variants: self, is_lower_bounded, no_std: $($v),+ }
}
fn is_upper_bounded(&self) -> bool {
define_numbers! { match_variants: self, is_lower_bounded, no_std: $($v),+ }
}
fn lower_bound(&self) -> Option<Self> {
define_numbers! { match_variants_rewrap: self, lower_bound, no_std: $($v),+ }
}
fn upper_bound(&self) -> Option<Self> {
define_numbers! { match_variants_rewrap: self, upper_bound, no_std: $($v),+ }
}
}
impl<N: Number> traits::Count for AllNumbers<N> {
fn is_countable(&self) -> bool {
define_numbers! { match_variants: self, is_countable, no_std: $($v),+ }
}
}
impl<N: Number> traits::Sign for AllNumbers<N> {
fn can_positive(&self) -> bool {
define_numbers! { match_variants: self, can_positive, no_std: $($v),+ }
}
fn can_negative(&self) -> bool {
define_numbers! { match_variants: self, can_negative, no_std: $($v),+ }
}
fn is_positive(&self) -> bool {
define_numbers! { match_variants: self, is_positive, no_std: $($v),+ }
}
fn is_negative(&self) -> bool {
define_numbers! { match_variants: self, is_negative, no_std: $($v),+ }
}
}
impl<N: Number> traits::Ident for AllNumbers<N> {
fn can_zero(&self) -> bool {
define_numbers! { match_variants: self, can_zero, no_std: $($v),+ }
}
fn can_one(&self) -> bool {
define_numbers! { match_variants: self, can_one, no_std: $($v),+ }
}
fn can_neg_one(&self) -> bool {
define_numbers! { match_variants: self, can_neg_one, no_std: $($v),+ }
}
fn is_zero(&self) -> bool {
define_numbers! { match_variants: self, is_zero, no_std: $($v),+ }
}
fn is_one(&self) -> bool {
define_numbers! { match_variants: self, is_one, no_std: $($v),+ }
}
fn is_neg_one(&self) -> bool {
define_numbers! { match_variants: self, is_neg_one, no_std: $($v),+ }
}
}
$(
impl<N: Number> From<$t> for AllNumbers<N> {
#[inline]
fn from(n: $t) -> AllNumbers<N> { AllNumbers::$v(n) }
}
)+
$(
impl<N: Number> TryFrom<AllNumbers<N>> for $t {
type Error = crate::error::NumeraErrors;
fn try_from(n: AllNumbers<N>) -> core::result::Result<$t, Self::Error> {
match n {
AllNumbers::$v(n) => Ok(n),
_ => Err(Self::Error::Conversion)
}
}
}
)+
};
}
#[rustfmt::skip]
define_numbers![build_variants:
no_std:
Integer, AllIntegers,
Rational, AllRationals
];