Skip to main content

libm/math/
mod.rs

1#![allow(clippy::approx_constant)] // many false positives
2
3macro_rules! force_eval {
4    ($e:expr) => {
5        unsafe { ::core::ptr::read_volatile(&$e) }
6    };
7}
8
9#[cfg(not(debug_assertions))]
10macro_rules! i {
11    ($array:expr, $index:expr) => {
12        unsafe { *$array.get_unchecked($index) }
13    };
14    ($array:expr, $index:expr, = , $rhs:expr) => {
15        unsafe {
16            *$array.get_unchecked_mut($index) = $rhs;
17        }
18    };
19    ($array:expr, $index:expr, += , $rhs:expr) => {
20        unsafe {
21            *$array.get_unchecked_mut($index) += $rhs;
22        }
23    };
24    ($array:expr, $index:expr, -= , $rhs:expr) => {
25        unsafe {
26            *$array.get_unchecked_mut($index) -= $rhs;
27        }
28    };
29    ($array:expr, $index:expr, &= , $rhs:expr) => {
30        unsafe {
31            *$array.get_unchecked_mut($index) &= $rhs;
32        }
33    };
34    ($array:expr, $index:expr, == , $rhs:expr) => {
35        unsafe { *$array.get_unchecked_mut($index) == $rhs }
36    };
37}
38
39#[cfg(debug_assertions)]
40macro_rules! i {
41    ($array:expr, $index:expr) => {
42        *$array.get($index).unwrap()
43    };
44    ($array:expr, $index:expr, = , $rhs:expr) => {
45        *$array.get_mut($index).unwrap() = $rhs;
46    };
47    ($array:expr, $index:expr, -= , $rhs:expr) => {
48        *$array.get_mut($index).unwrap() -= $rhs;
49    };
50    ($array:expr, $index:expr, += , $rhs:expr) => {
51        *$array.get_mut($index).unwrap() += $rhs;
52    };
53    ($array:expr, $index:expr, &= , $rhs:expr) => {
54        *$array.get_mut($index).unwrap() &= $rhs;
55    };
56    ($array:expr, $index:expr, == , $rhs:expr) => {
57        *$array.get_mut($index).unwrap() == $rhs
58    };
59}
60
61// Temporary macro to avoid panic codegen for division (in debug mode too). At
62// the time of this writing this is only used in a few places, and once
63// rust-lang/rust#72751 is fixed then this macro will no longer be necessary and
64// the native `/` operator can be used and panics won't be codegen'd.
65#[cfg(any(debug_assertions, not(intrinsics_enabled)))]
66macro_rules! div {
67    ($a:expr, $b:expr) => {
68        $a / $b
69    };
70}
71
72#[cfg(all(not(debug_assertions), intrinsics_enabled))]
73macro_rules! div {
74    ($a:expr, $b:expr) => {
75        unsafe { core::intrinsics::unchecked_div($a, $b) }
76    };
77}
78
79// `support` may be public for testing
80#[macro_use]
81#[cfg(feature = "unstable-public-internals")]
82pub mod support;
83
84#[macro_use]
85#[cfg(not(feature = "unstable-public-internals"))]
86pub(crate) mod support;
87
88cfg_if! {
89    if #[cfg(feature = "unstable-public-internals")] {
90        pub mod generic;
91    } else {
92        mod generic;
93    }
94}
95
96// Private modules
97mod arch;
98mod expo2;
99mod k_cos;
100mod k_cosf;
101mod k_expo2;
102mod k_expo2f;
103mod k_sin;
104mod k_sinf;
105mod k_tan;
106mod k_tanf;
107mod rem_pio2;
108mod rem_pio2_large;
109mod rem_pio2f;
110
111// Private re-imports
112use self::expo2::expo2;
113use self::k_cos::k_cos;
114use self::k_cosf::k_cosf;
115use self::k_expo2::k_expo2;
116use self::k_expo2f::k_expo2f;
117use self::k_sin::k_sin;
118use self::k_sinf::k_sinf;
119use self::k_tan::k_tan;
120use self::k_tanf::k_tanf;
121use self::rem_pio2::rem_pio2;
122use self::rem_pio2_large::rem_pio2_large;
123use self::rem_pio2f::rem_pio2f;
124#[allow(unused_imports)]
125use self::support::{CastFrom, CastInto, DFloat, DInt, Float, HFloat, HInt, Int, IntTy, MinInt};
126
127// Public modules
128mod acos;
129mod acosf;
130mod acosh;
131mod acoshf;
132mod asin;
133mod asinf;
134mod asinh;
135mod asinhf;
136mod atan;
137mod atan2;
138mod atan2f;
139mod atanf;
140mod atanh;
141mod atanhf;
142mod cbrt;
143mod cbrtf;
144mod ceil;
145mod copysign;
146mod cos;
147mod cosf;
148mod cosh;
149mod coshf;
150mod erf;
151mod erff;
152mod exp;
153mod exp10;
154mod exp10f;
155mod exp2;
156mod exp2f;
157mod expf;
158mod expm1;
159mod expm1f;
160mod fabs;
161mod fdim;
162mod floor;
163mod fma;
164mod fmin_fmax;
165mod fminimum_fmaximum;
166mod fminimum_fmaximum_num;
167mod fmod;
168mod frexp;
169mod frexpf;
170mod hypot;
171mod hypotf;
172mod ilogb;
173mod ilogbf;
174mod j0;
175mod j0f;
176mod j1;
177mod j1f;
178mod jn;
179mod jnf;
180mod ldexp;
181mod lgamma;
182mod lgamma_r;
183mod lgammaf;
184mod lgammaf_r;
185mod log;
186mod log10;
187mod log10f;
188mod log1p;
189mod log1pf;
190mod log2;
191mod log2f;
192mod logf;
193mod modf;
194mod modff;
195mod nextafter;
196mod nextafterf;
197mod pow;
198mod powf;
199mod remainder;
200mod remainderf;
201mod remquo;
202mod remquof;
203mod rint;
204mod round;
205mod roundeven;
206mod scalbn;
207mod sin;
208mod sincos;
209mod sincosf;
210mod sinf;
211mod sinh;
212mod sinhf;
213mod sqrt;
214mod tan;
215mod tanf;
216mod tanh;
217mod tanhf;
218mod tgamma;
219mod tgammaf;
220mod trunc;
221
222// Use separated imports instead of {}-grouped imports for easier merging.
223pub use self::acos::acos;
224pub use self::acosf::acosf;
225pub use self::acosh::acosh;
226pub use self::acoshf::acoshf;
227pub use self::asin::asin;
228pub use self::asinf::asinf;
229pub use self::asinh::asinh;
230pub use self::asinhf::asinhf;
231pub use self::atan::atan;
232pub use self::atan2::atan2;
233pub use self::atan2f::atan2f;
234pub use self::atanf::atanf;
235pub use self::atanh::atanh;
236pub use self::atanhf::atanhf;
237pub use self::cbrt::cbrt;
238pub use self::cbrtf::cbrtf;
239pub use self::ceil::{ceil, ceilf};
240pub use self::copysign::{copysign, copysignf};
241pub use self::cos::cos;
242pub use self::cosf::cosf;
243pub use self::cosh::cosh;
244pub use self::coshf::coshf;
245pub use self::erf::{erf, erfc};
246pub use self::erff::{erfcf, erff};
247pub use self::exp::exp;
248pub use self::exp2::exp2;
249pub use self::exp2f::exp2f;
250pub use self::exp10::exp10;
251pub use self::exp10f::exp10f;
252pub use self::expf::expf;
253pub use self::expm1::expm1;
254pub use self::expm1f::expm1f;
255pub use self::fabs::{fabs, fabsf};
256pub use self::fdim::{fdim, fdimf};
257pub use self::floor::{floor, floorf};
258pub use self::fma::{fma, fmaf};
259pub use self::fmin_fmax::{fmax, fmaxf, fmin, fminf};
260pub use self::fminimum_fmaximum::{fmaximum, fmaximumf, fminimum, fminimumf};
261pub use self::fminimum_fmaximum_num::{fmaximum_num, fmaximum_numf, fminimum_num, fminimum_numf};
262pub use self::fmod::{fmod, fmodf};
263pub use self::frexp::frexp;
264pub use self::frexpf::frexpf;
265pub use self::hypot::hypot;
266pub use self::hypotf::hypotf;
267pub use self::ilogb::ilogb;
268pub use self::ilogbf::ilogbf;
269pub use self::j0::{j0, y0};
270pub use self::j0f::{j0f, y0f};
271pub use self::j1::{j1, y1};
272pub use self::j1f::{j1f, y1f};
273pub use self::jn::{jn, yn};
274pub use self::jnf::{jnf, ynf};
275pub use self::ldexp::{ldexp, ldexpf};
276pub use self::lgamma::lgamma;
277pub use self::lgamma_r::lgamma_r;
278pub use self::lgammaf::lgammaf;
279pub use self::lgammaf_r::lgammaf_r;
280pub use self::log::log;
281pub use self::log1p::log1p;
282pub use self::log1pf::log1pf;
283pub use self::log2::log2;
284pub use self::log2f::log2f;
285pub use self::log10::log10;
286pub use self::log10f::log10f;
287pub use self::logf::logf;
288pub use self::modf::modf;
289pub use self::modff::modff;
290pub use self::nextafter::nextafter;
291pub use self::nextafterf::nextafterf;
292pub use self::pow::pow;
293pub use self::powf::powf;
294pub use self::remainder::remainder;
295pub use self::remainderf::remainderf;
296pub use self::remquo::remquo;
297pub use self::remquof::remquof;
298pub use self::rint::{rint, rintf};
299pub use self::round::{round, roundf};
300pub use self::roundeven::{roundeven, roundevenf};
301pub use self::scalbn::{scalbn, scalbnf};
302pub use self::sin::sin;
303pub use self::sincos::sincos;
304pub use self::sincosf::sincosf;
305pub use self::sinf::sinf;
306pub use self::sinh::sinh;
307pub use self::sinhf::sinhf;
308pub use self::sqrt::{sqrt, sqrtf};
309pub use self::tan::tan;
310pub use self::tanf::tanf;
311pub use self::tanh::tanh;
312pub use self::tanhf::tanhf;
313pub use self::tgamma::tgamma;
314pub use self::tgammaf::tgammaf;
315pub use self::trunc::{trunc, truncf};
316
317cfg_if! {
318    if #[cfg(f16_enabled)] {
319        // verify-sorted-start
320        pub use self::ceil::ceilf16;
321        pub use self::copysign::copysignf16;
322        pub use self::fabs::fabsf16;
323        pub use self::fdim::fdimf16;
324        pub use self::floor::floorf16;
325        pub use self::fmin_fmax::{fmaxf16, fminf16};
326        pub use self::fminimum_fmaximum::{fmaximumf16, fminimumf16};
327        pub use self::fminimum_fmaximum_num::{fmaximum_numf16, fminimum_numf16};
328        pub use self::fmod::fmodf16;
329        pub use self::ldexp::ldexpf16;
330        pub use self::rint::rintf16;
331        pub use self::round::roundf16;
332        pub use self::roundeven::roundevenf16;
333        pub use self::scalbn::scalbnf16;
334        pub use self::sqrt::sqrtf16;
335        pub use self::trunc::truncf16;
336        // verify-sorted-end
337
338        #[allow(unused_imports)]
339        pub(crate) use self::fma::fmaf16;
340    }
341}
342
343cfg_if! {
344    if #[cfg(f128_enabled)] {
345        // verify-sorted-start
346        pub use self::ceil::ceilf128;
347        pub use self::copysign::copysignf128;
348        pub use self::fabs::fabsf128;
349        pub use self::fdim::fdimf128;
350        pub use self::floor::floorf128;
351        pub use self::fma::fmaf128;
352        pub use self::fmin_fmax::{fmaxf128, fminf128};
353        pub use self::fminimum_fmaximum::{fmaximumf128, fminimumf128};
354        pub use self::fminimum_fmaximum_num::{fmaximum_numf128, fminimum_numf128};
355        pub use self::fmod::fmodf128;
356        pub use self::ldexp::ldexpf128;
357        pub use self::rint::rintf128;
358        pub use self::round::roundf128;
359        pub use self::roundeven::roundevenf128;
360        pub use self::scalbn::scalbnf128;
361        pub use self::sqrt::sqrtf128;
362        pub use self::trunc::truncf128;
363        // verify-sorted-end
364    }
365}
366
367#[inline]
368fn get_high_word(x: f64) -> u32 {
369    (x.to_bits() >> 32) as u32
370}
371
372#[inline]
373fn get_low_word(x: f64) -> u32 {
374    x.to_bits() as u32
375}
376
377#[inline]
378fn with_set_high_word(f: f64, hi: u32) -> f64 {
379    let mut tmp = f.to_bits();
380    tmp &= 0x00000000_ffffffff;
381    tmp |= (hi as u64) << 32;
382    f64::from_bits(tmp)
383}
384
385#[inline]
386fn with_set_low_word(f: f64, lo: u32) -> f64 {
387    let mut tmp = f.to_bits();
388    tmp &= 0xffffffff_00000000;
389    tmp |= lo as u64;
390    f64::from_bits(tmp)
391}
392
393#[inline]
394fn combine_words(hi: u32, lo: u32) -> f64 {
395    f64::from_bits(((hi as u64) << 32) | lo as u64)
396}