import math


def bound_value(value, minimum=-math.inf, maximum=math.inf, to_int=False):
    """
    Bounds a value between a minimum and maximum

    :param value: the value to bound
    :type value: int/float

    :param minimum: the lower bound
    :type minimum: int/float

    :param maximum: the upper bound
    :type maximum: int/float

    :param to_int: whether or not to cast the result to an int
    :type to_int: bool


    :returns: the bounded value
    """
    if minimum is None:  # in case None is passed in
        minimum = -math.inf
    if maximum is None:
        maximum = math.inf
    if to_int:
        if isinstance(minimum, float) and minimum != -math.inf:
            return int(min(max(value, math.ceil(minimum)), maximum))
        return int(min(max(value, minimum), maximum))
    return min(max(value, minimum), maximum)