Skip to content

Commit 00fbe40

Browse files
authored
Add Abs, Min(x, y) & Max(x, y) helper methods to the UnitMath (#859)
1 parent 8efee7e commit 00fbe40

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

UnitsNet.Tests/UnitMathTests.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,44 @@ namespace UnitsNet.Tests
77
{
88
public class UnitMathTests
99
{
10+
[Fact]
11+
public void AbsoluteValueOfZeroReturnsZero()
12+
{
13+
var quantity = Length.Zero;
14+
15+
var result = quantity.Abs();
16+
17+
Assert.StrictEqual(quantity, result);
18+
}
19+
20+
[Fact]
21+
public void AbsoluteValueOfPositiveReturnsSameValue()
22+
{
23+
var quantity = Length.FromCentimeters(1);
24+
25+
var result = quantity.Abs();
26+
27+
Assert.StrictEqual(quantity, result);
28+
}
29+
30+
[Fact]
31+
public void AbsoluteValueOfNegativeReturnsPositive()
32+
{
33+
var quantity = Length.FromCentimeters(-1);
34+
35+
var result = quantity.Abs();
36+
37+
Assert.StrictEqual(-quantity, result);
38+
}
39+
40+
[Fact]
41+
public void AbsoluteValueOfNullReferenceThrowsException()
42+
{
43+
IQuantity quantity = null;
44+
45+
Assert.Throws<NullReferenceException>(() => quantity.Abs());
46+
}
47+
1048
[Fact]
1149
public void AverageOfDifferentUnitsThrowsException()
1250
{
@@ -23,6 +61,14 @@ public void AverageOfEmptySourceThrowsException()
2361
Assert.Throws<InvalidOperationException>(() => units.Average(LengthUnit.Centimeter));
2462
}
2563

64+
[Fact]
65+
public void AverageOfLengthsWithNullValueThrowsException()
66+
{
67+
var units = new IQuantity[] {Length.FromMeters(1), null};
68+
69+
Assert.Throws<NullReferenceException>(() => units.Average(LengthUnit.Centimeter));
70+
}
71+
2672
[Fact]
2773
public void AverageOfLengthsCalculatesCorrectly()
2874
{
@@ -61,6 +107,18 @@ public void AverageOfLengthsWithSelectorCalculatesCorrectly()
61107
Assert.Equal(LengthUnit.Centimeter, average.Unit);
62108
}
63109

110+
[Fact]
111+
public void MaxOfTwoLengthsReturnsTheLargestValue()
112+
{
113+
var firstValue = Length.FromMeters(1);
114+
var secondValue = Length.FromCentimeters(50);
115+
116+
Length max = UnitMath.Max(firstValue, secondValue);
117+
118+
Assert.Equal(1, max.Value);
119+
Assert.Equal(LengthUnit.Meter, max.Unit);
120+
}
121+
64122
[Fact]
65123
public void MaxOfDifferentUnitsThrowsException()
66124
{
@@ -69,6 +127,14 @@ public void MaxOfDifferentUnitsThrowsException()
69127
Assert.Throws<ArgumentException>(() => units.Max(LengthUnit.Centimeter));
70128
}
71129

130+
[Fact]
131+
public void MaxOfLengthsWithNullValueThrowsException()
132+
{
133+
var units = new IQuantity[] {Length.FromMeters(1), null};
134+
135+
Assert.Throws<NullReferenceException>(() => units.Max(LengthUnit.Centimeter));
136+
}
137+
72138
[Fact]
73139
public void MaxOfEmptySourceThrowsException()
74140
{
@@ -115,6 +181,18 @@ public void MaxOfLengthsWithSelectorCalculatesCorrectly()
115181
Assert.Equal(LengthUnit.Centimeter, max.Unit);
116182
}
117183

184+
[Fact]
185+
public void MinOfTwoLengthsReturnsTheSmallestValue()
186+
{
187+
var firstValue = Length.FromMeters(1);
188+
var secondValue = Length.FromCentimeters(50);
189+
190+
Length min = UnitMath.Min(firstValue, secondValue);
191+
192+
Assert.Equal(50, min.Value);
193+
Assert.Equal(LengthUnit.Centimeter, min.Unit);
194+
}
195+
118196
[Fact]
119197
public void MinOfDifferentUnitsThrowsException()
120198
{
@@ -123,6 +201,14 @@ public void MinOfDifferentUnitsThrowsException()
123201
Assert.Throws<ArgumentException>(() => units.Min(LengthUnit.Centimeter));
124202
}
125203

204+
[Fact]
205+
public void MinOfLengthsWithNullValueThrowsException()
206+
{
207+
var units = new IQuantity[] {Length.FromMeters(1), null};
208+
209+
Assert.Throws<NullReferenceException>(() => units.Min(LengthUnit.Centimeter));
210+
}
211+
126212
[Fact]
127213
public void MinOfEmptySourceThrowsException()
128214
{
@@ -177,6 +263,14 @@ public void SumOfDifferentUnitsThrowsException()
177263
Assert.Throws<ArgumentException>(() => units.Sum(LengthUnit.Centimeter));
178264
}
179265

266+
[Fact]
267+
public void SumOfLengthsWithNullValueThrowsException()
268+
{
269+
var units = new IQuantity[] {Length.FromMeters(1), null};
270+
271+
Assert.Throws<NullReferenceException>(() => units.Sum(LengthUnit.Centimeter));
272+
}
273+
180274
[Fact]
181275
public void SumOfEmptySourceReturnsZero()
182276
{

UnitsNet/UnitMath.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ namespace UnitsNet
99
/// </summary>
1010
public static class UnitMath
1111
{
12+
/// <summary>Returns the absolute value of a <typeparamref name="TQuantity" />.</summary>
13+
/// <param name="value">
14+
/// A quantity with a value that is greater than or equal to <see cref="F:System.Double.MinValue" />,
15+
/// but less than or equal to <see cref="F:System.Double.MaxValue" />.
16+
/// </param>
17+
/// <returns>A quantity with a value, such that 0 ≤ value ≤ <see cref="F:System.Double.MaxValue" />.</returns>
18+
public static TQuantity Abs<TQuantity>(this TQuantity value) where TQuantity : IQuantity
19+
{
20+
return value.Value >= 0 ? value : (TQuantity) Quantity.From(-value.Value, value.Unit);
21+
}
22+
1223
/// <summary>Computes the sum of a sequence of <typeparamref name="TQuantity" /> values.</summary>
1324
/// <param name="source">A sequence of <typeparamref name="TQuantity" /> values to calculate the sum of.</param>
1425
/// <param name="unitType">The desired unit type for the resulting quantity</param>
@@ -47,6 +58,16 @@ public static TQuantity Sum<TSource, TQuantity>(this IEnumerable<TSource> source
4758
return source.Select(selector).Sum(unitType);
4859
}
4960

61+
/// <summary>Returns the smaller of two <typeparamref name="TQuantity" /> values.</summary>
62+
/// <typeparam name="TQuantity">The type of quantities to compare.</typeparam>
63+
/// <param name="val1">The first of two <typeparamref name="TQuantity" /> values to compare.</param>
64+
/// <param name="val2">The second of two <typeparamref name="TQuantity" /> values to compare.</param>
65+
/// <returns>Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is smaller.</returns>
66+
public static TQuantity Min<TQuantity>(TQuantity val1, TQuantity val2) where TQuantity : IComparable, IQuantity
67+
{
68+
return val1.CompareTo(val2) == 1 ? val2 : val1;
69+
}
70+
5071
/// <summary>Computes the min of a sequence of <typeparamref name="TQuantity" /> values.</summary>
5172
/// <param name="source">A sequence of <typeparamref name="TQuantity" /> values to calculate the min of.</param>
5273
/// <param name="unitType">The desired unit type for the resulting quantity</param>
@@ -87,6 +108,16 @@ public static TQuantity Min<TSource, TQuantity>(this IEnumerable<TSource> source
87108
return source.Select(selector).Min(unitType);
88109
}
89110

111+
/// <summary>Returns the larger of two <typeparamref name="TQuantity" /> values.</summary>
112+
/// <typeparam name="TQuantity">The type of quantities to compare.</typeparam>
113+
/// <param name="val1">The first of two <typeparamref name="TQuantity" /> values to compare.</param>
114+
/// <param name="val2">The second of two <typeparamref name="TQuantity" /> values to compare.</param>
115+
/// <returns>Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is larger.</returns>
116+
public static TQuantity Max<TQuantity>(TQuantity val1, TQuantity val2) where TQuantity : IComparable, IQuantity
117+
{
118+
return val1.CompareTo(val2) == -1 ? val2 : val1;
119+
}
120+
90121
/// <summary>Computes the max of a sequence of <typeparamref name="TQuantity" /> values.</summary>
91122
/// <param name="source">A sequence of <typeparamref name="TQuantity" /> values to calculate the max of.</param>
92123
/// <param name="unitType">The desired unit type for the resulting quantity</param>

0 commit comments

Comments
 (0)