diff --git a/adafruit_simplemath.py b/adafruit_simplemath.py
index 10326f0..4f2aac7 100644
--- a/adafruit_simplemath.py
+++ b/adafruit_simplemath.py
@@ -1,4 +1,5 @@
 # SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries LLC
+# SPDX-FileCopyrightText: 2021 James Carr
 #
 # SPDX-License-Identifier: MIT
 """
@@ -8,7 +9,7 @@
 Math utility functions
 
 
-* Author(s): Adafruit Industries
+* Author(s): Dan Halbert, James Carr
 
 Implementation Notes
 --------------------
@@ -27,12 +28,59 @@ def map_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 ``map()`` function,
-    but returns a floating point result, and constrains the output value to be between
-    ``out_min`` and ``out_max``.
-    If ``in_min`` is greater than ``in_max`` or ``out_min`` is greater than ``out_max``,
-    the corresponding range is reversed, allowing, for example, mapping a range of 0-10 to 50-0.
+    Maps a number from one range to another. Somewhat similar to the Arduino
+    :attr:`map()` function, but returns a floating point result, and
+    constrains 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_unconstrained_range`
+
+    .. code-block::
+
+        from adafruit_simplemath import map_range
+
+        percent = 23
+        screen_width = 320  # or board.DISPLAY.width
+        x = map_range(percent, 0, 100, 0, screen_width - 1)
+        print("X position", percent, "% from the left of screen is", x)
+
+    :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
+    """
+
+    mapped = map_unconstrained_range(x, in_min, in_max, out_min, out_max)
+    return constrain(mapped, out_min, out_max)
+
+
+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.
@@ -50,22 +98,26 @@ def map_range(
         mapped = 0.5
     mapped *= out_max - out_min
     mapped += out_min
-    if out_min <= out_max:
-        return max(min(mapped, out_max), out_min)
-    return min(max(mapped, out_max), out_min)
+
+    return mapped
 
 
 def constrain(x: float, out_min: float, out_max: float) -> float:
-    """Constrains ``x`` to be within the inclusive range [``out_min``, ``out_max``].
-    Sometimes called ``clip`` or ``clamp`` in other libraries.
-    ``out_min`` should be less than or equal to ``out_max``.
-    If ``x`` is less than ``out_min``, return ``out_min``.
-    If ``x`` is greater than ``out_max``, return ``out_max``.
-    Otherwise just return ``x``.
+    """Constrains :attr:`x` to be within the inclusive range
+    [:attr:`out_min`, :attr:`out_max`]. Sometimes called :attr:`clip` or
+    :attr:`clamp` in other libraries. :attr:`out_min` should be less than or
+    equal to :attr:`out_max`.
+    If :attr:`x` is less than :attr:`out_min`, return :attr:`out_min`.
+    If :attr:`x` is greater than :attr:`out_max`, return :attr:`out_max`.
+    Otherwise just return :attr:`x`.
+    If :attr:`max_value` is less than :attr:`min_value`, they will be swapped.
 
+    :param float x: Value to constrain
     :param float out_min: Lower bound of output range.
     :param float out_max: Upper bound of output range.
     :return: Returns value constrained to given range.
     :rtype: float
     """
-    return max(out_min, min(x, out_max))
+    if out_min <= out_max:
+        return max(min(x, out_max), out_min)
+    return min(max(x, out_max), out_min)
diff --git a/examples/simplemath_simpletest.py b/examples/simplemath_simpletest.py
index e73f6a6..de14f9e 100644
--- a/examples/simplemath_simpletest.py
+++ b/examples/simplemath_simpletest.py
@@ -1,13 +1,54 @@
-# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
+# SPDX-FileCopyrightText: 2021 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: 2021 James Carr
 #
 # SPDX-License-Identifier: Unlicense
 
-from adafruit_simplemath import map_range, constrain
+from adafruit_simplemath import map_range, map_unconstrained_range, constrain
 
+print("map_range() examples")
 # Map, say, a sensor value, from a range of 0-255 to 0-1023.
-print(map_range(30, 0, 255, 0, 1023))
+sensor_input_value = 30
+sensor_converted_value = map_range(sensor_input_value, 0, 255, 0, 1023)
+print(
+    "Sensor input value:",
+    sensor_input_value,
+    "Converted value:",
+    sensor_converted_value,
+)
 
+percent = 23
+screen_width = 320  # or board.DISPLAY.width
+x = map_range(percent, 0, 100, 0, screen_width - 1)
+print("X position", percent, "% from the left of screen is", x)
+
+print("\nmap_unconstrained_range() examples")
+celsius = 20
+fahrenheit = map_unconstrained_range(celsius, 0, 100, 32, 212)
+print(celsius, "degress Celsius =", fahrenheit, "degrees Fahrenheit")
+
+celsius = -20
+fahrenheit = map_unconstrained_range(celsius, 0, 100, 32, 212)
+print(celsius, "degress Celsius =", fahrenheit, "degrees Fahrenheit")
+
+print("\nconstrain() examples")
 # Constrain a value to a range.
-print(constrain(0, 1, 3))  # prints 1
-print(constrain(4, 1, 3))  # prints 3
-print(constrain(2, 2, 3))  # prints 2
+def constrain_example(value, min_value, max_value):
+    constrained_value = constrain(value, min_value, max_value)
+    print(
+        "Constrain",
+        value,
+        "between [",
+        min_value,
+        "and",
+        max_value,
+        "] gives",
+        constrained_value,
+    )
+
+
+constrain_example(0, 1, 3)  # expects 1
+constrain_example(0, 3, 1)  # expects 1
+constrain_example(4, 1, 3)  # expects 3
+constrain_example(4, 3, 1)  # expects 3
+constrain_example(2, 2, 3)  # expects 2
+constrain_example(2, 3, 2)  # expects 2
diff --git a/tests/constrain_test.py b/tests/constrain_test.py
index e52808d..3a935dd 100644
--- a/tests/constrain_test.py
+++ b/tests/constrain_test.py
@@ -1,4 +1,5 @@
 # SPDX-FileCopyrightText: 2021 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: 2021 James Carr
 #
 # SPDX-License-Identifier: Unlicense
 
@@ -10,3 +11,8 @@ def test_constrain():
     assert constrain(10, 1, 10) == 10
     assert constrain(0, 1, 10) == 1
     assert constrain(11, 1, 10) == 10
+
+    # Check out_min > out_max
+    assert constrain(5, 10, 0) == 5
+    assert constrain(-5, 10, 0) == 0
+    assert constrain(15, 10, 0) == 10
diff --git a/tests/map_range_test.py b/tests/map_range_test.py
index fee5025..3faacf7 100644
--- a/tests/map_range_test.py
+++ b/tests/map_range_test.py
@@ -13,3 +13,6 @@ def test_map_range():
     assert map_range(1, 10, 0, 0, 5) == 4.5
     assert map_range(1, 0, 10, 10, 0) == 9.0
     assert map_range(10, 1, 10, 1, 20) == 20.0
+    # Tests for out-of-range descending output order
+    assert map_range(11, 1, 10, 20, 1) == 1.0
+    assert map_range(-1, 1, 10, 20, 1) == 20.0
diff --git a/tests/map_unconstrained_range_test.py b/tests/map_unconstrained_range_test.py
new file mode 100644
index 0000000..5d21837
--- /dev/null
+++ b/tests/map_unconstrained_range_test.py
@@ -0,0 +1,11 @@
+# SPDX-FileCopyrightText: 2021 James Carr
+#
+# SPDX-License-Identifier: Unlicense
+
+from adafruit_simplemath import map_unconstrained_range
+
+
+def test_map_unconstrained_range():
+    assert map_unconstrained_range(-40, 32, 212, 0, 100) == -40.0
+    assert map_unconstrained_range(50, 32, 212, 0, 100) == 10.0
+    assert map_unconstrained_range(392, 32, 212, 0, 100) == 200.0