[issue41458] Avoid overflow/underflow in math.prod()

Raymond Hettinger report at bugs.python.org
Thu Aug 6 00:43:35 EDT 2020


Raymond Hettinger <raymond.hettinger at gmail.com> added the comment:

Here's variant (minimally tested) that has a fast path for the common case (no overflow or underflow), that uses a list instead of a deque, that keeps memory use small (only storing pending values that can't be combined without triggering an overflow or underflow).

----------------------------

from math import fabs, prod, isfinite

def product(seq, start=1.0):
    total = start
    s = []                 # values that would overflow the total
    s_side = False         # true if s_i increase the magnitude of the product
    for x in seq:
        old_total = total
        total *= x
        underflow = not total and old_total and not x
        if isfinite(total) and not underflow:
            continue       # fast-path for multiplies that doesn't overflow/underflow
        total = old_total

        side = fabs(x) > 1.0
        if not s or side == s_side:
            s.append(x)
            s_side = side
            continue

        t = [x, total]
        while s and t:      # opposite sides:  matter and antimatter
            x = s.pop() * t.pop()
            side = fabs(x) > 1.0
            s.append(x) if side == s_side else t.append(y)
        if t:
            s = t
            s_side = not s_side
        total = s.pop()
    return prod(s, start=total)

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41458>
_______________________________________


More information about the Python-bugs-list mailing list