Split out integer functions from the math module

Small ints, yes.

My point was, that this “work” isn’t too helpful. Simple benchmark:

prod(i): Mean +- std dev: 389 us +- 24 us
reduce(mul, i, 1): Mean +- std dev: 384 us +- 0 us
prod(f): Mean +- std dev: 3.09 us +- 0.11 us
reduce(mul, f, 1): Mean +- std dev: 8.12 us +- 0.31 us
prod(c): Mean +- std dev: 13.8 us +- 0.0 us
reduce(mul, c, 1): Mean +- std dev: 13.0 us +- 0.1 us
prod(r): Mean +- std dev: 2.25 ms +- 0.01 ms
reduce(mul, r, 1): Mean +- std dev: 2.28 ms +- 0.01 ms
prod(d): Mean +- std dev: 87.0 us +- 1.2 us
reduce(mul, d, 1): Mean +- std dev: 87.6 us +- 1.0 us

There is even a speed loss for complex or bigints (which is rather artificIal example). So, really these “generics” do something helpful only for the libm’s-style math module.

import pyperf

import fractions
import decimal
import random
from operator import mul
from functools import reduce
from math import prod

random.seed(1)
data = [random.random() for _ in range(100)]
f = data.copy()
c = [complex(_) for _ in data]
r = [fractions.Fraction(_) for _ in data]
d = [decimal.Decimal(_) for _ in data]
i = [random.randint(1<<100, 1<<128) for _ in range(100)]

runner = pyperf.Runner()

runner.bench_func('prod(i)', prod, i)
runner.bench_func('reduce(mul, i, 1)', reduce, mul, i, 1)

runner.bench_func('prod(c)', prod, c)
runner.bench_func('reduce(mul, c, 1)', reduce, mul, c, 1)

runner.bench_func('prod(r)', prod, r)
runner.bench_func('reduce(mul, r, 1)', reduce, mul, r, 1)

runner.bench_func('prod(d)', prod, d)
runner.bench_func('reduce(mul, d, 1)', reduce, mul, d, 1)