[pypy-commit] pypy default: (B. Cannon, A. Gaynor) Specialize math.log and math.log10.

brettsky noreply at buildbot.pypy.org
Mon Jul 18 00:19:04 CEST 2011


Author: Brett Cannon <brett at python.org>
Branch: 
Changeset: r45703:522ca49e62aa
Date: 2011-07-17 15:18 -0700
http://bitbucket.org/pypy/pypy/changeset/522ca49e62aa/

Log:	(B. Cannon, A. Gaynor) Specialize math.log and math.log10.

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -185,6 +185,7 @@
     Jim Baker
     Philip Jenvey
     Rodrigo Ara&#250;jo
+    Brett Cannon
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_math.py
@@ -0,0 +1,32 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestMath(BaseTestPyPyC):
+    def test_log(self):
+        def main(n):
+            import math
+
+            i = 1
+            s = 0.0
+            while i < n:
+                s += math.log(i) - math.log10(i)
+                i += 1
+            return s
+        log = self.run(main, [500])
+        assert round(log.result, 6) == round(main(500), 6)
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i2 = int_lt(i0, i1)
+            guard_true(i2, descr=...)
+            guard_not_invalidated(descr=...)
+            f1 = cast_int_to_float(i0)
+            i3 = float_le(f1, 0)
+            guard_false(i3, descr=...)
+            f2 = call(ConstClass(log), f1)
+            f3 = call(ConstClass(log10), f1)
+            f4 = float_sub(f2, f3)
+            f5 = float_add(f0, f4)
+            i4 = int_add(i0, 1)
+            --TICK--
+            jump(i4, i1, f5)
+        """)
diff --git a/pypy/rpython/extfuncregistry.py b/pypy/rpython/extfuncregistry.py
--- a/pypy/rpython/extfuncregistry.py
+++ b/pypy/rpython/extfuncregistry.py
@@ -30,24 +30,28 @@
                       export_name="ll_math.ll_math_%s" % name,
                        sandboxsafe=True, llimpl=llimpl)
 
-register_external(rfloat.isinf, [float], bool,
-                  export_name="ll_math.ll_math_isinf", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_isinf)
-register_external(rfloat.isnan, [float], bool,
-                  export_name="ll_math.ll_math_isnan", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_isnan)
-register_external(rfloat.isfinite, [float], bool,
-                  export_name="ll_math.ll_math_isfinite", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_isfinite)
-register_external(rfloat.copysign, [float, float], float,
-                  export_name="ll_math.ll_math_copysign", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_copysign)
-register_external(math.floor, [float], float,
-                  export_name="ll_math.ll_math_floor", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_floor)
-register_external(math.sqrt, [float], float,
-                  export_name="ll_math.ll_math_sqrt", sandboxsafe=True,
-                  llimpl=ll_math.ll_math_sqrt)
+_register = [  # (module, [(method name, arg types, return type), ...], ...)
+    (rfloat, [
+        ('isinf', [float], bool),
+        ('isnan', [float], bool),
+        ('isfinite', [float], bool),
+        ('copysign', [float, float], float),
+    ]),
+    (math, [
+       ('floor', [float], float),
+       ('sqrt', [float], float),
+       ('log', [float], float),
+       ('log10', [float], float),
+    ]),
+]
+for module, methods in _register:
+    for name, arg_types, return_type in methods:
+        method_name = 'll_math_%s' % name
+        register_external(getattr(module, name), arg_types, return_type,
+                          export_name='ll_math.%s' % method_name,
+                          sandboxsafe=True,
+                          llimpl=getattr(ll_math, method_name))
+
 
 complex_math_functions = [
     ('frexp', [float],        (float, int)),
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -68,8 +68,9 @@
 math_hypot = llexternal(underscore + 'hypot',
                         [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
 math_floor = llexternal('floor', [rffi.DOUBLE], rffi.DOUBLE, elidable_function=True)
-
 math_sqrt = llexternal('sqrt', [rffi.DOUBLE], rffi.DOUBLE)
+math_log = llexternal('log', [rffi.DOUBLE], rffi.DOUBLE)
+math_log10 = llexternal('log10', [rffi.DOUBLE], rffi.DOUBLE)
 
 @jit.elidable
 def sqrt_nonneg(x):
@@ -329,12 +330,22 @@
 def ll_math_sqrt(x):
     if x < 0.0:
         raise ValueError, "math domain error"
-    
+
     if isfinite(x):
         return sqrt_nonneg(x)
 
     return x   # +inf or nan
 
+def ll_math_log(x):
+    if x <= 0:
+        raise ValueError("math domain error")
+    return math_log(x)
+
+def ll_math_log10(x):
+    if x <= 0:
+        raise ValueError("math domain error")
+    return math_log10(x)
+
 # ____________________________________________________________
 #
 # Default implementations
@@ -373,7 +384,7 @@
 unary_math_functions = [
     'acos', 'asin', 'atan',
     'ceil', 'cos', 'cosh', 'exp', 'fabs',
-    'sin', 'sinh', 'tan', 'tanh', 'log', 'log10',
+    'sin', 'sinh', 'tan', 'tanh',
     'acosh', 'asinh', 'atanh', 'log1p', 'expm1',
     ]
 unary_math_functions_can_overflow = [
diff --git a/pypy/rpython/lltypesystem/module/test/test_llinterp_math.py b/pypy/rpython/lltypesystem/module/test/test_llinterp_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_llinterp_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_llinterp_math.py
@@ -1,6 +1,4 @@
-
-""" Just another bunch of tests for llmath, run on top of llinterp
-"""
+"""Just another bunch of tests for llmath, run on top of llinterp."""
 
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin
 from pypy.rpython.lltypesystem.module import ll_math
@@ -39,7 +37,7 @@
             assert self.interpret(f, [0.3, 0.4]) == f(0.3, 0.4)
         return next_test
 
-    for name in ll_math.unary_math_functions + ['sqrt']:
+    for name in ll_math.unary_math_functions + ['log', 'log10', 'sqrt']:
         func_name = 'test_%s' % (name,)
         next_test = new_unary_test(name)
         next_test.func_name = func_name


More information about the pypy-commit mailing list