def RANDOM(a, b):
    if not is_number(a):
        raise ValueError(
            f"First parameter of RANDOM function is not a number: {safe_cut(a)}"
        )
    if not is_number(b):
        raise ValueError(
            f"Second parameter of RANDOM function is not a number: {safe_cut(b)}"
        )

    a = float(a)
    b = float(b)

    return random.uniform(a, b)
def MATH(a, b, c):
    operations = "+-*/^"
    if not is_number(a):
        raise ValueError(
            f"First parameter of MATH function is not a number: {safe_cut(a)}")
    if b not in operations:
        raise ValueError(
            f"Operation parameter of MATH function not an operation: {safe_cut(b)}"
        )
    if not is_number(c):
        raise ValueError(
            f"Second parameter of MATH function is not a number: {safe_cut(c)}"
        )

    a = int(a) if is_whole(a) else float(a)
    c = int(c) if is_whole(c) else float(c)

    if b == "+": return a + c
    if b == "-": return a - c

    if b == "*":
        if abs(a) > 1e50:
            raise ValueError(
                f"First parameter of MATH function too large to safely multiply: {safe_cut(a)} (limit 10^50)"
            )
        if abs(c) > 1e50:
            raise ValueError(
                f"Second parameter of MATH function too large to safely multiply: {safe_cut(a)} (limit 10^50)"
            )
        return a * c

    if b == "/":
        if c == 0:
            raise ZeroDivisionError(
                f"Second parameter of MATH function in division cannot be zero"
            )
        return a / c

    if b == "^":
        if abs(a) > 1024:
            raise ValueError(
                f"First parameter of MATH function too large to safely exponentiate: {safe_cut(a)} (limit 1024)"
            )
        if abs(c) > 128:
            raise ValueError(
                f"Second parameter of MATH function too large to safely exponentiate: {safe_cut(c)} (limit 128)"
            )
        return a**c
def MOD(a, b):
    if not is_number(a):
        raise ValueError(
            f"First parameter of MOD function is not a number: {safe_cut(a)}")
    if not is_number(b):
        raise ValueError(
            f"First parameter of MOD function is not a number: {safe_cut(a)}")

    a = int(a) if is_whole(a) else float(a)
    b = int(b) if is_whole(b) else float(b)

    if b == 0:
        raise ZeroDivisionError(
            f"Second parameter of MOD function cannot be zero")

    return a % b
def COMPARE(a, b, c):
    operations = [">", "<", ">=", "<=", "!=", "="]
    if b not in operations:
        raise ValueError(
            f"Operation parameter of COMPARE function is not a comparison operator: {safe_cut(b)}"
        )

    if is_number(a): a = float(a)
    if is_number(c): c = float(c)

    if operations.index(b) <= 3 and type(a) != type(c):
        raise TypeError(
            f"Entries to compare in COMPARE function are not the same type")

    if b == ">": return int(a > c)
    if b == "<": return int(a < c)
    if b == ">=": return int(a >= c)
    if b == "<=": return int(a <= c)
    if b == "!=": return int(a != c)
    if b == "=": return int(a == c)
def CEIL(a):
    if not is_number(a):
        raise ValueError(
            f"CEIL function parameter is not a number: {safe_cut(a)}")

    return np.ceil(float(a))
def FLOOR(a):
    if not is_number(a):
        raise ValueError(
            f"FLOOR function parameter is not a number: {safe_cut(a)}")

    return int(float(a))
def ROUND(a):
    if not is_number(a):
        raise ValueError(
            f"ROUND function parameter is not a number: {safe_cut(a)}")

    return int(round(float(a)))
def ABS(a):
    if not is_number(a):
        raise TypeError(
            f"Parameter of ABS function must be a number: {safe_cut(a)}")

    return abs(int(a) if is_whole(a) else float(a))