Skip to content

Commit a1318a5

Browse files
committed
Ensure that very large inputs are handled
1 parent 549ef80 commit a1318a5

File tree

1 file changed

+128
-38
lines changed
  • src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics

1 file changed

+128
-38
lines changed

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

Lines changed: 128 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static TVectorDouble CosDouble<TVectorDouble, TVectorInt64>(TVectorDouble
102102
result = TVectorDouble.MultiplyAddEstimate(TVectorDouble.Create(-0.5), x2, TVectorDouble.One);
103103
}
104104
}
105-
else
105+
else if (TVectorDouble.LessThanAll(ax, TVectorDouble.Create(5000000.0)))
106106
{
107107
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
108108
(TVectorDouble r, TVectorDouble rr, TVectorInt64 region) = SinCosReduce<TVectorDouble, TVectorInt64>(ax);
@@ -136,12 +136,29 @@ public static TVectorDouble CosDouble<TVectorDouble, TVectorInt64>(TVectorDouble
136136
result
137137
);
138138
}
139+
else
140+
{
141+
return ScalarFallback(x);
142+
}
139143

140144
return TVectorDouble.ConditionalSelect(
141145
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
142146
result, // for elements: |x| >= 2^-27, infinity, or NaN
143147
TVectorDouble.One // for elements: 2^-27 > |x|
144148
);
149+
150+
static TVectorDouble ScalarFallback(TVectorDouble x)
151+
{
152+
TVectorDouble result = TVectorDouble.Zero;
153+
154+
for (int i = 0; i < TVectorDouble.Count; i++)
155+
{
156+
double scalar = double.Cos(x[i]);
157+
result = result.WithElement(i, scalar);
158+
}
159+
160+
return result;
161+
}
145162
}
146163

147164
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -244,7 +261,7 @@ public static TVectorSingle CosSingle<TVectorSingle, TVectorInt32, TVectorDouble
244261
result = TVectorSingle.MultiplyAddEstimate(TVectorSingle.Create(-0.5f), x2, TVectorSingle.One);
245262
}
246263
}
247-
else
264+
else if (TVectorSingle.LessThanAll(ax, TVectorSingle.Create(5000000.0f)))
248265
{
249266
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
250267

@@ -276,6 +293,10 @@ public static TVectorSingle CosSingle<TVectorSingle, TVectorInt32, TVectorDouble
276293
result
277294
);
278295
}
296+
else
297+
{
298+
return ScalarFallback(x);
299+
}
279300

280301
return TVectorSingle.ConditionalSelect(
281302
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
@@ -303,6 +324,19 @@ static TVectorDouble CoreImpl(TVectorDouble ax)
303324
-result // region 1 or 2
304325
);
305326
}
327+
328+
static TVectorSingle ScalarFallback(TVectorSingle x)
329+
{
330+
TVectorSingle result = TVectorSingle.Zero;
331+
332+
for (int i = 0; i < TVectorSingle.Count; i++)
333+
{
334+
float scalar = float.Cos(x[i]);
335+
result = result.WithElement(i, scalar);
336+
}
337+
338+
return result;
339+
}
306340
}
307341

308342
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1733,24 +1767,22 @@ public static (TVectorDouble Sin, TVectorDouble Cos) SinCosDouble<TVectorDouble,
17331767
cosResult = TVectorDouble.MultiplyAddEstimate(TVectorDouble.Create(-0.5), x2, TVectorDouble.One);
17341768
}
17351769
}
1736-
else
1770+
else if (TVectorDouble.LessThanAll(ax, TVectorDouble.Create(5000000.0)))
17371771
{
17381772
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
17391773
(TVectorDouble r, TVectorDouble rr, TVectorInt64 region) = SinCosReduce<TVectorDouble, TVectorInt64>(ax);
17401774

17411775
TVectorDouble sin = SinDoubleLarge(r, rr);
17421776
TVectorDouble cos = CosDoubleLarge(r, rr);
17431777

1744-
TVectorDouble regionMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero));
1745-
17461778
sinResult = TVectorDouble.ConditionalSelect(
1747-
regionMask,
1779+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
17481780
sin, // region 0 or 2
17491781
cos // region 1 or 3
17501782
);
17511783

17521784
cosResult = TVectorDouble.ConditionalSelect(
1753-
regionMask,
1785+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
17541786
cos, // region 0 or 2
17551787
sin // region 1 or 3
17561788
);
@@ -1770,51 +1802,64 @@ public static (TVectorDouble Sin, TVectorDouble Cos) SinCosDouble<TVectorDouble,
17701802
);
17711803

17721804
// Propagate the NaN that was passed in
1773-
TVectorDouble nanMask = TVectorDouble.IsNaN(x);
1774-
17751805
sinResult = TVectorDouble.ConditionalSelect(
1776-
nanMask,
1806+
TVectorDouble.IsNaN(x),
17771807
x,
17781808
sinResult
17791809
);
17801810

17811811
cosResult = TVectorDouble.ConditionalSelect(
1782-
nanMask,
1812+
TVectorDouble.IsNaN(x),
17831813
x,
17841814
cosResult
17851815
);
17861816

17871817
// Return NaN for infinity
1788-
TVectorDouble infinityMask = TVectorDouble.IsPositiveInfinity(ax);
1789-
17901818
sinResult = TVectorDouble.ConditionalSelect(
1791-
infinityMask,
1819+
TVectorDouble.IsPositiveInfinity(ax),
17921820
TVectorDouble.Create(double.NaN),
17931821
sinResult
17941822
);
17951823

17961824
cosResult = TVectorDouble.ConditionalSelect(
1797-
infinityMask,
1825+
TVectorDouble.IsPositiveInfinity(ax),
17981826
TVectorDouble.Create(double.NaN),
17991827
cosResult
18001828
);
18011829
}
1802-
1803-
TVectorDouble argNotSmallerMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1)));
1830+
else
1831+
{
1832+
return ScalarFallback(x);
1833+
}
18041834

18051835
sinResult = TVectorDouble.ConditionalSelect(
1806-
argNotSmallerMask,
1836+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
18071837
sinResult, // for elements: |x| >= 2^-27, infinity, or NaN
18081838
x // for elements: 2^-27 > |x|
18091839
);
18101840

18111841
cosResult = TVectorDouble.ConditionalSelect(
1812-
argNotSmallerMask,
1842+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
18131843
cosResult, // for elements: |x| >= 2^-27, infinity, or NaN
18141844
TVectorDouble.One // for elements: 2^-27 > |x|
18151845
);
18161846

18171847
return (sinResult, cosResult);
1848+
1849+
static (TVectorDouble Sin, TVectorDouble Cos) ScalarFallback(TVectorDouble x)
1850+
{
1851+
TVectorDouble sinResult = TVectorDouble.Zero;
1852+
TVectorDouble cosResult = TVectorDouble.Zero;
1853+
1854+
for (int i = 0; i < TVectorDouble.Count; i++)
1855+
{
1856+
(double sinScalar, double cosScalar) = double.SinCos(x[i]);
1857+
sinResult = sinResult.WithElement(i, sinScalar);
1858+
cosResult = cosResult.WithElement(i, cosScalar);
1859+
}
1860+
1861+
return (sinResult, cosResult);
1862+
}
18181863
}
18191864

18201865
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1886,7 +1931,7 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle<TVectorSingle,
18861931
cosResult = TVectorSingle.MultiplyAddEstimate(TVectorSingle.Create(-0.5f), x2, TVectorSingle.One);
18871932
}
18881933
}
1889-
else
1934+
else if (TVectorSingle.LessThanAll(ax, TVectorSingle.Create(5000000.0f)))
18901935
{
18911936
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
18921937

@@ -1907,48 +1952,46 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle<TVectorSingle,
19071952
}
19081953

19091954
// Propagate the NaN that was passed in
1910-
TVectorSingle nanMask = TVectorSingle.IsNaN(x);
1911-
19121955
sinResult = TVectorSingle.ConditionalSelect(
1913-
nanMask,
1956+
TVectorSingle.IsNaN(x),
19141957
x,
19151958
sinResult
19161959
);
19171960

19181961
cosResult = TVectorSingle.ConditionalSelect(
1919-
nanMask,
1962+
TVectorSingle.IsNaN(x),
19201963
x,
19211964
cosResult
19221965
);
19231966

19241967
// Return NaN for infinity
1925-
TVectorSingle infinityMask = TVectorSingle.IsPositiveInfinity(ax);
1926-
19271968
sinResult = TVectorSingle.ConditionalSelect(
1928-
infinityMask,
1969+
TVectorSingle.IsPositiveInfinity(ax),
19291970
TVectorSingle.Create(float.NaN),
19301971
sinResult
19311972
);
19321973

19331974
cosResult = TVectorSingle.ConditionalSelect(
1934-
infinityMask,
1975+
TVectorSingle.IsPositiveInfinity(ax),
19351976
TVectorSingle.Create(float.NaN),
19361977
cosResult
19371978
);
19381979

19391980
return (sinResult, cosResult);
19401981
}
1941-
1942-
TVectorSingle argNotSmallerMask = Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1)));
1982+
else
1983+
{
1984+
return ScalarFallback(x);
1985+
}
19431986

19441987
sinResult = TVectorSingle.ConditionalSelect(
1945-
argNotSmallerMask,
1988+
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
19461989
sinResult, // for elements: |x| >= 2^-27, infinity, or NaN
19471990
x // for elements: 2^-27 > |x|
19481991
);
19491992

19501993
cosResult = TVectorSingle.ConditionalSelect(
1951-
argNotSmallerMask,
1994+
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
19521995
cosResult, // for elements: |x| >= 2^-27, infinity, or NaN
19531996
TVectorSingle.One // for elements: 2^-27 > |x|
19541997
);
@@ -1963,16 +2006,14 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle<TVectorSingle,
19632006
TVectorDouble sin = SinSinglePoly(r);
19642007
TVectorDouble cos = CosSingleLarge(r);
19652008

1966-
TVectorDouble regionMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero));
1967-
19682009
TVectorDouble sinResult = TVectorDouble.ConditionalSelect(
1969-
regionMask,
2010+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
19702011
sin, // region 0 or 2
19712012
cos // region 1 or 3
19722013
);
19732014

19742015
TVectorDouble cosResult = TVectorDouble.ConditionalSelect(
1975-
regionMask,
2016+
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
19762017
cos, // region 0 or 2
19772018
sin // region 1 or 3
19782019
);
@@ -1993,6 +2034,21 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle<TVectorSingle,
19932034

19942035
return (sinResult, cosResult);
19952036
}
2037+
2038+
static (TVectorSingle Sin, TVectorSingle Cos) ScalarFallback(TVectorSingle x)
2039+
{
2040+
TVectorSingle sinResult = TVectorSingle.Zero;
2041+
TVectorSingle cosResult = TVectorSingle.Zero;
2042+
2043+
for (int i = 0; i < TVectorSingle.Count; i++)
2044+
{
2045+
(float sinScalar, float cosScalar) = float.SinCos(x[i]);
2046+
sinResult = sinResult.WithElement(i, sinScalar);
2047+
cosResult = cosResult.WithElement(i, cosScalar);
2048+
}
2049+
2050+
return (sinResult, cosResult);
2051+
}
19962052
}
19972053

19982054
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -2076,7 +2132,7 @@ public static TVectorDouble SinDouble<TVectorDouble, TVectorInt64>(TVectorDouble
20762132
result = TVectorDouble.MultiplyAddEstimate(TVectorDouble.Create(-0.16666666666666666), x3, x);
20772133
}
20782134
}
2079-
else
2135+
else if (TVectorDouble.LessThanAll(ax, TVectorDouble.Create(5000000.0)))
20802136
{
20812137
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
20822138
(TVectorDouble r, TVectorDouble rr, TVectorInt64 region) = SinCosReduce<TVectorDouble, TVectorInt64>(ax);
@@ -2112,12 +2168,29 @@ public static TVectorDouble SinDouble<TVectorDouble, TVectorInt64>(TVectorDouble
21122168
result
21132169
);
21142170
}
2171+
else
2172+
{
2173+
return ScalarFallback(x);
2174+
}
21152175

21162176
return TVectorDouble.ConditionalSelect(
21172177
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
21182178
result, // for elements: |x| >= 2^-27, infinity, or NaN
21192179
x // for elements: 2^-27 > |x|
21202180
);
2181+
2182+
static TVectorDouble ScalarFallback(TVectorDouble x)
2183+
{
2184+
TVectorDouble result = TVectorDouble.Zero;
2185+
2186+
for (int i = 0; i < TVectorDouble.Count; i++)
2187+
{
2188+
double scalar = double.Sin(x[i]);
2189+
result = result.WithElement(i, scalar);
2190+
}
2191+
2192+
return result;
2193+
}
21212194
}
21222195

21232196
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -2215,7 +2288,7 @@ public static TVectorSingle SinSingle<TVectorSingle, TVectorInt32, TVectorDouble
22152288
result = TVectorSingle.MultiplyAddEstimate(TVectorSingle.Create(-0.16666667f), x3, x);
22162289
}
22172290
}
2218-
else
2291+
else if (TVectorSingle.LessThanAll(ax, TVectorSingle.Create(5000000.0f)))
22192292
{
22202293
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
22212294

@@ -2247,6 +2320,10 @@ public static TVectorSingle SinSingle<TVectorSingle, TVectorInt32, TVectorDouble
22472320
result
22482321
);
22492322
}
2323+
else
2324+
{
2325+
return ScalarFallback(x);
2326+
}
22502327

22512328
return TVectorSingle.ConditionalSelect(
22522329
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
@@ -2277,6 +2354,19 @@ static TVectorDouble CoreImpl(TVectorDouble x)
22772354
-result // negative in region 0 or 2, positive in region 1 or 3
22782355
);
22792356
}
2357+
2358+
static TVectorSingle ScalarFallback(TVectorSingle x)
2359+
{
2360+
TVectorSingle result = TVectorSingle.Zero;
2361+
2362+
for (int i = 0; i < TVectorSingle.Count; i++)
2363+
{
2364+
float scalar = float.Sin(x[i]);
2365+
result = result.WithElement(i, scalar);
2366+
}
2367+
2368+
return result;
2369+
}
22802370
}
22812371

22822372
[MethodImpl(MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)