# [pypy-svn] r71824 - in pypy/trunk/pypy/rpython/lltypesystem/module: . test

arigo at codespeak.net arigo at codespeak.net
Fri Mar 5 19:26:58 CET 2010

```Author: arigo
Date: Fri Mar  5 19:26:57 2010
New Revision: 71824

Modified:
pypy/trunk/pypy/rpython/lltypesystem/module/ll_math.py
pypy/trunk/pypy/rpython/lltypesystem/module/test/test_ll_math.py
Log:
Test and fix.  On Mac OS/X, this triggers a use case
where the C function ldexp() fails to set errno=ERANGE
in case it overflows, but where we still really want
the OverflowError from RPython.

Modified: pypy/trunk/pypy/rpython/lltypesystem/module/ll_math.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/module/ll_math.py	(original)
+++ pypy/trunk/pypy/rpython/lltypesystem/module/ll_math.py	Fri Mar  5 19:26:57 2010
@@ -7,6 +7,7 @@
from pypy.tool.sourcetools import func_with_new_name
from pypy.rlib import rposix
from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rlib.rarithmetic import isinf

math_frexp = rffi.llexternal('frexp', [rffi.DOUBLE, rffi.INTP], rffi.DOUBLE,
sandboxsafe=True)
@@ -26,16 +27,24 @@

def ll_math_frexp(x):
exp_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
-    mantissa = math_frexp(x, exp_p)
-    exponent = rffi.cast(lltype.Signed, exp_p[0])
-    lltype.free(exp_p, flavor='raw')
+    try:
+        _error_reset()
+        mantissa = math_frexp(x, exp_p)
+        _check_error(mantissa)
+        exponent = rffi.cast(lltype.Signed, exp_p[0])
+    finally:
+        lltype.free(exp_p, flavor='raw')
return (mantissa, exponent)

def ll_math_modf(x):
intpart_p = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
-    fracpart = math_modf(x, intpart_p)
-    intpart = intpart_p[0]
-    lltype.free(intpart_p, flavor='raw')
+    try:
+        _error_reset()
+        fracpart = math_modf(x, intpart_p)
+        _check_error(fracpart)
+        intpart = intpart_p[0]
+    finally:
+        lltype.free(intpart_p, flavor='raw')
return (fracpart, intpart)

def ll_math_ldexp(x, exp):
@@ -50,6 +59,8 @@
ERANGE = errno.ERANGE
def _check_error(x):
errno = rposix.get_errno()
+    if isinf(x):
+        errno = ERANGE
if errno:
if errno == ERANGE:
if not x:

Modified: pypy/trunk/pypy/rpython/lltypesystem/module/test/test_ll_math.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/module/test/test_ll_math.py	(original)
+++ pypy/trunk/pypy/rpython/lltypesystem/module/test/test_ll_math.py	Fri Mar  5 19:26:57 2010
@@ -45,3 +45,26 @@
# underflows give 0.0 with no exception raised
assert f(1.0, -10000) == 0.0     # sanity-check the host Python
assert self.interpret(f, [1.0, -10000]) == 0.0
+
+    def test_overflow_1(self):
+        # this (probably, depending on platform) tests the case
+        # where the C function pow() sets ERANGE.
+        def f(x, y):
+            try:
+                return math.pow(x, y)
+            except OverflowError:
+                return -42.0
+
+        assert self.interpret(f, [10.0, 40000.0]) == -42.0
+
+    def test_overflow_2(self):
+        # this (not on Linux but on Mac OS/X at least) tests the case
+        # where the C function ldexp() does not set ERANGE, but
+        # returns +infinity.
+        def f(x, y):
+            try:
+                return math.ldexp(x, y)
+            except OverflowError:
+                return -42.0
+
+        assert self.interpret(f, [10.0, 40000]) == -42.0

```