[Python-checkins] r60724 - in python/branches/trunk-math: Include/floatobject.h Include/pystate.h Lib/contextlib.py Lib/test/test_contextlib.py Modules/mathmodule.c Objects/floatobject.c Python/pystate.c
christian.heimes
python-checkins at python.org
Mon Feb 11 04:59:29 CET 2008
Author: christian.heimes
Date: Mon Feb 11 04:59:29 2008
New Revision: 60724
Modified:
python/branches/trunk-math/Include/floatobject.h
python/branches/trunk-math/Include/pystate.h
python/branches/trunk-math/Lib/contextlib.py
python/branches/trunk-math/Lib/test/test_contextlib.py
python/branches/trunk-math/Modules/mathmodule.c
python/branches/trunk-math/Objects/floatobject.c
python/branches/trunk-math/Python/pystate.c
Log:
Added IEEE 754 context for f/0. as discussed on the Python general list. Inside the context f/0. returns NAN for f=0. and (negative) infinity for the (negative) rest.
Modified: python/branches/trunk-math/Include/floatobject.h
==============================================================================
--- python/branches/trunk-math/Include/floatobject.h (original)
+++ python/branches/trunk-math/Include/floatobject.h Mon Feb 11 04:59:29 2008
@@ -51,6 +51,9 @@
preserve precision across conversions. */
PyAPI_FUNC(void) PyFloat_AsString(char*, PyFloatObject *v);
+PyAPI_FUNC(int) PyFloat_GetIEEE754(void);
+PyAPI_FUNC(int) PyFloat_SetIEEE754(int);
+
/* _PyFloat_{Pack,Unpack}{4,8}
*
* The struct and pickle (at least) modules need an efficient platform-
Modified: python/branches/trunk-math/Include/pystate.h
==============================================================================
--- python/branches/trunk-math/Include/pystate.h (original)
+++ python/branches/trunk-math/Include/pystate.h Mon Feb 11 04:59:29 2008
@@ -95,6 +95,8 @@
PyObject *async_exc; /* Asynchronous exception to raise */
long thread_id; /* Thread id where this tstate was created */
+ int float_ieee754; /* PyFloat behavior */
+
/* XXX signal handlers should also be here */
} PyThreadState;
Modified: python/branches/trunk-math/Lib/contextlib.py
==============================================================================
--- python/branches/trunk-math/Lib/contextlib.py (original)
+++ python/branches/trunk-math/Lib/contextlib.py Mon Feb 11 04:59:29 2008
@@ -1,8 +1,9 @@
"""Utilities for with-statement contexts. See PEP 343."""
import sys
+import math as _math
-__all__ = ["contextmanager", "nested", "closing"]
+__all__ = ["contextmanager", "nested", "closing", "ieee754"]
class GeneratorContextManager(object):
"""Helper for @contextmanager decorator."""
@@ -155,3 +156,24 @@
return self.thing
def __exit__(self, *exc_info):
self.thing.close()
+
+class ieee754(object):
+ """Context for IEEE 754 floating point behavior
+
+ Example:
+ >>> with ieee754():
+ ... r1 = 42./0.
+ ... r2 = -23./0.
+ ... r2 = 0./0.
+ ...
+ >>> print r1, r2, r3
+ (inf, -inf, nan)
+ """
+ def __init__(self, state=True):
+ self.new_state = state
+
+ def __enter__(self):
+ self.old_state = _math.set_ieee754(self.new_state)
+
+ def __exit__(self, *args):
+ _math.set_ieee754(self.old_state)
Modified: python/branches/trunk-math/Lib/test/test_contextlib.py
==============================================================================
--- python/branches/trunk-math/Lib/test/test_contextlib.py (original)
+++ python/branches/trunk-math/Lib/test/test_contextlib.py Mon Feb 11 04:59:29 2008
@@ -10,6 +10,7 @@
import threading
from contextlib import * # Tests __all__
from test import test_support
+import math
class ContextManagerTestCase(unittest.TestCase):
@@ -330,6 +331,25 @@
return True
self.boilerPlate(lock, locked)
+class IEEE754TestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.state = math.get_ieee754()
+
+ def tearDown(self):
+ math.set_ieee754(self.state)
+
+ def test_ieee754(self):
+ with ieee754():
+ r1 = 42./0.
+ r2 = -23./0.
+ r3 = 0./0.
+ self.assert_(math.isinf(r1))
+ self.assert_(r1 > 0)
+ self.assert_(math.isinf(r2))
+ self.assert_(r2 < 0)
+ self.assert_(math.isnan(r3))
+
# This is needed to make the test actually run under regrtest.py!
def test_main():
test_support.run_unittest(__name__)
Modified: python/branches/trunk-math/Modules/mathmodule.c
==============================================================================
--- python/branches/trunk-math/Modules/mathmodule.c (original)
+++ python/branches/trunk-math/Modules/mathmodule.c Mon Feb 11 04:59:29 2008
@@ -599,6 +599,29 @@
"isinf(x) -> bool\n\
Checks if float x is infinite (positive or negative)");
+static PyObject *
+math_set_ieee754(PyObject *self, PyObject *arg)
+{
+ int state;
+
+ state = PyObject_IsTrue(arg);
+ if (state == -1)
+ return NULL;
+
+ return PyBool_FromLong((long)PyFloat_SetIEEE754(state));
+}
+
+PyDoc_STRVAR(math_set_ieee754_doc,
+"set_ieee754(bool) -> bool");
+
+static PyObject *
+math_get_ieee754(PyObject *self, PyObject *arg)
+{
+ return PyBool_FromLong((long)PyFloat_GetIEEE754());
+}
+
+PyDoc_STRVAR(math_get_ieee754_doc,
+"get_ieee754() -> bool");
static PyMethodDef math_methods[] = {
{"acos", math_acos, METH_O, math_acos_doc},
@@ -618,6 +641,7 @@
{"floor", math_floor, METH_O, math_floor_doc},
{"fmod", math_fmod, METH_VARARGS, math_fmod_doc},
{"frexp", math_frexp, METH_O, math_frexp_doc},
+ {"get_ieee754", math_get_ieee754, METH_NOARGS, math_get_ieee754_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},
@@ -628,6 +652,7 @@
{"modf", math_modf, METH_O, math_modf_doc},
{"pow", math_pow, METH_VARARGS, math_pow_doc},
{"radians", math_radians, METH_O, math_radians_doc},
+ {"set_ieee754", math_set_ieee754, METH_O, math_set_ieee754_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},
Modified: python/branches/trunk-math/Objects/floatobject.c
==============================================================================
--- python/branches/trunk-math/Objects/floatobject.c (original)
+++ python/branches/trunk-math/Objects/floatobject.c Mon Feb 11 04:59:29 2008
@@ -882,8 +882,11 @@
CONVERT_TO_DOUBLE(v, a);
CONVERT_TO_DOUBLE(w, b);
if (b == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float division");
- return NULL;
+ if (PyFloat_GetIEEE754() == 0) {
+ PyErr_SetString(PyExc_ZeroDivisionError,
+ "float division");
+ return NULL;
+ }
}
PyFPE_START_PROTECT("divide", return 0)
a = a / b;
@@ -901,10 +904,12 @@
PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)
return NULL;
if (b == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float division");
- return NULL;
- }
- PyFPE_START_PROTECT("divide", return 0)
+ if (PyFloat_GetIEEE754() == 0) {
+ PyErr_SetString(PyExc_ZeroDivisionError,
+ "float division");
+ return NULL;
+ }
+ } PyFPE_START_PROTECT("divide", return 0)
a = a / b;
PyFPE_END_PROTECT(a)
return PyFloat_FromDouble(a);
@@ -1746,6 +1751,25 @@
}
}
+/* inline this */
+int
+PyFloat_GetIEEE754(void)
+{
+ PyThreadState *tstate = PyThreadState_GET();
+ return tstate->float_ieee754;
+}
+
+int
+PyFloat_SetIEEE754(state)
+{
+ int old_state;
+ PyThreadState *tstate = PyThreadState_GET();
+
+ old_state = tstate->float_ieee754;
+ tstate->float_ieee754 = state;
+ return old_state;
+}
+
/*----------------------------------------------------------------------------
* _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
*
Modified: python/branches/trunk-math/Python/pystate.c
==============================================================================
--- python/branches/trunk-math/Python/pystate.c (original)
+++ python/branches/trunk-math/Python/pystate.c Mon Feb 11 04:59:29 2008
@@ -193,6 +193,8 @@
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
+ tstate->float_ieee754 = 0;
+
#ifdef WITH_THREAD
_PyGILState_NoteThreadState(tstate);
#endif
More information about the Python-checkins
mailing list