Skip to content
52 changes: 52 additions & 0 deletions src/libraries/Common/tests/System/GenericMathTestMemberData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,58 @@ public static IEnumerable<object[]> CopySignSingle
}
}

public static IEnumerable<object[]> AcosDouble
{
get
{
yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 };
yield return new object[] { -1.0, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { -0.78539816339744831, 2.4741354375614093, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(pi / 4)
yield return new object[] { -0.70710678118654752, 2.3561944901923450, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(1 / sqrt(2))
yield return new object[] { -0.69314718055994531, 2.3366425216139770, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(ln(2))
yield return new object[] { -0.63661977236758134, 2.2609034181694367, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(2 / pi)
yield return new object[] { -0.43429448190325183, 2.0200512174769663, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(log10(e))
yield return new object[] { -0.31830988618379067, 1.8947424337268775, DoubleCrossPlatformMachineEpsilon * 10 }; // value: -(1 / pi)
yield return new object[] { -0.0, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { double.NaN, double.NaN, 0.0 };
yield return new object[] { 0.0, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { 0.31830988618379067, 1.2468502198629159, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi)
yield return new object[] { 0.43429448190325183, 1.1215414361128270, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e))
yield return new object[] { 0.63661977236758134, 0.88068923542035660, DoubleCrossPlatformMachineEpsilon }; // value: (2 / pi)
yield return new object[] { 0.69314718055994531, 0.80495013197581640, DoubleCrossPlatformMachineEpsilon }; // value: (ln(2))
yield return new object[] { 0.70710678118654752, 0.78539816339744828, DoubleCrossPlatformMachineEpsilon }; // value: (1 / sqrt(2)), expected: (pi / 4)
yield return new object[] { 0.78539816339744831, 0.66745721602838380, DoubleCrossPlatformMachineEpsilon }; // value: (pi / 4)
yield return new object[] { 1.0, 0.0, 0.0 };
yield return new object[] { double.PositiveInfinity, double.NaN, 0.0 };
}
}

public static IEnumerable<object[]> AcosSingle
{
get
{
yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f };
yield return new object[] { -1.0f, 3.14159274f, SingleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { -0.785398163f, 2.47413540f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(pi / 4)
yield return new object[] { -0.707106781f, 2.35619450f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(1 / sqrt(2))
yield return new object[] { -0.693147181f, 2.33664250f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(ln(2))
yield return new object[] { -0.636619772f, 2.26090336f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(2 / pi)
yield return new object[] { -0.434294482f, 2.02005124f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(log10(e))
yield return new object[] { -0.318309886f, 1.89474249f, SingleCrossPlatformMachineEpsilon * 10 }; // value: -(1 / pi)
yield return new object[] { -0.0f, 1.57079637f, SingleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { float.NaN, float.NaN, 0.0f };
yield return new object[] { 0.0f, 1.57079637f, SingleCrossPlatformMachineEpsilon * 10 };
yield return new object[] { 0.318309886f, 1.24685025f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi)
yield return new object[] { 0.434294482f, 1.12154138f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e))
yield return new object[] { 0.636619772f, 0.880689263f, SingleCrossPlatformMachineEpsilon }; // value: (2 / pi)
yield return new object[] { 0.693147181f, 0.804950058f, SingleCrossPlatformMachineEpsilon }; // value: (ln(2))
yield return new object[] { 0.707106781f, 0.785398185f, SingleCrossPlatformMachineEpsilon }; // value: (1 / sqrt(2)), expected: (pi / 4)
yield return new object[] { 0.785398163f, 0.667457163f, SingleCrossPlatformMachineEpsilon }; // value: (pi / 4)
yield return new object[] { 1.0f, 0.0f, 0.0f };
yield return new object[] { float.PositiveInfinity, float.NaN, 0.0f };
}
}

public static IEnumerable<object[]> AsinDouble
{
get
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Runtime.Intrinsics;

namespace System.Numerics.Tensors
Expand Down Expand Up @@ -29,11 +30,65 @@ public static void Acos<T>(ReadOnlySpan<T> x, Span<T> destination)
private readonly struct AcosOperator<T> : IUnaryOperator<T, T>
where T : ITrigonometricFunctions<T>
{
public static bool Vectorizable => false; // TODO: Vectorize
public static bool Vectorizable =>
#if NET11_0_OR_GREATER
typeof(T) == typeof(float) || typeof(T) == typeof(double);
#else
false;
#endif

public static T Invoke(T x) => T.Acos(x);
public static Vector128<T> Invoke(Vector128<T> x) => throw new NotSupportedException();
public static Vector256<T> Invoke(Vector256<T> x) => throw new NotSupportedException();
public static Vector512<T> Invoke(Vector512<T> x) => throw new NotSupportedException();

public static Vector128<T> Invoke(Vector128<T> x)
{
#if NET11_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector128.Acos(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector128.Acos(x.AsSingle()).As<float, T>();
}
#else
throw new NotSupportedException();
#endif
}

public static Vector256<T> Invoke(Vector256<T> x)
{
#if NET11_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector256.Acos(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector256.Acos(x.AsSingle()).As<float, T>();
}
#else
throw new NotSupportedException();
#endif
}

public static Vector512<T> Invoke(Vector512<T> x)
{
#if NET11_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector512.Acos(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector512.Acos(x.AsSingle()).As<float, T>();
}
#else
throw new NotSupportedException();
#endif
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ public static IEnumerable<object[]> SpanDestinationFunctionsToTest()
T? trigTolerance = IsFmaSupported ? null : Helpers.DetermineTolerance<T>(doubleTolerance: 1e-10, floatTolerance: 1e-4f);

yield return Create(TensorPrimitives.Acosh, T.Acosh);
yield return Create(TensorPrimitives.AcosPi, T.AcosPi);
yield return Create(TensorPrimitives.Acos, T.Acos);
yield return Create(TensorPrimitives.AcosPi, T.AcosPi, Helpers.DetermineTolerance<T>(doubleTolerance: 2e-9, floatTolerance: 1e-6f));
yield return Create(TensorPrimitives.Acos, T.Acos, Helpers.DetermineTolerance<T>(doubleTolerance: 2e-9, floatTolerance: 1e-6f));
yield return Create(TensorPrimitives.Asinh, T.Asinh);
yield return Create(TensorPrimitives.AsinPi, T.AsinPi);
yield return Create(TensorPrimitives.Asin, T.Asin, trigTolerance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,47 @@ public static Vector128<float> Asin(Vector128<float> vector)
}
}

/// <inheritdoc cref="Vector64.Acos(Vector64{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<double> Acos(Vector128<double> vector)
{
if (IsHardwareAccelerated)
{
return VectorMath.AcosDouble<Vector128<double>>(vector);
}
else
{
return Create(
Vector64.Acos(vector._lower),
Vector64.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector64.Acos(Vector64{float})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> Acos(Vector128<float> vector)
{
if (IsHardwareAccelerated)
{
if (Vector256.IsHardwareAccelerated)
{
return VectorMath.AcosSingle<Vector128<float>, Vector128<int>, Vector256<double>, Vector256<long>>(vector);
}
else
{
return VectorMath.AcosSingle<Vector128<float>, Vector128<int>, Vector128<double>, Vector128<long>>(vector);
}
}
else
{
return Create(
Vector64.Acos(vector._lower),
Vector64.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector64.Cos(Vector64{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<double> Cos(Vector128<double> vector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,47 @@ public static Vector256<float> Asin(Vector256<float> vector)
}
}

/// <inheritdoc cref="Vector128.Acos(Vector128{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<double> Acos(Vector256<double> vector)
{
if (IsHardwareAccelerated)
{
return VectorMath.AcosDouble<Vector256<double>>(vector);
}
else
{
return Create(
Vector128.Acos(vector._lower),
Vector128.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector128.Acos(Vector128{float})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Acos(Vector256<float> vector)
{
if (IsHardwareAccelerated)
{
if (Vector512.IsHardwareAccelerated)
{
return VectorMath.AcosSingle<Vector256<float>, Vector256<int>, Vector512<double>, Vector512<long>>(vector);
}
else
{
return VectorMath.AcosSingle<Vector256<float>, Vector256<int>, Vector256<double>, Vector256<long>>(vector);
}
}
else
{
return Create(
Vector128.Acos(vector._lower),
Vector128.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector128.Cos(Vector128{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<double> Cos(Vector256<double> vector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,40 @@ public static Vector512<float> Asin(Vector512<float> vector)
}
}

/// <inheritdoc cref="Vector256.Acos(Vector256{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<double> Acos(Vector512<double> vector)
{
if (IsHardwareAccelerated)
{
return VectorMath.AcosDouble<Vector512<double>>(vector);
}
else
{
return Create(
Vector256.Acos(vector._lower),
Vector256.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector256.Acos(Vector256{float})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<float> Acos(Vector512<float> vector)
{
if (IsHardwareAccelerated)
{
return VectorMath.AcosSingle<Vector512<float>, Vector512<int>, Vector512<double>, Vector512<long>>(vector);
}
else
{
return Create(
Vector256.Acos(vector._lower),
Vector256.Acos(vector._upper)
);
}
}

/// <inheritdoc cref="Vector256.Cos(Vector256{double})" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<double> Cos(Vector512<double> vector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,47 @@ public static Vector64<float> Asin(Vector64<float> vector)
}
}

/// <summary>Computes the arc cosine of each element in a vector.</summary>
/// <param name="vector">The vector whose arc cosine is to be computed.</param>
/// <returns>A vector whose elements are the arc cosine of the corresponding elements in <paramref name="vector" />.</returns>
/// <remarks>The angles are returned in radians, and the input should be in the range [-1, 1].</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector64<double> Acos(Vector64<double> vector)
{
if (IsHardwareAccelerated)
{
return VectorMath.AcosDouble<Vector64<double>>(vector);
}
else
{
return Acos<double>(vector);
}
}

/// <summary>Computes the arc cosine of each element in a vector.</summary>
/// <param name="vector">The vector whose arc cosine is to be computed.</param>
/// <returns>A vector whose elements are the arc cosine of the corresponding elements in <paramref name="vector" />.</returns>
/// <remarks>The angles are returned in radians, and the input should be in the range [-1, 1].</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector64<float> Acos(Vector64<float> vector)
{
if (IsHardwareAccelerated)
{
if (Vector128.IsHardwareAccelerated)
{
return VectorMath.AcosSingle<Vector64<float>, Vector64<int>, Vector128<double>, Vector128<long>>(vector);
}
else
{
return VectorMath.AcosSingle<Vector64<float>, Vector64<int>, Vector64<double>, Vector64<long>>(vector);
}
}
else
{
return Acos<float>(vector);
}
}

/// <summary>Computes the cos of each element in a vector.</summary>
/// <param name="vector">The vector that will have its Cos computed.</param>
/// <returns>A vector whose elements are the cos of the elements in <paramref name="vector" />.</returns>
Expand Down Expand Up @@ -3696,6 +3737,20 @@ public static Vector64<float> ShuffleNative(Vector64<float> vector, Vector64<int
#endif
}

internal static Vector64<T> Acos<T>(Vector64<T> vector)
where T : ITrigonometricFunctions<T>
{
Unsafe.SkipInit(out Vector64<T> result);

for (int index = 0; index < Vector64<T>.Count; index++)
{
T value = T.Acos(vector.GetElementUnsafe(index));
result.SetElementUnsafe(index, value);
}

return result;
}

internal static Vector64<T> Asin<T>(Vector64<T> vector)
where T : ITrigonometricFunctions<T>
{
Expand Down
Loading
Loading