[pypy-svn] r75945 - in pypy/branch/fast-forward/pypy: module/math module/math/test rlib rpython/lltypesystem/module

benjamin at codespeak.net benjamin at codespeak.net
Wed Jul 7 01:20:10 CEST 2010


Author: benjamin
Date: Wed Jul  7 01:20:08 2010
New Revision: 75945

Modified:
   pypy/branch/fast-forward/pypy/module/math/__init__.py
   pypy/branch/fast-forward/pypy/module/math/interp_math.py
   pypy/branch/fast-forward/pypy/module/math/test/test_math.py
   pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/module/ll_math.py
Log:
add log1p, asinh, acosh, and atanh

Modified: pypy/branch/fast-forward/pypy/module/math/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/math/__init__.py	(original)
+++ pypy/branch/fast-forward/pypy/module/math/__init__.py	Wed Jul  7 01:20:08 2010
@@ -40,5 +40,9 @@
        'trunc'          : 'interp_math.trunc',
        'fsum'           : 'interp_math.fsum',
        'factorial'      : 'interp_math.factorial',
+       'asinh'          : 'interp_math.asinh',
+       'acosh'          : 'interp_math.acosh',
+       'atanh'          : 'interp_math.atanh',
+       'log1p'          : 'interp_math.log1p',
 }
 

Modified: pypy/branch/fast-forward/pypy/module/math/interp_math.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/math/interp_math.py	(original)
+++ pypy/branch/fast-forward/pypy/module/math/interp_math.py	Wed Jul  7 01:20:08 2010
@@ -396,3 +396,23 @@
     for i in range(1, x + 1):
         w_res = space.mul(w_res, space.wrap(i))
     return w_res
+
+def log1p(space, x):
+    """Find log(x + 1)."""
+    return math1(space, rarithmetic.log1p, x)
+log1p.unwrap_spec = [ObjSpace, float]
+
+def acosh(space, x):
+    """Inverse hyperbolic cosine"""
+    return math1(space, rarithmetic.acosh, x)
+acosh.unwrap_spec = [ObjSpace, float]
+
+def asinh(space, x):
+    """Inverse hyperbolic sine"""
+    return math1(space, rarithmetic.asinh, x)
+asinh.unwrap_spec = [ObjSpace, float]
+
+def atanh(space, x):
+    """Inverse hyperbolic tangent"""
+    return math1(space, rarithmetic.atanh, x)
+atanh.unwrap_spec = [ObjSpace, float]

Modified: pypy/branch/fast-forward/pypy/module/math/test/test_math.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/math/test/test_math.py	(original)
+++ pypy/branch/fast-forward/pypy/module/math/test/test_math.py	Wed Jul  7 01:20:08 2010
@@ -8,6 +8,10 @@
         cls.space = gettestobjspace(usemodules=['math'])
         cls.w_cases = cls.space.wrap(test_direct.MathTests.TESTCASES)
         cls.w_consistent_host = cls.space.wrap(test_direct.consistent_host)
+        cls.w_ftest = cls.space.appexec((), """():
+        def ftest(actual, expected):
+            assert abs(actual - expected) < 10E-5
+        return ftest""")
 
     def test_all_cases(self):
         if not self.consistent_host:
@@ -86,6 +90,35 @@
         raises(ValueError, math.factorial, -1.)
         raises(ValueError, math.factorial, 1.1)
 
+    def test_log1p(self):
+        import math
+        self.ftest(math.log1p(1/math.e-1), -1)
+        self.ftest(math.log1p(0), 0)
+        self.ftest(math.log1p(math.e-1), 1)
+        self.ftest(math.log1p(1), math.log(2))
+
+    def test_acosh(self):
+        import math
+        self.ftest(math.acosh(1), 0)
+        self.ftest(math.acosh(2), 1.3169578969248168)
+        assert math.isinf(math.asinh(float("inf")))
+        raises(ValueError, math.acosh, 0)
+
+    def test_asinh(self):
+        import math
+        self.ftest(math.asinh(0), 0)
+        self.ftest(math.asinh(1), 0.88137358701954305)
+        self.ftest(math.asinh(-1), -0.88137358701954305)
+        assert math.isinf(math.asinh(float("inf")))
+
+    def test_atanh(self):
+        import math
+        self.ftest(math.atanh(0), 0)
+        self.ftest(math.atanh(0.5), 0.54930614433405489)
+        self.ftest(math.atanh(-0.5), -0.54930614433405489)
+        raises(ValueError, math.atanh, 1.)
+        assert math.isnan(math.atanh(float("nan")))
+
     def test_mtestfile(self):
         import math
         import abc

Modified: pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	Wed Jul  7 01:20:08 2010
@@ -35,8 +35,8 @@
 """
 import math
 from pypy.rpython import extregistry
-
 from pypy.rlib import objectmodel
+
 # set up of machine internals
 _bits = 0
 _itest = 1
@@ -54,7 +54,8 @@
 NAN = INFINITY / INFINITY
 
 try:
-    from math import isinf, isnan, copysign
+    # Try to get math functions added in 2.6.
+    from math import isinf, isnan, copysign, acosh, asinh, atanh, log1p
 except ImportError:
     def isinf(x):
         return x == INFINITY or x == -INFINITY
@@ -69,6 +70,67 @@
         else:
             return -math.fabs(x)
 
+    _2_to_m28 = 3.7252902984619141E-09; # 2**-28
+    _2_to_p28 = 268435456.0; # 2**28
+    _ln2 = 6.93147180559945286227E-01
+
+    def acosh(x):
+        if isnan(x):
+            return NAN
+        if x < 1.:
+            raise ValueError("math domain error")
+        if x >= _2_to_p28:
+            if isinf(x):
+                return x
+            else:
+                return math.log(x) + _ln2
+        if x == 1.:
+            return 0.
+        if x >= 2.:
+            t = x * x
+            return math.log(2. * x - 1. / (x + math.sqrt(t - 1.0)))
+        t = x - 1.0
+        return log1p(t + math.sqrt(2. * t + t * t))
+
+    def asinh(x):
+        absx = abs(x)
+        if isnan(x) or isinf(x):
+            return x
+        if absx < _2_to_m28:
+            return x
+        if absx > _2_to_p28:
+            w = math.log(absx) + _ln2
+        elif absx > 2.:
+            w = math.log(2. * absx + 1. // (math.sqrt(x * x + 1.) + absx))
+        else:
+            t = x * x
+            w = log1p(absx + t // (1. + math.sqrt(1. + t)))
+        return copysign(w, x)
+
+    def atanh(x):
+        if isnan(x):
+            return x
+        absx = abs(x)
+        if absx >= 1.:
+            raise ValueError("math domain error")
+        if absx < _2_to_m28:
+            return x
+        if absx < .5:
+            t = absx + absx
+            t = .5 * log1p(t + t * absx // (1. - absx))
+        else:
+            t = .5 * log1p((absx + absx) // (1. - absx))
+        return copysign(t, x)
+
+    def log1p(x):
+        from pypy.rlib import rfloat
+        if abs(x) < rfloat.DBL_EPSILON // 2.:
+            return x
+        elif -.5 <= x <= 1.:
+            y = 1. + x
+            return math.log(y) - ((y - 1.) - x) // y
+        else:
+            return math.log(1. + x)
 
 def intmask(n):
     if isinstance(n, int):

Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/module/ll_math.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/module/ll_math.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/module/ll_math.py	Wed Jul  7 01:20:08 2010
@@ -316,7 +316,7 @@
     'acos', 'asin', 'atan',
     'ceil', 'cos', 'cosh', 'exp', 'fabs', 'floor',
     'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'log', 'log10',
-    # 'log1p', 'acosh', 'asinh', 'atanh',   -- added in Python 2.6
+    'acosh', 'asinh', 'atanh',   # -- added in Python 2.6
     ]
 unary_math_functions_can_overflow = [
     'cosh', 'exp', 'log1p', 'sinh', # why log1p? CPython does it



More information about the Pypy-commit mailing list