Source code for rpylib.tools.generic

"""Generic helpers for Python code
"""

from itertools import accumulate
from math import floor
from operator import mul

from gmpy2 import qdiv


[docs]def lazy_indices_product(args: list[int]): """itertools.product can blow up the memory because: 'Before `product()` runs, it completely consumes the input iterables, keeping pools of values in memory to generate the products.' (-> https://docs.python.org/3/library/itertools.html#itertools.product). There is sometimes a need for a 'lazy' cartesian product. The following code is inspired from: http://phrogz.net/lazy-cartesian-product and we are also following the advice in (https://hackernoon.com/generating-the-nth-cartesian-product-e48db41bed3f) and we are using gmpy2 (not bigfloat) for floating-point division. This function generate all the possible tuples of indices (i1, i2,...) for i1 in range(l1), i2 in range(l2),... where l1, l2,... are the args passed to the function :return: 'lazy' cartesian product """ moduli = args denominators = [1] + list(accumulate(reversed(moduli[1:]), mul)) nb_of_elements = denominators[-1] * args[0] for n in range(nb_of_elements): yield tuple( int(floor(qdiv(n, denominators[k])) % moduli[k]) for k, _ in enumerate(args) )