Skip to content

Commit 09dd755

Browse files
committed
Ensure Hypot for double handles insignificant results
1 parent 753df42 commit 09dd755

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y)
5353
|| (typeof(T) == typeof(nint)));
5454

5555
return Vector128.ConditionalSelect(
56-
(Vector128.GreaterThan(xMag, yMag) & IsPositive(yMag)) | IsNegative(xMag),
56+
(Vector128.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector128.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag),
5757
x,
5858
y
5959
);
@@ -95,7 +95,7 @@ public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y)
9595
|| (typeof(T) == typeof(nint)));
9696

9797
return Vector256.ConditionalSelect(
98-
(Vector256.GreaterThan(xMag, yMag) & IsPositive(yMag)) | IsNegative(xMag),
98+
(Vector256.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector256.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag),
9999
x,
100100
y
101101
);
@@ -137,7 +137,7 @@ public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y)
137137
|| (typeof(T) == typeof(nint)));
138138

139139
return Vector512.ConditionalSelect(
140-
(Vector512.GreaterThan(xMag, yMag) & IsPositive(yMag)) | IsNegative(xMag),
140+
(Vector512.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector512.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag),
141141
x,
142142
y
143143
);

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y)
5252
|| (typeof(T) == typeof(nint)));
5353

5454
return Vector128.ConditionalSelect(
55-
(Vector128.LessThan(xMag, yMag) & IsPositive(xMag)) | IsNegative(yMag),
55+
(Vector128.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector128.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag),
5656
x,
5757
y
5858
);
@@ -94,7 +94,7 @@ public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y)
9494
|| (typeof(T) == typeof(nint)));
9595

9696
return Vector256.ConditionalSelect(
97-
(Vector256.LessThan(xMag, yMag) & IsPositive(xMag)) | IsNegative(yMag),
97+
(Vector256.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector256.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag),
9898
x,
9999
y
100100
);
@@ -136,7 +136,7 @@ public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y)
136136
|| (typeof(T) == typeof(nint)));
137137

138138
return Vector512.ConditionalSelect(
139-
(Vector512.LessThan(xMag, yMag) & IsPositive(xMag)) | IsNegative(yMag),
139+
(Vector512.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector512.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag),
140140
x,
141141
y
142142
);

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ public static TVectorDouble HypotDouble<TVectorDouble, TVectorUInt64>(TVectorDou
336336

337337
TVectorUInt64 expDiff = xExp - yExp;
338338

339+
// Cover cases where x or y is insignifican compared to the other
340+
TVectorDouble insignificanMask = Unsafe.BitCast<TVectorUInt64, TVectorDouble>(
341+
TVectorUInt64.GreaterThanOrEqual(expDiff, TVectorUInt64.Create(double.SignificandLength + 1)) &
342+
TVectorUInt64.LessThanOrEqual(expDiff, TVectorUInt64.Create(unchecked((ulong)(-double.SignificandLength - 1))))
343+
);
344+
TVectorDouble insignificantResult = ax + ay;
345+
339346
// To prevent overflow, scale down by 2^+600
340347
TVectorUInt64 expBiasP500 = TVectorUInt64.Create(double.ExponentBias + 500);
341348
TVectorUInt64 scaleDownMask = TVectorUInt64.GreaterThan(xExp, expBiasP500) | TVectorUInt64.GreaterThan(yExp, expBiasP500);
@@ -427,6 +434,7 @@ public static TVectorDouble HypotDouble<TVectorDouble, TVectorUInt64>(TVectorDou
427434
// the inputs is NaN. Otherwise if either input
428435
// is NaN, we return NaN
429436

437+
result = TVectorDouble.ConditionalSelect(insignificanMask, insignificantResult, result);
430438
result = TVectorDouble.ConditionalSelect(nanMask, TVectorDouble.Create(double.NaN), result);
431439
result = TVectorDouble.ConditionalSelect(infinityMask, TVectorDouble.Create(double.PositiveInfinity), result);
432440

@@ -1179,7 +1187,7 @@ public static TVector MaxMagnitudeNumber<TVector, T>(TVector x, TVector y)
11791187
|| (typeof(T) == typeof(nint)));
11801188

11811189
return TVector.ConditionalSelect(
1182-
(TVector.GreaterThan(xMag, yMag) & TVector.IsPositive(yMag)) | TVector.IsNegative(xMag),
1190+
(TVector.LessThan(xMag, yMag) & TVector.IsPositive(xMag)) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(x)) | TVector.IsNegative(yMag),
11831191
x,
11841192
y
11851193
);
@@ -1266,7 +1274,7 @@ public static TVector MinMagnitudeNumber<TVector, T>(TVector x, TVector y)
12661274
|| (typeof(T) == typeof(nint)));
12671275

12681276
return TVector.ConditionalSelect(
1269-
(TVector.LessThan(xMag, yMag) & TVector.IsPositive(xMag)) | TVector.IsNegative(yMag),
1277+
(TVector.LessThan(xMag, yMag) & TVector.IsPositive(xMag)) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(x)) | TVector.IsNegative(yMag),
12701278
x,
12711279
y
12721280
);

0 commit comments

Comments
 (0)