diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.netcore.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.netcore.cs index 5e60f5f293678..0eabb88ce51fa 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.netcore.cs @@ -12736,12 +12736,14 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct Exp2Operator : IUnaryOperator where T : IExponentialFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + private const double NaturalLog2 = 0.6931471805599453; + + public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); public static T Invoke(T x) => T.Exp2(x); - public static Vector128 Invoke(Vector128 x) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x) => throw new NotSupportedException(); + public static Vector128 Invoke(Vector128 x) => ExpOperator.Invoke(x * Vector128.Create(T.CreateTruncating(NaturalLog2))); + public static Vector256 Invoke(Vector256 x) => ExpOperator.Invoke(x * Vector256.Create(T.CreateTruncating(NaturalLog2))); + public static Vector512 Invoke(Vector512 x) => ExpOperator.Invoke(x * Vector512.Create(T.CreateTruncating(NaturalLog2))); } /// T.Exp2M1(x) @@ -12760,12 +12762,14 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct Exp10Operator : IUnaryOperator where T : IExponentialFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + private const double NaturalLog10 = 2.302585092994046; + + public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); public static T Invoke(T x) => T.Exp10(x); - public static Vector128 Invoke(Vector128 x) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x) => throw new NotSupportedException(); + public static Vector128 Invoke(Vector128 x) => ExpOperator.Invoke(x * Vector128.Create(T.CreateTruncating(NaturalLog10))); + public static Vector256 Invoke(Vector256 x) => ExpOperator.Invoke(x * Vector256.Create(T.CreateTruncating(NaturalLog10))); + public static Vector512 Invoke(Vector512 x) => ExpOperator.Invoke(x * Vector512.Create(T.CreateTruncating(NaturalLog10))); } /// T.Exp10M1(x) @@ -12784,11 +12788,48 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct PowOperator : IBinaryOperator where T : IPowerFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static T Invoke(T x, T y) => T.Pow(x, y); - public static Vector128 Invoke(Vector128 x, Vector128 y) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x, Vector256 y) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x, Vector512 y) => throw new NotSupportedException(); + + public static Vector128 Invoke(Vector128 x, Vector128 y) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(y.AsSingle() * LogOperator.Invoke(x.AsSingle())).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(y.AsDouble() * LogOperator.Invoke(x.AsDouble())).As(); + } + } + + public static Vector256 Invoke(Vector256 x, Vector256 y) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(y.AsSingle() * LogOperator.Invoke(x.AsSingle())).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(y.AsDouble() * LogOperator.Invoke(x.AsDouble())).As(); + } + } + + public static Vector512 Invoke(Vector512 x, Vector512 y) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(y.AsSingle() * LogOperator.Invoke(x.AsSingle())).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(y.AsDouble() * LogOperator.Invoke(x.AsDouble())).As(); + } + } } /// T.Sqrt(x) @@ -12806,22 +12847,59 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct CbrtOperator : IUnaryOperator where T : IRootFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static T Invoke(T x) => T.Cbrt(x); - public static Vector128 Invoke(Vector128 x) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x) => throw new NotSupportedException(); + + public static Vector128 Invoke(Vector128 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector128.Create(3f)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector128.Create(3d)).As(); + } + } + + public static Vector256 Invoke(Vector256 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector256.Create(3f)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector256.Create(3d)).As(); + } + } + + public static Vector512 Invoke(Vector512 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector512.Create(3f)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector512.Create(3d)).As(); + } + } } /// T.Hypot(x, y) internal readonly struct HypotOperator : IBinaryOperator where T : IRootFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + public static bool Vectorizable => true; public static T Invoke(T x, T y) => T.Hypot(x, y); - public static Vector128 Invoke(Vector128 x, Vector128 y) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x, Vector256 y) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x, Vector512 y) => throw new NotSupportedException(); + public static Vector128 Invoke(Vector128 x, Vector128 y) => Vector128.Sqrt((x * x) + (y * y)); + public static Vector256 Invoke(Vector256 x, Vector256 y) => Vector256.Sqrt((x * x) + (y * y)); + public static Vector512 Invoke(Vector512 x, Vector512 y) => Vector512.Sqrt((x * x) + (y * y)); } /// T.Acos(x) @@ -14546,11 +14624,12 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct Log10Operator : IUnaryOperator where T : ILogarithmicFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + private const double NaturalLog10 = 2.302585092994046; + public static bool Vectorizable => LogOperator.Vectorizable; public static T Invoke(T x) => T.Log10(x); - public static Vector128 Invoke(Vector128 x) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x) => throw new NotSupportedException(); + public static Vector128 Invoke(Vector128 x) => LogOperator.Invoke(x) / Vector128.Create(T.CreateTruncating(NaturalLog10)); + public static Vector256 Invoke(Vector256 x) => LogOperator.Invoke(x) / Vector256.Create(T.CreateTruncating(NaturalLog10)); + public static Vector512 Invoke(Vector512 x) => LogOperator.Invoke(x) / Vector512.Create(T.CreateTruncating(NaturalLog10)); } /// T.LogP1(x) @@ -14590,11 +14669,11 @@ public static Vector512 Invoke(Vector512 x) internal readonly struct LogBaseOperator : IBinaryOperator where T : ILogarithmicFunctions { - public static bool Vectorizable => false; // TODO: Vectorize + public static bool Vectorizable => LogOperator.Vectorizable; public static T Invoke(T x, T y) => T.Log(x, y); - public static Vector128 Invoke(Vector128 x, Vector128 y) => throw new NotSupportedException(); - public static Vector256 Invoke(Vector256 x, Vector256 y) => throw new NotSupportedException(); - public static Vector512 Invoke(Vector512 x, Vector512 y) => throw new NotSupportedException(); + public static Vector128 Invoke(Vector128 x, Vector128 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); + public static Vector256 Invoke(Vector256 x, Vector256 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); + public static Vector512 Invoke(Vector512 x, Vector512 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -15063,13 +15142,48 @@ internal readonly struct RootNOperator(int n) : IStatefulUnaryOperator whe { private readonly int _n = n; - public static bool Vectorizable => false; // TODO: Vectorize + public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); public T Invoke(T x) => T.RootN(x, _n); - public Vector128 Invoke(Vector128 x) => throw new NotSupportedException(); - public Vector256 Invoke(Vector256 x) => throw new NotSupportedException(); - public Vector512 Invoke(Vector512 x) => throw new NotSupportedException(); + public Vector128 Invoke(Vector128 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector128.Create((float)_n)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector128.Create((double)_n)).As(); + } + } + + public Vector256 Invoke(Vector256 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector256.Create((float)_n)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector256.Create((double)_n)).As(); + } + } + + public Vector512 Invoke(Vector512 x) + { + if (typeof(T) == typeof(float)) + { + return ExpOperator.Invoke(LogOperator.Invoke(x.AsSingle()) / Vector512.Create((float)_n)).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(double)); + return ExpOperator.Invoke(LogOperator.Invoke(x.AsDouble()) / Vector512.Create((double)_n)).As(); + } + } } /// T.Round