[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