From d3c3db741f5c81842eb03c8f5255bc1ae5b5b174 Mon Sep 17 00:00:00 2001 From: lipchev Date: Sun, 17 Aug 2025 15:06:45 +0300 Subject: [PATCH 1/4] - refactored the clamp function: no longer converting the clamped result - updated the tests --- UnitsNet.Tests/UnitMathTests.cs | 44 ++++++++++++++++--------- UnitsNet/UnitMath.cs | 58 +++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/UnitsNet.Tests/UnitMathTests.cs b/UnitsNet.Tests/UnitMathTests.cs index 80e4720840..e81881c0c5 100644 --- a/UnitsNet.Tests/UnitMathTests.cs +++ b/UnitsNet.Tests/UnitMathTests.cs @@ -164,28 +164,42 @@ public void SumOfLengthsWithSelectorCalculatesCorrectly() } [Fact] - public void ClampCalculatesCorrectly() + public void Clamp_ReturnsValue_WhenWithinBounds() { var min = Length.FromMeters(-1); var max = Length.FromCentimeters(150); - - var value1 = Length.FromMillimeters(33); - - Length clampedValue = UnitMath.Clamp(value1, min, max); + var value = Length.FromMillimeters(33); + + Length clampedValue = UnitMath.Clamp(value, min, max); + Assert.Equal(33, clampedValue.Value); Assert.Equal(LengthUnit.Millimeter, clampedValue.Unit); + } - var value2 = Length.FromMillimeters(-1500); - - Length clampedMin = UnitMath.Clamp(value2, min, max); - Assert.Equal(-1000, clampedMin.Value); - Assert.Equal(LengthUnit.Millimeter, clampedMin.Unit); - - var value3 = Length.FromMillimeters(2000); + [Fact] + public void Clamp_ReturnsMin_WhenValueIsBelowMin() + { + var min = Length.FromMeters(-1); + var max = Length.FromCentimeters(150); + var value = Length.FromMillimeters(-1500); + + Length clampedMin = UnitMath.Clamp(value, min, max); + + Assert.Equal(-1, clampedMin.Value); + Assert.Equal(LengthUnit.Meter, clampedMin.Unit); + } - Length clampedMax = UnitMath.Clamp(value3, min, max); - Assert.Equal(1500, clampedMax.Value); - Assert.Equal(LengthUnit.Millimeter, clampedMax.Unit); + [Fact] + public void Clamp_ReturnsMax_WhenValueIsAboveMax() + { + var min = Length.FromMeters(-1); + var max = Length.FromCentimeters(150); + var value = Length.FromMillimeters(2000); + + Length clampedMax = UnitMath.Clamp(value, min, max); + + Assert.Equal(150, clampedMax.Value); + Assert.Equal(LengthUnit.Centimeter, clampedMax.Unit); } [Fact] diff --git a/UnitsNet/UnitMath.cs b/UnitsNet/UnitMath.cs index 64eb866210..cf149f7433 100644 --- a/UnitsNet/UnitMath.cs +++ b/UnitsNet/UnitMath.cs @@ -57,43 +57,53 @@ public static TQuantity Max(TQuantity val1, TQuantity val2) { return val1.CompareTo(val2) == -1 ? val2 : val1; } - - /// Returns clamped to the inclusive range of and . - /// The value to be clamped. - /// The lower bound of the result. - /// The upper bound of the result. + + /// + /// Clamps the specified to the inclusive range defined by and + /// . + /// + /// + /// The type of the quantity, which must implement and . + /// + /// The value to clamp. + /// The minimum allowable value. + /// The maximum allowable value. /// - /// if . - /// - /// -or- - /// - /// (converted to value.Unit) if < . - /// - /// -or- - /// - /// (converted to value.Unit) if < . + /// The clamped value: + /// + /// + /// + /// if it lies within the range [, + /// ]. + /// + /// + /// + /// if is less than . + /// + /// + /// if is greater than . + /// + /// /// /// - /// cannot be greater than . + /// Thrown if is greater than . /// - public static TQuantity Clamp(TQuantity value, TQuantity min, TQuantity max) where TQuantity : IComparable, IQuantity + public static TQuantity Clamp(TQuantity value, TQuantity min, TQuantity max) + where TQuantity : IQuantity, IComparable { - var minValue = (TQuantity)min.ToUnit(value.Unit); - var maxValue = (TQuantity)max.ToUnit(value.Unit); - - if (minValue.CompareTo(maxValue) > 0) + if (min.CompareTo(max) > 0) { throw new ArgumentException($"min ({min}) cannot be greater than max ({max})", nameof(min)); } - if (value.CompareTo(minValue) < 0) + if (value.CompareTo(min) < 0) { - return minValue; + return min; } - if (value.CompareTo(maxValue) > 0) + if (value.CompareTo(max) > 0) { - return maxValue; + return max; } return value; From 18e576a17131fab132ce1c08cf706a9153a8d40c Mon Sep 17 00:00:00 2001 From: lipchev Date: Mon, 18 Aug 2025 12:52:18 +0300 Subject: [PATCH 2/4] reverted the clamp behavior- converting the result back to the value unit --- UnitsNet.Tests/UnitMathTests.cs | 12 ++++++------ UnitsNet/UnitMath.cs | 25 +++++++++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/UnitsNet.Tests/UnitMathTests.cs b/UnitsNet.Tests/UnitMathTests.cs index d52e0857e4..67509044fd 100644 --- a/UnitsNet.Tests/UnitMathTests.cs +++ b/UnitsNet.Tests/UnitMathTests.cs @@ -169,7 +169,7 @@ public void Clamp_ReturnsValue_WhenWithinBounds() } [Fact] - public void Clamp_ReturnsMin_WhenValueIsBelowMin() + public void Clamp_ReturnsMinAsValueUnit_WhenValueIsBelowMin() { var min = Length.FromMeters(-1); var max = Length.FromCentimeters(150); @@ -177,12 +177,12 @@ public void Clamp_ReturnsMin_WhenValueIsBelowMin() Length clampedMin = UnitMath.Clamp(value, min, max); - Assert.Equal(-1, clampedMin.Value); - Assert.Equal(LengthUnit.Meter, clampedMin.Unit); + Assert.Equal(-1000, clampedMin.Value); + Assert.Equal(LengthUnit.Millimeter, clampedMin.Unit); } [Fact] - public void Clamp_ReturnsMax_WhenValueIsAboveMax() + public void Clamp_ReturnsMaxAsValueUnit_WhenValueIsAboveMax() { var min = Length.FromMeters(-1); var max = Length.FromCentimeters(150); @@ -190,8 +190,8 @@ public void Clamp_ReturnsMax_WhenValueIsAboveMax() Length clampedMax = UnitMath.Clamp(value, min, max); - Assert.Equal(150, clampedMax.Value); - Assert.Equal(LengthUnit.Centimeter, clampedMax.Unit); + Assert.Equal(1500, clampedMax.Value); + Assert.Equal(LengthUnit.Millimeter, clampedMax.Unit); } [Fact] diff --git a/UnitsNet/UnitMath.cs b/UnitsNet/UnitMath.cs index f5f1f31637..9d3de0e9be 100644 --- a/UnitsNet/UnitMath.cs +++ b/UnitsNet/UnitMath.cs @@ -52,10 +52,10 @@ public static TQuantity Max(TQuantity val1, TQuantity val2) /// /// /// - /// if is less than . + /// (converted to value.Unit) if is less than . /// /// - /// if is greater than . + /// (converted to value.Unit) if is greater than . /// /// /// @@ -63,21 +63,30 @@ public static TQuantity Max(TQuantity val1, TQuantity val2) /// Thrown if is greater than . /// public static TQuantity Clamp(TQuantity value, TQuantity min, TQuantity max) - where TQuantity : IQuantity, IComparable + where TQuantity : IQuantityOfType, IComparable { - if (min.CompareTo(max) > 0) + UnitKey unitKey = value.UnitKey; + #if NET + TQuantity minValue = TQuantity.Create(min.As(unitKey), unitKey); + TQuantity maxValue = TQuantity.Create(max.As(unitKey), unitKey); + #else + TQuantity minValue = value.QuantityInfo.Create(min.As(unitKey), unitKey); + TQuantity maxValue = value.QuantityInfo.Create(max.As(unitKey), unitKey); + #endif + + if (minValue.CompareTo(maxValue) > 0) { throw new ArgumentException($"min ({min}) cannot be greater than max ({max})", nameof(min)); } - if (value.CompareTo(min) < 0) + if (value.CompareTo(minValue) < 0) { - return min; + return minValue; } - if (value.CompareTo(max) > 0) + if (value.CompareTo(maxValue) > 0) { - return max; + return maxValue; } return value; From c1affc2acc03b66d1e807ae842d6b14695d69541 Mon Sep 17 00:00:00 2001 From: lipchev Date: Mon, 18 Aug 2025 13:45:52 +0300 Subject: [PATCH 3/4] fixing the comment and re-formatting UnitMath.cs --- UnitsNet/UnitMath.cs | 161 ++++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/UnitsNet/UnitMath.cs b/UnitsNet/UnitMath.cs index 9d3de0e9be..4f437eda34 100644 --- a/UnitsNet/UnitMath.cs +++ b/UnitsNet/UnitMath.cs @@ -1,95 +1,96 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; +namespace UnitsNet; -namespace UnitsNet +/// +/// A set of extension methods for some of the most common Math operations, such as Min, Max, Sum and Average +/// +public static class UnitMath { + /// Returns the smaller of two values. + /// The type of quantities to compare. + /// The first of two values to compare. + /// The second of two values to compare. + /// Parameter or , whichever is smaller. + public static TQuantity Min(TQuantity val1, TQuantity val2) + where TQuantity : IQuantity, IComparable + { + return val1.CompareTo(val2) == 1 ? val2 : val1; + } + + /// Returns the larger of two values. + /// The type of quantities to compare. + /// The first of two values to compare. + /// The second of two values to compare. + /// Parameter or , whichever is larger. + public static TQuantity Max(TQuantity val1, TQuantity val2) + where TQuantity : IQuantity, IComparable + { + return val1.CompareTo(val2) == -1 ? val2 : val1; + } + /// - /// A set of extension methods for some of the most common Math operations, such as Min, Max, Sum and Average + /// Clamps the specified to the inclusive range defined by and + /// . /// - public static class UnitMath + /// + /// The type of the quantity, which must implement and + /// . + /// + /// The value to clamp. + /// The minimum allowable value. + /// The maximum allowable value. + /// + /// The clamped value: + /// + /// + /// + /// if it lies within the range [, + /// ]. + /// + /// + /// + /// + /// (converted to value.Unit) if is less than + /// . + /// + /// + /// + /// + /// (converted to value.Unit) if is greater than + /// . + /// + /// + /// + /// + /// + /// Thrown if is greater than . + /// + public static TQuantity Clamp(TQuantity value, TQuantity min, TQuantity max) + where TQuantity : IQuantityOfType, IComparable { - /// Returns the smaller of two values. - /// The type of quantities to compare. - /// The first of two values to compare. - /// The second of two values to compare. - /// Parameter or , whichever is smaller. - public static TQuantity Min(TQuantity val1, TQuantity val2) - where TQuantity : IQuantity, IComparable + UnitKey unitKey = value.UnitKey; +#if NET + TQuantity minValue = TQuantity.Create(min.As(unitKey), unitKey); + TQuantity maxValue = TQuantity.Create(max.As(unitKey), unitKey); +#else + TQuantity minValue = value.QuantityInfo.Create(min.As(unitKey), unitKey); + TQuantity maxValue = value.QuantityInfo.Create(max.As(unitKey), unitKey); +#endif + + if (minValue.CompareTo(maxValue) > 0) { - return val1.CompareTo(val2) == 1 ? val2 : val1; + throw new ArgumentException($"min ({min}) cannot be greater than max ({max})", nameof(min)); } - /// Returns the larger of two values. - /// The type of quantities to compare. - /// The first of two values to compare. - /// The second of two values to compare. - /// Parameter or , whichever is larger. - public static TQuantity Max(TQuantity val1, TQuantity val2) - where TQuantity : IQuantity, IComparable + if (value.CompareTo(minValue) < 0) { - return val1.CompareTo(val2) == -1 ? val2 : val1; + return minValue; } - /// - /// Clamps the specified to the inclusive range defined by and - /// . - /// - /// - /// The type of the quantity, which must implement and . - /// - /// The value to clamp. - /// The minimum allowable value. - /// The maximum allowable value. - /// - /// The clamped value: - /// - /// - /// - /// if it lies within the range [, - /// ]. - /// - /// - /// - /// (converted to value.Unit) if is less than . - /// - /// - /// (converted to value.Unit) if is greater than . - /// - /// - /// - /// - /// Thrown if is greater than . - /// - public static TQuantity Clamp(TQuantity value, TQuantity min, TQuantity max) - where TQuantity : IQuantityOfType, IComparable + if (value.CompareTo(maxValue) > 0) { - UnitKey unitKey = value.UnitKey; - #if NET - TQuantity minValue = TQuantity.Create(min.As(unitKey), unitKey); - TQuantity maxValue = TQuantity.Create(max.As(unitKey), unitKey); - #else - TQuantity minValue = value.QuantityInfo.Create(min.As(unitKey), unitKey); - TQuantity maxValue = value.QuantityInfo.Create(max.As(unitKey), unitKey); - #endif - - if (minValue.CompareTo(maxValue) > 0) - { - throw new ArgumentException($"min ({min}) cannot be greater than max ({max})", nameof(min)); - } - - if (value.CompareTo(minValue) < 0) - { - return minValue; - } - - if (value.CompareTo(maxValue) > 0) - { - return maxValue; - } - - return value; + return maxValue; } + + return value; } } From ac62dc1a87d848e40ba8f925777c18affad06666 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Tue, 19 Aug 2025 08:13:29 +0200 Subject: [PATCH 4/4] Update UnitMath.cs Edit class xmldoc, no longer much math operations left here. --- UnitsNet/UnitMath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UnitsNet/UnitMath.cs b/UnitsNet/UnitMath.cs index 4f437eda34..a6fb77465b 100644 --- a/UnitsNet/UnitMath.cs +++ b/UnitsNet/UnitMath.cs @@ -1,7 +1,7 @@ namespace UnitsNet; /// -/// A set of extension methods for some of the most common Math operations, such as Min, Max, Sum and Average +/// Extension methods for common math operations. /// public static class UnitMath {