diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/TensorPrimitives.IIndexOfMinMaxOperator.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/TensorPrimitives.IIndexOfMinMaxOperator.cs index 9887a65da80968..12d290ab014f04 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/TensorPrimitives.IIndexOfMinMaxOperator.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/TensorPrimitives.IIndexOfMinMaxOperator.cs @@ -93,7 +93,7 @@ private static int IndexOfMinMaxVectorized128Size4Plus(ReadO Vector128 result = Vector128.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(result); + Vector128 nanMask = Vector128.IsNaN(result); if (nanMask != Vector128.Zero) { return IndexOfFirstMatch(nanMask); @@ -126,7 +126,7 @@ private static int IndexOfMinMaxVectorized128Size4Plus(ReadO // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(current); + Vector128 nanMask = Vector128.IsNaN(current); if (nanMask != Vector128.Zero) { return int.CreateTruncating(currentIndex.ToScalar()) + IndexOfFirstMatch(nanMask); @@ -160,7 +160,7 @@ private static int IndexOfMinMaxVectorized128Size2(ReadOnlySpan Vector128 result = Vector128.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(result); + Vector128 nanMask = Vector128.IsNaN(result); if (nanMask != Vector128.Zero) { return IndexOfFirstMatch(nanMask); @@ -194,7 +194,7 @@ private static int IndexOfMinMaxVectorized128Size2(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(current); + Vector128 nanMask = Vector128.IsNaN(current); if (nanMask != Vector128.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); @@ -235,7 +235,7 @@ private static int IndexOfMinMaxVectorized128Size1(ReadOnlySpan Vector128 result = Vector128.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(result); + Vector128 nanMask = Vector128.IsNaN(result); if (nanMask != Vector128.Zero) { return IndexOfFirstMatch(nanMask); @@ -271,7 +271,7 @@ private static int IndexOfMinMaxVectorized128Size1(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector128 nanMask = IsNaN(current); + Vector128 nanMask = Vector128.IsNaN(current); if (nanMask != Vector128.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); @@ -324,7 +324,7 @@ private static int IndexOfMinMaxVectorized256Size4Plus(ReadO Vector256 result = Vector256.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(result); + Vector256 nanMask = Vector256.IsNaN(result); if (nanMask != Vector256.Zero) { return IndexOfFirstMatch(nanMask); @@ -357,7 +357,7 @@ private static int IndexOfMinMaxVectorized256Size4Plus(ReadO // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(current); + Vector256 nanMask = Vector256.IsNaN(current); if (nanMask != Vector256.Zero) { return int.CreateTruncating(currentIndex.ToScalar()) + IndexOfFirstMatch(nanMask); @@ -391,7 +391,7 @@ private static int IndexOfMinMaxVectorized256Size2(ReadOnlySpan Vector256 result = Vector256.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(result); + Vector256 nanMask = Vector256.IsNaN(result); if (nanMask != Vector256.Zero) { return IndexOfFirstMatch(nanMask); @@ -425,7 +425,7 @@ private static int IndexOfMinMaxVectorized256Size2(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(current); + Vector256 nanMask = Vector256.IsNaN(current); if (nanMask != Vector256.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); @@ -466,7 +466,7 @@ private static int IndexOfMinMaxVectorized256Size1(ReadOnlySpan Vector256 result = Vector256.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(result); + Vector256 nanMask = Vector256.IsNaN(result); if (nanMask != Vector256.Zero) { return IndexOfFirstMatch(nanMask); @@ -502,7 +502,7 @@ private static int IndexOfMinMaxVectorized256Size1(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector256 nanMask = IsNaN(current); + Vector256 nanMask = Vector256.IsNaN(current); if (nanMask != Vector256.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); @@ -555,7 +555,7 @@ private static int IndexOfMinMaxVectorized512Size4Plus(ReadO Vector512 result = Vector512.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(result); + Vector512 nanMask = Vector512.IsNaN(result); if (nanMask != Vector512.Zero) { return IndexOfFirstMatch(nanMask); @@ -588,7 +588,7 @@ private static int IndexOfMinMaxVectorized512Size4Plus(ReadO // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(current); + Vector512 nanMask = Vector512.IsNaN(current); if (nanMask != Vector512.Zero) { return int.CreateTruncating(currentIndex.ToScalar()) + IndexOfFirstMatch(nanMask); @@ -622,7 +622,7 @@ private static int IndexOfMinMaxVectorized512Size2(ReadOnlySpan Vector512 result = Vector512.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(result); + Vector512 nanMask = Vector512.IsNaN(result); if (nanMask != Vector512.Zero) { return IndexOfFirstMatch(nanMask); @@ -656,7 +656,7 @@ private static int IndexOfMinMaxVectorized512Size2(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(current); + Vector512 nanMask = Vector512.IsNaN(current); if (nanMask != Vector512.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); @@ -697,7 +697,7 @@ private static int IndexOfMinMaxVectorized512Size1(ReadOnlySpan Vector512 result = Vector512.Create(x); if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(result); + Vector512 nanMask = Vector512.IsNaN(result); if (nanMask != Vector512.Zero) { return IndexOfFirstMatch(nanMask); @@ -733,7 +733,7 @@ private static int IndexOfMinMaxVectorized512Size1(ReadOnlySpan // Quick return if possible. if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - Vector512 nanMask = IsNaN(current); + Vector512 nanMask = Vector512.IsNaN(current); if (nanMask != Vector512.Zero) { return (int)currentIndex.ToScalar() + IndexOfFirstMatch(nanMask); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Exp.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Exp.cs index a08601b977858b..699cdfbe5b2d53 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Exp.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Exp.cs @@ -85,493 +85,5 @@ public static Vector512 Invoke(Vector512 x) } } } - -#if !NET - /// double.Exp(x) - private readonly struct ExpOperatorDouble : IUnaryOperator - { - // This code is based on `vrd2_exp` from amd/aocl-libm-ose - // Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Implementation Notes - // ---------------------- - // 1. Argument Reduction: - // e^x = 2^(x/ln2) = 2^(x*(64/ln(2))/64) --- (1) - // - // Choose 'n' and 'f', such that - // x * 64/ln2 = n + f --- (2) | n is integer - // | |f| <= 0.5 - // Choose 'm' and 'j' such that, - // n = (64 * m) + j --- (3) - // - // From (1), (2) and (3), - // e^x = 2^((64*m + j + f)/64) - // = (2^m) * (2^(j/64)) * 2^(f/64) - // = (2^m) * (2^(j/64)) * e^(f*(ln(2)/64)) - // - // 2. Table Lookup - // Values of (2^(j/64)) are precomputed, j = 0, 1, 2, 3 ... 63 - // - // 3. Polynomial Evaluation - // From (2), - // f = x*(64/ln(2)) - n - // Let, - // r = f*(ln(2)/64) = x - n*(ln(2)/64) - // - // 4. Reconstruction - // Thus, - // e^x = (2^m) * (2^(j/64)) * e^r - - private const ulong V_ARG_MAX = 0x40862000_00000000; - private const ulong V_DP64_BIAS = 1023; - - private const double V_EXPF_HUGE = 6755399441055744; - private const double V_TBL_LN2 = 1.4426950408889634; - - private const double V_LN2_HEAD = +0.693359375; - private const double V_LN2_TAIL = -0.00021219444005469057; - - private const double C3 = 0.5000000000000018; - private const double C4 = 0.1666666666666617; - private const double C5 = 0.04166666666649277; - private const double C6 = 0.008333333333559272; - private const double C7 = 0.001388888895122404; - private const double C8 = 0.00019841269432677495; - private const double C9 = 2.4801486521374483E-05; - private const double C10 = 2.7557622532543023E-06; - private const double C11 = 2.7632293298250954E-07; - private const double C12 = 2.499430431958571E-08; - - public static bool Vectorizable => true; - - public static double Invoke(double x) => double.Exp(x); - - public static Vector128 Invoke(Vector128 x) - { - // Check if -709 < vx < 709 - if (Vector128.LessThanOrEqualAll(Vector128.Abs(x).AsUInt64(), Vector128.Create(V_ARG_MAX))) - { - // x * (64.0 / ln(2)) - Vector128 z = x * Vector128.Create(V_TBL_LN2); - - Vector128 dn = z + Vector128.Create(V_EXPF_HUGE); - - // n = (int)z - Vector128 n = dn.AsUInt64(); - - // dn = (double)n - dn -= Vector128.Create(V_EXPF_HUGE); - - // r = x - (dn * (ln(2) / 64)) - // where ln(2) / 64 is split into Head and Tail values - Vector128 r = x - (dn * Vector128.Create(V_LN2_HEAD)) - (dn * Vector128.Create(V_LN2_TAIL)); - - Vector128 r2 = r * r; - Vector128 r4 = r2 * r2; - Vector128 r8 = r4 * r4; - - // Compute polynomial - Vector128 poly = ((Vector128.Create(C12) * r + Vector128.Create(C11)) * r2 + - Vector128.Create(C10) * r + Vector128.Create(C9)) * r8 + - ((Vector128.Create(C8) * r + Vector128.Create(C7)) * r2 + - (Vector128.Create(C6) * r + Vector128.Create(C5))) * r4 + - ((Vector128.Create(C4) * r + Vector128.Create(C3)) * r2 + (r + Vector128.One)); - - // m = (n - j) / 64 - // result = polynomial * 2^m - return poly * ((n + Vector128.Create(V_DP64_BIAS)) << 52).AsDouble(); - } - else - { - return ScalarFallback(x); - - static Vector128 ScalarFallback(Vector128 x) => - Vector128.Create(Math.Exp(x.GetElement(0)), - Math.Exp(x.GetElement(1))); - } - } - - public static Vector256 Invoke(Vector256 x) - { - // Check if -709 < vx < 709 - if (Vector256.LessThanOrEqualAll(Vector256.Abs(x).AsUInt64(), Vector256.Create(V_ARG_MAX))) - { - // x * (64.0 / ln(2)) - Vector256 z = x * Vector256.Create(V_TBL_LN2); - - Vector256 dn = z + Vector256.Create(V_EXPF_HUGE); - - // n = (int)z - Vector256 n = dn.AsUInt64(); - - // dn = (double)n - dn -= Vector256.Create(V_EXPF_HUGE); - - // r = x - (dn * (ln(2) / 64)) - // where ln(2) / 64 is split into Head and Tail values - Vector256 r = x - (dn * Vector256.Create(V_LN2_HEAD)) - (dn * Vector256.Create(V_LN2_TAIL)); - - Vector256 r2 = r * r; - Vector256 r4 = r2 * r2; - Vector256 r8 = r4 * r4; - - // Compute polynomial - Vector256 poly = ((Vector256.Create(C12) * r + Vector256.Create(C11)) * r2 + - Vector256.Create(C10) * r + Vector256.Create(C9)) * r8 + - ((Vector256.Create(C8) * r + Vector256.Create(C7)) * r2 + - (Vector256.Create(C6) * r + Vector256.Create(C5))) * r4 + - ((Vector256.Create(C4) * r + Vector256.Create(C3)) * r2 + (r + Vector256.One)); - - // m = (n - j) / 64 - // result = polynomial * 2^m - return poly * ((n + Vector256.Create(V_DP64_BIAS)) << 52).AsDouble(); - } - else - { - return ScalarFallback(x); - - static Vector256 ScalarFallback(Vector256 x) => - Vector256.Create(Math.Exp(x.GetElement(0)), - Math.Exp(x.GetElement(1)), - Math.Exp(x.GetElement(2)), - Math.Exp(x.GetElement(3))); - } - } - - public static Vector512 Invoke(Vector512 x) - { - // Check if -709 < vx < 709 - if (Vector512.LessThanOrEqualAll(Vector512.Abs(x).AsUInt64(), Vector512.Create(V_ARG_MAX))) - { - // x * (64.0 / ln(2)) - Vector512 z = x * Vector512.Create(V_TBL_LN2); - - Vector512 dn = z + Vector512.Create(V_EXPF_HUGE); - - // n = (int)z - Vector512 n = dn.AsUInt64(); - - // dn = (double)n - dn -= Vector512.Create(V_EXPF_HUGE); - - // r = x - (dn * (ln(2) / 64)) - // where ln(2) / 64 is split into Head and Tail values - Vector512 r = x - (dn * Vector512.Create(V_LN2_HEAD)) - (dn * Vector512.Create(V_LN2_TAIL)); - - Vector512 r2 = r * r; - Vector512 r4 = r2 * r2; - Vector512 r8 = r4 * r4; - - // Compute polynomial - Vector512 poly = ((Vector512.Create(C12) * r + Vector512.Create(C11)) * r2 + - Vector512.Create(C10) * r + Vector512.Create(C9)) * r8 + - ((Vector512.Create(C8) * r + Vector512.Create(C7)) * r2 + - (Vector512.Create(C6) * r + Vector512.Create(C5))) * r4 + - ((Vector512.Create(C4) * r + Vector512.Create(C3)) * r2 + (r + Vector512.One)); - - // m = (n - j) / 64 - // result = polynomial * 2^m - return poly * ((n + Vector512.Create(V_DP64_BIAS)) << 52).AsDouble(); - } - else - { - return ScalarFallback(x); - - static Vector512 ScalarFallback(Vector512 x) => - Vector512.Create(Math.Exp(x.GetElement(0)), - Math.Exp(x.GetElement(1)), - Math.Exp(x.GetElement(2)), - Math.Exp(x.GetElement(3)), - Math.Exp(x.GetElement(4)), - Math.Exp(x.GetElement(5)), - Math.Exp(x.GetElement(6)), - Math.Exp(x.GetElement(7))); - } - } - } - - /// float.Exp(x) - private readonly struct ExpOperatorSingle : IUnaryOperator - { - // This code is based on `vrs4_expf` from amd/aocl-libm-ose - // Copyright (C) 2019-2022 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Implementation Notes: - // 1. Argument Reduction: - // e^x = 2^(x/ln2) --- (1) - // - // Let x/ln(2) = z --- (2) - // - // Let z = n + r , where n is an integer --- (3) - // |r| <= 1/2 - // - // From (1), (2) and (3), - // e^x = 2^z - // = 2^(N+r) - // = (2^N)*(2^r) --- (4) - // - // 2. Polynomial Evaluation - // From (4), - // r = z - N - // 2^r = C1 + C2*r + C3*r^2 + C4*r^3 + C5 *r^4 + C6*r^5 - // - // 4. Reconstruction - // Thus, - // e^x = (2^N) * (2^r) - - private const uint V_ARG_MAX = 0x42AE0000; - - private const float V_EXPF_MIN = -103.97208f; - private const float V_EXPF_MAX = +88.72284f; - - private const double V_EXPF_HUGE = 6755399441055744; - private const double V_TBL_LN2 = 1.4426950408889634; - - private const double C1 = 1.0000000754895704; - private const double C2 = 0.6931472254087585; - private const double C3 = 0.2402210737432219; - private const double C4 = 0.05550297297702539; - private const double C5 = 0.009676036358193323; - private const double C6 = 0.001341000536524434; - - public static bool Vectorizable => true; - - public static float Invoke(float x) => float.Exp(x); - - public static Vector128 Invoke(Vector128 x) - { - // Convert x to double precision - (Vector128 xl, Vector128 xu) = Vector128.Widen(x); - - // x * (64.0 / ln(2)) - Vector128 v_tbl_ln2 = Vector128.Create(V_TBL_LN2); - - Vector128 zl = xl * v_tbl_ln2; - Vector128 zu = xu * v_tbl_ln2; - - Vector128 v_expf_huge = Vector128.Create(V_EXPF_HUGE); - - Vector128 dnl = zl + v_expf_huge; - Vector128 dnu = zu + v_expf_huge; - - // n = (int)z - Vector128 nl = dnl.AsUInt64(); - Vector128 nu = dnu.AsUInt64(); - - // dn = (double)n - dnl -= v_expf_huge; - dnu -= v_expf_huge; - - // r = z - dn - Vector128 c1 = Vector128.Create(C1); - Vector128 c2 = Vector128.Create(C2); - Vector128 c3 = Vector128.Create(C3); - Vector128 c4 = Vector128.Create(C4); - Vector128 c5 = Vector128.Create(C5); - Vector128 c6 = Vector128.Create(C6); - - Vector128 rl = zl - dnl; - - Vector128 rl2 = rl * rl; - Vector128 rl4 = rl2 * rl2; - - Vector128 polyl = (c4 * rl + c3) * rl2 - + ((c6 * rl + c5) * rl4 - + (c2 * rl + c1)); - - - Vector128 ru = zu - dnu; - - Vector128 ru2 = ru * ru; - Vector128 ru4 = ru2 * ru2; - - Vector128 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); - - // result = (float)(poly + (n << 52)) - Vector128 ret = Vector128.Narrow( - (polyl.AsUInt64() + (nl << 52)).AsDouble(), - (polyu.AsUInt64() + (nu << 52)).AsDouble() - ); - - // Check if -103 < |x| < 88 - if (Vector128.GreaterThanAny(Vector128.Abs(x).AsUInt32(), Vector128.Create(V_ARG_MAX))) - { - // (x > V_EXPF_MAX) ? float.PositiveInfinity : x - Vector128 infinityMask = Vector128.GreaterThan(x, Vector128.Create(V_EXPF_MAX)); - - ret = Vector128.ConditionalSelect( - infinityMask, - Vector128.Create(float.PositiveInfinity), - ret - ); - - // (x < V_EXPF_MIN) ? 0 : x - ret = Vector128.AndNot(ret, Vector128.LessThan(x, Vector128.Create(V_EXPF_MIN))); - } - - return ret; - } - - public static Vector256 Invoke(Vector256 x) - { - // Convert x to double precision - (Vector256 xl, Vector256 xu) = Vector256.Widen(x); - - // x * (64.0 / ln(2)) - Vector256 v_tbl_ln2 = Vector256.Create(V_TBL_LN2); - - Vector256 zl = xl * v_tbl_ln2; - Vector256 zu = xu * v_tbl_ln2; - - Vector256 v_expf_huge = Vector256.Create(V_EXPF_HUGE); - - Vector256 dnl = zl + v_expf_huge; - Vector256 dnu = zu + v_expf_huge; - - // n = (int)z - Vector256 nl = dnl.AsUInt64(); - Vector256 nu = dnu.AsUInt64(); - - // dn = (double)n - dnl -= v_expf_huge; - dnu -= v_expf_huge; - - // r = z - dn - Vector256 c1 = Vector256.Create(C1); - Vector256 c2 = Vector256.Create(C2); - Vector256 c3 = Vector256.Create(C3); - Vector256 c4 = Vector256.Create(C4); - Vector256 c5 = Vector256.Create(C5); - Vector256 c6 = Vector256.Create(C6); - - Vector256 rl = zl - dnl; - - Vector256 rl2 = rl * rl; - Vector256 rl4 = rl2 * rl2; - - Vector256 polyl = (c4 * rl + c3) * rl2 - + ((c6 * rl + c5) * rl4 - + (c2 * rl + c1)); - - - Vector256 ru = zu - dnu; - - Vector256 ru2 = ru * ru; - Vector256 ru4 = ru2 * ru2; - - Vector256 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); - - // result = (float)(poly + (n << 52)) - Vector256 ret = Vector256.Narrow( - (polyl.AsUInt64() + (nl << 52)).AsDouble(), - (polyu.AsUInt64() + (nu << 52)).AsDouble() - ); - - // Check if -103 < |x| < 88 - if (Vector256.GreaterThanAny(Vector256.Abs(x).AsUInt32(), Vector256.Create(V_ARG_MAX))) - { - // (x > V_EXPF_MAX) ? float.PositiveInfinity : x - Vector256 infinityMask = Vector256.GreaterThan(x, Vector256.Create(V_EXPF_MAX)); - - ret = Vector256.ConditionalSelect( - infinityMask, - Vector256.Create(float.PositiveInfinity), - ret - ); - - // (x < V_EXPF_MIN) ? 0 : x - ret = Vector256.AndNot(ret, Vector256.LessThan(x, Vector256.Create(V_EXPF_MIN))); - } - - return ret; - } - - public static Vector512 Invoke(Vector512 x) - { - // Convert x to double precision - (Vector512 xl, Vector512 xu) = Vector512.Widen(x); - - // x * (64.0 / ln(2)) - Vector512 v_tbl_ln2 = Vector512.Create(V_TBL_LN2); - - Vector512 zl = xl * v_tbl_ln2; - Vector512 zu = xu * v_tbl_ln2; - - Vector512 v_expf_huge = Vector512.Create(V_EXPF_HUGE); - - Vector512 dnl = zl + v_expf_huge; - Vector512 dnu = zu + v_expf_huge; - - // n = (int)z - Vector512 nl = dnl.AsUInt64(); - Vector512 nu = dnu.AsUInt64(); - - // dn = (double)n - dnl -= v_expf_huge; - dnu -= v_expf_huge; - - // r = z - dn - Vector512 c1 = Vector512.Create(C1); - Vector512 c2 = Vector512.Create(C2); - Vector512 c3 = Vector512.Create(C3); - Vector512 c4 = Vector512.Create(C4); - Vector512 c5 = Vector512.Create(C5); - Vector512 c6 = Vector512.Create(C6); - - Vector512 rl = zl - dnl; - - Vector512 rl2 = rl * rl; - Vector512 rl4 = rl2 * rl2; - - Vector512 polyl = (c4 * rl + c3) * rl2 - + ((c6 * rl + c5) * rl4 - + (c2 * rl + c1)); - - - Vector512 ru = zu - dnu; - - Vector512 ru2 = ru * ru; - Vector512 ru4 = ru2 * ru2; - - Vector512 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); - - // result = (float)(poly + (n << 52)) - Vector512 ret = Vector512.Narrow( - (polyl.AsUInt64() + (nl << 52)).AsDouble(), - (polyu.AsUInt64() + (nu << 52)).AsDouble() - ); - - // Check if -103 < |x| < 88 - if (Vector512.GreaterThanAny(Vector512.Abs(x).AsUInt32(), Vector512.Create(V_ARG_MAX))) - { - // (x > V_EXPF_MAX) ? float.PositiveInfinity : x - Vector512 infinityMask = Vector512.GreaterThan(x, Vector512.Create(V_EXPF_MAX)); - - ret = Vector512.ConditionalSelect( - infinityMask, - Vector512.Create(float.PositiveInfinity), - ret - ); - - // (x < V_EXPF_MIN) ? 0 : x - ret = Vector512.AndNot(ret, Vector512.LessThan(x, Vector512.Create(V_EXPF_MIN))); - } - - return ret; - } - } -#endif } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMax.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMax.cs index 7ea6f2f349a797..96ff23100609e3 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMax.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMax.cs @@ -51,7 +51,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector128 equalResult = IsPositive(x) & IsNegative(y); + Vector128 equalResult = Vector128.IsPositive(x) & Vector128.IsNegative(y); return Vector128.GreaterThan(x, y) | (Vector128.Equals(x, y) & equalResult); } else @@ -65,7 +65,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector256 equalResult = IsPositive(x) & IsNegative(y); + Vector256 equalResult = Vector256.IsPositive(x) & Vector256.IsNegative(y); return Vector256.GreaterThan(x, y) | (Vector256.Equals(x, y) & equalResult); } else @@ -79,7 +79,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector512 equalResult = IsPositive(x) & IsNegative(y); + Vector512 equalResult = Vector512.IsPositive(x) & Vector512.IsNegative(y); return Vector512.GreaterThan(x, y) | (Vector512.Equals(x, y) & equalResult); } else diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMaxMagnitude.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMaxMagnitude.cs index 5ca77310c5fa3d..60cc1e891cddef 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMaxMagnitude.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMaxMagnitude.cs @@ -62,7 +62,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector128 equalResult = IsPositive(x) & IsNegative(y); + Vector128 equalResult = Vector128.IsPositive(x) & Vector128.IsNegative(y); return Vector128.GreaterThan(xMag, yMag) | (Vector128.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -72,7 +72,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector128.AndNot(Vector128.GreaterThan(xMag, yMag) | IsNegative(xMag), IsNegative(yMag)); + return Vector128.AndNot(Vector128.GreaterThan(xMag, yMag) | Vector128.IsNegative(xMag), Vector128.IsNegative(yMag)); } else { @@ -86,7 +86,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector256 equalResult = IsPositive(x) & IsNegative(y); + Vector256 equalResult = Vector256.IsPositive(x) & Vector256.IsNegative(y); return Vector256.GreaterThan(xMag, yMag) | (Vector256.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -96,7 +96,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector256.AndNot(Vector256.GreaterThan(xMag, yMag) | IsNegative(xMag), IsNegative(yMag)); + return Vector256.AndNot(Vector256.GreaterThan(xMag, yMag) | Vector256.IsNegative(xMag), Vector256.IsNegative(yMag)); } else { @@ -110,7 +110,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector512 equalResult = IsPositive(x) & IsNegative(y); + Vector512 equalResult = Vector512.IsPositive(x) & Vector512.IsNegative(y); return Vector512.GreaterThan(xMag, yMag) | (Vector512.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -120,7 +120,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector512.AndNot(Vector512.GreaterThan(xMag, yMag) | IsNegative(xMag), IsNegative(yMag)); + return Vector512.AndNot(Vector512.GreaterThan(xMag, yMag) | Vector512.IsNegative(xMag), Vector512.IsNegative(yMag)); } else { diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMin.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMin.cs index 135ca0ac294cc6..4da71bcecabbff 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMin.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMin.cs @@ -50,7 +50,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector128 equalResult = IsNegative(x) & IsPositive(y); + Vector128 equalResult = Vector128.IsNegative(x) & Vector128.IsPositive(y); return Vector128.LessThan(x, y) | (Vector128.Equals(x, y) & equalResult); } else @@ -64,7 +64,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector256 equalResult = IsNegative(x) & IsPositive(y); + Vector256 equalResult = Vector256.IsNegative(x) & Vector256.IsPositive(y); return Vector256.LessThan(x, y) | (Vector256.Equals(x, y) & equalResult); } else @@ -78,7 +78,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) { if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector512 equalResult = IsNegative(x) & IsPositive(y); + Vector512 equalResult = Vector512.IsNegative(x) & Vector512.IsPositive(y); return Vector512.LessThan(x, y) | (Vector512.Equals(x, y) & equalResult); } else diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMinMagnitude.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMinMagnitude.cs index 437c9537e6962e..2421fd48fe13f6 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMinMagnitude.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IndexOfMinMagnitude.cs @@ -62,7 +62,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector128 equalResult = IsNegative(x) & IsPositive(y); + Vector128 equalResult = Vector128.IsNegative(x) & Vector128.IsPositive(y); return Vector128.LessThan(xMag, yMag) | (Vector128.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -72,7 +72,7 @@ public static Vector128 Compare(Vector128 x, Vector128 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector128.AndNot(Vector128.LessThan(xMag, yMag) | IsNegative(yMag), IsNegative(xMag)); + return Vector128.AndNot(Vector128.LessThan(xMag, yMag) | Vector128.IsNegative(yMag), Vector128.IsNegative(xMag)); } else { @@ -86,7 +86,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector256 equalResult = IsNegative(x) & IsPositive(y); + Vector256 equalResult = Vector256.IsNegative(x) & Vector256.IsPositive(y); return Vector256.LessThan(xMag, yMag) | (Vector256.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -96,7 +96,7 @@ public static Vector256 Compare(Vector256 x, Vector256 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector256.AndNot(Vector256.LessThan(xMag, yMag) | IsNegative(yMag), IsNegative(xMag)); + return Vector256.AndNot(Vector256.LessThan(xMag, yMag) | Vector256.IsNegative(yMag), Vector256.IsNegative(xMag)); } else { @@ -110,7 +110,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); if (typeof(T) == typeof(double) || typeof(T) == typeof(float)) { - Vector512 equalResult = IsNegative(x) & IsPositive(y); + Vector512 equalResult = Vector512.IsNegative(x) & Vector512.IsPositive(y); return Vector512.LessThan(xMag, yMag) | (Vector512.Equals(xMag, yMag) & equalResult); } else if (typeof(T) == typeof(sbyte) @@ -120,7 +120,7 @@ public static Vector512 Compare(Vector512 x, Vector512 y) || typeof(T) == typeof(nint)) { // Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude. - return Vector512.AndNot(Vector512.LessThan(xMag, yMag) | IsNegative(yMag), IsNegative(xMag)); + return Vector512.AndNot(Vector512.LessThan(xMag, yMag) | Vector512.IsNegative(yMag), Vector512.IsNegative(xMag)); } else { diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNaN.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNaN.cs index dab9118573a69f..7e38263b25a347 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNaN.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNaN.cs @@ -65,9 +65,9 @@ private static bool MayBeNaN() => { public static bool Vectorizable => true; public static bool Invoke(T x) => T.IsNaN(x); - public static Vector128 Invoke(Vector128 x) => IsNaN(x); - public static Vector256 Invoke(Vector256 x) => IsNaN(x); - public static Vector512 Invoke(Vector512 x) => IsNaN(x); + public static Vector128 Invoke(Vector128 x) => Vector128.IsNaN(x); + public static Vector256 Invoke(Vector256 x) => Vector256.IsNaN(x); + public static Vector512 Invoke(Vector512 x) => Vector512.IsNaN(x); } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNegative.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNegative.cs index 86b062b91c5762..3ed5de79558d1a 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNegative.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsNegative.cs @@ -69,9 +69,9 @@ private static bool MayBeNegative() => { public static bool Vectorizable => true; public static bool Invoke(T x) => T.IsNegative(x); - public static Vector128 Invoke(Vector128 x) => IsNegative(x); - public static Vector256 Invoke(Vector256 x) => IsNegative(x); - public static Vector512 Invoke(Vector512 x) => IsNegative(x); + public static Vector128 Invoke(Vector128 x) => Vector128.IsNegative(x); + public static Vector256 Invoke(Vector256 x) => Vector256.IsNegative(x); + public static Vector512 Invoke(Vector512 x) => Vector512.IsNegative(x); } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsPositive.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsPositive.cs index 0547de34ebb86f..187b57c1b37bc0 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsPositive.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsPositive.cs @@ -47,9 +47,9 @@ public static bool IsPositiveAny(ReadOnlySpan x) { public static bool Vectorizable => true; public static bool Invoke(T x) => T.IsPositive(x); - public static Vector128 Invoke(Vector128 x) => IsPositive(x); - public static Vector256 Invoke(Vector256 x) => IsPositive(x); - public static Vector512 Invoke(Vector512 x) => IsPositive(x); + public static Vector128 Invoke(Vector128 x) => Vector128.IsPositive(x); + public static Vector256 Invoke(Vector256 x) => Vector256.IsPositive(x); + public static Vector512 Invoke(Vector512 x) => Vector512.IsPositive(x); } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsRealNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsRealNumber.cs index 8c5e9a9877c7db..daadd47a83ab3b 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsRealNumber.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.IsRealNumber.cs @@ -65,9 +65,9 @@ private static bool AlwaysReal() => { public static bool Vectorizable => true; public static bool Invoke(T x) => T.IsRealNumber(x); - public static Vector128 Invoke(Vector128 x) => ~IsNaN(x); - public static Vector256 Invoke(Vector256 x) => ~IsNaN(x); - public static Vector512 Invoke(Vector512 x) => ~IsNaN(x); + public static Vector128 Invoke(Vector128 x) => ~Vector128.IsNaN(x); + public static Vector256 Invoke(Vector256 x) => ~Vector256.IsNaN(x); + public static Vector512 Invoke(Vector512 x) => ~Vector512.IsNaN(x); } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs index 8e096dc594e89f..6b4e0d75c073f0 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs @@ -152,599 +152,5 @@ public static Vector512 Invoke(Vector512 x) 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); } - -#if !NET - /// double.Log(x) - private readonly struct LogOperatorDouble : IUnaryOperator - { - // This code is based on `vrd2_log` from amd/aocl-libm-ose - // Copyright (C) 2018-2020 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Reduce x into the form: - // x = (-1)^s*2^n*m - // s will be always zero, as log is defined for positive numbers - // n is an integer known as the exponent - // m is mantissa - // - // x is reduced such that the mantissa, m lies in [2/3,4/3] - // x = 2^n*m where m is in [2/3,4/3] - // log(x) = log(2^n*m) We have log(a*b) = log(a)+log(b) - // = log(2^n) + log(m) We have log(a^n) = n*log(a) - // = n*log(2) + log(m) - // = n*log(2) + log(1+(m-1)) - // = n*log(2) + log(1+f) Where f = m-1 - // = n*log(2) + log1p(f) f lies in [-1/3,+1/3] - // - // Thus we have : - // log(x) = n*log(2) + log1p(f) - // In the above, the first term n*log(2), n can be calculated by using right shift operator and the value of log(2) - // is known and is stored as a constant - // The second term log1p(F) is approximated by using a polynomial - - private const ulong V_MIN = 0x00100000_00000000; // SmallestNormal - private const ulong V_MAX = 0x7FF00000_00000000; // +Infinity - private const ulong V_MSK = 0x000FFFFF_FFFFFFFF; // (1 << 52) - 1 - private const ulong V_OFF = 0x3FE55555_55555555; // 2.0 / 3.0 - - private const double LN2_HEAD = 0.693359375; - private const double LN2_TAIL = -0.00021219444005469057; - - private const double C02 = -0.499999999999999560; - private const double C03 = +0.333333333333414750; - private const double C04 = -0.250000000000297430; - private const double C05 = +0.199999999975985220; - private const double C06 = -0.166666666608919500; - private const double C07 = +0.142857145600277100; - private const double C08 = -0.125000005127831270; - private const double C09 = +0.111110952357159440; - private const double C10 = -0.099999750495501240; - private const double C11 = +0.090914349823462390; - private const double C12 = -0.083340600527551860; - private const double C13 = +0.076817603328311300; - private const double C14 = -0.071296718946287310; - private const double C15 = +0.067963465211535730; - private const double C16 = -0.063995035098960040; - private const double C17 = +0.049370587082412105; - private const double C18 = -0.045370170994891980; - private const double C19 = +0.088970636003577750; - private const double C20 = -0.086906174116908760; - - public static bool Vectorizable => true; - - public static double Invoke(double x) => double.Log(x); - - public static Vector128 Invoke(Vector128 x) - { - Vector128 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector128 specialMask = Vector128.GreaterThanOrEqual(x.AsUInt64() - Vector128.Create(V_MIN), Vector128.Create(V_MAX - V_MIN)); - - if (specialMask != Vector128.Zero) - { - Vector128 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector128 lessThanZeroMask = Vector128.LessThan(xBits, Vector128.Zero).AsDouble(); - - specialResult = Vector128.ConditionalSelect( - lessThanZeroMask, - Vector128.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector128 zeroMask = Vector128.Equals(xBits << 1, Vector128.Zero).AsDouble(); - - specialResult = Vector128.ConditionalSelect( - zeroMask, - Vector128.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector128 temp = zeroMask - | lessThanZeroMask - | Vector128.GreaterThanOrEqual(xBits, Vector128.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector128 subnormalMask = Vector128.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector128.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector128.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector128 vx = x.AsUInt64() - Vector128.Create(V_OFF); - Vector128 n = Vector128.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector128.Create(V_MSK)) + Vector128.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector128 r = vx.AsDouble() - Vector128.One; - - Vector128 r02 = r * r; - Vector128 r04 = r02 * r02; - Vector128 r08 = r04 * r04; - Vector128 r16 = r08 * r08; - - // Compute log(x + 1) using Polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector128 poly = (((r04 * C20) - + ((((r * C19) + Vector128.Create(C18)) * r02) - + ((r * C17) + Vector128.Create(C16)))) * r16) - + (((((((r * C15) + Vector128.Create(C14)) * r02) - + ((r * C13) + Vector128.Create(C12))) * r04) - + ((((r * C11) + Vector128.Create(C10)) * r02) - + ((r * C09) + Vector128.Create(C08)))) * r08) - + (((((r * C07) + Vector128.Create(C06)) * r02) - + ((r * C05) + Vector128.Create(C04))) * r04) - + ((((r * C03) + Vector128.Create(C02)) * r02) + r); - - return Vector128.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (n * LN2_HEAD) + ((n * LN2_TAIL) + poly) - ); - } - - public static Vector256 Invoke(Vector256 x) - { - Vector256 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector256 specialMask = Vector256.GreaterThanOrEqual(x.AsUInt64() - Vector256.Create(V_MIN), Vector256.Create(V_MAX - V_MIN)); - - if (specialMask != Vector256.Zero) - { - Vector256 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector256 lessThanZeroMask = Vector256.LessThan(xBits, Vector256.Zero).AsDouble(); - - specialResult = Vector256.ConditionalSelect( - lessThanZeroMask, - Vector256.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector256 zeroMask = Vector256.Equals(xBits << 1, Vector256.Zero).AsDouble(); - - specialResult = Vector256.ConditionalSelect( - zeroMask, - Vector256.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector256 temp = zeroMask - | lessThanZeroMask - | Vector256.GreaterThanOrEqual(xBits, Vector256.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector256 subnormalMask = Vector256.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector256.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector256.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector256 vx = x.AsUInt64() - Vector256.Create(V_OFF); - Vector256 n = Vector256.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector256.Create(V_MSK)) + Vector256.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector256 r = vx.AsDouble() - Vector256.One; - - Vector256 r02 = r * r; - Vector256 r04 = r02 * r02; - Vector256 r08 = r04 * r04; - Vector256 r16 = r08 * r08; - - // Compute log(x + 1) using Polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector256 poly = (((r04 * C20) - + ((((r * C19) + Vector256.Create(C18)) * r02) - + ((r * C17) + Vector256.Create(C16)))) * r16) - + (((((((r * C15) + Vector256.Create(C14)) * r02) - + ((r * C13) + Vector256.Create(C12))) * r04) - + ((((r * C11) + Vector256.Create(C10)) * r02) - + ((r * C09) + Vector256.Create(C08)))) * r08) - + (((((r * C07) + Vector256.Create(C06)) * r02) - + ((r * C05) + Vector256.Create(C04))) * r04) - + ((((r * C03) + Vector256.Create(C02)) * r02) + r); - - return Vector256.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (n * LN2_HEAD) + ((n * LN2_TAIL) + poly) - ); - } - - public static Vector512 Invoke(Vector512 x) - { - Vector512 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector512 specialMask = Vector512.GreaterThanOrEqual(x.AsUInt64() - Vector512.Create(V_MIN), Vector512.Create(V_MAX - V_MIN)); - - if (specialMask != Vector512.Zero) - { - Vector512 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector512 lessThanZeroMask = Vector512.LessThan(xBits, Vector512.Zero).AsDouble(); - - specialResult = Vector512.ConditionalSelect( - lessThanZeroMask, - Vector512.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector512 zeroMask = Vector512.Equals(xBits << 1, Vector512.Zero).AsDouble(); - - specialResult = Vector512.ConditionalSelect( - zeroMask, - Vector512.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector512 temp = zeroMask - | lessThanZeroMask - | Vector512.GreaterThanOrEqual(xBits, Vector512.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector512 subnormalMask = Vector512.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector512.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector512.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector512 vx = x.AsUInt64() - Vector512.Create(V_OFF); - Vector512 n = Vector512.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector512.Create(V_MSK)) + Vector512.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector512 r = vx.AsDouble() - Vector512.One; - - Vector512 r02 = r * r; - Vector512 r04 = r02 * r02; - Vector512 r08 = r04 * r04; - Vector512 r16 = r08 * r08; - - // Compute log(x + 1) using Polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector512 poly = (((r04 * C20) - + ((((r * C19) + Vector512.Create(C18)) * r02) - + ((r * C17) + Vector512.Create(C16)))) * r16) - + (((((((r * C15) + Vector512.Create(C14)) * r02) - + ((r * C13) + Vector512.Create(C12))) * r04) - + ((((r * C11) + Vector512.Create(C10)) * r02) - + ((r * C09) + Vector512.Create(C08)))) * r08) - + (((((r * C07) + Vector512.Create(C06)) * r02) - + ((r * C05) + Vector512.Create(C04))) * r04) - + ((((r * C03) + Vector512.Create(C02)) * r02) + r); - - return Vector512.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (n * LN2_HEAD) + ((n * LN2_TAIL) + poly) - ); - } - } - - /// float.Log(x) - private readonly struct LogOperatorSingle : IUnaryOperator - { - // This code is based on `vrs4_logf` from amd/aocl-libm-ose - // Copyright (C) 2018-2019 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Spec: - // logf(x) - // = logf(x) if x ∈ F and x > 0 - // = x if x = qNaN - // = 0 if x = 1 - // = -inf if x = (-0, 0} - // = NaN otherwise - // - // Assumptions/Expectations - // - ULP is derived to be << 4 (always) - // - Some FPU Exceptions may not be available - // - Performance is at least 3x - // - // Implementation Notes: - // 1. Range Reduction: - // x = 2^n*(1+f) .... (1) - // where n is exponent and is an integer - // (1+f) is mantissa ∈ [1,2). i.e., 1 ≤ 1+f < 2 .... (2) - // - // From (1), taking log on both sides - // log(x) = log(2^n * (1+f)) - // = log(2^n) + log(1+f) - // = n*log(2) + log(1+f) .... (3) - // - // let z = 1 + f - // log(z) = log(k) + log(z) - log(k) - // log(z) = log(kz) - log(k) - // - // From (2), range of z is [1, 2) - // by simply dividing range by 'k', z is in [1/k, 2/k) .... (4) - // Best choice of k is the one which gives equal and opposite values - // at extrema +- -+ - // 1 | 2 | - // --- - 1 = - |--- - 1 | - // k | k | .... (5) - // +- -+ - // - // Solving for k, k = 3/2, - // From (4), using 'k' value, range is therefore [-0.3333, 0.3333] - // - // 2. Polynomial Approximation: - // More information refer to tools/sollya/vrs4_logf.sollya - // - // 7th Deg - Error abs: 0x1.04c4ac98p-22 rel: 0x1.2216e6f8p-19 - // 6th Deg - Error abs: 0x1.179e97d8p-19 rel: 0x1.db676c1p-17 - - private const uint V_MIN = 0x00800000; - private const uint V_MAX = 0x7F800000; - private const uint V_MASK = 0x007FFFFF; - private const uint V_OFF = 0x3F2AAAAB; - - private const float V_LN2 = 0.6931472f; - - private const float C0 = 0.0f; - private const float C1 = 1.0f; - private const float C2 = -0.5000001f; - private const float C3 = 0.33332965f; - private const float C4 = -0.24999046f; - private const float C5 = 0.20018855f; - private const float C6 = -0.16700386f; - private const float C7 = 0.13902695f; - private const float C8 = -0.1197452f; - private const float C9 = 0.14401625f; - private const float C10 = -0.13657966f; - - public static bool Vectorizable => true; - - public static float Invoke(float x) => float.Log(x); - - public static Vector128 Invoke(Vector128 x) - { - Vector128 specialResult = x; - - // x is subnormal or infinity or NaN - Vector128 specialMask = Vector128.GreaterThanOrEqual(x.AsUInt32() - Vector128.Create(V_MIN), Vector128.Create(V_MAX - V_MIN)); - - if (specialMask != Vector128.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector128 zeroMask = Vector128.Equals(x, Vector128.Zero); - - specialResult = Vector128.ConditionalSelect( - zeroMask, - Vector128.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector128 lessThanZeroMask = Vector128.LessThan(x, Vector128.Zero); - - specialResult = Vector128.ConditionalSelect( - lessThanZeroMask, - Vector128.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector128 temp = zeroMask - | lessThanZeroMask - | ~Vector128.Equals(x, x) - | Vector128.Equals(x, Vector128.Create(float.PositiveInfinity)); - - // subnormal - Vector128 subnormalMask = Vector128.AndNot(specialMask.AsSingle(), temp); - - x = Vector128.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector128.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector128 vx = x.AsUInt32() - Vector128.Create(V_OFF); - Vector128 n = Vector128.ConvertToSingle(Vector128.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector128.Create(V_MASK)) + Vector128.Create(V_OFF); - - Vector128 r = vx.AsSingle() - Vector128.One; - - Vector128 r2 = r * r; - Vector128 r4 = r2 * r2; - Vector128 r8 = r4 * r4; - - Vector128 q = (Vector128.Create(C10) * r2 + (Vector128.Create(C9) * r + Vector128.Create(C8))) - * r8 + (((Vector128.Create(C7) * r + Vector128.Create(C6)) - * r2 + (Vector128.Create(C5) * r + Vector128.Create(C4))) - * r4 + ((Vector128.Create(C3) * r + Vector128.Create(C2)) - * r2 + (Vector128.Create(C1) * r + Vector128.Create(C0)))); - - return Vector128.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n * Vector128.Create(V_LN2) + q - ); - } - - public static Vector256 Invoke(Vector256 x) - { - Vector256 specialResult = x; - - // x is subnormal or infinity or NaN - Vector256 specialMask = Vector256.GreaterThanOrEqual(x.AsUInt32() - Vector256.Create(V_MIN), Vector256.Create(V_MAX - V_MIN)); - - if (specialMask != Vector256.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector256 zeroMask = Vector256.Equals(x, Vector256.Zero); - - specialResult = Vector256.ConditionalSelect( - zeroMask, - Vector256.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector256 lessThanZeroMask = Vector256.LessThan(x, Vector256.Zero); - - specialResult = Vector256.ConditionalSelect( - lessThanZeroMask, - Vector256.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector256 temp = zeroMask - | lessThanZeroMask - | ~Vector256.Equals(x, x) - | Vector256.Equals(x, Vector256.Create(float.PositiveInfinity)); - - // subnormal - Vector256 subnormalMask = Vector256.AndNot(specialMask.AsSingle(), temp); - - x = Vector256.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector256.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector256 vx = x.AsUInt32() - Vector256.Create(V_OFF); - Vector256 n = Vector256.ConvertToSingle(Vector256.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector256.Create(V_MASK)) + Vector256.Create(V_OFF); - - Vector256 r = vx.AsSingle() - Vector256.One; - - Vector256 r2 = r * r; - Vector256 r4 = r2 * r2; - Vector256 r8 = r4 * r4; - - Vector256 q = (Vector256.Create(C10) * r2 + (Vector256.Create(C9) * r + Vector256.Create(C8))) - * r8 + (((Vector256.Create(C7) * r + Vector256.Create(C6)) - * r2 + (Vector256.Create(C5) * r + Vector256.Create(C4))) - * r4 + ((Vector256.Create(C3) * r + Vector256.Create(C2)) - * r2 + (Vector256.Create(C1) * r + Vector256.Create(C0)))); - - return Vector256.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n * Vector256.Create(V_LN2) + q - ); - } - - public static Vector512 Invoke(Vector512 x) - { - Vector512 specialResult = x; - - // x is subnormal or infinity or NaN - Vector512 specialMask = Vector512.GreaterThanOrEqual(x.AsUInt32() - Vector512.Create(V_MIN), Vector512.Create(V_MAX - V_MIN)); - - if (specialMask != Vector512.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector512 zeroMask = Vector512.Equals(x, Vector512.Zero); - - specialResult = Vector512.ConditionalSelect( - zeroMask, - Vector512.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector512 lessThanZeroMask = Vector512.LessThan(x, Vector512.Zero); - - specialResult = Vector512.ConditionalSelect( - lessThanZeroMask, - Vector512.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector512 temp = zeroMask - | lessThanZeroMask - | ~Vector512.Equals(x, x) - | Vector512.Equals(x, Vector512.Create(float.PositiveInfinity)); - - // subnormal - Vector512 subnormalMask = Vector512.AndNot(specialMask.AsSingle(), temp); - - x = Vector512.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector512.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector512 vx = x.AsUInt32() - Vector512.Create(V_OFF); - Vector512 n = Vector512.ConvertToSingle(Vector512.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector512.Create(V_MASK)) + Vector512.Create(V_OFF); - - Vector512 r = vx.AsSingle() - Vector512.One; - - Vector512 r2 = r * r; - Vector512 r4 = r2 * r2; - Vector512 r8 = r4 * r4; - - Vector512 q = (Vector512.Create(C10) * r2 + (Vector512.Create(C9) * r + Vector512.Create(C8))) - * r8 + (((Vector512.Create(C7) * r + Vector512.Create(C6)) - * r2 + (Vector512.Create(C5) * r + Vector512.Create(C4))) - * r4 + ((Vector512.Create(C3) * r + Vector512.Create(C2)) - * r2 + (Vector512.Create(C1) * r + Vector512.Create(C0)))); - - return Vector512.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n * Vector512.Create(V_LN2) + q - ); - } - } -#endif } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log2.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log2.cs index d3e0ea8b09e2e2..a10483b1cfbb79 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log2.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log2.cs @@ -87,592 +87,5 @@ public static Vector512 Invoke(Vector512 x) } } } - -#if !NET - /// double.Log2(x) - private readonly struct Log2OperatorDouble : IUnaryOperator - { - // This code is based on `vrd2_log2` from amd/aocl-libm-ose - // Copyright (C) 2021-2022 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Reduce x into the form: - // x = (-1)^s*2^n*m - // s will be always zero, as log is defined for positive numbers - // n is an integer known as the exponent - // m is mantissa - // - // x is reduced such that the mantissa, m lies in [2/3,4/3] - // x = 2^n*m where m is in [2/3,4/3] - // log2(x) = log2(2^n*m) We have log(a*b) = log(a)+log(b) - // = log2(2^n) + log2(m) We have log(a^n) = n*log(a) - // = n + log2(m) - // = n + log2(1+(m-1)) - // = n + ln(1+f) * log2(e) Where f = m-1 - // = n + log1p(f) * log2(e) f lies in [-1/3,+1/3] - // - // Thus we have : - // log(x) = n + log1p(f) * log2(e) - // The second term log1p(F) is approximated by using a polynomial - - private const ulong V_MIN = 0x00100000_00000000; // SmallestNormal - private const ulong V_MAX = 0x7FF00000_00000000; // +Infinity - private const ulong V_MSK = 0x000FFFFF_FFFFFFFF; // (1 << 52) - 1 - private const ulong V_OFF = 0x3FE55555_55555555; // 2.0 / 3.0 - - private const double LN2_HEAD = 1.44269180297851562500E+00; - private const double LN2_TAIL = 3.23791044778235969970E-06; - - private const double C02 = -0.499999999999999560; - private const double C03 = +0.333333333333414750; - private const double C04 = -0.250000000000297430; - private const double C05 = +0.199999999975985220; - private const double C06 = -0.166666666608919500; - private const double C07 = +0.142857145600277100; - private const double C08 = -0.125000005127831270; - private const double C09 = +0.111110952357159440; - private const double C10 = -0.099999750495501240; - private const double C11 = +0.090914349823462390; - private const double C12 = -0.083340600527551860; - private const double C13 = +0.076817603328311300; - private const double C14 = -0.071296718946287310; - private const double C15 = +0.067963465211535730; - private const double C16 = -0.063995035098960040; - private const double C17 = +0.049370587082412105; - private const double C18 = -0.045370170994891980; - private const double C19 = +0.088970636003577750; - private const double C20 = -0.086906174116908760; - - public static bool Vectorizable => true; - - public static double Invoke(double x) => double.Log2(x); - - public static Vector128 Invoke(Vector128 x) - { - Vector128 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector128 specialMask = Vector128.GreaterThanOrEqual(x.AsUInt64() - Vector128.Create(V_MIN), Vector128.Create(V_MAX - V_MIN)); - - if (specialMask != Vector128.Zero) - { - Vector128 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector128 lessThanZeroMask = Vector128.LessThan(xBits, Vector128.Zero).AsDouble(); - - specialResult = Vector128.ConditionalSelect( - lessThanZeroMask, - Vector128.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector128 zeroMask = Vector128.Equals(xBits << 1, Vector128.Zero).AsDouble(); - - specialResult = Vector128.ConditionalSelect( - zeroMask, - Vector128.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector128 temp = zeroMask - | lessThanZeroMask - | Vector128.GreaterThanOrEqual(xBits, Vector128.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector128 subnormalMask = Vector128.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector128.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector128.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector128 vx = x.AsUInt64() - Vector128.Create(V_OFF); - Vector128 n = Vector128.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector128.Create(V_MSK)) + Vector128.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector128 r = vx.AsDouble() - Vector128.One; - - Vector128 r02 = r * r; - Vector128 r04 = r02 * r02; - Vector128 r08 = r04 * r04; - Vector128 r16 = r08 * r08; - - // Compute log(x + 1) using polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector128 poly = (((r04 * C20) - + ((((r * C19) + Vector128.Create(C18)) * r02) - + ((r * C17) + Vector128.Create(C16)))) * r16) - + (((((((r * C15) + Vector128.Create(C14)) * r02) - + ((r * C13) + Vector128.Create(C12))) * r04) - + ((((r * C11) + Vector128.Create(C10)) * r02) - + ((r * C09) + Vector128.Create(C08)))) * r08) - + (((((r * C07) + Vector128.Create(C06)) * r02) - + ((r * C05) + Vector128.Create(C04))) * r04) - + ((((r * C03) + Vector128.Create(C02)) * r02) + r); - - return Vector128.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (poly * LN2_HEAD) + ((poly * LN2_TAIL) + n) - ); - } - - public static Vector256 Invoke(Vector256 x) - { - Vector256 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector256 specialMask = Vector256.GreaterThanOrEqual(x.AsUInt64() - Vector256.Create(V_MIN), Vector256.Create(V_MAX - V_MIN)); - - if (specialMask != Vector256.Zero) - { - Vector256 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector256 lessThanZeroMask = Vector256.LessThan(xBits, Vector256.Zero).AsDouble(); - - specialResult = Vector256.ConditionalSelect( - lessThanZeroMask, - Vector256.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector256 zeroMask = Vector256.Equals(xBits << 1, Vector256.Zero).AsDouble(); - - specialResult = Vector256.ConditionalSelect( - zeroMask, - Vector256.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector256 temp = zeroMask - | lessThanZeroMask - | Vector256.GreaterThanOrEqual(xBits, Vector256.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector256 subnormalMask = Vector256.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector256.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector256.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector256 vx = x.AsUInt64() - Vector256.Create(V_OFF); - Vector256 n = Vector256.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector256.Create(V_MSK)) + Vector256.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector256 r = vx.AsDouble() - Vector256.One; - - Vector256 r02 = r * r; - Vector256 r04 = r02 * r02; - Vector256 r08 = r04 * r04; - Vector256 r16 = r08 * r08; - - // Compute log(x + 1) using polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector256 poly = (((r04 * C20) - + ((((r * C19) + Vector256.Create(C18)) * r02) - + ((r * C17) + Vector256.Create(C16)))) * r16) - + (((((((r * C15) + Vector256.Create(C14)) * r02) - + ((r * C13) + Vector256.Create(C12))) * r04) - + ((((r * C11) + Vector256.Create(C10)) * r02) - + ((r * C09) + Vector256.Create(C08)))) * r08) - + (((((r * C07) + Vector256.Create(C06)) * r02) - + ((r * C05) + Vector256.Create(C04))) * r04) - + ((((r * C03) + Vector256.Create(C02)) * r02) + r); - - return Vector256.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (poly * LN2_HEAD) + ((poly * LN2_TAIL) + n) - ); - } - - public static Vector512 Invoke(Vector512 x) - { - Vector512 specialResult = x; - - // x is zero, subnormal, infinity, or NaN - Vector512 specialMask = Vector512.GreaterThanOrEqual(x.AsUInt64() - Vector512.Create(V_MIN), Vector512.Create(V_MAX - V_MIN)); - - if (specialMask != Vector512.Zero) - { - Vector512 xBits = x.AsInt64(); - - // (x < 0) ? float.NaN : x - Vector512 lessThanZeroMask = Vector512.LessThan(xBits, Vector512.Zero).AsDouble(); - - specialResult = Vector512.ConditionalSelect( - lessThanZeroMask, - Vector512.Create(double.NaN), - specialResult - ); - - // double.IsZero(x) ? double.NegativeInfinity : x - Vector512 zeroMask = Vector512.Equals(xBits << 1, Vector512.Zero).AsDouble(); - - specialResult = Vector512.ConditionalSelect( - zeroMask, - Vector512.Create(double.NegativeInfinity), - specialResult - ); - - // double.IsZero(x) | (x < 0) | double.IsNaN(x) | double.IsPositiveInfinity(x) - Vector512 temp = zeroMask - | lessThanZeroMask - | Vector512.GreaterThanOrEqual(xBits, Vector512.Create(double.PositiveInfinity).AsInt64()).AsDouble(); - - // subnormal - Vector512 subnormalMask = Vector512.AndNot(specialMask.AsDouble(), temp); - - // multiply by 2^52, then normalize - x = Vector512.ConditionalSelect( - subnormalMask, - ((x * 4503599627370496.0).AsUInt64() - Vector512.Create(52ul << 52)).AsDouble(), - x - ); - - specialMask = temp.AsUInt64(); - } - - // Reduce the mantissa to [+2/3, +4/3] - Vector512 vx = x.AsUInt64() - Vector512.Create(V_OFF); - Vector512 n = Vector512.ConvertToDouble(vx.AsInt64() >> 52); - vx = (vx & Vector512.Create(V_MSK)) + Vector512.Create(V_OFF); - - // Adjust the mantissa to [-1/3, +1/3] - Vector512 r = vx.AsDouble() - Vector512.One; - - Vector512 r02 = r * r; - Vector512 r04 = r02 * r02; - Vector512 r08 = r04 * r04; - Vector512 r16 = r08 * r08; - - // Compute log(x + 1) using polynomial approximation - // C0 + (r * C1) + (r^2 * C2) + ... + (r^20 * C20) - - Vector512 poly = (((r04 * C20) - + ((((r * C19) + Vector512.Create(C18)) * r02) - + ((r * C17) + Vector512.Create(C16)))) * r16) - + (((((((r * C15) + Vector512.Create(C14)) * r02) - + ((r * C13) + Vector512.Create(C12))) * r04) - + ((((r * C11) + Vector512.Create(C10)) * r02) - + ((r * C09) + Vector512.Create(C08)))) * r08) - + (((((r * C07) + Vector512.Create(C06)) * r02) - + ((r * C05) + Vector512.Create(C04))) * r04) - + ((((r * C03) + Vector512.Create(C02)) * r02) + r); - - return Vector512.ConditionalSelect( - specialMask.AsDouble(), - specialResult, - (poly * LN2_HEAD) + ((poly * LN2_TAIL) + n) - ); - } - } - - /// float.Log2(x) - private readonly struct Log2OperatorSingle : IUnaryOperator - { - // This code is based on `vrs4_log2f` from amd/aocl-libm-ose - // Copyright (C) 2021-2022 Advanced Micro Devices, Inc. All rights reserved. - // - // Licensed under the BSD 3-Clause "New" or "Revised" License - // See THIRD-PARTY-NOTICES.TXT for the full license text - - // Spec: - // log2f(x) - // = log2f(x) if x ∈ F and x > 0 - // = x if x = qNaN - // = 0 if x = 1 - // = -inf if x = (-0, 0} - // = NaN otherwise - // - // Assumptions/Expectations - // - Maximum ULP is observed to be at 4 - // - Some FPU Exceptions may not be available - // - Performance is at least 3x - // - // Implementation Notes: - // 1. Range Reduction: - // x = 2^n*(1+f) .... (1) - // where n is exponent and is an integer - // (1+f) is mantissa ∈ [1,2). i.e., 1 ≤ 1+f < 2 .... (2) - // - // From (1), taking log on both sides - // log2(x) = log2(2^n * (1+f)) - // = n + log2(1+f) .... (3) - // - // let z = 1 + f - // log2(z) = log2(k) + log2(z) - log2(k) - // log2(z) = log2(kz) - log2(k) - // - // From (2), range of z is [1, 2) - // by simply dividing range by 'k', z is in [1/k, 2/k) .... (4) - // Best choice of k is the one which gives equal and opposite values - // at extrema +- -+ - // 1 | 2 | - // --- - 1 = - |--- - 1 | - // k | k | .... (5) - // +- -+ - // - // Solving for k, k = 3/2, - // From (4), using 'k' value, range is therefore [-0.3333, 0.3333] - // - // 2. Polynomial Approximation: - // More information refer to tools/sollya/vrs4_logf.sollya - // - // 7th Deg - Error abs: 0x1.04c4ac98p-22 rel: 0x1.2216e6f8p-19 - - private const uint V_MIN = 0x00800000; - private const uint V_MAX = 0x7F800000; - private const uint V_MASK = 0x007FFFFF; - private const uint V_OFF = 0x3F2AAAAB; - - private const float C0 = 0.0f; - private const float C1 = 1.4426951f; - private const float C2 = -0.72134554f; - private const float C3 = 0.48089063f; - private const float C4 = -0.36084408f; - private const float C5 = 0.2888971f; - private const float C6 = -0.23594281f; - private const float C7 = 0.19948183f; - private const float C8 = -0.22616665f; - private const float C9 = 0.21228963f; - - public static bool Vectorizable => true; - - public static float Invoke(float x) => float.Log2(x); - - public static Vector128 Invoke(Vector128 x) - { - Vector128 specialResult = x; - - // x is subnormal or infinity or NaN - Vector128 specialMask = Vector128.GreaterThanOrEqual(x.AsUInt32() - Vector128.Create(V_MIN), Vector128.Create(V_MAX - V_MIN)); - - if (specialMask != Vector128.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector128 zeroMask = Vector128.Equals(x, Vector128.Zero); - - specialResult = Vector128.ConditionalSelect( - zeroMask, - Vector128.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector128 lessThanZeroMask = Vector128.LessThan(x, Vector128.Zero); - - specialResult = Vector128.ConditionalSelect( - lessThanZeroMask, - Vector128.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector128 temp = zeroMask - | lessThanZeroMask - | ~Vector128.Equals(x, x) - | Vector128.Equals(x, Vector128.Create(float.PositiveInfinity)); - - // subnormal - Vector128 subnormalMask = Vector128.AndNot(specialMask.AsSingle(), temp); - - x = Vector128.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector128.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector128 vx = x.AsUInt32() - Vector128.Create(V_OFF); - Vector128 n = Vector128.ConvertToSingle(Vector128.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector128.Create(V_MASK)) + Vector128.Create(V_OFF); - - Vector128 r = vx.AsSingle() - Vector128.One; - - Vector128 r2 = r * r; - Vector128 r4 = r2 * r2; - Vector128 r8 = r4 * r4; - - Vector128 poly = (Vector128.Create(C9) * r + Vector128.Create(C8)) * r8 - + (((Vector128.Create(C7) * r + Vector128.Create(C6)) * r2 - + (Vector128.Create(C5) * r + Vector128.Create(C4))) * r4 - + ((Vector128.Create(C3) * r + Vector128.Create(C2)) * r2 - + (Vector128.Create(C1) * r + Vector128.Create(C0)))); - - return Vector128.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n + poly - ); - } - - public static Vector256 Invoke(Vector256 x) - { - Vector256 specialResult = x; - - // x is subnormal or infinity or NaN - Vector256 specialMask = Vector256.GreaterThanOrEqual(x.AsUInt32() - Vector256.Create(V_MIN), Vector256.Create(V_MAX - V_MIN)); - - if (specialMask != Vector256.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector256 zeroMask = Vector256.Equals(x, Vector256.Zero); - - specialResult = Vector256.ConditionalSelect( - zeroMask, - Vector256.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector256 lessThanZeroMask = Vector256.LessThan(x, Vector256.Zero); - - specialResult = Vector256.ConditionalSelect( - lessThanZeroMask, - Vector256.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector256 temp = zeroMask - | lessThanZeroMask - | ~Vector256.Equals(x, x) - | Vector256.Equals(x, Vector256.Create(float.PositiveInfinity)); - - // subnormal - Vector256 subnormalMask = Vector256.AndNot(specialMask.AsSingle(), temp); - - x = Vector256.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector256.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector256 vx = x.AsUInt32() - Vector256.Create(V_OFF); - Vector256 n = Vector256.ConvertToSingle(Vector256.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector256.Create(V_MASK)) + Vector256.Create(V_OFF); - - Vector256 r = vx.AsSingle() - Vector256.One; - - Vector256 r2 = r * r; - Vector256 r4 = r2 * r2; - Vector256 r8 = r4 * r4; - - Vector256 poly = (Vector256.Create(C9) * r + Vector256.Create(C8)) * r8 - + (((Vector256.Create(C7) * r + Vector256.Create(C6)) * r2 - + (Vector256.Create(C5) * r + Vector256.Create(C4))) * r4 - + ((Vector256.Create(C3) * r + Vector256.Create(C2)) * r2 - + (Vector256.Create(C1) * r + Vector256.Create(C0)))); - - return Vector256.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n + poly - ); - } - - public static Vector512 Invoke(Vector512 x) - { - Vector512 specialResult = x; - - // x is subnormal or infinity or NaN - Vector512 specialMask = Vector512.GreaterThanOrEqual(x.AsUInt32() - Vector512.Create(V_MIN), Vector512.Create(V_MAX - V_MIN)); - - if (specialMask != Vector512.Zero) - { - // float.IsZero(x) ? float.NegativeInfinity : x - Vector512 zeroMask = Vector512.Equals(x, Vector512.Zero); - - specialResult = Vector512.ConditionalSelect( - zeroMask, - Vector512.Create(float.NegativeInfinity), - specialResult - ); - - // (x < 0) ? float.NaN : x - Vector512 lessThanZeroMask = Vector512.LessThan(x, Vector512.Zero); - - specialResult = Vector512.ConditionalSelect( - lessThanZeroMask, - Vector512.Create(float.NaN), - specialResult - ); - - // float.IsZero(x) | (x < 0) | float.IsNaN(x) | float.IsPositiveInfinity(x) - Vector512 temp = zeroMask - | lessThanZeroMask - | ~Vector512.Equals(x, x) - | Vector512.Equals(x, Vector512.Create(float.PositiveInfinity)); - - // subnormal - Vector512 subnormalMask = Vector512.AndNot(specialMask.AsSingle(), temp); - - x = Vector512.ConditionalSelect( - subnormalMask, - ((x * 8388608.0f).AsUInt32() - Vector512.Create(23u << 23)).AsSingle(), - x - ); - - specialMask = temp.AsUInt32(); - } - - Vector512 vx = x.AsUInt32() - Vector512.Create(V_OFF); - Vector512 n = Vector512.ConvertToSingle(Vector512.ShiftRightArithmetic(vx.AsInt32(), 23)); - - vx = (vx & Vector512.Create(V_MASK)) + Vector512.Create(V_OFF); - - Vector512 r = vx.AsSingle() - Vector512.One; - - Vector512 r2 = r * r; - Vector512 r4 = r2 * r2; - Vector512 r8 = r4 * r4; - - Vector512 poly = (Vector512.Create(C9) * r + Vector512.Create(C8)) * r8 - + (((Vector512.Create(C7) * r + Vector512.Create(C6)) * r2 - + (Vector512.Create(C5) * r + Vector512.Create(C4))) * r4 - + ((Vector512.Create(C3) * r + Vector512.Create(C2)) * r2 - + (Vector512.Create(C1) * r + Vector512.Create(C0)))); - - return Vector512.ConditionalSelect( - specialMask.AsSingle(), - specialResult, - n + poly - ); - } - } -#endif } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs index 8e42381c48e165..1e7249bd3fc751 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs @@ -106,129 +106,24 @@ public static void Max(ReadOnlySpan x, T y, Span destination) public static T Invoke(T x, T y) => T.Max(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector128.ConditionalSelect( - Vector128.LessThan(y, x) | IsNaN(x) | (Vector128.Equals(x, y) & IsNegative(y)), - x, - y - ); - } -#endif - - return Vector128.Max(x, y); - } + public static Vector128 Invoke(Vector128 x, Vector128 y) => Vector128.Max(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector256.ConditionalSelect( - Vector256.LessThan(y, x) | IsNaN(x) | (Vector256.Equals(x, y) & IsNegative(y)), - x, - y - ); - } -#endif - - return Vector256.Max(x, y); - } + public static Vector256 Invoke(Vector256 x, Vector256 y) => Vector256.Max(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector512.ConditionalSelect( - Vector512.LessThan(y, x) | IsNaN(x) | (Vector512.Equals(x, y) & IsNegative(y)), - x, - y - ); - } -#endif - - return Vector512.Max(x, y); - } + public static Vector512 Invoke(Vector512 x, Vector512 y) => Vector512.Max(x, y); public static T Invoke(Vector128 x) => HorizontalAggregate>(x); public static T Invoke(Vector256 x) => HorizontalAggregate>(x); public static T Invoke(Vector512 x) => HorizontalAggregate>(x); } - /// Gets whether each specified is NaN. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128 IsNaN(Vector128 vector) - { - return Vector128.IsNaN(vector); - } - - /// Gets whether each specified is NaN. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 IsNaN(Vector256 vector) - { - return Vector256.IsNaN(vector); - } - - /// Gets whether each specified is NaN. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector512 IsNaN(Vector512 vector) - { - return Vector512.IsNaN(vector); - } - - /// Gets whether each specified is negative. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128 IsNegative(Vector128 vector) - { - return Vector128.IsNegative(vector); - } - - /// Gets whether each specified is negative. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 IsNegative(Vector256 vector) - { - return Vector256.IsNegative(vector); - } - - /// Gets whether each specified is negative. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector512 IsNegative(Vector512 vector) - { - return Vector512.IsNegative(vector); - } - - /// Gets whether each specified is positive. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128 IsPositive(Vector128 vector) - { - return Vector128.IsPositive(vector); - } - - /// Gets whether each specified is positive. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 IsPositive(Vector256 vector) - { - return Vector256.IsPositive(vector); - } - - /// Gets whether each specified is positive. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector512 IsPositive(Vector512 vector) - { - return Vector512.IsPositive(vector); - } - - /// - /// This is the same as - /// with an identity transform, except it early exits on NaN. - /// - private static T MinMaxCore(ReadOnlySpan x) + /// + /// This is the same as + /// with an identity transform, except it early exits on NaN. + /// + private static T MinMaxCore(ReadOnlySpan x) where T : INumberBase where TMinMaxOperator : struct, IAggregationOperator { @@ -255,7 +150,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = IsNaN(result); + nanMask = Vector512.IsNaN(result); if (nanMask != Vector512.Zero) { return result.GetElement(IndexOfFirstMatch(nanMask)); @@ -386,7 +281,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = IsNaN(result); + nanMask = Vector128.IsNaN(result); if (nanMask != Vector128.Zero) { return result.GetElement(IndexOfFirstMatch(nanMask)); @@ -405,7 +300,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = IsNaN(current); + nanMask = Vector128.IsNaN(current); if (nanMask != Vector128.Zero) { return current.GetElement(IndexOfFirstMatch(nanMask)); @@ -424,7 +319,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = IsNaN(current); + nanMask = Vector128.IsNaN(current); if (nanMask != Vector128.Zero) { return current.GetElement(IndexOfFirstMatch(nanMask)); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs index 7efe4d84b2e2db..a9dcf10a9303bc 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs @@ -105,55 +105,13 @@ public static void Min(ReadOnlySpan x, T y, Span destination) public static T Invoke(T x, T y) => T.Min(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector128.ConditionalSelect( - Vector128.LessThan(x, y) | IsNaN(x) | (Vector128.Equals(x, y) & IsNegative(x)), - x, - y - ); - } -#endif - - return Vector128.Min(x, y); - } + public static Vector128 Invoke(Vector128 x, Vector128 y) => Vector128.Min(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector256.ConditionalSelect( - Vector256.LessThan(x, y) | IsNaN(x) | (Vector256.Equals(x, y) & IsNegative(x)), - x, - y - ); - } -#endif - - return Vector256.Min(x, y); - } + public static Vector256 Invoke(Vector256 x, Vector256 y) => Vector256.Min(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) - { -#if !NET - if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) - { - return Vector512.ConditionalSelect( - Vector512.LessThan(x, y) | IsNaN(x) | (Vector512.Equals(x, y) & IsNegative(x)), - x, - y - ); - } -#endif - - return Vector512.Min(x, y); - } + public static Vector512 Invoke(Vector512 x, Vector512 y) => Vector512.Min(x, y); public static T Invoke(Vector128 x) => HorizontalAggregate>(x); public static T Invoke(Vector256 x) => HorizontalAggregate>(x); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs index cf3728f5a986d3..ac210cb2d3a293 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs @@ -182,11 +182,6 @@ public static void Round(ReadOnlySpan x, int digits, MidpointRounding mode public static T Invoke(T x) => T.Round(x); -#if !NET - private const float SingleBoundary = 8388608.0f; // 2^23 - private const double DoubleBoundary = 4503599627370496.0; // 2^52 -#endif - public static Vector128 Invoke(Vector128 x) { if (typeof(T) == typeof(double)) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Sign.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Sign.cs index b037352a70ab52..f93014dcf93040 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Sign.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Sign.cs @@ -48,7 +48,7 @@ public static Vector128 Invoke(Vector128 x) return (value >> 31) | ((-value).AsUInt32() >> 31).AsInt32(); } - if (Vector128.EqualsAny(IsNaN(x).AsInt32(), Vector128.AllBitsSet)) + if (Vector128.EqualsAny(Vector128.IsNaN(x).AsInt32(), Vector128.AllBitsSet)) { ThrowHelper.ThrowArithmetic_NaN(); } @@ -75,7 +75,7 @@ public static Vector256 Invoke(Vector256 x) return (value >> 31) | ((-value).AsUInt32() >> 31).AsInt32(); } - if (Vector256.EqualsAny(IsNaN(x).AsInt32(), Vector256.AllBitsSet)) + if (Vector256.EqualsAny(Vector256.IsNaN(x).AsInt32(), Vector256.AllBitsSet)) { ThrowHelper.ThrowArithmetic_NaN(); } @@ -102,7 +102,7 @@ public static Vector512 Invoke(Vector512 x) return (value >> 31) | ((-value).AsUInt32() >> 31).AsInt32(); } - if (Vector512.EqualsAny(IsNaN(x).AsInt32(), Vector512.AllBitsSet)) + if (Vector512.EqualsAny(Vector512.IsNaN(x).AsInt32(), Vector512.AllBitsSet)) { ThrowHelper.ThrowArithmetic_NaN(); }