[pypy-svn] r75951 - pypy/branch/fast-forward/pypy/module/math

benjamin at codespeak.net benjamin at codespeak.net
Wed Jul 7 05:39:45 CEST 2010


Author: benjamin
Date: Wed Jul  7 05:39:42 2010
New Revision: 75951

Modified:
   pypy/branch/fast-forward/pypy/module/math/__init__.py
   pypy/branch/fast-forward/pypy/module/math/interp_math.py
Log:
add erf and erfc

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 05:39:42 2010
@@ -45,5 +45,7 @@
        'atanh'          : 'interp_math.atanh',
        'log1p'          : 'interp_math.log1p',
        'expm1'          : 'interp_math.expm1',
+       'erf'            : 'interp_math.erf',
+       'erfc'           : 'interp_math.erfc',
 }
 

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 05:39:42 2010
@@ -421,3 +421,74 @@
     """exp(x) - 1"""
     return math1(space, rarithmetic.expm1, x)
 expm1.unwrap_spec = [ObjSpace, float]
+
+def erf(space, x):
+    """The error function"""
+    return math1(space, _erf, x)
+erf.unwrap_spec = [ObjSpace, float]
+
+def erfc(space, x):
+    """The complementary error function"""
+    return math1(space, _erfc, x)
+erfc.unwrap_spec = [ObjSpace, float]
+
+# Implementation of the error function, the complimentary error function, the
+# gamma function, and the natural log of the gamma function.  This exist in
+# libm, but I hear those implementations are horrible.
+
+ERF_SERIES_CUTOFF = 1.5
+ERF_SERIES_TERMS = 25
+ERFC_CONTFRAC_CUTOFF = 30.
+ERFC_CONTFRAC_TERMS = 50
+_sqrtpi = 1.772453850905516027298167483341145182798;
+
+def _erf_series(x):
+    x2 = x * x
+    acc = 0.
+    fk = ERF_SERIES_TERMS * + .5
+    for i in range(ERF_SERIES_TERMS):
+        acc = 2.0 * x2 * acc / fk
+        fk -= 1.
+    return acc * x * math.exp(-x2) / _sqrtpi
+
+def _erfc_contfrac(x):
+    if x >= ERFC_CONTFRAC_CUTOFF:
+        return 0.
+    x2 = x * x
+    a = 0.
+    da = 0.
+    p = 1.
+    p_last = 0.
+    q = da + x2
+    q_last = 1.
+    for i in range(ERFC_CONTFRAC_TERMS):
+        a += da
+        da += 2.
+        b = da + x2
+        temp = p
+        p = b * p - a * p_last
+        p_last = temp
+        temp = q
+        q = b * q - a * q_last
+        q_last = temp
+    return p / q * x * math.exp(-x2) / _sqrtpi
+
+def _erf(x):
+    if rarithmetic.isnan(x):
+        return x
+    absx = abs(x)
+    if absx < ERF_SERIES_CUTOFF:
+        return _erf_series(x)
+    else:
+        cf = _erfc_contfrac(absx)
+        return 1. - cf if x > 0. else cf - 1.
+
+def _erfc(x):
+    if rarithmetic.isnan(x):
+        return x
+    absx = abs(x)
+    if absx < ERF_SERIES_CUTOFF:
+        return 1. - _erf_series(x)
+    else:
+        cf = _erfc_contfrac(absx)
+        return cf if x > 0. else 2. - cf



More information about the Pypy-commit mailing list