diff --git a/CHANGELOG.md b/CHANGELOG.md
index 407ce5b..6a42897 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## 3.2.0
### Added
+- X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`
- X10D: Added `RoundUpToPowerOf2()` for built-in integer types
- X10D: Added `Vector2.Deconstruct()`
- X10D: Added `Vector3.Deconstruct()`
diff --git a/X10D.Tests/src/Math/MathUtilityTests.cs b/X10D.Tests/src/Math/MathUtilityTests.cs
new file mode 100644
index 0000000..7ee327f
--- /dev/null
+++ b/X10D.Tests/src/Math/MathUtilityTests.cs
@@ -0,0 +1,46 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using X10D.Core;
+using X10D.Math;
+
+namespace X10D.Tests.Math;
+
+[TestClass]
+public class MathUtilityTests
+{
+ [TestMethod]
+ public void InverseLerp_ShouldReturn0_5_Given0_5_0_1()
+ {
+ double doubleResult = MathUtility.InverseLerp(0.5, 0.0, 1.0);
+ float floatResult = MathUtility.InverseLerp(0.5f, 0f, 1f);
+
+ Assert.AreEqual(0.5, doubleResult, 1e-6);
+ Assert.AreEqual(0.5f, floatResult, 1e-6f);
+ }
+
+ [TestMethod]
+ public void InverseLerp_ShouldReturn0_5_Given5_0_10()
+ {
+ double doubleResult = MathUtility.InverseLerp(5.0, 0.0, 10.0);
+ float floatResult = MathUtility.InverseLerp(5f, 0f, 10f);
+
+ Assert.AreEqual(0.5, doubleResult, 1e-6);
+ Assert.AreEqual(0.5f, floatResult, 1e-6f);
+ }
+
+ [TestMethod]
+ public void InverseLerp_ShouldReturn0_GivenTwoEqualValues()
+ {
+ var random = new Random();
+ double doubleA = random.NextDouble();
+ double doubleB = random.NextDouble();
+
+ float floatA = random.NextSingle();
+ float floatB = random.NextSingle();
+
+ double doubleResult = MathUtility.InverseLerp(doubleA, doubleB, doubleB);
+ float floatResult = MathUtility.InverseLerp(floatA, floatB, floatB);
+
+ Assert.AreEqual(0.0, doubleResult, 1e-6);
+ Assert.AreEqual(0.0f, floatResult, 1e-6f);
+ }
+}
diff --git a/X10D/src/Math/MathUtility.cs b/X10D/src/Math/MathUtility.cs
index 8613219..a75cc95 100644
--- a/X10D/src/Math/MathUtility.cs
+++ b/X10D/src/Math/MathUtility.cs
@@ -8,6 +8,54 @@ namespace X10D.Math;
///
public static class MathUtility
{
+ ///
+ /// Returns the linear interpolation inverse of a value, such that it determines where a value lies between two other
+ /// values.
+ ///
+ /// The value whose lerp inverse is to be found.
+ /// The start of the range.
+ /// The end of the range.
+ /// A value determined by (alpha - start) / (end - start).
+ [Pure]
+#if NETSTANDARD2_1
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+#endif
+ public static float InverseLerp(float alpha, float start, float end)
+ {
+ if (MathF.Abs(start - end) < float.Epsilon)
+ {
+ return 0f;
+ }
+
+ return (alpha - start) / (end - start);
+ }
+
+ ///
+ /// Returns the linear interpolation inverse of a value, such that it determines where a value lies between two other
+ /// values.
+ ///
+ /// The value whose lerp inverse is to be found.
+ /// The start of the range.
+ /// The end of the range.
+ /// A value determined by (alpha - start) / (end - start).
+ [Pure]
+#if NETSTANDARD2_1
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+#endif
+ public static double InverseLerp(double alpha, double start, double end)
+ {
+ if (System.Math.Abs(start - end) < double.Epsilon)
+ {
+ return 0.0;
+ }
+
+ return (alpha - start) / (end - start);
+ }
+
///
/// Linearly interpolates from one value to a target using a specified alpha.
///