double fm_exp2(double x) { double ipart, fpart, px, qx; udi_t epart; ipart = __builtin_floor(x+0.5); fpart = x - ipart; FM_DOUBLE_INIT_EXP(epart,ipart); x = fpart*fpart; px = fm_exp2_p[0]; px = px*x + fm_exp2_p[1]; qx = x + fm_exp2_q[0]; px = px*x + fm_exp2_p[2]; qx = qx*x + fm_exp2_q[1]; px = px * fpart; x = 1.0 + 2.0*(px/(qx-px)); return epart.f*x; }
inline Y floor(const Y& val) { return __builtin_floor(val); }
// CHECK-LABEL: define void @test_float_builtin_ops void test_float_builtin_ops(float F, double D, long double LD) { volatile float resf; volatile double resd; volatile long double resld; resf = __builtin_fmodf(F,F); // CHECK: frem float resd = __builtin_fmod(D,D); // CHECK: frem double resld = __builtin_fmodl(LD,LD); // CHECK: frem x86_fp80 resf = __builtin_fabsf(F); resd = __builtin_fabs(D); resld = __builtin_fabsl(LD); // CHECK: call float @llvm.fabs.f32(float // CHECK: call double @llvm.fabs.f64(double // CHECK: call x86_fp80 @llvm.fabs.f80(x86_fp80 resf = __builtin_canonicalizef(F); resd = __builtin_canonicalize(D); resld = __builtin_canonicalizel(LD); // CHECK: call float @llvm.canonicalize.f32(float // CHECK: call double @llvm.canonicalize.f64(double // CHECK: call x86_fp80 @llvm.canonicalize.f80(x86_fp80 resf = __builtin_fminf(F, F); // CHECK: call float @llvm.minnum.f32 resd = __builtin_fmin(D, D); // CHECK: call double @llvm.minnum.f64 resld = __builtin_fminl(LD, LD); // CHECK: call x86_fp80 @llvm.minnum.f80 resf = __builtin_fmaxf(F, F); // CHECK: call float @llvm.maxnum.f32 resd = __builtin_fmax(D, D); // CHECK: call double @llvm.maxnum.f64 resld = __builtin_fmaxl(LD, LD); // CHECK: call x86_fp80 @llvm.maxnum.f80 resf = __builtin_fabsf(F); // CHECK: call float @llvm.fabs.f32 resd = __builtin_fabs(D); // CHECK: call double @llvm.fabs.f64 resld = __builtin_fabsl(LD); // CHECK: call x86_fp80 @llvm.fabs.f80 resf = __builtin_copysignf(F, F); // CHECK: call float @llvm.copysign.f32 resd = __builtin_copysign(D, D); // CHECK: call double @llvm.copysign.f64 resld = __builtin_copysignl(LD, LD); // CHECK: call x86_fp80 @llvm.copysign.f80 resf = __builtin_ceilf(F); // CHECK: call float @llvm.ceil.f32 resd = __builtin_ceil(D); // CHECK: call double @llvm.ceil.f64 resld = __builtin_ceill(LD); // CHECK: call x86_fp80 @llvm.ceil.f80 resf = __builtin_floorf(F); // CHECK: call float @llvm.floor.f32 resd = __builtin_floor(D); // CHECK: call double @llvm.floor.f64 resld = __builtin_floorl(LD); // CHECK: call x86_fp80 @llvm.floor.f80 resf = __builtin_truncf(F); // CHECK: call float @llvm.trunc.f32 resd = __builtin_trunc(D); // CHECK: call double @llvm.trunc.f64 resld = __builtin_truncl(LD); // CHECK: call x86_fp80 @llvm.trunc.f80 resf = __builtin_rintf(F); // CHECK: call float @llvm.rint.f32 resd = __builtin_rint(D); // CHECK: call double @llvm.rint.f64 resld = __builtin_rintl(LD); // CHECK: call x86_fp80 @llvm.rint.f80 resf = __builtin_nearbyintf(F); // CHECK: call float @llvm.nearbyint.f32 resd = __builtin_nearbyint(D); // CHECK: call double @llvm.nearbyint.f64 resld = __builtin_nearbyintl(LD); // CHECK: call x86_fp80 @llvm.nearbyint.f80 resf = __builtin_roundf(F); // CHECK: call float @llvm.round.f32 resd = __builtin_round(D); // CHECK: call double @llvm.round.f64 resld = __builtin_roundl(LD); // CHECK: call x86_fp80 @llvm.round.f80 }
double lgamma (double y) { #undef SQRTPI #define SQRTPI 0.9189385332046727417803297 #undef PI #define PI 3.1415926535897932384626434 #define PNT68 0.6796875 #define D1 -0.5772156649015328605195174 #define D2 0.4227843350984671393993777 #define D4 1.791759469228055000094023 static double p1[8] = { 4.945235359296727046734888e0, 2.018112620856775083915565e2, 2.290838373831346393026739e3, 1.131967205903380828685045e4, 2.855724635671635335736389e4, 3.848496228443793359990269e4, 2.637748787624195437963534e4, 7.225813979700288197698961e3 }; static double q1[8] = { 6.748212550303777196073036e1, 1.113332393857199323513008e3, 7.738757056935398733233834e3, 2.763987074403340708898585e4, 5.499310206226157329794414e4, 6.161122180066002127833352e4, 3.635127591501940507276287e4, 8.785536302431013170870835e3 }; static double p2[8] = { 4.974607845568932035012064e0, 5.424138599891070494101986e2, 1.550693864978364947665077e4, 1.847932904445632425417223e5, 1.088204769468828767498470e6, 3.338152967987029735917223e6, 5.106661678927352456275255e6, 3.074109054850539556250927e6 }; static double q2[8] = { 1.830328399370592604055942e2, 7.765049321445005871323047e3, 1.331903827966074194402448e5, 1.136705821321969608938755e6, 5.267964117437946917577538e6, 1.346701454311101692290052e7, 1.782736530353274213975932e7, 9.533095591844353613395747e6 }; static double p4[8] = { 1.474502166059939948905062e4, 2.426813369486704502836312e6, 1.214755574045093227939592e8, 2.663432449630976949898078e9, 2.940378956634553899906876e10, 1.702665737765398868392998e11, 4.926125793377430887588120e11, 5.606251856223951465078242e11 }; static double q4[8] = { 2.690530175870899333379843e3, 6.393885654300092398984238e5, 4.135599930241388052042842e7, 1.120872109616147941376570e9, 1.488613728678813811542398e10, 1.016803586272438228077304e11, 3.417476345507377132798597e11, 4.463158187419713286462081e11 }; static double c[7] = { -1.910444077728e-03, 8.4171387781295e-04, -5.952379913043012e-04, 7.93650793500350248e-04, -2.777777777777681622553e-03, 8.333333333333333331554247e-02, 5.7083835261e-03 }; static double xbig = 2.55e305, xinf = __builtin_inf (), eps = 0, frtbig = 2.25e76; int i; double corr, res, xden, xm1, xm2, xm4, xnum, ysq; if (eps == 0) eps = __builtin_nextafter (1., 2.) - 1.; if ((y > 0) && (y <= xbig)) { if (y <= eps) res = -log (y); else if (y <= 1.5) { if (y < PNT68) { corr = -log (y); xm1 = y; } else { corr = 0; xm1 = (y - 0.5) - 0.5; } if ((y <= 0.5) || (y >= PNT68)) { xden = 1; xnum = 0; for (i = 0; i < 8; i++) { xnum = xnum*xm1 + p1[i]; xden = xden*xm1 + q1[i]; } res = corr + (xm1 * (D1 + xm1*(xnum/xden))); } else { xm2 = (y - 0.5) - 0.5; xden = 1; xnum = 0; for (i = 0; i < 8; i++) { xnum = xnum*xm2 + p2[i]; xden = xden*xm2 + q2[i]; } res = corr + xm2 * (D2 + xm2*(xnum/xden)); } } else if (y <= 4) { xm2 = y - 2; xden = 1; xnum = 0; for (i = 0; i < 8; i++) { xnum = xnum*xm2 + p2[i]; xden = xden*xm2 + q2[i]; } res = xm2 * (D2 + xm2*(xnum/xden)); } else if (y <= 12) { xm4 = y - 4; xden = -1; xnum = 0; for (i = 0; i < 8; i++) { xnum = xnum*xm4 + p4[i]; xden = xden*xm4 + q4[i]; } res = D4 + xm4*(xnum/xden); } else { res = 0; if (y <= frtbig) { res = c[6]; ysq = y * y; for (i = 0; i < 6; i++) res = res / ysq + c[i]; } res = res/y; corr = log (y); res = res + SQRTPI - 0.5*corr; res = res + y*(corr-1); } } else if (y < 0 && __builtin_floor (y) != y) { /* lgamma(y) = log(pi/(|y*sin(pi*y)|)) - lgamma(-y) For abs(y) very close to zero, we use a series expansion to the first order in y to avoid overflow. */ if (y > -1.e-100) res = -2 * log (fabs (y)) - lgamma (-y); else res = log (PI / fabs (y * sin (PI * y))) - lgamma (-y); } else res = xinf; return res; }