diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index bd3890e3398..5f623a10fb3 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -11,6 +11,8 @@ warnings.filterwarnings( from random import random from math import atan2 +INF = float("inf") +NAN = float("nan") # These tests ensure that complex math does the right thing class ComplexTest(unittest.TestCase): @@ -337,6 +339,18 @@ class ComplexTest(unittest.TestCase): self.assertEqual(-6j,complex(repr(-6j))) self.assertEqual(6j,complex(repr(6j))) + self.assertEqual(repr(complex(1., INF)), "(1+inf*j)") + self.assertEqual(repr(complex(1., -INF)), "(1-inf*j)") + self.assertEqual(repr(complex(INF, 1)), "(inf+1j)") + self.assertEqual(repr(complex(-INF, INF)), "(-inf+inf*j)") + self.assertEqual(repr(complex(NAN, 1)), "(nan+1j)") + self.assertEqual(repr(complex(1, NAN)), "(1+nan*j)") + self.assertEqual(repr(complex(NAN, NAN)), "(nan+nan*j)") + + self.assertEqual(repr(complex(0, INF)), "inf*j") + self.assertEqual(repr(complex(0, -INF)), "-inf*j") + self.assertEqual(repr(complex(0, NAN)), "nan*j") + def test_neg(self): self.assertEqual(-(1+6j), -1-6j) diff --git a/Misc/NEWS b/Misc/NEWS index 134ac7e7167..c4d64ceda64 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- +- Fixed repr() and str() of complex numbers with infinity or nan as real or + imaginary part. + - Clear all free list during a gc.collect() of the highest generation in order to allow pymalloc to free more arenas. Python may give back memory to the OS earlier. diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 4777ed14819..c87b9e8de2a 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -322,16 +322,49 @@ complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision) { char format[32]; if (v->cval.real == 0.) { - PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); - PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag); - strncat(buf, "j", 1); + if (!Py_IS_FINITE(v->cval.imag)) { + if (Py_IS_NAN(v->cval.imag)) + strncpy(buf, "nan*j", 6); + /* else if (copysign(1, v->cval.imag) == 1) */ + else if (v->cval.imag > 0) + strncpy(buf, "inf*j", 6); + else + strncpy(buf, "-inf*j", 7); + } + else { + PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); + PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag); + strncat(buf, "j", 1); + } } else { char re[64], im[64]; /* Format imaginary part with sign, real part without */ - PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); - PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real); - PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision); - PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag); + if (!Py_IS_FINITE(v->cval.real)) { + if (Py_IS_NAN(v->cval.real)) + strncpy(re, "nan", 4); + /* else if (copysign(1, v->cval.real) == 1) */ + else if (v->cval.real > 0) + strncpy(re, "inf", 4); + else + strncpy(re, "-inf", 5); + } + else { + PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); + PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real); + } + if (!Py_IS_FINITE(v->cval.imag)) { + if (Py_IS_NAN(v->cval.imag)) + strncpy(im, "+nan*", 6); + /* else if (copysign(1, v->cval.imag) == 1) */ + else if (v->cval.imag > 0) + strncpy(im, "+inf*", 6); + else + strncpy(im, "-inf*", 6); + } + else { + PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision); + PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag); + } PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im); } }