[Jython-checkins] jython: Pure python version of fsum for math module.

frank.wierzbicki jython-checkins at python.org
Fri May 18 23:37:36 CEST 2012


http://hg.python.org/jython/rev/ee12ca8ebf01
changeset:   6660:ee12ca8ebf01
user:        Miki Tebeka <miki.tebeka at gmail.com>
date:        Fri May 18 14:37:25 2012 -0700
summary:
  Pure python version of fsum for math module.

files:
  Lib/_fsum.py                     |  36 ++++++++++++++++++++
  src/org/python/modules/math.java |  11 +++--
  2 files changed, 43 insertions(+), 4 deletions(-)


diff --git a/Lib/_fsum.py b/Lib/_fsum.py
new file mode 100644
--- /dev/null
+++ b/Lib/_fsum.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+from sys import float_info
+import math
+
+
+mant_dig = float_info.mant_dig
+etiny = float_info.min_exp - mant_dig
+
+def fsum(iterable):
+    """Full precision summation.  Compute sum(iterable) without any
+    intermediate accumulation of error.  Based on the 'lsum' function
+    at http://code.activestate.com/recipes/393090/
+
+    """
+    tmant, texp = 0, 0
+    for x in iterable:
+        mant, exp = math.frexp(x)
+        mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
+        if texp > exp:
+            tmant <<= texp-exp
+            texp = exp
+        else:
+            mant <<= exp-texp
+        tmant += mant
+
+    # Round tmant * 2**texp to a float.  The original recipe
+    # used float(str(tmant)) * 2.0**texp for this, but that's
+    # a little unsafe because str -> float conversion can't be
+    # relied upon to do correct rounding on all platforms.
+    tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
+    if tail > 0:
+        h = 1 << (tail-1)
+        tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
+        texp += tail
+    return math.ldexp(tmant, texp)
diff --git a/src/org/python/modules/math.java b/src/org/python/modules/math.java
--- a/src/org/python/modules/math.java
+++ b/src/org/python/modules/math.java
@@ -9,7 +9,9 @@
 import org.python.core.PyInteger;
 import org.python.core.PyLong;
 import org.python.core.PyObject;
+import org.python.core.PySystemState;
 import org.python.core.PyTuple;
+import org.python.core.__builtin__;
 import org.python.modules.math_erf;
 
 public class math implements ClassDictInit {
@@ -507,12 +509,13 @@
         return log(ONE + v);
     }
     
-    public static double fsum(double... values) {
-        // TODO need an iterable
-        // TODO need sys.float_info
-        return 0;
+    public static double fsum(final PyObject iterable) {
+        PyFloat result = (PyFloat)__builtin__.__import__("_fsum")
+            .invoke("fsum", iterable);
+        return result.asDouble();
     }
 
+
     private static double calculateLongLog(PyLong v) {
         int exp[] = new int[1];
         double x = v.scaledDoubleValue(exp);

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list