1use core::fmt;
2use core::ops::*;
3
4pub trait Scalar:
9 Copy
10 + Clone
11 + Send
12 + Sync
13 + 'static
14 + Default
15 + PartialOrd
16 + Add<Output = Self>
17 + Sub<Output = Self>
18 + Mul<Output = Self>
19 + Div<Output = Self>
20 + Rem<Output = Self>
21 + Neg<Output = Self>
22 + AddAssign
23 + SubAssign
24 + MulAssign
25 + DivAssign
26 + fmt::Debug
27{
28 const ZERO: Self;
30 const ONE: Self;
32 const MIN: Self;
34 const MAX: Self;
36
37 fn abs(self) -> Self;
39 fn min(self, other: Self) -> Self;
41 fn max(self, other: Self) -> Self;
43 fn clamp(self, min: Self, max: Self) -> Self;
45
46 fn from_usize(n: usize) -> Self;
49}
50
51pub trait Transcendental: Scalar {
56 const PI: Self;
58
59 fn to_f32(self) -> f32;
61 fn from_f32(value: f32) -> Self;
63
64 fn to_f64(self) -> f64 {
66 self.to_f32() as f64
67 }
68
69 fn from_f64(value: f64) -> Self {
71 Self::from_f32(value as f32)
72 }
73
74 fn sqrt(self) -> Self;
76 fn exp(self) -> Self;
78 fn ln(self) -> Self;
80 fn sin(self) -> Self;
82 fn cos(self) -> Self;
84 fn tan(self) -> Self;
86
87 fn tanh(self) -> Self {
89 let e2x = (self + self).exp();
90 (e2x - Self::ONE) / (e2x + Self::ONE)
91 }
92
93 fn signum(self) -> Self;
95
96 fn random() -> Self;
98}
99
100impl Scalar for f32 {
105 const ZERO: f32 = 0.0;
106 const ONE: f32 = 1.0;
107 const MIN: f32 = -1.0;
108 const MAX: f32 = 1.0;
109
110 #[inline(always)]
111 fn abs(self) -> f32 {
112 self.abs()
113 }
114
115 #[inline(always)]
116 fn min(self, other: f32) -> f32 {
117 self.min(other)
118 }
119
120 #[inline(always)]
121 fn max(self, other: f32) -> f32 {
122 self.max(other)
123 }
124
125 #[inline(always)]
126 fn clamp(self, min: f32, max: f32) -> f32 {
127 self.clamp(min, max)
128 }
129
130 #[inline(always)]
131 fn from_usize(n: usize) -> f32 {
132 n as f32
133 }
134}
135
136impl Transcendental for f32 {
137 const PI: f32 = std::f32::consts::PI;
138
139 #[inline(always)]
140 fn to_f32(self) -> f32 {
141 self
142 }
143
144 #[inline(always)]
145 fn from_f32(value: f32) -> f32 {
146 value
147 }
148
149 #[inline(always)]
150 fn from_f64(value: f64) -> f32 {
151 value as f32
152 }
153
154 #[inline(always)]
155 fn sqrt(self) -> f32 {
156 self.sqrt()
157 }
158
159 #[inline(always)]
160 fn exp(self) -> f32 {
161 self.exp()
162 }
163
164 #[inline(always)]
165 fn ln(self) -> f32 {
166 self.ln()
167 }
168
169 #[inline(always)]
170 fn sin(self) -> f32 {
171 self.sin()
172 }
173
174 #[inline(always)]
175 fn cos(self) -> f32 {
176 self.cos()
177 }
178
179 #[inline(always)]
180 fn tan(self) -> f32 {
181 f32::tan(self)
182 }
183
184 #[inline(always)]
185 fn tanh(self) -> f32 {
186 f32::tanh(self)
187 }
188
189 #[inline(always)]
190 fn signum(self) -> f32 {
191 f32::signum(self)
192 }
193
194 #[inline(always)]
195 fn random() -> f32 {
196 rand::random::<f32>() * 2.0 - 1.0
197 }
198}
199
200impl Scalar for f64 {
205 const ZERO: f64 = 0.0;
206 const ONE: f64 = 1.0;
207 const MIN: f64 = -1.0;
208 const MAX: f64 = 1.0;
209
210 #[inline(always)]
211 fn abs(self) -> f64 {
212 self.abs()
213 }
214
215 #[inline(always)]
216 fn min(self, other: f64) -> f64 {
217 self.min(other)
218 }
219
220 #[inline(always)]
221 fn max(self, other: f64) -> f64 {
222 self.max(other)
223 }
224
225 #[inline(always)]
226 fn clamp(self, min: f64, max: f64) -> f64 {
227 self.clamp(min, max)
228 }
229
230 #[inline(always)]
231 fn from_usize(n: usize) -> f64 {
232 n as f64
233 }
234}
235
236impl Transcendental for f64 {
237 const PI: f64 = std::f64::consts::PI;
238
239 #[inline(always)]
240 fn to_f32(self) -> f32 {
241 self as f32
242 }
243
244 #[inline(always)]
245 fn from_f32(value: f32) -> f64 {
246 value as f64
247 }
248
249 #[inline(always)]
250 fn from_f64(value: f64) -> f64 {
251 value
252 }
253
254 #[inline(always)]
255 fn sqrt(self) -> f64 {
256 self.sqrt()
257 }
258
259 #[inline(always)]
260 fn exp(self) -> f64 {
261 self.exp()
262 }
263
264 #[inline(always)]
265 fn ln(self) -> f64 {
266 self.ln()
267 }
268
269 #[inline(always)]
270 fn sin(self) -> f64 {
271 self.sin()
272 }
273
274 #[inline(always)]
275 fn cos(self) -> f64 {
276 self.cos()
277 }
278
279 #[inline(always)]
280 fn tan(self) -> f64 {
281 self.tan()
282 }
283
284 #[inline(always)]
285 fn tanh(self) -> f64 {
286 self.tanh()
287 }
288
289 #[inline(always)]
290 fn signum(self) -> f64 {
291 self.signum()
292 }
293
294 #[inline(always)]
295 fn random() -> f64 {
296 rand::random::<f64>() * 2.0 - 1.0
297 }
298}
299
300macro_rules! impl_scalar_int {
305 ($ty:ty, $zero:expr, $one:expr, $min:expr, $max:expr) => {
306 impl Scalar for $ty {
307 const ZERO: $ty = $zero;
308 const ONE: $ty = $one;
309 const MIN: $ty = $min;
310 const MAX: $ty = $max;
311
312 #[inline(always)]
313 fn abs(self) -> $ty {
314 if self >= 0 {
315 self
316 } else {
317 -self
318 }
319 }
320
321 #[inline(always)]
322 fn min(self, other: $ty) -> $ty {
323 core::cmp::Ord::min(self, other)
324 }
325
326 #[inline(always)]
327 fn max(self, other: $ty) -> $ty {
328 core::cmp::Ord::max(self, other)
329 }
330
331 #[inline(always)]
332 fn clamp(self, lo: $ty, hi: $ty) -> $ty {
333 core::cmp::Ord::clamp(self, lo, hi)
334 }
335
336 #[inline(always)]
337 fn from_usize(n: usize) -> $ty {
338 n as $ty
339 }
340 }
341 };
342}
343
344impl_scalar_int!(i8, 0, 1, i8::MIN, i8::MAX);
345impl_scalar_int!(i16, 0, 1, i16::MIN, i16::MAX);
346impl_scalar_int!(i32, 0, 1, i32::MIN, i32::MAX);
347impl_scalar_int!(i64, 0, 1, i64::MIN, i64::MAX);