Skip to content

Commit 84d447f

Browse files
committed
Codegen improvements to Guard.IsCloseTo
1 parent a412d31 commit 84d447f

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

Microsoft.Toolkit/Diagnostics/Guard.Comparable.Numeric.cs

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ public static partial class Guard
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2424
public static void IsCloseTo(int value, int target, uint delta, string name)
2525
{
26-
// Cast to long before calculating the difference to avoid overflows
27-
// when the values are at the two extremes of the supported range.
28-
// Then cast to double to calculate the absolute value: this allows
29-
// the JIT compiler to use AVX instructions on X64 CPUs instead of
30-
// conditional jumps, which results in more efficient assembly code.
31-
// The IEEE 754 specs guarantees that a 32 bit integer value can
32-
// be stored within a double precision floating point value with
33-
// no loss of precision, so the result will always be correct here.
34-
// The difference is then cast to uint as that's the maximum possible
35-
// value it can have, and comparing two 32 bit integer values
36-
// results in shorter and slightly faster code than using doubles.
37-
if ((uint)Math.Abs((double)((long)value - target)) <= delta)
26+
uint difference;
27+
28+
if (value >= target)
29+
{
30+
difference = (uint)(value - target);
31+
}
32+
else
33+
{
34+
difference = (uint)(target - value);
35+
}
36+
37+
if (difference <= delta)
3838
{
3939
return;
4040
}
@@ -53,7 +53,18 @@ public static void IsCloseTo(int value, int target, uint delta, string name)
5353
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5454
public static void IsNotCloseTo(int value, int target, uint delta, string name)
5555
{
56-
if ((uint)Math.Abs((double)((long)value - target)) > delta)
56+
uint difference;
57+
58+
if (value >= target)
59+
{
60+
difference = (uint)(value - target);
61+
}
62+
else
63+
{
64+
difference = (uint)(target - value);
65+
}
66+
67+
if (difference > delta)
5768
{
5869
return;
5970
}
@@ -69,12 +80,21 @@ public static void IsNotCloseTo(int value, int target, uint delta, string name)
6980
/// <param name="delta">The maximum distance to allow between <paramref name="value"/> and <paramref name="target"/>.</param>
7081
/// <param name="name">The name of the input parameter being tested.</param>
7182
/// <exception cref="ArgumentException">Thrown if (<paramref name="value"/> - <paramref name="target"/>) > <paramref name="delta"/>.</exception>
72-
[MethodImpl(MethodImplOptions.NoInlining)]
83+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7384
public static void IsCloseTo(long value, long target, ulong delta, string name)
7485
{
75-
// This method and the one below are not inlined because
76-
// using the decimal type results in quite a bit of code.
77-
if ((ulong)Math.Abs((decimal)value - target) <= delta)
86+
ulong difference;
87+
88+
if (value >= target)
89+
{
90+
difference = (ulong)(value - target);
91+
}
92+
else
93+
{
94+
difference = (ulong)(target - value);
95+
}
96+
97+
if (difference <= delta)
7898
{
7999
return;
80100
}
@@ -90,10 +110,21 @@ public static void IsCloseTo(long value, long target, ulong delta, string name)
90110
/// <param name="delta">The maximum distance to allow between <paramref name="value"/> and <paramref name="target"/>.</param>
91111
/// <param name="name">The name of the input parameter being tested.</param>
92112
/// <exception cref="ArgumentException">Thrown if (<paramref name="value"/> - <paramref name="target"/>) &lt;= <paramref name="delta"/>.</exception>
93-
[MethodImpl(MethodImplOptions.NoInlining)]
113+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
94114
public static void IsNotCloseTo(long value, long target, ulong delta, string name)
95115
{
96-
if ((ulong)Math.Abs((decimal)value - target) > delta)
116+
ulong difference;
117+
118+
if (value >= target)
119+
{
120+
difference = (ulong)(value - target);
121+
}
122+
else
123+
{
124+
difference = (ulong)(target - value);
125+
}
126+
127+
if (difference > delta)
97128
{
98129
return;
99130
}

0 commit comments

Comments
 (0)