use core::fmt;
use core::ops::*;
pub trait Scalar:
Copy
+ Clone
+ Send
+ Sync
+ 'static
+ Default
+ PartialOrd
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Rem<Output = Self>
+ Neg<Output = Self>
+ AddAssign
+ SubAssign
+ MulAssign
+ DivAssign
+ fmt::Debug
{
const ZERO: Self;
const ONE: Self;
const MIN: Self;
const MAX: Self;
fn abs(self) -> Self;
fn min(self, other: Self) -> Self;
fn max(self, other: Self) -> Self;
fn clamp(self, min: Self, max: Self) -> Self;
}
pub trait Transcendental: Scalar {
const PI: Self;
fn to_f32(self) -> f32;
fn from_f32(value: f32) -> Self;
fn to_f64(self) -> f64 {
self.to_f32() as f64
}
fn from_f64(value: f64) -> Self {
Self::from_f32(value as f32)
}
fn sqrt(self) -> Self;
fn exp(self) -> Self;
fn ln(self) -> Self;
fn sin(self) -> Self;
fn cos(self) -> Self;
fn tan(self) -> Self;
}
impl Scalar for f32 {
const ZERO: f32 = 0.0;
const ONE: f32 = 1.0;
const MIN: f32 = -1.0;
const MAX: f32 = 1.0;
#[inline(always)]
fn abs(self) -> f32 {
self.abs()
}
#[inline(always)]
fn min(self, other: f32) -> f32 {
self.min(other)
}
#[inline(always)]
fn max(self, other: f32) -> f32 {
self.max(other)
}
#[inline(always)]
fn clamp(self, min: f32, max: f32) -> f32 {
self.clamp(min, max)
}
}
impl Transcendental for f32 {
const PI: f32 = std::f32::consts::PI;
#[inline(always)]
fn to_f32(self) -> f32 {
self
}
#[inline(always)]
fn from_f32(value: f32) -> f32 {
value
}
#[inline(always)]
fn from_f64(value: f64) -> f32 {
value as f32
}
#[inline(always)]
fn sqrt(self) -> f32 {
self.sqrt()
}
#[inline(always)]
fn exp(self) -> f32 {
self.exp()
}
#[inline(always)]
fn ln(self) -> f32 {
self.ln()
}
#[inline(always)]
fn sin(self) -> f32 {
self.sin()
}
#[inline(always)]
fn cos(self) -> f32 {
self.cos()
}
#[inline(always)]
fn tan(self) -> f32 {
self.tan()
}
}
impl Scalar for f64 {
const ZERO: f64 = 0.0;
const ONE: f64 = 1.0;
const MIN: f64 = -1.0;
const MAX: f64 = 1.0;
#[inline(always)]
fn abs(self) -> f64 {
self.abs()
}
#[inline(always)]
fn min(self, other: f64) -> f64 {
self.min(other)
}
#[inline(always)]
fn max(self, other: f64) -> f64 {
self.max(other)
}
#[inline(always)]
fn clamp(self, min: f64, max: f64) -> f64 {
self.clamp(min, max)
}
}
impl Transcendental for f64 {
const PI: f64 = std::f64::consts::PI;
#[inline(always)]
fn to_f32(self) -> f32 {
self as f32
}
#[inline(always)]
fn from_f32(value: f32) -> f64 {
value as f64
}
#[inline(always)]
fn from_f64(value: f64) -> f64 {
value
}
#[inline(always)]
fn sqrt(self) -> f64 {
self.sqrt()
}
#[inline(always)]
fn exp(self) -> f64 {
self.exp()
}
#[inline(always)]
fn ln(self) -> f64 {
self.ln()
}
#[inline(always)]
fn sin(self) -> f64 {
self.sin()
}
#[inline(always)]
fn cos(self) -> f64 {
self.cos()
}
#[inline(always)]
fn tan(self) -> f64 {
self.tan()
}
}
macro_rules! impl_scalar_int {
($ty:ty, $zero:expr, $one:expr, $min:expr, $max:expr) => {
impl Scalar for $ty {
const ZERO: $ty = $zero;
const ONE: $ty = $one;
const MIN: $ty = $min;
const MAX: $ty = $max;
#[inline(always)]
fn abs(self) -> $ty {
if self >= 0 {
self
} else {
-self
}
}
#[inline(always)]
fn min(self, other: $ty) -> $ty {
core::cmp::Ord::min(self, other)
}
#[inline(always)]
fn max(self, other: $ty) -> $ty {
core::cmp::Ord::max(self, other)
}
#[inline(always)]
fn clamp(self, lo: $ty, hi: $ty) -> $ty {
core::cmp::Ord::clamp(self, lo, hi)
}
}
};
}
impl_scalar_int!(i8, 0, 1, i8::MIN, i8::MAX);
impl_scalar_int!(i16, 0, 1, i16::MIN, i16::MAX);
impl_scalar_int!(i32, 0, 1, i32::MIN, i32::MAX);
impl_scalar_int!(i64, 0, 1, i64::MIN, i64::MAX);