• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// Returns a very close approximation of `self.clamp(-1.0, 1.0).acos()`.
2 #[inline]
acos_approx_f32(v: f32) -> f323 fn acos_approx_f32(v: f32) -> f32 {
4     // Based on https://github.com/microsoft/DirectXMath `XMScalarAcos`
5     // Clamp input to [-1,1].
6     let nonnegative = v >= 0.0;
7     let x = abs(v);
8     let mut omx = 1.0 - x;
9     if omx < 0.0 {
10         omx = 0.0;
11     }
12     let root = sqrt(omx);
13 
14     // 7-degree minimax approximation
15     #[allow(clippy::approx_constant)]
16     let mut result =
17         ((((((-0.001_262_491_1 * x + 0.006_670_09) * x - 0.017_088_126) * x + 0.030_891_88) * x
18             - 0.050_174_303)
19             * x
20             + 0.088_978_99)
21             * x
22             - 0.214_598_8)
23             * x
24             + 1.570_796_3;
25     result *= root;
26 
27     // acos(x) = pi - acos(-x) when x < 0
28     if nonnegative {
29         result
30     } else {
31         core::f32::consts::PI - result
32     }
33 }
34 
35 #[cfg(feature = "libm")]
36 mod libm_math {
37     #[inline(always)]
abs(f: f32) -> f3238     pub(crate) fn abs(f: f32) -> f32 {
39         libm::fabsf(f)
40     }
41 
42     #[inline(always)]
acos_approx(f: f32) -> f3243     pub(crate) fn acos_approx(f: f32) -> f32 {
44         super::acos_approx_f32(f)
45     }
46 
47     #[inline(always)]
atan2(f: f32, other: f32) -> f3248     pub(crate) fn atan2(f: f32, other: f32) -> f32 {
49         libm::atan2f(f, other)
50     }
51 
52     #[allow(unused)]
53     #[inline(always)]
sin(f: f32) -> f3254     pub(crate) fn sin(f: f32) -> f32 {
55         libm::sinf(f)
56     }
57 
58     #[inline(always)]
sin_cos(f: f32) -> (f32, f32)59     pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
60         libm::sincosf(f)
61     }
62 
63     #[inline(always)]
tan(f: f32) -> f3264     pub(crate) fn tan(f: f32) -> f32 {
65         libm::tanf(f)
66     }
67 
68     #[inline(always)]
sqrt(f: f32) -> f3269     pub(crate) fn sqrt(f: f32) -> f32 {
70         libm::sqrtf(f)
71     }
72 
73     #[inline(always)]
copysign(f: f32, sign: f32) -> f3274     pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
75         libm::copysignf(f, sign)
76     }
77 
78     #[inline(always)]
signum(f: f32) -> f3279     pub(crate) fn signum(f: f32) -> f32 {
80         if f.is_nan() {
81             f32::NAN
82         } else {
83             copysign(1.0, f)
84         }
85     }
86 
87     #[inline(always)]
round(f: f32) -> f3288     pub(crate) fn round(f: f32) -> f32 {
89         libm::roundf(f)
90     }
91 
92     #[inline(always)]
trunc(f: f32) -> f3293     pub(crate) fn trunc(f: f32) -> f32 {
94         libm::truncf(f)
95     }
96 
97     #[inline(always)]
ceil(f: f32) -> f3298     pub(crate) fn ceil(f: f32) -> f32 {
99         libm::ceilf(f)
100     }
101 
102     #[inline(always)]
floor(f: f32) -> f32103     pub(crate) fn floor(f: f32) -> f32 {
104         libm::floorf(f)
105     }
106 
107     #[inline(always)]
exp(f: f32) -> f32108     pub(crate) fn exp(f: f32) -> f32 {
109         libm::expf(f)
110     }
111 
112     #[inline(always)]
powf(f: f32, n: f32) -> f32113     pub(crate) fn powf(f: f32, n: f32) -> f32 {
114         libm::powf(f, n)
115     }
116 
117     #[inline(always)]
mul_add(a: f32, b: f32, c: f32) -> f32118     pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
119         libm::fmaf(a, b, c)
120     }
121 
122     #[inline]
div_euclid(a: f32, b: f32) -> f32123     pub fn div_euclid(a: f32, b: f32) -> f32 {
124         // Based on https://doc.rust-lang.org/src/std/f32.rs.html#293
125         let q = libm::truncf(a / b);
126         if a % b < 0.0 {
127             return if b > 0.0 { q - 1.0 } else { q + 1.0 };
128         }
129         q
130     }
131 
132     #[inline]
rem_euclid(a: f32, b: f32) -> f32133     pub fn rem_euclid(a: f32, b: f32) -> f32 {
134         let r = a % b;
135         if r < 0.0 {
136             r + abs(b)
137         } else {
138             r
139         }
140     }
141 }
142 
143 #[cfg(all(not(feature = "libm"), feature = "std"))]
144 mod std_math {
145     #[inline(always)]
abs(f: f32) -> f32146     pub(crate) fn abs(f: f32) -> f32 {
147         f32::abs(f)
148     }
149 
150     #[inline(always)]
acos_approx(f: f32) -> f32151     pub(crate) fn acos_approx(f: f32) -> f32 {
152         super::acos_approx_f32(f)
153     }
154 
155     #[inline(always)]
atan2(f: f32, other: f32) -> f32156     pub(crate) fn atan2(f: f32, other: f32) -> f32 {
157         f32::atan2(f, other)
158     }
159 
160     #[allow(unused)]
161     #[inline(always)]
sin(f: f32) -> f32162     pub(crate) fn sin(f: f32) -> f32 {
163         f32::sin(f)
164     }
165 
166     #[inline(always)]
sin_cos(f: f32) -> (f32, f32)167     pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
168         f32::sin_cos(f)
169     }
170 
171     #[inline(always)]
tan(f: f32) -> f32172     pub(crate) fn tan(f: f32) -> f32 {
173         f32::tan(f)
174     }
175 
176     #[inline(always)]
sqrt(f: f32) -> f32177     pub(crate) fn sqrt(f: f32) -> f32 {
178         f32::sqrt(f)
179     }
180 
181     #[inline(always)]
copysign(f: f32, sign: f32) -> f32182     pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
183         f32::copysign(f, sign)
184     }
185 
186     #[inline(always)]
signum(f: f32) -> f32187     pub(crate) fn signum(f: f32) -> f32 {
188         f32::signum(f)
189     }
190 
191     #[inline(always)]
round(f: f32) -> f32192     pub(crate) fn round(f: f32) -> f32 {
193         f32::round(f)
194     }
195 
196     #[inline(always)]
trunc(f: f32) -> f32197     pub(crate) fn trunc(f: f32) -> f32 {
198         f32::trunc(f)
199     }
200 
201     #[inline(always)]
ceil(f: f32) -> f32202     pub(crate) fn ceil(f: f32) -> f32 {
203         f32::ceil(f)
204     }
205 
206     #[inline(always)]
floor(f: f32) -> f32207     pub(crate) fn floor(f: f32) -> f32 {
208         f32::floor(f)
209     }
210 
211     #[inline(always)]
exp(f: f32) -> f32212     pub(crate) fn exp(f: f32) -> f32 {
213         f32::exp(f)
214     }
215 
216     #[inline(always)]
powf(f: f32, n: f32) -> f32217     pub(crate) fn powf(f: f32, n: f32) -> f32 {
218         f32::powf(f, n)
219     }
220 
221     #[inline(always)]
mul_add(a: f32, b: f32, c: f32) -> f32222     pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
223         f32::mul_add(a, b, c)
224     }
225 
226     #[inline]
div_euclid(a: f32, b: f32) -> f32227     pub fn div_euclid(a: f32, b: f32) -> f32 {
228         f32::div_euclid(a, b)
229     }
230 
231     #[inline]
rem_euclid(a: f32, b: f32) -> f32232     pub fn rem_euclid(a: f32, b: f32) -> f32 {
233         f32::rem_euclid(a, b)
234     }
235 }
236 
237 // Used to reduce the number of compilation errors, in the event that no other
238 // math backend is specified.
239 #[cfg(all(not(feature = "libm"), not(feature = "std")))]
240 mod no_backend_math {
abs(_: f32) -> f32241     pub(crate) fn abs(_: f32) -> f32 {
242         unimplemented!()
243     }
244 
acos_approx(_: f32) -> f32245     pub(crate) fn acos_approx(_: f32) -> f32 {
246         unimplemented!()
247     }
248 
atan2(_: f32, _: f32) -> f32249     pub(crate) fn atan2(_: f32, _: f32) -> f32 {
250         unimplemented!()
251     }
252 
sin(_: f32) -> f32253     pub(crate) fn sin(_: f32) -> f32 {
254         unimplemented!()
255     }
256 
sin_cos(_: f32) -> (f32, f32)257     pub(crate) fn sin_cos(_: f32) -> (f32, f32) {
258         unimplemented!()
259     }
260 
tan(_: f32) -> f32261     pub(crate) fn tan(_: f32) -> f32 {
262         unimplemented!()
263     }
264 
sqrt(_: f32) -> f32265     pub(crate) fn sqrt(_: f32) -> f32 {
266         unimplemented!()
267     }
268 
copysign(_: f32, _: f32) -> f32269     pub(crate) fn copysign(_: f32, _: f32) -> f32 {
270         unimplemented!()
271     }
272 
signum(_: f32) -> f32273     pub(crate) fn signum(_: f32) -> f32 {
274         unimplemented!()
275     }
276 
round(_: f32) -> f32277     pub(crate) fn round(_: f32) -> f32 {
278         unimplemented!()
279     }
280 
trunc(_: f32) -> f32281     pub(crate) fn trunc(_: f32) -> f32 {
282         unimplemented!()
283     }
284 
ceil(_: f32) -> f32285     pub(crate) fn ceil(_: f32) -> f32 {
286         unimplemented!()
287     }
288 
floor(_: f32) -> f32289     pub(crate) fn floor(_: f32) -> f32 {
290         unimplemented!()
291     }
292 
exp(_: f32) -> f32293     pub(crate) fn exp(_: f32) -> f32 {
294         unimplemented!()
295     }
296 
powf(_: f32, _: f32) -> f32297     pub(crate) fn powf(_: f32, _: f32) -> f32 {
298         unimplemented!()
299     }
300 
mul_add(_: f32, _: f32, _: f32) -> f32301     pub(crate) fn mul_add(_: f32, _: f32, _: f32) -> f32 {
302         unimplemented!()
303     }
304 
div_euclid(_: f32, _: f32) -> f32305     pub fn div_euclid(_: f32, _: f32) -> f32 {
306         unimplemented!()
307     }
308 
rem_euclid(_: f32, _: f32) -> f32309     pub fn rem_euclid(_: f32, _: f32) -> f32 {
310         unimplemented!()
311     }
312 }
313 
314 #[cfg(feature = "libm")]
315 pub(crate) use libm_math::*;
316 
317 #[cfg(all(not(feature = "libm"), feature = "std"))]
318 pub(crate) use std_math::*;
319 
320 #[cfg(all(not(feature = "libm"), not(feature = "std")))]
321 pub(crate) use no_backend_math::*;
322