]> granicus.if.org Git - python/commitdiff
Added math.isinf() and math.isnan()
authorChristian Heimes <christian@cheimes.de>
Thu, 3 Jan 2008 20:23:15 +0000 (20:23 +0000)
committerChristian Heimes <christian@cheimes.de>
Thu, 3 Jan 2008 20:23:15 +0000 (20:23 +0000)
Doc/library/math.rst
Lib/test/test_math.py
Misc/NEWS
Modules/mathmodule.c

index f92610f0f0b6a8a59eff10e638c6a70f4a30e13d..d0b03ed1b7127cea38395a63a4c5c2d0706d9b08 100644 (file)
@@ -66,6 +66,23 @@ Number-theoretic and representation functions:
    apart" the internal representation of a float in a portable way.
 
 
+.. function:: isinf(x)
+
+   Checks if the float *x* is positive or negative infinite.
+
+   ..versionadded:: 2.6
+
+
+.. function:: isnan(x)
+
+   Checks if the float *x* is a NaN (not a number). NaNs are part of the
+   IEEE 754 standards. Operation like but not limited to ``inf * 0``, 
+   ``inf / inf`` or any operation involving a NaN, e.g. ``nan * 1``, return
+   a NaN.
+
+   ..versionadded:: 2.6
+
+
 .. function:: ldexp(x, i)
 
    Return ``x * (2**i)``.  This is essentially the inverse of function
index 98e4623c2988c16dc070368ff183646c68cee329..d2da59bb966fcba07c38d6d97dd3a3d1eda6310e 100644 (file)
@@ -229,6 +229,22 @@ class MathTests(unittest.TestCase):
         self.ftest('tanh(0)', math.tanh(0), 0)
         self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
 
+    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
index 3e3f07446cc5c498fc62b6dd1847403c61240f31..95845b6e6a33bfc90747a9416c48c8a86366ca22 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 2.6 alpha 1?
 Core and builtins
 -----------------
 
+- Issue #1640: Added math.isinf() and math.isnan() functions.
+
 - Issue #1726: Remove Python/atof.c from PCBuild/pythoncore.vcproj
 
 - Removed PCbuild8/ directory and added a new build directory for VS 2005
index 431590c01d1d469fdf61fa65a73a7247812dae93..7540b5d04f3d295f2179a0c1017c80600f34c2be 100644 (file)
@@ -315,9 +315,8 @@ math_log10(PyObject *self, PyObject *arg)
 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)
@@ -325,7 +324,7 @@ math_degrees(PyObject *self, PyObject *arg)
        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,
@@ -343,6 +342,33 @@ math_radians(PyObject *self, PyObject *arg)
 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 PyMethodDef math_methods[] = {
        {"acos",        math_acos,      METH_O,         math_acos_doc},
        {"asin",        math_asin,      METH_O,         math_asin_doc},
@@ -358,6 +384,8 @@ static PyMethodDef math_methods[] = {
        {"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},
@@ -389,13 +417,13 @@ initmath(void)
        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;