Skip to content

Commit 42255ea

Browse files
Fix Scalar.Abs for TInteger.MinValue (#95597)
* Fix Scalar.Abs for TInteger.MinValue Fixes #95592. * Fix build, add tests
1 parent 8094803 commit 42255ea

File tree

5 files changed

+75
-6
lines changed

5 files changed

+75
-6
lines changed

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Scalar.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,30 +139,55 @@ public static T One
139139
public static T Abs(T value)
140140
{
141141
// byte, ushort, uint, and ulong should have already been handled
142-
142+
// avoid Math.Abs for integers since it throws for MinValue
143143
if (typeof(T) == typeof(double))
144144
{
145145
return (T)(object)Math.Abs((double)(object)value);
146146
}
147147
else if (typeof(T) == typeof(short))
148148
{
149-
return (T)(object)Math.Abs((short)(object)value);
149+
short v = (short)(object)value;
150+
if (v < 0)
151+
{
152+
v = (short)-v;
153+
}
154+
return (T)(object)v;
150155
}
151156
else if (typeof(T) == typeof(int))
152157
{
153-
return (T)(object)Math.Abs((int)(object)value);
158+
int v = (int)(object)value;
159+
if (v < 0)
160+
{
161+
v = -v;
162+
}
163+
return (T)(object)v;
154164
}
155165
else if (typeof(T) == typeof(long))
156166
{
157-
return (T)(object)Math.Abs((long)(object)value);
167+
long v = (long)(object)value;
168+
if (v < 0)
169+
{
170+
v = -v;
171+
}
172+
return (T)(object)v;
158173
}
159174
else if (typeof(T) == typeof(nint))
160175
{
161-
return (T)(object)Math.Abs((nint)(object)value);
176+
nint v = (nint)(object)value;
177+
if (v < 0)
178+
{
179+
v = -v;
180+
}
181+
return (T)(object)v;
162182
}
163183
else if (typeof(T) == typeof(sbyte))
164184
{
165-
return (T)(object)Math.Abs((sbyte)(object)value);
185+
sbyte v = (sbyte)(object)value;
186+
if (v < 0)
187+
{
188+
v = (sbyte)-v;
189+
}
190+
return (T)(object)v;
166191
}
167192
else if (typeof(T) == typeof(float))
168193
{

src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4533,6 +4533,17 @@ public void Vector128SingleCopyToOffsetTest()
45334533
Assert.True(array.AsSpan().SequenceEqual([0.0f, 2.0f, 2.0f, 2.0f, 2.0f]));
45344534
}
45354535

4536+
[Fact]
4537+
public void Vector128SByteAbs_MinValue()
4538+
{
4539+
Vector128<sbyte> vector = Vector128.Create(sbyte.MinValue);
4540+
Vector128<sbyte> abs = Vector128.Abs(vector);
4541+
for (int index = 0; index < Vector128<sbyte>.Count; index++)
4542+
{
4543+
Assert.Equal(sbyte.MinValue, vector.GetElement(index));
4544+
}
4545+
}
4546+
45364547
[Fact]
45374548
public void IsSupportedByte() => TestIsSupported<byte>();
45384549

src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5555,6 +5555,17 @@ public void Vector256SingleCopyToOffsetTest()
55555555
Assert.True(array.AsSpan().SequenceEqual([0.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f]));
55565556
}
55575557

5558+
[Fact]
5559+
public void Vector256SByteAbs_MinValue()
5560+
{
5561+
Vector256<sbyte> vector = Vector256.Create(sbyte.MinValue);
5562+
Vector256<sbyte> abs = Vector256.Abs(vector);
5563+
for (int index = 0; index < Vector256<sbyte>.Count; index++)
5564+
{
5565+
Assert.Equal(sbyte.MinValue, vector.GetElement(index));
5566+
}
5567+
}
5568+
55585569
[Fact]
55595570
public void IsSupportedByte() => TestIsSupported<byte>();
55605571

src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5032,6 +5032,17 @@ public void Vector512SingleCopyToOffsetTest()
50325032
Assert.True(array.AsSpan().SequenceEqual([0.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f]));
50335033
}
50345034

5035+
[Fact]
5036+
public void Vector512SByteAbs_MinValue()
5037+
{
5038+
Vector512<sbyte> vector = Vector512.Create(sbyte.MinValue);
5039+
Vector512<sbyte> abs = Vector512.Abs(vector);
5040+
for (int index = 0; index < Vector512<sbyte>.Count; index++)
5041+
{
5042+
Assert.Equal(sbyte.MinValue, vector.GetElement(index));
5043+
}
5044+
}
5045+
50355046
[Fact]
50365047
public void IsSupportedByte() => TestIsSupported<byte>();
50375048

src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,6 +3953,17 @@ public void Vector64SingleCopyToOffsetTest()
39533953
Assert.True(array.AsSpan().SequenceEqual([0.0f, 2.0f, 2.0f]));
39543954
}
39553955

3956+
[Fact]
3957+
public void Vector64SByteAbs_MinValue()
3958+
{
3959+
Vector64<sbyte> vector = Vector64.Create(sbyte.MinValue);
3960+
Vector64<sbyte> abs = Vector64.Abs(vector);
3961+
for (int index = 0; index < Vector64<sbyte>.Count; index++)
3962+
{
3963+
Assert.Equal(sbyte.MinValue, vector.GetElement(index));
3964+
}
3965+
}
3966+
39563967
[Fact]
39573968
public void IsSupportedByte() => TestIsSupported<byte>();
39583969

0 commit comments

Comments
 (0)