diff --git a/CHANGELOG.md b/CHANGELOG.md index 512b4b3..4b5c2ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - X10D: Added `MathUtility.Bias(float, float)` and `MathUtility.Bias(double, double)`. - X10D: Added `MathUtility.ExponentialDecay(float, float, float)` and `MathUtility.ExponentialDecay(double, double, double)`. - X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`. +- X10D: Added `MathUtility.Sawtooth(float)` and `MathUtility.Sawtooth(double)`. - X10D: Added `MathUtility.ScaleRange(float, float, float, float, float)` and `MathUtility.ScaleRange(double, double, double, double, double)` - X10D: Added `MathUtility.Sigmoid(float)` and `MathUtility.Sigmoid(double)`. diff --git a/X10D.Tests/src/Math/MathUtilityTests.cs b/X10D.Tests/src/Math/MathUtilityTests.cs index 45c37ab..f58835c 100644 --- a/X10D.Tests/src/Math/MathUtilityTests.cs +++ b/X10D.Tests/src/Math/MathUtilityTests.cs @@ -163,6 +163,72 @@ public class MathUtilityTests Assert.AreEqual(1.0f, floatResult); } + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_Given0Point5AsDouble() + { + const double value = 0.5; + + const double expected = 0.5; + double actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6); + } + + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_Given0Point5AsSingle() + { + const float value = 0.5f; + + const float expected = 0.5f; + float actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6f); + } + + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_Given1Point5AsDouble() + { + const double value = 1.5; + + const double expected = 0.5; + double actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6); + } + + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_Given1Point5AsSingle() + { + const float value = 1.5f; + + const float expected = 0.5f; + float actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6f); + } + + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_GivenNegative1Point5AsDouble() + { + const double value = -1.5; + + const double expected = 0.5; + double actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6); + } + + [TestMethod] + public void Sawtooth_ShouldReturn0Point5_GivenNegative1Point5AsSingle() + { + const float value = -1.5f; + + const float expected = 0.5f; + float actual = MathUtility.Sawtooth(value); + + Assert.AreEqual(expected, actual, 1e-6f); + } + [TestMethod] public void ScaleRangeDouble_ShouldScaleRange_GivenItsValues() { diff --git a/X10D/src/Math/MathUtility.cs b/X10D/src/Math/MathUtility.cs index dc9b2f7..18d0009 100644 --- a/X10D/src/Math/MathUtility.cs +++ b/X10D/src/Math/MathUtility.cs @@ -287,6 +287,26 @@ public static class MathUtility return System.Math.Pow(value, 1.0 / gamma); } + /// + /// Returns the incremental sawtooth wave of a given value. + /// + /// The value to calculate. + /// The sawtooth wave of the given value. + public static float Sawtooth(float value) + { + return (value - MathF.Floor(value)); + } + + /// + /// Returns the incremental sawtooth wave of a given value. + /// + /// The value to calculate. + /// The sawtooth wave of the given value. + public static double Sawtooth(double value) + { + return (value - System.Math.Floor(value)); + } + /// /// Converts a value from being a percentage of one range, to being the same percentage in a new range. ///