-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlib.rs
More file actions
108 lines (98 loc) · 3.41 KB
/
lib.rs
File metadata and controls
108 lines (98 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Public modules
#[cfg(feature = "complex")]
pub mod cmath;
pub mod math;
// Internal modules
mod err;
// Native libm via FFI (unix/windows)
#[cfg(any(unix, windows))]
pub(crate) mod m;
// Pure Rust libm for WASM and other targets
#[cfg(not(any(unix, windows)))]
#[path = "m_rust.rs"]
pub(crate) mod m;
#[cfg(any(unix, windows))]
mod m_sys;
#[cfg(test)]
mod test;
// Re-export error types at root level
pub use err::{Error, Result};
/// Fused multiply-add operation.
/// When `mul_add` feature is enabled, uses hardware FMA instruction.
/// Otherwise, uses separate multiply and add operations.
#[inline(always)]
pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 {
if cfg!(feature = "mul_add") {
a.mul_add(b, c)
} else {
a * b + c
}
}
macro_rules! pyo3_proptest {
($fn_name:ident(Result<_>), $test_name:ident, $proptest_name:ident, $edgetest_name:ident) => {
#[cfg(test)]
fn $test_name(x: f64) {
use pyo3::prelude::*;
let rs_result = $fn_name(x);
pyo3::Python::attach(|py| {
let math = PyModule::import(py, "math").unwrap();
let py_func = math
.getattr(stringify!($fn_name))
.unwrap();
let r = py_func.call1((x,));
let Some((py_result, rs_result)) = crate::test::unwrap(py, r, rs_result) else {
return;
};
let py_result_repr = py_result.to_bits();
let rs_result_repr = rs_result.to_bits();
assert_eq!(py_result_repr, rs_result_repr, "x = {x}, py_result = {py_result}, rs_result = {rs_result}");
});
}
crate::pyo3_proptest!(@proptest, $test_name, $proptest_name);
crate::pyo3_proptest!(@edgetest, $test_name, $edgetest_name);
};
($fn_name:ident(_), $test_name:ident, $proptest_name:ident, $edgetest_name:ident) => {
#[cfg(test)]
fn $test_name(x: f64) {
use pyo3::prelude::*;
let rs_result = Ok($fn_name(x));
pyo3::Python::attach(|py| {
let math = PyModule::import(py, "math").unwrap();
let py_func = math
.getattr(stringify!($fn_name))
.unwrap();
let r = py_func.call1((x,));
let Some((py_result, rs_result)) = crate::test::unwrap(py, r, rs_result) else {
return;
};
let py_result_repr = py_result.to_bits();
let rs_result_repr = rs_result.to_bits();
assert_eq!(py_result_repr, rs_result_repr, "x = {x}, py_result = {py_result}, rs_result = {rs_result}");
});
}
crate::pyo3_proptest!(@proptest, $test_name, $proptest_name);
};
(@proptest, $test_name:ident, $proptest_name:ident) => {
#[cfg(test)]
proptest::proptest! {
#[test]
fn $proptest_name(x: f64) {
$test_name(x);
}
}
};
(@edgetest, $test_name:ident, $edgetest_name:ident) => {
#[test]
fn $edgetest_name() {
$test_name(f64::MIN);
$test_name(-f64::MIN);
$test_name(f64::NAN);
$test_name(-f64::NAN);
$test_name(f64::INFINITY);
$test_name(-f64::NEG_INFINITY);
$test_name(0.0);
$test_name(-0.0);
}
};
}
use pyo3_proptest;