@@ -28,14 +28,41 @@ pub fn phase(z: Complex64) -> Result<f64> {
2828 }
2929}
3030
31+ #[ inline]
32+ fn c_abs_raw ( z : Complex64 ) -> f64 {
33+ if !z. re . is_finite ( ) || !z. im . is_finite ( ) {
34+ // C99 rules: if either part is infinite, return infinity,
35+ // even if the other part is NaN.
36+ if z. re . is_infinite ( ) {
37+ return m:: fabs ( z. re ) ;
38+ }
39+ if z. im . is_infinite ( ) {
40+ return m:: fabs ( z. im ) ;
41+ }
42+ return f64:: NAN ;
43+ }
44+ m:: hypot ( z. re , z. im )
45+ }
46+
47+ #[ inline]
48+ fn c_abs_checked ( z : Complex64 ) -> Result < f64 > {
49+ if !z. re . is_finite ( ) || !z. im . is_finite ( ) {
50+ return Ok ( c_abs_raw ( z) ) ;
51+ }
52+ crate :: err:: set_errno ( 0 ) ;
53+ let r = m:: hypot ( z. re , z. im ) ;
54+ if r. is_infinite ( ) {
55+ Err ( Error :: ERANGE )
56+ } else {
57+ Ok ( r)
58+ }
59+ }
60+
3161/// Convert z to polar coordinates (r, phi).
3262#[ inline]
3363pub fn polar ( z : Complex64 ) -> Result < ( f64 , f64 ) > {
3464 let phi = m:: atan2 ( z. im , z. re ) ;
35- let r = m:: hypot ( z. re , z. im ) ;
36- if r. is_infinite ( ) && z. re . is_finite ( ) && z. im . is_finite ( ) {
37- return Err ( Error :: ERANGE ) ;
38- }
65+ let r = c_abs_checked ( z) ?;
3966 Ok ( ( r, phi) )
4067}
4168
@@ -94,7 +121,7 @@ pub fn isinf(z: Complex64) -> bool {
94121/// Complex absolute value (magnitude).
95122#[ inline]
96123pub fn abs ( z : Complex64 ) -> f64 {
97- m :: hypot ( z . re , z . im )
124+ c_abs_raw ( z )
98125}
99126
100127/// Determine whether two complex numbers are close in value.
@@ -169,8 +196,7 @@ mod tests {
169196 }
170197 Err ( e) => {
171198 // Python raised an exception - check we got an error too
172- if rs_result. is_ok ( ) {
173- let rs_val = rs_result. unwrap ( ) ;
199+ if let Ok ( rs_val) = rs_result {
174200 if e. is_instance_of :: < pyo3:: exceptions:: PyValueError > ( py) {
175201 panic ! ( "phase({re}, {im}): py raised ValueError but rs={rs_val}" ) ;
176202 } else if e. is_instance_of :: < pyo3:: exceptions:: PyOverflowError > ( py) {
@@ -185,8 +211,8 @@ mod tests {
185211
186212 #[ test]
187213 fn edgetest_phase ( ) {
188- for & re in & EDGE_VALUES {
189- for & im in & EDGE_VALUES {
214+ for & re in EDGE_VALUES {
215+ for & im in EDGE_VALUES {
190216 test_phase_impl ( re, im) ;
191217 }
192218 }
@@ -250,8 +276,8 @@ mod tests {
250276
251277 #[ test]
252278 fn edgetest_polar ( ) {
253- for & re in & EDGE_VALUES {
254- for & im in & EDGE_VALUES {
279+ for & re in EDGE_VALUES {
280+ for & im in EDGE_VALUES {
255281 test_polar_impl ( re, im) ;
256282 }
257283 }
@@ -297,8 +323,8 @@ mod tests {
297323
298324 #[ test]
299325 fn edgetest_rect ( ) {
300- for & r in & EDGE_VALUES {
301- for & phi in & EDGE_VALUES {
326+ for & r in EDGE_VALUES {
327+ for & phi in EDGE_VALUES {
302328 test_rect_impl ( r, phi) ;
303329 }
304330 }
0 commit comments