The following program fails on Mono and returns +∞ instead of NaN as expected. This is likely an error somewhere in the branch handling edge case inputs at the end of the Invoke function. It was caught as part of #97114
// 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^rusingSystem.Runtime.Intrinsics;varres=Invoke(Vector128.Create(double.NaN));Console.WriteLine(res);constulongV_ARG_MAX=0x40862000_00000000;constulongV_DP64_BIAS=1023;constdoubleV_EXPF_MIN=-709.782712893384;constdoubleV_EXPF_MAX=+709.782712893384;constdoubleV_EXPF_HUGE=6755399441055744;constdoubleV_TBL_LN2=1.4426950408889634;constdoubleV_LN2_HEAD=+0.693359375;constdoubleV_LN2_TAIL=-0.00021219444005469057;constdoubleC3=0.5000000000000018;constdoubleC4=0.1666666666666617;constdoubleC5=0.04166666666649277;constdoubleC6=0.008333333333559272;constdoubleC7=0.001388888895122404;constdoubleC8=0.00019841269432677495;constdoubleC9=2.4801486521374483E-05;constdoubleC10=2.7557622532543023E-06;constdoubleC11=2.7632293298250954E-07;constdoubleC12=2.499430431958571E-08;staticVector128<double>Invoke(Vector128<double>x){// x * (64.0 / ln(2))Vector128<double>z=x*Vector128.Create(V_TBL_LN2);Vector128<double>dn=z+Vector128.Create(V_EXPF_HUGE);// n = (int)zVector128<ulong>n=dn.AsUInt64();// dn = (double)ndn-=Vector128.Create(V_EXPF_HUGE);// r = x - (dn * (ln(2) / 64))// where ln(2) / 64 is split into Head and Tail valuesVector128<double>r=x-(dn*Vector128.Create(V_LN2_HEAD))-(dn*Vector128.Create(V_LN2_TAIL));Vector128<double>r2=r*r;Vector128<double>r4=r2*r2;Vector128<double>r8=r4*r4;// Compute polynomialVector128<double>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<double>.One));// m = (n - j) / 64// result = polynomial * 2^mVector128<double>ret=poly*((n+Vector128.Create(V_DP64_BIAS))<<52).AsDouble();// Check if -709 < vx < 709if(Vector128.GreaterThanAny(Vector128.Abs(x).AsUInt64(),Vector128.Create(V_ARG_MAX))){// (x > V_EXPF_MAX) ? double.PositiveInfinity : xVector128<double>infinityMask=Vector128.GreaterThan(x,Vector128.Create(V_EXPF_MAX));ret=Vector128.ConditionalSelect(infinityMask,Vector128.Create(double.PositiveInfinity),ret);// (x < V_EXPF_MIN) ? 0 : xret=Vector128.AndNot(ret,Vector128.LessThan(x,Vector128.Create(V_EXPF_MIN)));}returnret;}
The following program fails on Mono and returns
+∞instead ofNaNas expected. This is likely an error somewhere in the branch handling edge case inputs at the end of theInvokefunction. It was caught as part of #97114