# Path: liam2/utils.py
# def prod(values):
#     res = 1
#     for value in values:
#         res *= value
#     return res


import math
    import numpy as np
from types import BuiltinFunctionType, FunctionType
from liam2.utils import prod
            array = func(*args, **kwargs)
        except MemoryError:
            self.free(nbytes)
            array = func(*args, **kwargs)
            print("succeeded!")
        # make sure the given size was correct
        assert array.nbytes == nbytes
        return array

    def decorate(self, sizefunc, func):
        def decorated(*args, **kwargs):
            return self.safe_call(sizefunc(*args, **kwargs),
                                  func, *args, **kwargs)
        decorated.__name__ = func.__name__
        return decorated

    def free(self, nbytes):
        print("mem is full, puring %d elements from cache" % len(self.cache))
        self.cache.clear()


class ManagedModule(object):
    def __init__(self, module, manager, sizefuncs):
        self.module = module
        self.manager = manager
        self.sizefuncs = sizefuncs

    def __getattr__(self, key):
        func = getattr(self.module, key)
        assert isinstance(func, (BuiltinFunctionType, FunctionType))

# Path: liam2/utils.py
# def prod(values):
#     res = 1
#     for value in values:
#         res *= value
#     return res


# Path: liam2/memory.py
import math
    import numpy as np
from types import BuiltinFunctionType, FunctionType
from liam2.utils import prod

            array = func(*args, **kwargs)
        except MemoryError:
            self.free(nbytes)
            array = func(*args, **kwargs)
            print("succeeded!")
        # make sure the given size was correct
        assert array.nbytes == nbytes
        return array

    def decorate(self, sizefunc, func):
        def decorated(*args, **kwargs):
            return self.safe_call(sizefunc(*args, **kwargs),
                                  func, *args, **kwargs)
        decorated.__name__ = func.__name__
        return decorated

    def free(self, nbytes):
        print("mem is full, puring %d elements from cache" % len(self.cache))
        self.cache.clear()


class ManagedModule(object):
    def __init__(self, module, manager, sizefuncs):
        self.module = module
        self.manager = manager
        self.sizefuncs = sizefuncs

    def __getattr__(self, key):
        func = getattr(self.module, key)
        assert isinstance(func, (BuiltinFunctionType, FunctionType))

        return self.manager.decorate(self.sizefuncs[key], func)