use core::{
fmt::Debug,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
};
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use super::type_lists::with_all_scalar_types;
use crate::{
ops::{Abs, HasScalar, Negate, One, Select, Zero},
scalar::Float,
};
pub trait Scalar:
Copy
+ Debug
+ HasScalar
+ Zero
+ One
+ Select
+ PartialEq
+ PartialOrd
+ ScalarCasts
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<Output = Self>
+ MulAssign
+ Div<Output = Self>
+ DivAssign
{
const MAX: Self;
const MIN: Self;
#[inline]
fn from_scalar<T: Scalar>(value: T) -> Self
where
Self: ScalarCast<T>,
{
<Self as ScalarCast<T>>::from_scalar_impl(value)
}
#[inline]
fn as_scalar<T: Scalar>(&self) -> T
where
Self: ScalarCast<T>,
{
<Self as ScalarCast<T>>::as_scalar_impl(self)
}
}
pub trait FloatScalar:
Scalar + Float + AbsDiffEq<Epsilon = Self> + RelativeEq<Epsilon = Self> + UlpsEq<Epsilon = Self>
{
}
pub trait IntScalar: Scalar + Ord + Eq {}
pub trait UIntScalar: IntScalar {}
pub trait SIntScalar: IntScalar + Negate + Abs {}
pub trait ScalarCast<T>: Sized {
fn from_scalar_impl(value: T) -> Self;
fn as_scalar_impl(&self) -> T;
}
macro_rules! define_scalar_casts_trait {
($($ty:ty),+ $(,)?) => {
pub trait ScalarCasts: $(ScalarCast<$ty> +)+ {}
impl<T> ScalarCasts for T where T: $(ScalarCast<$ty> +)+ {}
};
}
with_all_scalar_types!(define_scalar_casts_trait);