@@ -17,8 +17,15 @@ static RECT_SPECIAL_VALUES: [[Complex64; 7]; 7] = [
1717
1818/// Return the phase angle (argument) of z.
1919#[ inline]
20- pub fn phase ( z : Complex64 ) -> f64 {
21- m:: atan2 ( z. im , z. re )
20+ pub fn phase ( z : Complex64 ) -> Result < f64 > {
21+ crate :: err:: set_errno ( 0 ) ;
22+ let phi = m:: atan2 ( z. im , z. re ) ;
23+ match crate :: err:: get_errno ( ) {
24+ 0 => Ok ( phi) ,
25+ libc:: EDOM => Err ( Error :: EDOM ) ,
26+ libc:: ERANGE => Err ( Error :: ERANGE ) ,
27+ _ => Err ( Error :: EDOM ) , // Unknown errno treated as domain error (like PyErr_SetFromErrno)
28+ }
2229}
2330
2431/// Convert z to polar coordinates (r, phi).
@@ -123,20 +130,40 @@ mod tests {
123130 pyo3:: Python :: attach ( |py| {
124131 let cmath = pyo3:: types:: PyModule :: import ( py, "cmath" ) . unwrap ( ) ;
125132 let py_func = cmath. getattr ( "phase" ) . unwrap ( ) ;
126- let py_result: f64 = py_func
127- . call1 ( ( pyo3:: types:: PyComplex :: from_doubles ( py, re, im) , ) )
128- . unwrap ( )
129- . extract ( )
130- . unwrap ( ) ;
131-
132- if py_result. is_nan ( ) && rs_result. is_nan ( ) {
133- return ;
133+ let py_result = py_func. call1 ( ( pyo3:: types:: PyComplex :: from_doubles ( py, re, im) , ) ) ;
134+
135+ match py_result {
136+ Ok ( result) => {
137+ let py_val: f64 = result. extract ( ) . unwrap ( ) ;
138+ match rs_result {
139+ Ok ( rs_val) => {
140+ if py_val. is_nan ( ) && rs_val. is_nan ( ) {
141+ return ;
142+ }
143+ assert_eq ! (
144+ py_val. to_bits( ) ,
145+ rs_val. to_bits( ) ,
146+ "phase({re}, {im}): py={py_val} vs rs={rs_val}"
147+ ) ;
148+ }
149+ Err ( e) => {
150+ panic ! ( "phase({re}, {im}): py={py_val} but rs returned error {e:?}" ) ;
151+ }
152+ }
153+ }
154+ Err ( e) => {
155+ // Python raised an exception - check we got an error too
156+ if rs_result. is_ok ( ) {
157+ let rs_val = rs_result. unwrap ( ) ;
158+ if e. is_instance_of :: < pyo3:: exceptions:: PyValueError > ( py) {
159+ panic ! ( "phase({re}, {im}): py raised ValueError but rs={rs_val}" ) ;
160+ } else if e. is_instance_of :: < pyo3:: exceptions:: PyOverflowError > ( py) {
161+ panic ! ( "phase({re}, {im}): py raised OverflowError but rs={rs_val}" ) ;
162+ }
163+ }
164+ // Both raised errors - OK
165+ }
134166 }
135- assert_eq ! (
136- py_result. to_bits( ) ,
137- rs_result. to_bits( ) ,
138- "phase({re}, {im}): py={py_result} vs rs={rs_result}"
139- ) ;
140167 } ) ;
141168 }
142169
0 commit comments