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 1147ec5bea5f78..ba0c4238ef14d6 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 @@ -196,18 +196,25 @@ public static Vector128 Invoke(Vector128 x) // 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 r; + r = MultiplyAddEstimateOperator.Invoke(dn, Vector128.Create(-V_LN2_HEAD), x); + r = MultiplyAddEstimateOperator.Invoke(dn, Vector128.Create(-V_LN2_TAIL), r); + // POLY_EVAL_ODD_9 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)); + Vector128 a0 = MultiplyAddEstimateOperator.Invoke(Vector128.Create(C12), r, Vector128.Create(C11)); + Vector128 a1 = MultiplyAddEstimateOperator.Invoke(Vector128.Create(C10), r, Vector128.Create(C9)); + Vector128 a2 = MultiplyAddEstimateOperator.Invoke(Vector128.Create(C8), r, Vector128.Create(C7)); + Vector128 a3 = MultiplyAddEstimateOperator.Invoke(Vector128.Create(C6), r, Vector128.Create(C5)); + Vector128 a4 = MultiplyAddEstimateOperator.Invoke(Vector128.Create(C4), r, Vector128.Create(C3)); + Vector128 a5 = MultiplyAddEstimateOperator.Invoke(a0, r2, a1); + Vector128 a6 = MultiplyAddEstimateOperator.Invoke(a2, r2, a3); + Vector128 a7 = MultiplyAddEstimateOperator.Invoke(a4, r2, r + Vector128.One); + //poly = a5 * r8 + a6 * r4 + a7; + Vector128 poly = MultiplyAddEstimateOperator.Invoke(a6, r4, a7); + poly = MultiplyAddEstimateOperator.Invoke(a5, r8, poly); // m = (n - j) / 64 // result = polynomial * 2^m @@ -247,18 +254,25 @@ public static Vector256 Invoke(Vector256 x) // 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 r; + r = MultiplyAddEstimateOperator.Invoke(dn, Vector256.Create(-V_LN2_HEAD), x); + r = MultiplyAddEstimateOperator.Invoke(dn, Vector256.Create(-V_LN2_TAIL), r); + // POLY_EVAL_ODD_9 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)); + Vector256 a0 = MultiplyAddEstimateOperator.Invoke(Vector256.Create(C12), r, Vector256.Create(C11)); + Vector256 a1 = MultiplyAddEstimateOperator.Invoke(Vector256.Create(C10), r, Vector256.Create(C9)); + Vector256 a2 = MultiplyAddEstimateOperator.Invoke(Vector256.Create(C8), r, Vector256.Create(C7)); + Vector256 a3 = MultiplyAddEstimateOperator.Invoke(Vector256.Create(C6), r, Vector256.Create(C5)); + Vector256 a4 = MultiplyAddEstimateOperator.Invoke(Vector256.Create(C4), r, Vector256.Create(C3)); + Vector256 a5 = MultiplyAddEstimateOperator.Invoke(a0, r2, a1); + Vector256 a6 = MultiplyAddEstimateOperator.Invoke(a2, r2, a3); + Vector256 a7 = MultiplyAddEstimateOperator.Invoke(a4, r2, r + Vector256.One); + //poly = a5 * r8 + a6 * r4 + a7; + Vector256 poly = MultiplyAddEstimateOperator.Invoke(a6, r4, a7); + poly = MultiplyAddEstimateOperator.Invoke(a5, r8, poly); // m = (n - j) / 64 // result = polynomial * 2^m @@ -298,18 +312,25 @@ public static Vector512 Invoke(Vector512 x) // 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 r; + r = MultiplyAddEstimateOperator.Invoke(dn, Vector512.Create(-V_LN2_HEAD), x); + r = MultiplyAddEstimateOperator.Invoke(dn, Vector512.Create(-V_LN2_TAIL), r); + // POLY_EVAL_ODD_9 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)); + Vector512 a0 = MultiplyAddEstimateOperator.Invoke(Vector512.Create(C12), r, Vector512.Create(C11)); + Vector512 a1 = MultiplyAddEstimateOperator.Invoke(Vector512.Create(C10), r, Vector512.Create(C9)); + Vector512 a2 = MultiplyAddEstimateOperator.Invoke(Vector512.Create(C8), r, Vector512.Create(C7)); + Vector512 a3 = MultiplyAddEstimateOperator.Invoke(Vector512.Create(C6), r, Vector512.Create(C5)); + Vector512 a4 = MultiplyAddEstimateOperator.Invoke(Vector512.Create(C4), r, Vector512.Create(C3)); + Vector512 a5 = MultiplyAddEstimateOperator.Invoke(a0, r2, a1); + Vector512 a6 = MultiplyAddEstimateOperator.Invoke(a2, r2, a3); + Vector512 a7 = MultiplyAddEstimateOperator.Invoke(a4, r2, r + Vector512.One); + //poly = a5 * r8 + a6 * r4 + a7; + Vector512 poly = MultiplyAddEstimateOperator.Invoke(a6, r4, a7); + poly = MultiplyAddEstimateOperator.Invoke(a5, r8, poly); // m = (n - j) / 64 // result = polynomial * 2^m @@ -411,6 +432,10 @@ public static Vector128 Invoke(Vector128 x) dnu -= v_expf_huge; // r = z - dn + Vector128 rl = zl - dnl; + Vector128 ru = zu - dnu; + + // POLY_EVAL_6 Vector128 c1 = Vector128.Create(C1); Vector128 c2 = Vector128.Create(C2); Vector128 c3 = Vector128.Create(C3); @@ -418,24 +443,21 @@ public static Vector128 Invoke(Vector128 x) 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 al0 = MultiplyAddEstimateOperator.Invoke(c4, rl, c3); + Vector128 al1 = MultiplyAddEstimateOperator.Invoke(c6, rl, c5); + Vector128 al2 = MultiplyAddEstimateOperator.Invoke(c2, rl, c1); + Vector128 polyl = MultiplyAddEstimateOperator.Invoke(al1, rl4, al2); + polyl = MultiplyAddEstimateOperator.Invoke(al0, rl2, polyl); Vector128 ru2 = ru * ru; Vector128 ru4 = ru2 * ru2; - - Vector128 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); + Vector128 au0 = MultiplyAddEstimateOperator.Invoke(c4, ru, c3); + Vector128 au1 = MultiplyAddEstimateOperator.Invoke(c6, ru, c5); + Vector128 au2 = MultiplyAddEstimateOperator.Invoke(c2, ru, c1); + Vector128 polyu = MultiplyAddEstimateOperator.Invoke(au1, ru4, au2); + polyu = MultiplyAddEstimateOperator.Invoke(au0, ru2, polyu); // result = (float)(poly + (n << 52)) Vector128 ret = Vector128.Narrow( @@ -487,6 +509,10 @@ public static Vector256 Invoke(Vector256 x) dnu -= v_expf_huge; // r = z - dn + Vector256 rl = zl - dnl; + Vector256 ru = zu - dnu; + + // POLY_EVAL_6 Vector256 c1 = Vector256.Create(C1); Vector256 c2 = Vector256.Create(C2); Vector256 c3 = Vector256.Create(C3); @@ -494,24 +520,21 @@ public static Vector256 Invoke(Vector256 x) 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 al0 = MultiplyAddEstimateOperator.Invoke(c4, rl, c3); + Vector256 al1 = MultiplyAddEstimateOperator.Invoke(c6, rl, c5); + Vector256 al2 = MultiplyAddEstimateOperator.Invoke(c2, rl, c1); + Vector256 polyl = MultiplyAddEstimateOperator.Invoke(al1, rl4, al2); + polyl = MultiplyAddEstimateOperator.Invoke(al0, rl2, polyl); Vector256 ru2 = ru * ru; Vector256 ru4 = ru2 * ru2; - - Vector256 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); + Vector256 au0 = MultiplyAddEstimateOperator.Invoke(c4, ru, c3); + Vector256 au1 = MultiplyAddEstimateOperator.Invoke(c6, ru, c5); + Vector256 au2 = MultiplyAddEstimateOperator.Invoke(c2, ru, c1); + Vector256 polyu = MultiplyAddEstimateOperator.Invoke(au1, ru4, au2); + polyu = MultiplyAddEstimateOperator.Invoke(au0, ru2, polyu); // result = (float)(poly + (n << 52)) Vector256 ret = Vector256.Narrow( @@ -563,6 +586,10 @@ public static Vector512 Invoke(Vector512 x) dnu -= v_expf_huge; // r = z - dn + Vector512 rl = zl - dnl; + Vector512 ru = zu - dnu; + + // POLY_EVAL_6 Vector512 c1 = Vector512.Create(C1); Vector512 c2 = Vector512.Create(C2); Vector512 c3 = Vector512.Create(C3); @@ -570,24 +597,21 @@ public static Vector512 Invoke(Vector512 x) 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 al0 = MultiplyAddEstimateOperator.Invoke(c4, rl, c3); + Vector512 al1 = MultiplyAddEstimateOperator.Invoke(c6, rl, c5); + Vector512 al2 = MultiplyAddEstimateOperator.Invoke(c2, rl, c1); + Vector512 polyl = MultiplyAddEstimateOperator.Invoke(al1, rl4, al2); + polyl = MultiplyAddEstimateOperator.Invoke(al0, rl2, polyl); Vector512 ru2 = ru * ru; Vector512 ru4 = ru2 * ru2; - - Vector512 polyu = (c4 * ru + c3) * ru2 - + ((c6 * ru + c5) * ru4 - + (c2 * ru + c1)); + Vector512 au0 = MultiplyAddEstimateOperator.Invoke(c4, ru, c3); + Vector512 au1 = MultiplyAddEstimateOperator.Invoke(c6, ru, c5); + Vector512 au2 = MultiplyAddEstimateOperator.Invoke(c2, ru, c1); + Vector512 polyu = MultiplyAddEstimateOperator.Invoke(au1, ru4, au2); + polyu = MultiplyAddEstimateOperator.Invoke(au0, ru2, polyu); // result = (float)(poly + (n << 52)) Vector512 ret = Vector512.Narrow( diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index a887e777949a03..cba1f4f1b95ea2 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -374,15 +374,14 @@ public static IEnumerable SpanDestinationFunctionsToTest() yield return Create(TensorPrimitives.DegreesToRadians, T.DegreesToRadians); yield return Create(TensorPrimitives.Exp, T.Exp); // TODO https://github.com/dotnet/runtime/issues/98861 - yield return Create(TensorPrimitives.Exp2, T.Exp2, Helpers.DetermineTolerance(doubleTolerance: 1e-6, floatTolerance: 1e-5f)); + yield return Create(TensorPrimitives.Exp2, T.Exp2, Helpers.DetermineTolerance(doubleTolerance: 1e-14, floatTolerance: 1e-5f)); // TODO https://github.com/dotnet/runtime/issues/98861 - yield return Create(TensorPrimitives.Exp10, T.Exp10, Helpers.DetermineTolerance(doubleTolerance: 1e-6, floatTolerance: 1e-5f)); + yield return Create(TensorPrimitives.Exp10, T.Exp10, Helpers.DetermineTolerance(doubleTolerance: 1e-13, floatTolerance: 1e-5f)); + yield return Create(TensorPrimitives.ExpM1, T.ExpM1); // TODO https://github.com/dotnet/runtime/issues/98861 - yield return Create(TensorPrimitives.ExpM1, T.ExpM1, Helpers.DetermineTolerance(doubleTolerance: 1e-6)); + yield return Create(TensorPrimitives.Exp2M1, T.Exp2M1, Helpers.DetermineTolerance(doubleTolerance: 1e-14, floatTolerance: 1e-5f)); // TODO https://github.com/dotnet/runtime/issues/98861 - yield return Create(TensorPrimitives.Exp2M1, T.Exp2M1, Helpers.DetermineTolerance(doubleTolerance: 1e-6, floatTolerance: 1e-5f)); - // TODO https://github.com/dotnet/runtime/issues/98861 - yield return Create(TensorPrimitives.Exp10M1, T.Exp10M1, Helpers.DetermineTolerance(doubleTolerance: 1e-6, floatTolerance: 1e-5f)); + yield return Create(TensorPrimitives.Exp10M1, T.Exp10M1, Helpers.DetermineTolerance(doubleTolerance: 1e-13, floatTolerance: 1e-5f)); yield return Create(TensorPrimitives.Floor, T.Floor); yield return Create(TensorPrimitives.Log, T.Log); yield return Create(TensorPrimitives.Log2, T.Log2);