<filename>src/animated_parse_tree/utils/custom_functions.py
from functools import lru_cache
from math import factorial


@lru_cache
def tetrate(a, b):
    if not (b <= 2 or a * b < 10):
        raise MemoryError('Value too large to compute')
    if b == 0:
        return 1
    return a ** tetrate(a, b - 1)


@lru_cache
def double_factorial(a: int):
    if a < 0:
        raise ValueError('Argument to double factorial must be a positive integer')
    if a == 0 or a == 1:
        return 1
    return a * double_factorial(a - 2)


@lru_cache
def superfactorial(a: int):
    if a < 0:
        raise ValueError('Argument to superfactorial must be a positive integer')
    if a == 0:
        return 1
    return factorial(a) * superfactorial(a - 1)

@lru_cache
def hyperfactorial(a: int):
    if a < 0:
        raise ValueError('Argument to hyperfactorial must be a positive integer')
    if a == 0:
        return 1
    return (a ** a) * hyperfactorial(a - 1)

### FUTURE FEATURES ###

# def series(start: int, end: int, function):
#     pass

<filename>src/animated_parse_tree/utils/custom_functions.py
from functools import lru_cache
from math import factorial


@lru_cache
def tetrate(a, b):
    if not (b <= 2 or a * b < 10):
        raise MemoryError('Value too large to compute')
    if b == 0:
        return 1
    return a ** tetrate(a, b - 1)


@lru_cache
def double_factorial(a: int):
    if a < 0:
        raise ValueError('Argument to double factorial must be a positive integer')
    if a == 0 or a == 1:
        return 1
    return a * double_factorial(a - 2)


@lru_cache
def superfactorial(a: int):
    if a < 0:
        raise ValueError('Argument to superfactorial must be a positive integer')
    if a == 0:
        return 1
    return factorial(a) * superfactorial(a - 1)

@lru_cache
def hyperfactorial(a: int):
    if a < 0:
        raise ValueError('Argument to hyperfactorial must be a positive integer')
    if a == 0:
        return 1
    return (a ** a) * hyperfactorial(a - 1)

### FUTURE FEATURES ###

# def series(start: int, end: int, function):
#     pass

### FUTURE FEATURES ### # def series(start: int, end: int, function): #     pass