use num_traits::{AsPrimitive, Float, FromPrimitive, Signed, ToPrimitive, float::FloatCore};
use std::{
fmt::{Debug, Display, LowerExp},
hash::Hash,
ops::{AddAssign, DivAssign, MulAssign, Neg, SubAssign},
};
pub trait GenericScalar
where
Self: Display
+ Debug
+ Float
+ FloatCore
+ FromPrimitive
+ ToPrimitive
+ MulAssign
+ DivAssign
+ AddAssign
+ SubAssign
+ Default
+ std::str::FromStr
+ Sync
+ Send
+ Into<f64>
+ From<f32>
+ From<u16>
+ From<i16>
+ From<i8>
+ From<u8>
+ Neg<Output = Self>
+ Signed
+ LowerExp
+ AsPrimitive<f64>
+ AsPrimitive<f32>
+ AsPrimitive<usize>
+ AsPrimitive<isize>
+ AsPrimitive<u64>
+ AsPrimitive<i64>
+ AsPrimitive<u32>
+ AsPrimitive<i32>
+ AsPrimitive<u16>
+ AsPrimitive<i16>
+ AsPrimitive<u8>
+ AsPrimitive<i8>
+ approx::UlpsEq<Epsilon = Self>,
{
type BitsType: Hash + Eq + Ord + Display + Debug;
const ZERO: Self;
const ONE: Self;
const TWO: Self;
const THREE: Self;
const FOUR: Self;
const INFINITY: Self;
const NEG_INFINITY: Self;
const EPSILON: Self;
const MAX: Self;
const MIN: Self;
fn to_bits(self) -> Self::BitsType;
fn from_bits(bits: Self::BitsType) -> Self;
}
macro_rules! impl_generic_scalar {
($type:ty, $bits_type:ty) => {
impl GenericScalar for $type {
type BitsType = $bits_type;
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
const TWO: Self = 2.0;
const THREE: Self = 3.0;
const FOUR: Self = 4.0;
const INFINITY: Self = <$type>::INFINITY;
const NEG_INFINITY: Self = <$type>::NEG_INFINITY;
const EPSILON: Self = <$type>::EPSILON;
const MAX: Self = <$type>::MAX;
const MIN: Self = <$type>::MIN;
#[inline(always)]
fn to_bits(self) -> Self::BitsType {
<$type>::to_bits(self)
}
#[inline(always)]
fn from_bits(bits: Self::BitsType) -> Self {
<$type>::from_bits(bits)
}
}
};
}
impl_generic_scalar!(f32, u32);
impl_generic_scalar!(f64, u64);