Christian Heimes added the comment:
The trunk_math_sign_inf_nan patch contains just three new method
isnan(), isinf() and sign(). It also fixes a minor numerical issue with
one function that did small / (small / large) instead of small * (large
/ small).
Added file: http://bugs.python.org/file8989/trunk_math_sign_inf_nan.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1640>
__________________________________
Index: Lib/test/test_math.py
===================================================================
--- Lib/test/test_math.py (revision 59558)
+++ Lib/test/test_math.py (working copy)
@@ -203,6 +203,31 @@
self.ftest('tanh(0)', math.tanh(0), 0)
self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
+ def testSign(self):
+ self.assertEqual(math.sign(0), 0)
+ self.assertEqual(math.sign(-2), -1)
+ self.assertEqual(math.sign(+2), 1)
+ self.assertEqual(math.sign(0.), 1)
+ self.assertEqual(math.sign(-0.), -1)
+ self.assertEqual(math.sign(-2.), -1)
+ self.assertEqual(math.sign(+2.), 1)
+
+ def testIsnan(self):
+ self.assert_(math.isnan(float("nan")))
+ self.assert_(math.isnan(float("inf")* 0.))
+ self.failIf(math.isnan(float("inf")))
+ self.failIf(math.isnan(0.))
+ self.failIf(math.isnan(1.))
+
+ def testIsinf(self):
+ self.assert_(math.isinf(float("inf")))
+ self.assert_(math.isinf(float("-inf")))
+ self.assert_(math.isinf(1E400))
+ self.assert_(math.isinf(-1E400))
+ self.failIf(math.isinf(float("nan")))
+ self.failIf(math.isinf(0.))
+ self.failIf(math.isinf(1.))
+
# RED_FLAG 16-Oct-2000 Tim
# While 2.0 is more consistent about exceptions than previous releases, it
# still fails this part of the test on some platforms. For now, we only
@@ -247,3 +272,4 @@
if __name__ == '__main__':
test_main()
+
Index: Modules/mathmodule.c
===================================================================
--- Modules/mathmodule.c (revision 59558)
+++ Modules/mathmodule.c (working copy)
@@ -277,9 +277,8 @@
PyDoc_STRVAR(math_log10_doc,
"log10(x) -> the base 10 logarithm of x.");
-/* XXX(nnorwitz): Should we use the platform M_PI or something more accurate
- like: 3.14159265358979323846264338327950288 */
-static const double degToRad = 3.141592653589793238462643383 / 180.0;
+static const double degToRad = Py_MATH_PI / 180.0;
+static const double radToDeg = 180.0 / Py_MATH_PI;
static PyObject *
math_degrees(PyObject *self, PyObject *arg)
@@ -287,7 +286,7 @@
double x = PyFloat_AsDouble(arg);
if (x == -1.0 && PyErr_Occurred())
return NULL;
- return PyFloat_FromDouble(x / degToRad);
+ return PyFloat_FromDouble(x * radToDeg);
}
PyDoc_STRVAR(math_degrees_doc,
@@ -305,6 +304,76 @@
PyDoc_STRVAR(math_radians_doc,
"radians(x) -> converts angle x from degrees to radians");
+static PyObject *
+math_isnan(PyObject *self, PyObject *arg)
+{
+ double x = PyFloat_AsDouble(arg);
+ if (x == -1.0 && PyErr_Occurred())
+ return NULL;
+ return PyBool_FromLong((long)Py_IS_NAN(x));
+}
+
+PyDoc_STRVAR(math_isnan_doc,
+"isnan(x) -> bool\n\
+Checks if float x is not a number (NaN)");
+
+static PyObject *
+math_isinf(PyObject *self, PyObject *arg)
+{
+ double x = PyFloat_AsDouble(arg);
+ if (x == -1.0 && PyErr_Occurred())
+ return NULL;
+ return PyBool_FromLong((long)Py_IS_INFINITY(x));
+}
+
+PyDoc_STRVAR(math_isinf_doc,
+"isinf(x) -> bool\n\
+Checks if float x is infinite (positive or negative)");
+
+static PyObject *
+math_sign(PyObject *self, PyObject *arg)
+{
+ int result = -2;
+ if (PyInt_Check(arg)) {
+ long l = PyInt_AsLong(arg);
+ if (l == -1.0 && PyErr_Occurred())
+ return NULL;
+ result = l > 0 ? 1 :
+ l < 0 ? -1 : 0;
+
+ }
+ if (PyLong_Check(arg)) {
+ result = _PyLong_Sign(arg);
+ }
+ else if (PyFloat_Check(arg)) {
+ double x = PyFloat_AsDouble(arg);
+ if (x == -1.0 && PyErr_Occurred())
+ return NULL;
+#ifdef HAVE_COPYSIGN
+ result = (int)copysign(1., x);
+#elif defined(MS_WINDOWS)
+ result = (int)_copysign(1.0, x);
+#else
+ result = x > 0.0 ? 1 :
+ x < 0.0 ? -1 : 0;
+#endif
+ }
+ if (result == -2) {
+ PyErr_Format(PyExc_TypeError,
+ "sign() expected int, long or float, found %s",
+ Py_Type(arg)->tp_name);
+ return NULL;
+ }
+ return PyInt_FromLong((long)result);
+}
+
+PyDoc_STRVAR(math_sign_doc,
+"sign(x) -> +1 / 0 / -1\n\
+Return the sign of an int, long or float. On platforms with full IEEE 754\n\
+semantic sign(0.) returns +1 and sign(-0.) returns -1. On other platforms\n\
+sign(0.) always returns 0.");
+
+
static PyMethodDef math_methods[] = {
{"acos", math_acos, METH_O, math_acos_doc},
{"asin", math_asin, METH_O, math_asin_doc},
@@ -320,12 +389,15 @@
{"fmod", math_fmod, METH_VARARGS, math_fmod_doc},
{"frexp", math_frexp, METH_O, math_frexp_doc},
{"hypot", math_hypot, METH_VARARGS, math_hypot_doc},
+ {"isinf", math_isinf, METH_O, math_isinf_doc},
+ {"isnan", math_isnan, METH_O, math_isnan_doc},
{"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc},
{"log", math_log, METH_VARARGS, math_log_doc},
{"log10", math_log10, METH_O, math_log10_doc},
{"modf", math_modf, METH_O, math_modf_doc},
{"pow", math_pow, METH_VARARGS, math_pow_doc},
{"radians", math_radians, METH_O, math_radians_doc},
+ {"sign", math_sign, METH_O, math_sign_doc},
{"sin", math_sin, METH_O, math_sin_doc},
{"sinh", math_sinh, METH_O, math_sinh_doc},
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
@@ -351,13 +423,13 @@
if (d == NULL)
goto finally;
- if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0)))
+ if (!(v = PyFloat_FromDouble(Py_MATH_PI)))
goto finally;
if (PyDict_SetItemString(d, "pi", v) < 0)
goto finally;
Py_DECREF(v);
- if (!(v = PyFloat_FromDouble(exp(1.0))))
+ if (!(v = PyFloat_FromDouble(Py_MATH_E)))
goto finally;
if (PyDict_SetItemString(d, "e", v) < 0)
goto finally;
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com