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;
29 const ONE: Self;
30 const MIN: Self;
31 const MAX: Self;
32
33 fn abs(self) -> Self;
34 fn min(self, other: Self) -> Self;
35 fn max(self, other: Self) -> Self;
36 fn clamp(self, min: Self, max: Self) -> Self;
37}
38
39pub trait Transcendental: Scalar {
44 const PI: Self;
45
46 fn to_f32(self) -> f32;
47 fn from_f32(value: f32) -> Self;
48
49 fn to_f64(self) -> f64 {
50 self.to_f32() as f64
51 }
52
53 fn from_f64(value: f64) -> Self {
54 Self::from_f32(value as f32)
55 }
56
57 fn sqrt(self) -> Self;
58 fn exp(self) -> Self;
59 fn ln(self) -> Self;
60 fn sin(self) -> Self;
61 fn cos(self) -> Self;
62 fn tan(self) -> Self;
63}
64
65impl Scalar for f32 {
70 const ZERO: f32 = 0.0;
71 const ONE: f32 = 1.0;
72 const MIN: f32 = -1.0;
73 const MAX: f32 = 1.0;
74
75 #[inline(always)]
76 fn abs(self) -> f32 { self.abs() }
77
78 #[inline(always)]
79 fn min(self, other: f32) -> f32 { self.min(other) }
80
81 #[inline(always)]
82 fn max(self, other: f32) -> f32 { self.max(other) }
83
84 #[inline(always)]
85 fn clamp(self, min: f32, max: f32) -> f32 { self.clamp(min, max) }
86}
87
88impl Transcendental for f32 {
89 const PI: f32 = std::f32::consts::PI;
90
91 #[inline(always)]
92 fn to_f32(self) -> f32 { self }
93
94 #[inline(always)]
95 fn from_f32(value: f32) -> f32 { value }
96
97 #[inline(always)]
98 fn from_f64(value: f64) -> f32 { value as f32 }
99
100 #[inline(always)]
101 fn sqrt(self) -> f32 { self.sqrt() }
102
103 #[inline(always)]
104 fn exp(self) -> f32 { self.exp() }
105
106 #[inline(always)]
107 fn ln(self) -> f32 { self.ln() }
108
109 #[inline(always)]
110 fn sin(self) -> f32 { self.sin() }
111
112 #[inline(always)]
113 fn cos(self) -> f32 { self.cos() }
114
115 #[inline(always)]
116 fn tan(self) -> f32 { self.tan() }
117}
118
119impl Scalar for f64 {
124 const ZERO: f64 = 0.0;
125 const ONE: f64 = 1.0;
126 const MIN: f64 = -1.0;
127 const MAX: f64 = 1.0;
128
129 #[inline(always)]
130 fn abs(self) -> f64 { self.abs() }
131
132 #[inline(always)]
133 fn min(self, other: f64) -> f64 { self.min(other) }
134
135 #[inline(always)]
136 fn max(self, other: f64) -> f64 { self.max(other) }
137
138 #[inline(always)]
139 fn clamp(self, min: f64, max: f64) -> f64 { self.clamp(min, max) }
140}
141
142impl Transcendental for f64 {
143 const PI: f64 = std::f64::consts::PI;
144
145 #[inline(always)]
146 fn to_f32(self) -> f32 { self as f32 }
147
148 #[inline(always)]
149 fn from_f32(value: f32) -> f64 { value as f64 }
150
151 #[inline(always)]
152 fn from_f64(value: f64) -> f64 { value }
153
154 #[inline(always)]
155 fn sqrt(self) -> f64 { self.sqrt() }
156
157 #[inline(always)]
158 fn exp(self) -> f64 { self.exp() }
159
160 #[inline(always)]
161 fn ln(self) -> f64 { self.ln() }
162
163 #[inline(always)]
164 fn sin(self) -> f64 { self.sin() }
165
166 #[inline(always)]
167 fn cos(self) -> f64 { self.cos() }
168
169 #[inline(always)]
170 fn tan(self) -> f64 { self.tan() }
171}
172
173macro_rules! impl_scalar_int {
178 ($ty:ty, $zero:expr, $one:expr, $min:expr, $max:expr) => {
179 impl Scalar for $ty {
180 const ZERO: $ty = $zero;
181 const ONE: $ty = $one;
182 const MIN: $ty = $min;
183 const MAX: $ty = $max;
184
185 #[inline(always)]
186 fn abs(self) -> $ty { if self >= 0 { self } else { -self } }
187
188 #[inline(always)]
189 fn min(self, other: $ty) -> $ty { core::cmp::Ord::min(self, other) }
190
191 #[inline(always)]
192 fn max(self, other: $ty) -> $ty { core::cmp::Ord::max(self, other) }
193
194 #[inline(always)]
195 fn clamp(self, lo: $ty, hi: $ty) -> $ty { core::cmp::Ord::clamp(self, lo, hi) }
196 }
197 };
198}
199
200impl_scalar_int!(i8, 0, 1, i8::MIN, i8::MAX);
201impl_scalar_int!(i16, 0, 1, i16::MIN, i16::MAX);
202impl_scalar_int!(i32, 0, 1, i32::MIN, i32::MAX);
203impl_scalar_int!(i64, 0, 1, i64::MIN, i64::MAX);