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