1#[inline]
14pub fn floor(x: f64) -> f64 {
15 #[cfg(feature = "std")]
16 {
17 x.floor()
18 }
19 #[cfg(not(feature = "std"))]
20 {
21 libm::floor(x)
22 }
23}
24
25#[inline]
27pub fn round(x: f64) -> f64 {
28 #[cfg(feature = "std")]
29 {
30 x.round()
31 }
32 #[cfg(not(feature = "std"))]
33 {
34 libm::round(x)
35 }
36}
37
38#[inline]
40pub fn trunc(x: f64) -> f64 {
41 #[cfg(feature = "std")]
42 {
43 x.trunc()
44 }
45 #[cfg(not(feature = "std"))]
46 {
47 libm::trunc(x)
48 }
49}
50
51#[inline]
53pub fn fract(x: f64) -> f64 {
54 #[cfg(feature = "std")]
55 {
56 x.fract()
57 }
58 #[cfg(not(feature = "std"))]
59 {
60 x - libm::trunc(x)
61 }
62}
63
64#[inline]
69pub fn abs(x: f64) -> f64 {
70 #[cfg(feature = "std")]
71 {
72 x.abs()
73 }
74 #[cfg(not(feature = "std"))]
75 {
76 libm::fabs(x)
77 }
78}
79
80#[inline]
82pub fn signum(x: f64) -> f64 {
83 #[cfg(feature = "std")]
84 {
85 x.signum()
86 }
87 #[cfg(not(feature = "std"))]
88 {
89 if x.is_nan() {
90 f64::NAN
91 } else {
92 libm::copysign(1.0, x)
93 }
94 }
95}
96
97#[inline]
99pub fn sqrt(x: f64) -> f64 {
100 #[cfg(feature = "std")]
101 {
102 x.sqrt()
103 }
104 #[cfg(not(feature = "std"))]
105 {
106 libm::sqrt(x)
107 }
108}
109
110#[inline]
112pub fn cbrt(x: f64) -> f64 {
113 #[cfg(feature = "std")]
114 {
115 x.cbrt()
116 }
117 #[cfg(not(feature = "std"))]
118 {
119 libm::cbrt(x)
120 }
121}
122
123#[inline]
125pub fn powi(x: f64, n: i32) -> f64 {
126 #[cfg(feature = "std")]
127 {
128 x.powi(n)
129 }
130 #[cfg(not(feature = "std"))]
131 {
132 libm::pow(x, n as f64)
133 }
134}
135
136#[inline]
138pub fn powf(x: f64, n: f64) -> f64 {
139 #[cfg(feature = "std")]
140 {
141 x.powf(n)
142 }
143 #[cfg(not(feature = "std"))]
144 {
145 libm::pow(x, n)
146 }
147}
148
149#[inline]
151pub fn mul_add(a: f64, b: f64, c: f64) -> f64 {
152 #[cfg(feature = "std")]
153 {
154 a.mul_add(b, c)
155 }
156 #[cfg(not(feature = "std"))]
157 {
158 libm::fma(a, b, c)
159 }
160}
161
162#[inline]
167pub fn sin(x: f64) -> f64 {
168 #[cfg(feature = "std")]
169 {
170 x.sin()
171 }
172 #[cfg(not(feature = "std"))]
173 {
174 libm::sin(x)
175 }
176}
177
178#[inline]
180pub fn cos(x: f64) -> f64 {
181 #[cfg(feature = "std")]
182 {
183 x.cos()
184 }
185 #[cfg(not(feature = "std"))]
186 {
187 libm::cos(x)
188 }
189}
190
191#[inline]
193pub fn tan(x: f64) -> f64 {
194 #[cfg(feature = "std")]
195 {
196 x.tan()
197 }
198 #[cfg(not(feature = "std"))]
199 {
200 libm::tan(x)
201 }
202}
203
204#[inline]
206pub fn sin_cos(x: f64) -> (f64, f64) {
207 #[cfg(feature = "std")]
208 {
209 x.sin_cos()
210 }
211 #[cfg(not(feature = "std"))]
212 {
213 libm::sincos(x)
214 }
215}
216
217#[inline]
219pub fn asin(x: f64) -> f64 {
220 #[cfg(feature = "std")]
221 {
222 x.asin()
223 }
224 #[cfg(not(feature = "std"))]
225 {
226 libm::asin(x)
227 }
228}
229
230#[inline]
232pub fn acos(x: f64) -> f64 {
233 #[cfg(feature = "std")]
234 {
235 x.acos()
236 }
237 #[cfg(not(feature = "std"))]
238 {
239 libm::acos(x)
240 }
241}
242
243#[inline]
245pub fn atan(x: f64) -> f64 {
246 #[cfg(feature = "std")]
247 {
248 x.atan()
249 }
250 #[cfg(not(feature = "std"))]
251 {
252 libm::atan(x)
253 }
254}
255
256#[inline]
258pub fn atan2(y: f64, x: f64) -> f64 {
259 #[cfg(feature = "std")]
260 {
261 y.atan2(x)
262 }
263 #[cfg(not(feature = "std"))]
264 {
265 libm::atan2(y, x)
266 }
267}
268
269#[inline]
274pub fn sinh(x: f64) -> f64 {
275 #[cfg(feature = "std")]
276 {
277 x.sinh()
278 }
279 #[cfg(not(feature = "std"))]
280 {
281 libm::sinh(x)
282 }
283}
284
285#[inline]
287pub fn cosh(x: f64) -> f64 {
288 #[cfg(feature = "std")]
289 {
290 x.cosh()
291 }
292 #[cfg(not(feature = "std"))]
293 {
294 libm::cosh(x)
295 }
296}
297
298#[inline]
300pub fn tanh(x: f64) -> f64 {
301 #[cfg(feature = "std")]
302 {
303 x.tanh()
304 }
305 #[cfg(not(feature = "std"))]
306 {
307 libm::tanh(x)
308 }
309}
310
311#[inline]
313pub fn asinh(x: f64) -> f64 {
314 #[cfg(feature = "std")]
315 {
316 x.asinh()
317 }
318 #[cfg(not(feature = "std"))]
319 {
320 libm::asinh(x)
321 }
322}
323
324#[inline]
326pub fn acosh(x: f64) -> f64 {
327 #[cfg(feature = "std")]
328 {
329 x.acosh()
330 }
331 #[cfg(not(feature = "std"))]
332 {
333 libm::acosh(x)
334 }
335}
336
337#[inline]
339pub fn atanh(x: f64) -> f64 {
340 #[cfg(feature = "std")]
341 {
342 x.atanh()
343 }
344 #[cfg(not(feature = "std"))]
345 {
346 libm::atanh(x)
347 }
348}
349
350#[inline]
355pub fn ln(x: f64) -> f64 {
356 #[cfg(feature = "std")]
357 {
358 x.ln()
359 }
360 #[cfg(not(feature = "std"))]
361 {
362 libm::log(x)
363 }
364}
365
366#[inline]
368pub fn log10(x: f64) -> f64 {
369 #[cfg(feature = "std")]
370 {
371 x.log10()
372 }
373 #[cfg(not(feature = "std"))]
374 {
375 libm::log10(x)
376 }
377}
378
379#[inline]
384pub const fn to_degrees(x: f64) -> f64 {
385 x * (180.0 / core::f64::consts::PI)
386}
387
388#[inline]
390pub const fn to_radians(x: f64) -> f64 {
391 x * (core::f64::consts::PI / 180.0)
392}
393
394#[cfg(test)]
395mod tests {
396 use super::*;
397
398 #[test]
399 fn test_sqrt() {
400 assert!(abs(sqrt(2.0) - core::f64::consts::SQRT_2) < 1e-15);
401 }
402
403 #[test]
404 fn test_sin_cos_matches() {
405 let (s, c) = sin_cos(0.5);
406 assert!(abs(s - sin(0.5)) < 1e-15);
407 assert!(abs(c - cos(0.5)) < 1e-15);
408 }
409
410 #[test]
411 fn test_atan2() {
412 assert!(abs(atan2(1.0, 1.0) - core::f64::consts::FRAC_PI_4) < 1e-15);
413 }
414}