[Python-checkins] r60852 - in python/branches/trunk-math: Include/complexobject.h Lib/test/cmath.ctest Modules/cmathmodule.c Objects/complexobject.c

mark.dickinson python-checkins at python.org
Sat Feb 16 03:14:13 CET 2008


Author: mark.dickinson
Date: Sat Feb 16 03:14:12 2008
New Revision: 60852

Modified:
   python/branches/trunk-math/Include/complexobject.h
   python/branches/trunk-math/Lib/test/cmath.ctest
   python/branches/trunk-math/Modules/cmathmodule.c
   python/branches/trunk-math/Objects/complexobject.c
Log:
Fix cmath.polar to make it work on Windows (I hope) and to make sure 
that it raises OverflowError where appropriate.  Add extra test for overflow.

Move common code for complex_abs and cmath_polar into a new function 
c_abs in complexobject.c.

Correct comments for cmath_rect in cmathmodule.c.


Modified: python/branches/trunk-math/Include/complexobject.h
==============================================================================
--- python/branches/trunk-math/Include/complexobject.h	(original)
+++ python/branches/trunk-math/Include/complexobject.h	Sat Feb 16 03:14:12 2008
@@ -19,6 +19,7 @@
 #define c_prod _Py_c_prod
 #define c_quot _Py_c_quot
 #define c_pow _Py_c_pow
+#define c_abs _Py_c_abs
 
 PyAPI_FUNC(Py_complex) c_sum(Py_complex, Py_complex);
 PyAPI_FUNC(Py_complex) c_diff(Py_complex, Py_complex);
@@ -26,6 +27,7 @@
 PyAPI_FUNC(Py_complex) c_prod(Py_complex, Py_complex);
 PyAPI_FUNC(Py_complex) c_quot(Py_complex, Py_complex);
 PyAPI_FUNC(Py_complex) c_pow(Py_complex, Py_complex);
+PyAPI_FUNC(double) c_abs(Py_complex);
 
 
 /* Complex object interface */

Modified: python/branches/trunk-math/Lib/test/cmath.ctest
==============================================================================
--- python/branches/trunk-math/Lib/test/cmath.ctest	(original)
+++ python/branches/trunk-math/Lib/test/cmath.ctest	Sat Feb 16 03:14:12 2008
@@ -2064,6 +2064,9 @@
 -- imaginary parts of polar (as cabs and carg, respectively, which in turn
 -- are defined in terms of the functions hypot and atan2).
 
+-- overflow
+polar0100 polar 1.4e308 1.4e308 -> inf 0.78539816339744828      overflow
+
 -- special values
 polar1000 polar 0.0 0.0 -> 0.0 0.0
 polar1001 polar 0.0 -0.0 -> 0.0 -0.0

Modified: python/branches/trunk-math/Modules/cmathmodule.c
==============================================================================
--- python/branches/trunk-math/Modules/cmathmodule.c	(original)
+++ python/branches/trunk-math/Modules/cmathmodule.c	Sat Feb 16 03:14:12 2008
@@ -977,10 +977,9 @@
 	double r, phi;
 	if (!PyArg_ParseTuple(args, "D:polar", &z))
 		return NULL;
-	errno = 0;
 	PyFPE_START_PROTECT("polar function", return 0)
-	r = hypot(z.real, z.imag);
-	phi = atan2(z.imag, z.real);
+	phi = atan2(z.imag, z.real); /* should not cause any exception */
+	r = c_abs(z); /* sets errno to ERANGE on overflow;  otherwise 0 */
 	PyFPE_END_PROTECT(r)
 	if (errno != 0)
 		return math_error();
@@ -997,10 +996,10 @@
   rect() isn't covered by the C99 standard, but it's not too hard to
   figure out 'spirit of C99' rules for special value handing:
 
-    rect(x, t) should behave like exp(log(x), t) for positive-signed x
-    rect(x, t) should behave like -exp(log(-x), t) for negative-signed x
-    rect(nan, t) should behave like exp(nan, t), except that rect(nan, 0)
-      gives nan +- 0j with the sign of the imaginary part unspecified.
+    rect(x, t) should behave like exp(log(x) + it) for positive-signed x
+    rect(x, t) should behave like -exp(log(-x) + it) for negative-signed x
+    rect(nan, t) should behave like exp(nan + it), except that rect(nan, 0)
+      gives nan +- i0 with the sign of the imaginary part unspecified.
 
 */
 

Modified: python/branches/trunk-math/Objects/complexobject.c
==============================================================================
--- python/branches/trunk-math/Objects/complexobject.c	(original)
+++ python/branches/trunk-math/Objects/complexobject.c	Sat Feb 16 03:14:12 2008
@@ -183,6 +183,38 @@
 
 }
 
+double
+c_abs(Py_complex z)
+{
+	/* sets errno = ERANGE on overflow;  otherwise errno = 0 */
+	double result;
+
+	if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) {
+		/* C99 rules: if either the real or the imaginary part is an
+		   infinity, return infinity, even if the other part is a
+		   NaN. */
+		if (Py_IS_INFINITY(z.real)) {
+			result = fabs(z.real);
+			errno = 0;
+			return result;
+		}
+		if (Py_IS_INFINITY(z.imag)) {
+			result = fabs(z.imag);
+			errno = 0;
+			return result;
+		}
+		/* either the real or imaginary part is a NaN,
+		   and neither is infinite. Result should be NaN. */
+		return Py_NAN;
+	}
+	result = hypot(z.real, z.imag);
+	if (!Py_IS_FINITE(result))
+		errno = ERANGE;
+	else
+		errno = 0;
+	return result;
+}
+
 static PyObject *
 complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)
 {
@@ -648,22 +680,12 @@
 complex_abs(PyComplexObject *v)
 {
 	double result;
-	/* if either the real or imaginary part is an infinity, return
-	   infinity, even if the other part is a NaN */
-        if (Py_IS_INFINITY(v->cval.real))
-		return PyFloat_FromDouble(fabs(v->cval.real));
-	if (Py_IS_INFINITY(v->cval.imag))
-		return PyFloat_FromDouble(fabs(v->cval.imag));
 
 	PyFPE_START_PROTECT("complex_abs", return 0)
-	result = hypot(v->cval.real,v->cval.imag);
+	result = c_abs(v->cval);
 	PyFPE_END_PROTECT(result)
 
-	/* an infinite result from finite operands should
-	   result in OverflowError */
-	if (Py_IS_INFINITY(result) &&
-	    Py_IS_FINITE(v->cval.real) &&
-	    Py_IS_FINITE(v->cval.imag)) {
+	if (errno == ERANGE) {
 		PyErr_SetString(PyExc_OverflowError,
 				"absolute value too large");
 		return NULL;


More information about the Python-checkins mailing list