22from test import support
33
44from random import random
5- from math import atan2
5+ from math import atan2 , isnan , copysign
66
77INF = float ("inf" )
88NAN = float ("nan" )
@@ -37,6 +37,29 @@ def assertCloseAbs(self, x, y, eps=1e-9):
3737 # check that relative difference < eps
3838 self .assert_ (abs ((x - y )/ y ) < eps )
3939
40+ def assertFloatsAreIdentical (self , x , y ):
41+ """assert that floats x and y are identical, in the sense that:
42+ (1) both x and y are nans, or
43+ (2) both x and y are infinities, with the same sign, or
44+ (3) both x and y are zeros, with the same sign, or
45+ (4) x and y are both finite and nonzero, and x == y
46+
47+ """
48+ msg = 'floats {!r} and {!r} are not identical'
49+
50+ if isnan (x ) or isnan (y ):
51+ if isnan (x ) and isnan (y ):
52+ return
53+ elif x == y :
54+ if x != 0.0 :
55+ return
56+ # both zero; check that signs match
57+ elif copysign (1.0 , x ) == copysign (1.0 , y ):
58+ return
59+ else :
60+ msg += ': zeros have different signs'
61+ self .fail (msg .format (x , y ))
62+
4063 def assertClose (self , x , y , eps = 1e-9 ):
4164 """Return true iff complexes x and y "are close\" """
4265 self .assertCloseAbs (x .real , y .real , eps )
@@ -202,6 +225,8 @@ def __complex__(self): return self.value
202225 self .assertAlmostEqual (complex ("+1" ), + 1 )
203226 self .assertAlmostEqual (complex ("(1+2j)" ), 1 + 2j )
204227 self .assertAlmostEqual (complex ("(1.3+2.2j)" ), 1.3 + 2.2j )
228+ self .assertAlmostEqual (complex ("3.14+1J" ), 3.14 + 1j )
229+ self .assertAlmostEqual (complex (" ( +3.14-6J )" ), 3.14 - 6j )
205230
206231 class complex2 (complex ): pass
207232 self .assertAlmostEqual (complex (complex2 (1 + 1j )), 1 + 1j )
@@ -229,8 +254,6 @@ def split_zeros(x):
229254 self .assertRaises (TypeError , complex , "1" , "1" )
230255 self .assertRaises (TypeError , complex , 1 , "1" )
231256
232- self .assertEqual (complex (" 3.14+J " ), 3.14 + 1j )
233-
234257 # SF bug 543840: complex(string) accepts strings with \0
235258 # Fixed in 2.3.
236259 self .assertRaises (ValueError , complex , '1+1j\0 j' )
@@ -254,6 +277,11 @@ def split_zeros(x):
254277 self .assertRaises (ValueError , complex , "(1+2j)123" )
255278 self .assertRaises (ValueError , complex , "1" * 500 )
256279 self .assertRaises (ValueError , complex , "x" )
280+ self .assertRaises (ValueError , complex , "J" )
281+ self .assertRaises (ValueError , complex , "1j+2" )
282+ self .assertRaises (ValueError , complex , "1e1ej" )
283+ self .assertRaises (ValueError , complex , "1e++1ej" )
284+ self .assertRaises (ValueError , complex , ")1+2j(" )
257285
258286 class EvilExc (Exception ):
259287 pass
@@ -318,17 +346,17 @@ def test_repr(self):
318346 self .assertEqual (- 6j ,complex (repr (- 6j )))
319347 self .assertEqual (6j ,complex (repr (6j )))
320348
321- self .assertEqual (repr (complex (1. , INF )), "(1+inf*j )" )
322- self .assertEqual (repr (complex (1. , - INF )), "(1-inf*j )" )
349+ self .assertEqual (repr (complex (1. , INF )), "(1+infj )" )
350+ self .assertEqual (repr (complex (1. , - INF )), "(1-infj )" )
323351 self .assertEqual (repr (complex (INF , 1 )), "(inf+1j)" )
324- self .assertEqual (repr (complex (- INF , INF )), "(-inf+inf*j )" )
352+ self .assertEqual (repr (complex (- INF , INF )), "(-inf+infj )" )
325353 self .assertEqual (repr (complex (NAN , 1 )), "(nan+1j)" )
326- self .assertEqual (repr (complex (1 , NAN )), "(1+nan*j )" )
327- self .assertEqual (repr (complex (NAN , NAN )), "(nan+nan*j )" )
354+ self .assertEqual (repr (complex (1 , NAN )), "(1+nanj )" )
355+ self .assertEqual (repr (complex (NAN , NAN )), "(nan+nanj )" )
328356
329- self .assertEqual (repr (complex (0 , INF )), "inf*j " )
330- self .assertEqual (repr (complex (0 , - INF )), "-inf*j " )
331- self .assertEqual (repr (complex (0 , NAN )), "nan*j " )
357+ self .assertEqual (repr (complex (0 , INF )), "infj " )
358+ self .assertEqual (repr (complex (0 , - INF )), "-infj " )
359+ self .assertEqual (repr (complex (0 , NAN )), "nanj " )
332360
333361 def test_neg (self ):
334362 self .assertEqual (- (1 + 6j ), - 1 - 6j )
@@ -367,6 +395,21 @@ def test_plus_minus_0j(self):
367395 self .assertEquals (atan2 (z1 .imag , - 1. ), atan2 (0. , - 1. ))
368396 self .assertEquals (atan2 (z2 .imag , - 1. ), atan2 (- 0. , - 1. ))
369397
398+ @unittest .skipUnless (float .__getformat__ ("double" ).startswith ("IEEE" ),
399+ "test requires IEEE 754 doubles" )
400+ def test_repr_roundtrip (self ):
401+ # complex(repr(z)) should recover z exactly, even for complex numbers
402+ # involving an infinity, nan, or negative zero
403+ vals = [0.0 , 1e-200 , 0.0123 , 3.1415 , 1e50 , INF , NAN ]
404+ vals += [- v for v in vals ]
405+ for x in vals :
406+ for y in vals :
407+ z = complex (x , y )
408+ roundtrip = complex (repr (z ))
409+ self .assertFloatsAreIdentical (z .real , roundtrip .real )
410+ self .assertFloatsAreIdentical (z .imag , roundtrip .imag )
411+
412+
370413def test_main ():
371414 support .run_unittest (ComplexTest )
372415
0 commit comments