1pub trait FloatMath: Sized {
5 fn abs(self) -> Self;
6 fn sin(self) -> Self;
7 fn cos(self) -> Self;
8 fn tan(self) -> Self;
9 fn sqrt(self) -> Self;
10 fn ln(self) -> Self;
11 fn log10(self) -> Self;
12 fn exp(self) -> Self;
13 fn atan2(self, x: Self) -> Self;
14 fn powf(self, n: Self) -> Self;
15 fn tanh(self) -> Self;
16}
17
18impl FloatMath for f32 {
19 #[inline(always)]
20 fn abs(self) -> f32 {
21 #[cfg(feature = "std")]
22 {
23 self.abs()
24 }
25 #[cfg(all(not(feature = "std"), feature = "libm"))]
26 {
27 libm::fabsf(self)
28 }
29 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
30 {
31 f32::from_bits(self.to_bits() & 0x7FFF_FFFF)
32 }
33 }
34
35 #[inline(always)]
36 fn sin(self) -> f32 {
37 #[cfg(feature = "std")]
38 {
39 self.sin()
40 }
41 #[cfg(all(not(feature = "std"), feature = "libm"))]
42 {
43 libm::sinf(self)
44 }
45 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
46 {
47 core::compile_error!(
48 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
49 );
50 }
51 }
52
53 #[inline(always)]
54 fn cos(self) -> f32 {
55 #[cfg(feature = "std")]
56 {
57 self.cos()
58 }
59 #[cfg(all(not(feature = "std"), feature = "libm"))]
60 {
61 libm::cosf(self)
62 }
63 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
64 {
65 core::compile_error!(
66 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
67 );
68 }
69 }
70
71 #[inline(always)]
72 fn tan(self) -> f32 {
73 #[cfg(feature = "std")]
74 {
75 self.tan()
76 }
77 #[cfg(all(not(feature = "std"), feature = "libm"))]
78 {
79 libm::tanf(self)
80 }
81 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
82 {
83 core::compile_error!(
84 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
85 );
86 }
87 }
88
89 #[inline(always)]
90 fn sqrt(self) -> f32 {
91 #[cfg(feature = "std")]
92 {
93 self.sqrt()
94 }
95 #[cfg(all(not(feature = "std"), feature = "libm"))]
96 {
97 libm::sqrtf(self)
98 }
99 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
100 {
101 core::compile_error!(
102 "Either feature 'std' or feature 'libm' must be enabled for floating-point sqrt."
103 );
104 }
105 }
106
107 #[inline(always)]
108 fn ln(self) -> f32 {
109 #[cfg(feature = "std")]
110 {
111 self.ln()
112 }
113 #[cfg(all(not(feature = "std"), feature = "libm"))]
114 {
115 libm::logf(self)
116 }
117 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
118 {
119 core::compile_error!(
120 "Either feature 'std' or feature 'libm' must be enabled for floating-point log."
121 );
122 }
123 }
124
125 #[inline(always)]
126 fn log10(self) -> f32 {
127 #[cfg(feature = "std")]
128 {
129 self.log10()
130 }
131 #[cfg(all(not(feature = "std"), feature = "libm"))]
132 {
133 libm::log10f(self)
134 }
135 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
136 {
137 core::compile_error!(
138 "Either feature 'std' or feature 'libm' must be enabled for floating-point log10."
139 );
140 }
141 }
142
143 #[inline(always)]
144 fn exp(self) -> f32 {
145 #[cfg(feature = "std")]
146 {
147 self.exp()
148 }
149 #[cfg(all(not(feature = "std"), feature = "libm"))]
150 {
151 libm::expf(self)
152 }
153 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
154 {
155 core::compile_error!(
156 "Either feature 'std' or feature 'libm' must be enabled for floating-point exp."
157 );
158 }
159 }
160
161 #[inline(always)]
162 fn atan2(self, x: f32) -> f32 {
163 #[cfg(feature = "std")]
164 {
165 self.atan2(x)
166 }
167 #[cfg(all(not(feature = "std"), feature = "libm"))]
168 {
169 libm::atan2f(self, x)
170 }
171 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
172 {
173 core::compile_error!(
174 "Either feature 'std' or feature 'libm' must be enabled for floating-point atan2."
175 );
176 }
177 }
178
179 #[inline(always)]
180 fn powf(self, n: f32) -> f32 {
181 #[cfg(feature = "std")]
182 {
183 self.powf(n)
184 }
185 #[cfg(all(not(feature = "std"), feature = "libm"))]
186 {
187 libm::powf(self, n)
188 }
189 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
190 {
191 core::compile_error!(
192 "Either feature 'std' or feature 'libm' must be enabled for floating-point powf."
193 );
194 }
195 }
196
197 #[inline(always)]
198 fn tanh(self) -> f32 {
199 #[cfg(feature = "std")]
200 {
201 self.tanh()
202 }
203 #[cfg(all(not(feature = "std"), feature = "libm"))]
204 {
205 libm::tanhf(self)
206 }
207 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
208 {
209 core::compile_error!(
210 "Either feature 'std' or feature 'libm' must be enabled for floating-point tanh."
211 );
212 }
213 }
214}
215
216impl FloatMath for f64 {
217 #[inline(always)]
218 fn abs(self) -> f64 {
219 #[cfg(feature = "std")]
220 {
221 self.abs()
222 }
223 #[cfg(all(not(feature = "std"), feature = "libm"))]
224 {
225 libm::fabs(self)
226 }
227 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
228 {
229 f64::from_bits(self.to_bits() & 0x7FFF_FFFF_FFFF_FFFF)
230 }
231 }
232
233 #[inline(always)]
234 fn sin(self) -> f64 {
235 #[cfg(feature = "std")]
236 {
237 self.sin()
238 }
239 #[cfg(all(not(feature = "std"), feature = "libm"))]
240 {
241 libm::sin(self)
242 }
243 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
244 {
245 core::compile_error!(
246 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
247 );
248 }
249 }
250
251 #[inline(always)]
252 fn cos(self) -> f64 {
253 #[cfg(feature = "std")]
254 {
255 self.cos()
256 }
257 #[cfg(all(not(feature = "std"), feature = "libm"))]
258 {
259 libm::cos(self)
260 }
261 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
262 {
263 core::compile_error!(
264 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
265 );
266 }
267 }
268
269 #[inline(always)]
270 fn tan(self) -> f64 {
271 #[cfg(feature = "std")]
272 {
273 self.tan()
274 }
275 #[cfg(all(not(feature = "std"), feature = "libm"))]
276 {
277 libm::tan(self)
278 }
279 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
280 {
281 core::compile_error!(
282 "Either feature 'std' or feature 'libm' must be enabled for floating-point trig functions."
283 );
284 }
285 }
286
287 #[inline(always)]
288 fn sqrt(self) -> f64 {
289 #[cfg(feature = "std")]
290 {
291 self.sqrt()
292 }
293 #[cfg(all(not(feature = "std"), feature = "libm"))]
294 {
295 libm::sqrt(self)
296 }
297 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
298 {
299 core::compile_error!(
300 "Either feature 'std' or feature 'libm' must be enabled for floating-point sqrt."
301 );
302 }
303 }
304
305 #[inline(always)]
306 fn ln(self) -> f64 {
307 #[cfg(feature = "std")]
308 {
309 self.ln()
310 }
311 #[cfg(all(not(feature = "std"), feature = "libm"))]
312 {
313 libm::log(self)
314 }
315 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
316 {
317 core::compile_error!(
318 "Either feature 'std' or feature 'libm' must be enabled for floating-point log."
319 );
320 }
321 }
322
323 #[inline(always)]
324 fn log10(self) -> f64 {
325 #[cfg(feature = "std")]
326 {
327 self.log10()
328 }
329 #[cfg(all(not(feature = "std"), feature = "libm"))]
330 {
331 libm::log10(self)
332 }
333 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
334 {
335 core::compile_error!(
336 "Either feature 'std' or feature 'libm' must be enabled for floating-point log10."
337 );
338 }
339 }
340
341 #[inline(always)]
342 fn exp(self) -> f64 {
343 #[cfg(feature = "std")]
344 {
345 self.exp()
346 }
347 #[cfg(all(not(feature = "std"), feature = "libm"))]
348 {
349 libm::exp(self)
350 }
351 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
352 {
353 core::compile_error!(
354 "Either feature 'std' or feature 'libm' must be enabled for floating-point exp."
355 );
356 }
357 }
358
359 #[inline(always)]
360 fn atan2(self, x: f64) -> f64 {
361 #[cfg(feature = "std")]
362 {
363 self.atan2(x)
364 }
365 #[cfg(all(not(feature = "std"), feature = "libm"))]
366 {
367 libm::atan2(self, x)
368 }
369 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
370 {
371 core::compile_error!(
372 "Either feature 'std' or feature 'libm' must be enabled for floating-point atan2."
373 );
374 }
375 }
376
377 #[inline(always)]
378 fn powf(self, n: f64) -> f64 {
379 #[cfg(feature = "std")]
380 {
381 self.powf(n)
382 }
383 #[cfg(all(not(feature = "std"), feature = "libm"))]
384 {
385 libm::pow(self, n)
386 }
387 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
388 {
389 core::compile_error!(
390 "Either feature 'std' or feature 'libm' must be enabled for floating-point powf."
391 );
392 }
393 }
394
395 #[inline(always)]
396 fn tanh(self) -> f64 {
397 #[cfg(feature = "std")]
398 {
399 self.tanh()
400 }
401 #[cfg(all(not(feature = "std"), feature = "libm"))]
402 {
403 libm::tanh(self)
404 }
405 #[cfg(all(not(feature = "std"), not(feature = "libm")))]
406 {
407 core::compile_error!(
408 "Either feature 'std' or feature 'libm' must be enabled for floating-point tanh."
409 );
410 }
411 }
412}
413
414#[inline]
416pub(crate) fn isqrt_u32(n: u32) -> u32 {
417 if n <= 1 {
418 return n;
419 }
420 let mut x = n;
421 let mut y = (x + 1) / 2;
422 while y < x {
423 x = y;
424 y = x.saturating_add(n / x) / 2;
425 }
426 x
427}
428
429#[inline]
431pub(crate) fn isqrt_u64(n: u64) -> u64 {
432 if n <= 1 {
433 return n;
434 }
435 let mut x = n;
436 let mut y = (x + 1) / 2;
437 while y < x {
438 x = y;
439 y = x.saturating_add(n / x) / 2;
440 }
441 x
442}