Skip to content

Commit

Permalink
Ensure that very large inputs are handled
Browse files Browse the repository at this point in the history
  • Loading branch information
tannergooding committed Jul 15, 2024
1 parent 549ef80 commit a1318a5
Showing 1 changed file with 128 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public static TVectorDouble CosDouble<TVectorDouble, TVectorInt64>(TVectorDouble
result = TVectorDouble.MultiplyAddEstimate(TVectorDouble.Create(-0.5), x2, TVectorDouble.One);
}
}
else
else if (TVectorDouble.LessThanAll(ax, TVectorDouble.Create(5000000.0)))
{
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
(TVectorDouble r, TVectorDouble rr, TVectorInt64 region) = SinCosReduce<TVectorDouble, TVectorInt64>(ax);
Expand Down Expand Up @@ -136,12 +136,29 @@ public static TVectorDouble CosDouble<TVectorDouble, TVectorInt64>(TVectorDouble
result
);
}
else
{
return ScalarFallback(x);
}

return TVectorDouble.ConditionalSelect(
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
result, // for elements: |x| >= 2^-27, infinity, or NaN
TVectorDouble.One // for elements: 2^-27 > |x|
);

static TVectorDouble ScalarFallback(TVectorDouble x)
{
TVectorDouble result = TVectorDouble.Zero;

for (int i = 0; i < TVectorDouble.Count; i++)
{
double scalar = double.Cos(x[i]);
result = result.WithElement(i, scalar);
}

return result;
}
}

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

Expand Down Expand Up @@ -276,6 +293,10 @@ public static TVectorSingle CosSingle<TVectorSingle, TVectorInt32, TVectorDouble
result
);
}
else
{
return ScalarFallback(x);
}

return TVectorSingle.ConditionalSelect(
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
Expand Down Expand Up @@ -303,6 +324,19 @@ static TVectorDouble CoreImpl(TVectorDouble ax)
-result // region 1 or 2
);
}

static TVectorSingle ScalarFallback(TVectorSingle x)
{
TVectorSingle result = TVectorSingle.Zero;

for (int i = 0; i < TVectorSingle.Count; i++)
{
float scalar = float.Cos(x[i]);
result = result.WithElement(i, scalar);
}

return result;
}
}

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

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

TVectorDouble regionMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero));

sinResult = TVectorDouble.ConditionalSelect(
regionMask,
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
sin, // region 0 or 2
cos // region 1 or 3
);

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

// Propagate the NaN that was passed in
TVectorDouble nanMask = TVectorDouble.IsNaN(x);

sinResult = TVectorDouble.ConditionalSelect(
nanMask,
TVectorDouble.IsNaN(x),
x,
sinResult
);

cosResult = TVectorDouble.ConditionalSelect(
nanMask,
TVectorDouble.IsNaN(x),
x,
cosResult
);

// Return NaN for infinity
TVectorDouble infinityMask = TVectorDouble.IsPositiveInfinity(ax);

sinResult = TVectorDouble.ConditionalSelect(
infinityMask,
TVectorDouble.IsPositiveInfinity(ax),
TVectorDouble.Create(double.NaN),
sinResult
);

cosResult = TVectorDouble.ConditionalSelect(
infinityMask,
TVectorDouble.IsPositiveInfinity(ax),
TVectorDouble.Create(double.NaN),
cosResult
);
}

TVectorDouble argNotSmallerMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1)));
else
{
return ScalarFallback(x);
}

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

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

return (sinResult, cosResult);

static (TVectorDouble Sin, TVectorDouble Cos) ScalarFallback(TVectorDouble x)
{
TVectorDouble sinResult = TVectorDouble.Zero;
TVectorDouble cosResult = TVectorDouble.Zero;

for (int i = 0; i < TVectorDouble.Count; i++)
{
(double sinScalar, double cosScalar) = double.SinCos(x[i]);
sinResult = sinResult.WithElement(i, sinScalar);
cosResult = cosResult.WithElement(i, cosScalar);
}

return (sinResult, cosResult);
}
}

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

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

// Propagate the NaN that was passed in
TVectorSingle nanMask = TVectorSingle.IsNaN(x);

sinResult = TVectorSingle.ConditionalSelect(
nanMask,
TVectorSingle.IsNaN(x),
x,
sinResult
);

cosResult = TVectorSingle.ConditionalSelect(
nanMask,
TVectorSingle.IsNaN(x),
x,
cosResult
);

// Return NaN for infinity
TVectorSingle infinityMask = TVectorSingle.IsPositiveInfinity(ax);

sinResult = TVectorSingle.ConditionalSelect(
infinityMask,
TVectorSingle.IsPositiveInfinity(ax),
TVectorSingle.Create(float.NaN),
sinResult
);

cosResult = TVectorSingle.ConditionalSelect(
infinityMask,
TVectorSingle.IsPositiveInfinity(ax),
TVectorSingle.Create(float.NaN),
cosResult
);

return (sinResult, cosResult);
}

TVectorSingle argNotSmallerMask = Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1)));
else
{
return ScalarFallback(x);
}

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

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

TVectorDouble regionMask = Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero));

TVectorDouble sinResult = TVectorDouble.ConditionalSelect(
regionMask,
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.Equals(region & TVectorInt64.One, TVectorInt64.Zero)),
sin, // region 0 or 2
cos // region 1 or 3
);

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

return (sinResult, cosResult);
}

static (TVectorSingle Sin, TVectorSingle Cos) ScalarFallback(TVectorSingle x)
{
TVectorSingle sinResult = TVectorSingle.Zero;
TVectorSingle cosResult = TVectorSingle.Zero;

for (int i = 0; i < TVectorSingle.Count; i++)
{
(float sinScalar, float cosScalar) = float.SinCos(x[i]);
sinResult = sinResult.WithElement(i, sinScalar);
cosResult = cosResult.WithElement(i, cosScalar);
}

return (sinResult, cosResult);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -2076,7 +2132,7 @@ public static TVectorDouble SinDouble<TVectorDouble, TVectorInt64>(TVectorDouble
result = TVectorDouble.MultiplyAddEstimate(TVectorDouble.Create(-0.16666666666666666), x3, x);
}
}
else
else if (TVectorDouble.LessThanAll(ax, TVectorDouble.Create(5000000.0)))
{
// at least one element is: |x| > (pi / 4) -or- infinite -or- nan
(TVectorDouble r, TVectorDouble rr, TVectorInt64 region) = SinCosReduce<TVectorDouble, TVectorInt64>(ax);
Expand Down Expand Up @@ -2112,12 +2168,29 @@ public static TVectorDouble SinDouble<TVectorDouble, TVectorInt64>(TVectorDouble
result
);
}
else
{
return ScalarFallback(x);
}

return TVectorDouble.ConditionalSelect(
Unsafe.BitCast<TVectorInt64, TVectorDouble>(TVectorInt64.GreaterThan(ux, TVectorInt64.Create(ARG_SMALLER - 1))),
result, // for elements: |x| >= 2^-27, infinity, or NaN
x // for elements: 2^-27 > |x|
);

static TVectorDouble ScalarFallback(TVectorDouble x)
{
TVectorDouble result = TVectorDouble.Zero;

for (int i = 0; i < TVectorDouble.Count; i++)
{
double scalar = double.Sin(x[i]);
result = result.WithElement(i, scalar);
}

return result;
}
}

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

Expand Down Expand Up @@ -2247,6 +2320,10 @@ public static TVectorSingle SinSingle<TVectorSingle, TVectorInt32, TVectorDouble
result
);
}
else
{
return ScalarFallback(x);
}

return TVectorSingle.ConditionalSelect(
Unsafe.BitCast<TVectorInt32, TVectorSingle>(TVectorInt32.GreaterThan(ux, TVectorInt32.Create(ARG_SMALLER - 1))),
Expand Down Expand Up @@ -2277,6 +2354,19 @@ static TVectorDouble CoreImpl(TVectorDouble x)
-result // negative in region 0 or 2, positive in region 1 or 3
);
}

static TVectorSingle ScalarFallback(TVectorSingle x)
{
TVectorSingle result = TVectorSingle.Zero;

for (int i = 0; i < TVectorSingle.Count; i++)
{
float scalar = float.Sin(x[i]);
result = result.WithElement(i, scalar);
}

return result;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down

0 comments on commit a1318a5

Please sign in to comment.