def map_unconstrained_range(
    x: float, in_min: float, in_max: float, out_min: float, out_max: float
) -> float:
    """
    Maps a number from one range to another. Somewhat similar to the Arduino
    :attr:`map()` function, but returns a floating point result, and
    does not constrain the output value to be between :attr:`out_min` and
    :attr:`out_max`. If :attr:`in_min` is greater than :attr:`in_max` or
    :attr:`out_min` is greater than :attr:`out_max`, the corresponding range
    is reversed, allowing, for example, mapping a range of 0-10 to 50-0.

    See also :py:func:`map_range`

    .. code-block::

        from adafruit_simplemath import map_unconstrained_range

        celsius = -20
        fahrenheit = map_unconstrained_range(celsius, 0, 100, 32, 212)
        print(celsius, "degress Celsius =", fahrenheit, "degrees Fahrenheit")

    :param float x: Value to convert
    :param float in_min: Start value of input range.
    :param float in_max: End value of input range.
    :param float out_min: Start value of output range.
    :param float out_max: End value of output range.
    :return: Returns value mapped to new range.
    :rtype: float
    """
    in_range = in_max - in_min
    in_delta = x - in_min
    if in_range != 0:
        mapped = in_delta / in_range
    elif in_delta != 0:
        mapped = in_delta
    else:
        mapped = 0.5
    mapped *= out_max - out_min
    mapped += out_min

    return mapped