use crate::sealed::Sealed;
use crate::{ScalarComposite, ScalarOrVector, ScalarOrVectorTransform};
use core::num::NonZeroUsize;
pub unsafe trait Scalar: ScalarOrVector<Scalar = Self> + crate::sealed::Sealed {}
pub unsafe trait Number: Scalar {}
pub unsafe trait Integer: num_traits::PrimInt + Number {
const WIDTH: usize;
const SIGNED: bool;
}
pub unsafe trait SignedInteger: num_traits::Signed + Integer {}
pub unsafe trait UnsignedInteger: num_traits::Unsigned + Integer {}
pub unsafe trait Float: num_traits::Float + Number {
const WIDTH: usize;
}
macro_rules! impl_scalar {
(impl Scalar for $ty:ty;) => {
impl Sealed for $ty {}
impl ScalarComposite for $ty {
#[inline]
fn transform<F: ScalarOrVectorTransform>(self, f: &mut F) -> Self {
f.transform_scalar(self)
}
}
unsafe impl ScalarOrVector for $ty {
type Scalar = Self;
const N: NonZeroUsize = NonZeroUsize::new(1).unwrap();
}
unsafe impl Scalar for $ty {}
};
(impl Number for $ty:ty;) => {
unsafe impl Number for $ty {}
impl_scalar!(impl Scalar for $ty;);
};
(impl UnsignedInteger for $ty:ty;) => {
unsafe impl Integer for $ty {
const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
const SIGNED: bool = false;
}
unsafe impl UnsignedInteger for $ty {}
impl_scalar!(impl Number for $ty;);
};
(impl SignedInteger for $ty:ty;) => {
unsafe impl Integer for $ty {
const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
const SIGNED: bool = true;
}
unsafe impl SignedInteger for $ty {}
impl_scalar!(impl Number for $ty;);
};
(impl Float for $ty:ty;) => {
unsafe impl Float for $ty {
const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
}
impl_scalar!(impl Number for $ty;);
};
($(impl $trait:ident for $ty:ty;)+) => {
$(impl_scalar!(impl $trait for $ty;);)+
};
}
impl_scalar! {
impl UnsignedInteger for u8;
impl UnsignedInteger for u16;
impl UnsignedInteger for u32;
impl UnsignedInteger for u64;
impl SignedInteger for i8;
impl SignedInteger for i16;
impl SignedInteger for i32;
impl SignedInteger for i64;
impl Float for f32;
impl Float for f64;
impl Scalar for bool;
}
#[inline]
pub fn assert_is_integer<T: Integer>() {}