pub use ops::Neg; trait_alias!( pub Number, Cast + Default + ops::Add + ops::Sub + ops::Mul + ops::Div + EpsEq + Round + Pow + EucMod + Precise ); pub trait EpsEq: Copy + cmp::PartialOrd { fn eps_eq(self, r: Self) -> bool { self == r } fn trsh_eq(self, r: Self, _: Self) -> bool { self == r } } impl_trait_for!(EpsEq = bool, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl EpsEq for f16 { fn eps_eq(self, r: Self) -> bool { self.trsh_eq(r, f16::EPSILON) } fn trsh_eq(self, r: Self, e: Self) -> bool { let (l, r) = Vec2((self, r)); (l - r).abs() <= f32(e) } } impl EpsEq for f32 { fn eps_eq(self, r: Self) -> bool { self.trsh_eq(r, f32::EPSILON) } fn trsh_eq(self, r: Self, e: Self) -> bool { (self - r).abs() <= e } } impl EpsEq for f64 { fn eps_eq(self, r: Self) -> bool { self.trsh_eq(r, f64::EPSILON) } fn trsh_eq(self, r: Self, e: Self) -> bool { (self - r).abs() <= e } } pub trait Round: Copy + cmp::PartialOrd { fn round(self) -> Self { self } fn abs(self) -> Self { self } } impl_trait_for!(Round = u8, u16, u32, u64, u128, usize); macro_rules! rounding { ($($t: ty),+) => { $(impl Round for $t { fn abs(self) -> Self { self.abs() } })+ }; } rounding!(i8, i16, i32, i64, i128, isize); impl Round for f16 { fn round(self) -> Self { f16(f32(self).round()) } fn abs(self) -> Self { f16(f32(self).abs()) } } macro_rules! rounding_f { ($($t: ty),+) => { $(impl Round for $t { fn round(self) -> Self { self.round() } fn abs(self) -> Self { self.abs() } })+ }; } rounding_f!(f32, f64); pub trait Pow { fn power(self, _: T) -> Self; } macro_rules! pow { ($($t: ty),+) => { $(impl Pow for $t where u32: Cast, { fn power(self, r: T) -> Self { self.pow(u32(r)) } })+ }; } pow!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize); impl Pow for f16 where i32: Cast, { fn power(self, r: T) -> Self { f16(f32(self).powi(i32(r))) } } macro_rules! powi { ($($t: ty),+) => { $(impl Pow for $t where i32: Cast, { fn power(self, r: T) -> Self { self.powi(i32(r)) } })+ }; } powi!(f32, f64); pub trait EucMod { fn euc_mod(self, _: T) -> Self; } macro_rules! euc_mod { ($($t: ty),+) => { $(impl EucMod for $t where Self: Cast, { fn euc_mod(self, r: T) -> Self { self.rem_euclid(Self::to(r)) } })+ }; } euc_mod!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, usize, isize); impl EucMod for f16 where f32: Cast, { fn euc_mod(self, r: T) -> Self { f16(self.to_f32().rem_euclid(f32(r))) } } pub trait Precise: Default + PartialEq { fn mix(self, a: f32, r: Self) -> Self; fn root(self) -> Self; fn is_zero(&self) -> bool { self == &Default::default() } } macro_rules! sqrt { ($($t: ty),+) => { $(impl Precise for $t { fn mix(self, a: f32, r: Self) -> Self { Self::to(f32(self) * (1. - a) + f32(r) * a) } fn root(self) -> Self { Self::to(f32(self).sqrt()) } })+ }; } sqrt!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f16, f32, usize, isize); impl Precise for f64 { fn mix(self, a: f32, r: Self) -> Self { let a = f64(a); self * (1. - a) + r * a } fn root(self) -> Self { self.sqrt() } } use super::pre::*; use std::{cmp, ops};