grafix_toolbox/kit/policies/math/
math_ext.rs

1pub use ops::Neg;
2
3trait_alias!(
4	pub Number,
5	Cast<i32>
6		+ Default
7		+ ops::Add<Output = Self>
8		+ ops::Sub<Output = Self>
9		+ ops::Mul<Output = Self>
10		+ ops::Div<Output = Self>
11		+ EpsEq
12		+ Round
13		+ Pow<Self>
14		+ EucMod<Self>
15		+ Precise
16);
17
18pub trait EpsEq: Copy + cmp::PartialOrd {
19	fn eps_eq(self, r: Self) -> bool {
20		self == r
21	}
22	fn trsh_eq(self, r: Self, _: Self) -> bool {
23		self == r
24	}
25}
26impl_trait_for!(EpsEq = bool, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
27impl EpsEq for f16 {
28	fn eps_eq(self, r: Self) -> bool {
29		self.trsh_eq(r, f16::EPSILON)
30	}
31	fn trsh_eq(self, r: Self, e: Self) -> bool {
32		let (l, r) = Vec2((self, r));
33		(l - r).abs() <= f32(e)
34	}
35}
36impl EpsEq for f32 {
37	fn eps_eq(self, r: Self) -> bool {
38		self.trsh_eq(r, f32::EPSILON)
39	}
40	fn trsh_eq(self, r: Self, e: Self) -> bool {
41		(self - r).abs() <= e
42	}
43}
44impl EpsEq for f64 {
45	fn eps_eq(self, r: Self) -> bool {
46		self.trsh_eq(r, f64::EPSILON)
47	}
48	fn trsh_eq(self, r: Self, e: Self) -> bool {
49		(self - r).abs() <= e
50	}
51}
52
53pub trait Round: Copy + cmp::PartialOrd {
54	fn round(self) -> Self {
55		self
56	}
57	fn abs(self) -> Self {
58		self
59	}
60}
61impl_trait_for!(Round = u8, u16, u32, u64, u128, usize);
62macro_rules! rounding {
63	($($t: ty),+) => {
64		$(impl Round for $t {
65			fn abs(self) -> Self {
66				self.abs()
67			}
68		})+
69	};
70}
71rounding!(i8, i16, i32, i64, i128, isize);
72impl Round for f16 {
73	fn round(self) -> Self {
74		f16(f32(self).round())
75	}
76	fn abs(self) -> Self {
77		f16(f32(self).abs())
78	}
79}
80macro_rules! rounding_f {
81	($($t: ty),+) => {
82		$(impl Round for $t {
83			fn round(self) -> Self {
84				self.round()
85			}
86			fn abs(self) -> Self {
87				self.abs()
88			}
89		})+
90	};
91}
92rounding_f!(f32, f64);
93
94pub trait Pow<T> {
95	fn power(self, _: T) -> Self;
96}
97macro_rules! pow {
98	($($t: ty),+) => {
99		$(impl<T> Pow<T> for $t
100		where
101			u32: Cast<T>,
102		{
103			fn power(self, r: T) -> Self {
104				self.pow(u32(r))
105			}
106		})+
107	};
108}
109pow!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
110impl<T> Pow<T> for f16
111where
112	i32: Cast<T>,
113{
114	fn power(self, r: T) -> Self {
115		f16(f32(self).powi(i32(r)))
116	}
117}
118macro_rules! powi {
119	($($t: ty),+) => {
120		$(impl<T> Pow<T> for $t
121		where
122			i32: Cast<T>,
123		{
124			fn power(self, r: T) -> Self {
125				self.powi(i32(r))
126			}
127		})+
128	};
129}
130powi!(f32, f64);
131
132pub trait EucMod<T> {
133	fn euc_mod(self, _: T) -> Self;
134}
135macro_rules! euc_mod {
136	($($t: ty),+) => {
137		$(impl<T> EucMod<T> for $t
138		where
139			Self: Cast<T>,
140		{
141			fn euc_mod(self, r: T) -> Self {
142				self.rem_euclid(Self::to(r))
143			}
144		})+
145	};
146}
147euc_mod!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, usize, isize);
148impl<T> EucMod<T> for f16
149where
150	f32: Cast<T>,
151{
152	fn euc_mod(self, r: T) -> Self {
153		f16(self.to_f32().rem_euclid(f32(r)))
154	}
155}
156
157pub trait Precise: Default + PartialEq {
158	fn mix(self, a: f32, r: Self) -> Self;
159	fn root(self) -> Self;
160	fn is_zero(&self) -> bool {
161		self == &Default::default()
162	}
163}
164macro_rules! sqrt {
165	($($t: ty),+) => {
166		$(impl Precise for $t {
167			fn mix(self, a: f32, r: Self) -> Self {
168				Self::to(f32(self) * (1. - a) + f32(r) * a)
169			}
170			fn root(self) -> Self {
171				Self::to(f32(self).sqrt())
172			}
173		})+
174	};
175}
176sqrt!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f16, f32, usize, isize);
177impl Precise for f64 {
178	fn mix(self, a: f32, r: Self) -> Self {
179		let a = f64(a);
180		self * (1. - a) + r * a
181	}
182	fn root(self) -> Self {
183		self.sqrt()
184	}
185}
186
187use super::pre::*;
188use std::{cmp, ops};