use core::num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
};
use crate::{
error::{NumeraErrors, NumeraResult},
number::traits::{Bound, Count, Ident, Sign},
};
pub trait Number: Bound + Count + Ident + Sign {
type InnerRepr;
type InnermostRepr;
#[rustfmt::skip]
fn from_inner_repr(inner: Self::InnerRepr) -> NumeraResult<Self> where Self: Sized;
#[must_use]
#[cfg(not(feature = "safe"))]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
unsafe fn from_inner_repr_unchecked(inner: Self::InnerRepr) -> Self;
#[rustfmt::skip]
fn from_innermost_repr(innermost: Self::InnermostRepr) -> NumeraResult<Self> where Self: Sized;
#[must_use]
#[cfg(not(feature = "safe"))]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
unsafe fn from_innermost_repr_unchecked(innermost: Self::InnermostRepr) -> Self;
fn into_inner_repr(self) -> Self::InnerRepr;
fn into_innermost_repr(self) -> Self::InnermostRepr;
#[inline]
fn try_from_inner_repr(inner: impl Into<Self::InnerRepr>) -> NumeraResult<Self>
where
Self: Sized,
{
Number::from_inner_repr(inner.into())
}
}
macro_rules! impl_numbers {
($($t:ty ),+) => { $( impl_numbers![@$t]; )+ };
(@$t:ty) => {
impl Number for $t {
type InnerRepr = $t;
type InnermostRepr = $t;
#[inline]
fn from_inner_repr(value: Self::InnerRepr) -> NumeraResult<Self> { Ok(value) }
#[inline]
#[cfg(not(feature = "safe"))]
unsafe fn from_inner_repr_unchecked(value: Self::InnerRepr) -> Self { value }
#[inline]
fn from_innermost_repr(value: Self::InnermostRepr) -> NumeraResult<Self> { Ok(value) }
#[inline]
#[cfg(not(feature = "safe"))]
unsafe fn from_innermost_repr_unchecked(value: Self::InnermostRepr) -> Self { value }
#[inline]
fn into_inner_repr(self) -> Self::InnerRepr { self }
#[inline]
fn into_innermost_repr(self) -> Self::InnermostRepr { self }
}
};
(non0 $($t:ident + $i:ident ),+) => { $( impl_numbers![@non0 $t+$i]; )+ };
(@non0 $t:ident + $i:ident) => {
impl Number for $t {
type InnerRepr = $i;
type InnermostRepr = $i;
#[inline]
fn from_inner_repr(value: Self::InnerRepr) -> NumeraResult<Self> {
$t::new(value).ok_or(NumeraErrors::Conversion)
}
#[inline]
#[cfg(not(feature = "safe"))]
unsafe fn from_inner_repr_unchecked(value: Self::InnerRepr) -> Self {
$t::new_unchecked(value)
}
#[inline]
fn from_innermost_repr(value: Self::InnermostRepr) -> NumeraResult<Self> {
$t::new(value).ok_or(NumeraErrors::Conversion)
}
#[inline]
#[cfg(not(feature = "safe"))]
unsafe fn from_innermost_repr_unchecked(value: Self::InnermostRepr) -> Self {
$t::new_unchecked(value)
}
#[inline]
fn into_inner_repr(self) -> Self::InnerRepr { self.get() }
#[inline]
fn into_innermost_repr(self) -> Self::InnermostRepr { self.get() }
}
};
}
#[rustfmt::skip]
impl_numbers![f32, f64, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize];
#[rustfmt::skip]
impl_numbers![non0
NonZeroI8+i8, NonZeroI16+i16, NonZeroI32+i32, NonZeroI64+i64,
NonZeroI128+i128, NonZeroIsize+isize,
NonZeroU8+u8, NonZeroU16+u16, NonZeroU32+u32, NonZeroU64+u64,
NonZeroU128+u128, NonZeroUsize+usize
];
#[cfg(feature = "twofloat")]
impl_numbers![@twofloat::TwoFloat];
#[cfg(feature = "half")]
impl_numbers![half::bf16, half::f16];
#[cfg(feature = "dashu-int")]
impl_numbers![dashu_int::IBig, dashu_int::UBig];