1#![deny(missing_docs)]
2
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
5
6pub trait Float:
8 'static + Send + Sync
9 + Copy + Radians + One + Zero + Sqrt
10 + FromPrimitive
11 + Min + Max + Signum + Powf
12 + Trig
13 + PartialEq
14 + PartialOrd
15 + Add<Self, Output = Self> + AddAssign<Self>
16 + Mul<Self, Output = Self> + MulAssign<Self>
17 + Sub<Self, Output = Self> + SubAssign<Self>
18 + Div<Self, Output = Self> + DivAssign<Self>
19 + Rem<Self, Output = Self> + RemAssign<Self>
20 + Neg<Output = Self>
21 + Trig {}
22
23impl<T> Float for T where
24 T: 'static + Send + Sync
25 + Copy + Radians + One + Zero + Sqrt
26 + FromPrimitive
27 + Min + Max + Signum + Powf
28 + Trig
29 + PartialEq
30 + PartialOrd
31 + Add<T, Output = T> + AddAssign<T>
32 + Mul<T, Output = T> + MulAssign<T>
33 + Sub<T, Output = T> + SubAssign<T>
34 + Div<T, Output = T> + DivAssign<T>
35 + Rem<T, Output = T> + RemAssign<T>
36 + Neg<Output = T>
37 + Trig {}
38
39pub trait Min {
41 fn min(self, other: Self) -> Self;
43}
44
45impl Min for f32 {
46 #[inline(always)]
47 fn min(self, other: Self) -> Self { self.min(other) }
48}
49
50impl Min for f64 {
51 #[inline(always)]
52 fn min(self, other: Self) -> Self { self.min(other) }
53}
54
55pub trait Max {
57 fn max(self, other: Self) -> Self;
59}
60
61impl Max for f32 {
62 #[inline(always)]
63 fn max(self, other: Self) -> Self { self.max(other) }
64}
65
66impl Max for f64 {
67 #[inline(always)]
68 fn max(self, other: Self) -> Self { self.max(other) }
69}
70
71pub trait Signum {
73 fn signum(self) -> Self;
75}
76
77impl Signum for f32 {
78 #[inline(always)]
79 fn signum(self) -> Self { self.signum() }
80}
81
82impl Signum for f64 {
83 #[inline(always)]
84 fn signum(self) -> Self { self.signum() }
85}
86
87pub trait Powf {
89 fn powf(self, other: Self) -> Self;
91}
92
93impl Powf for f32 {
94 #[inline(always)]
95 fn powf(self, other: Self) -> Self { self.powf(other) }
96}
97
98impl Powf for f64 {
99 #[inline(always)]
100 fn powf(self, other: Self) -> Self { self.powf(other) }
101}
102
103pub trait Radians {
105 fn _90() -> Self;
107
108 fn _180() -> Self;
110
111 fn _360() -> Self;
113
114 fn deg_to_rad(self) -> Self;
117
118 fn rad_to_deg(self) -> Self;
121}
122
123impl Radians for f32 {
124 #[inline(always)]
125 fn _90() -> f32 {
126 ::std::f32::consts::FRAC_PI_2
127 }
128
129 #[inline(always)]
130 fn _180() -> f32 {
131 ::std::f32::consts::PI
132 }
133
134 #[inline(always)]
135 fn _360() -> f32 {
136 <Self as Radians>::_180() * 2.0
137 }
138
139 #[inline(always)]
140 fn deg_to_rad(self) -> Self {
141 self * (::std::f32::consts::PI / 180.0_f32)
142 }
143
144 #[inline(always)]
145 fn rad_to_deg(self) -> Self {
146 self * (180.0_f32 / ::std::f32::consts::PI)
147 }
148}
149
150impl Radians for f64 {
151 #[inline(always)]
152 fn _90() -> f64 {
153 ::std::f64::consts::FRAC_PI_2
154 }
155
156 #[inline(always)]
157 fn _180() -> f64 {
158 ::std::f64::consts::PI
159 }
160
161 #[inline(always)]
162 fn _360() -> f64 {
163 <Self as Radians>::_180() * 2.0
164 }
165
166 #[inline(always)]
167 fn deg_to_rad(self) -> Self {
168 self * (::std::f64::consts::PI / 180.0_f64)
169 }
170
171 #[inline(always)]
172 fn rad_to_deg(self) -> Self {
173 self * (180.0_f64 / ::std::f64::consts::PI)
174 }
175}
176
177pub trait One {
179 fn one() -> Self;
181}
182
183pub trait Zero {
185 fn zero() -> Self;
187}
188
189impl One for f32 {
190 #[inline(always)]
191 fn one() -> f32 { 1.0 }
192}
193
194impl One for f64 {
195 #[inline(always)]
196 fn one() -> f64 { 1.0 }
197}
198
199impl Zero for f32 {
200 #[inline(always)]
201 fn zero() -> f32 { 0.0 }
202}
203
204impl Zero for f64 {
205 #[inline(always)]
206 fn zero() -> f64 { 0.0 }
207}
208
209pub trait Sqrt {
211 fn sqrt(self) -> Self;
213}
214
215impl Sqrt for f32 {
216 #[inline(always)]
217 fn sqrt(self) -> f32 { self.sqrt() }
218}
219
220impl Sqrt for f64 {
221 #[inline(always)]
222 fn sqrt(self) -> f64 { self.sqrt() }
223}
224
225pub trait Trig {
227 fn sin(self) -> Self;
229 fn cos(self) -> Self;
231 fn tan(self) -> Self;
233 fn asin(self) -> Self;
235 fn acos(self) -> Self;
237 fn atan(self) -> Self;
239 fn atan2(self, other: Self) -> Self;
241 fn sinh(self) -> Self;
243 fn cosh(self) -> Self;
245 fn tanh(self) -> Self;
247 fn asinh(self) -> Self;
249 fn acosh(self) -> Self;
251 fn atanh(self) -> Self;
253}
254
255impl Trig for f32 {
256 #[inline(always)]
257 fn sin(self) -> f32 { self.sin() }
258
259 #[inline(always)]
260 fn cos(self) -> f32 { self.cos() }
261
262 #[inline(always)]
263 fn tan(self) -> f32 { self.tan() }
264
265 #[inline(always)]
266 fn asin(self) -> f32 { self.asin() }
267
268 #[inline(always)]
269 fn acos(self) -> f32 { self.acos() }
270
271 #[inline(always)]
272 fn atan(self) -> f32 { self.atan() }
273
274 #[inline(always)]
275 fn atan2(self, other: f32) -> f32 { self.atan2(other) }
276
277 #[inline(always)]
278 fn sinh(self) -> f32 { self.sinh() }
279
280 #[inline(always)]
281 fn cosh(self) -> f32 { self.cosh() }
282
283 #[inline(always)]
284 fn tanh(self) -> f32 { self.tanh() }
285
286 #[inline(always)]
287 fn asinh(self) -> f32 { self.asinh() }
288
289 #[inline(always)]
290 fn acosh(self) -> f32 { self.acosh() }
291
292 #[inline(always)]
293 fn atanh(self) -> f32 { self.atanh() }
294}
295
296impl Trig for f64 {
297 #[inline(always)]
298 fn sin(self) -> f64 { self.sin() }
299
300 #[inline(always)]
301 fn cos(self) -> f64 { self.cos() }
302
303 #[inline(always)]
304 fn tan(self) -> f64 { self.tan() }
305
306 #[inline(always)]
307 fn asin(self) -> f64 { self.asin() }
308
309 #[inline(always)]
310 fn acos(self) -> f64 { self.acos() }
311
312 #[inline(always)]
313 fn atan(self) -> f64 { self.atan() }
314
315 #[inline(always)]
316 fn atan2(self, other: f64) -> f64 { self.atan2(other) }
317
318 #[inline(always)]
319 fn sinh(self) -> f64 { self.sinh() }
320
321 #[inline(always)]
322 fn cosh(self) -> f64 { self.cosh() }
323
324 #[inline(always)]
325 fn tanh(self) -> f64 { self.tanh() }
326
327 #[inline(always)]
328 fn asinh(self) -> f64 { self.asinh() }
329
330 #[inline(always)]
331 fn acosh(self) -> f64 { self.acosh() }
332
333 #[inline(always)]
334 fn atanh(self) -> f64 { self.atanh() }
335}
336
337pub trait Cast<T> {
339 fn cast(self) -> T;
341}
342
343impl Cast<f32> for f64 {
344 #[inline(always)]
345 fn cast(self) -> f32 { self as f32 }
346}
347
348impl Cast<f64> for f32 {
349 #[inline(always)]
350 fn cast(self) -> f64 { self as f64 }
351}
352
353impl Cast<f32> for f32 {
354 #[inline(always)]
355 fn cast(self) -> f32 { self }
356}
357
358impl Cast<f64> for f64 {
359 #[inline(always)]
360 fn cast(self) -> f64 { self }
361}
362
363pub trait FromPrimitive {
365 fn from_f64(t: f64) -> Self;
367 fn from_f32(t: f32) -> Self;
369 fn from_isize(t: isize) -> Self;
371 fn from_u32(t: u32) -> Self;
373 fn from_i32(t: i32) -> Self;
375 }
377
378impl FromPrimitive for f64 {
379 #[inline(always)]
380 fn from_f64(t: f64) -> Self { t }
381 #[inline(always)]
382 fn from_f32(t: f32) -> Self { t as f64 }
383 #[inline(always)]
384 fn from_isize(t: isize) -> Self { t as f64 }
385 #[inline(always)]
386 fn from_u32(t: u32) -> Self { t as f64 }
387 #[inline(always)]
388 fn from_i32(t: i32) -> Self { t as f64 }
389}
390
391impl FromPrimitive for f32 {
392 #[inline(always)]
393 fn from_f64(t: f64) -> Self { t as f32 }
394 #[inline(always)]
395 fn from_f32(t: f32) -> Self { t }
396 #[inline(always)]
397 fn from_isize(t: isize) -> Self { t as f32 }
398 #[inline(always)]
399 fn from_u32(t: u32) -> Self { t as f32 }
400 #[inline(always)]
401 fn from_i32(t: i32) -> Self { t as f32 }
402}
403
404#[cfg(test)]
405mod test {
406 use super::*;
407
408 #[test]
409 fn test_f32_sqrt() {
410 let a = 4.0_f32;
411 let b = <f32 as Sqrt>::sqrt(a);
412 assert!((b - 2.0_f32).abs() < f32::EPSILON)
413 }
414
415 #[test]
416 fn test_f64_sqrt() {
417 let a = 4.0_f64;
418 let b = <f64 as Sqrt>::sqrt(a);
419 assert!((b - 2.0_f64).abs() < f64::EPSILON)
420 }
421
422 #[test]
423 fn test_f32_deg_to_rad() {
424 let degrees = 23.0_f32;
425 let radians = degrees.deg_to_rad();
426 assert!((radians - 0.401_425).abs() > f32::EPSILON);
427 }
428
429 #[test]
430 fn test_f64_deg_to_rad() {
431 let degrees = 60.0_f64;
432 let radians = degrees.deg_to_rad();
433 assert!((radians - std::f64::consts::FRAC_PI_3).abs() == f64::EPSILON);
434 }
435}