libm: sync with upstream.

There's potential here to maybe lose some/all of builtins.cpp, but I'll
look at that separately later.

Test: treehugger
Change-Id: I2c2bc1d0753affdd214daeb09fa1ac7cd73db347
diff --git a/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c b/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
index 5cb1f93..493ced3 100644
--- a/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
+++ b/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
@@ -29,37 +29,46 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * The original code, FreeBSD's old svn r93211, contained the following
+ * attribution:
+ *
+ *    This code by P. McIlroy, Oct 1992;
+ *
+ *    The financial support of UUNET Communications Services is greatfully
+ *    acknowledged.
+ *
+ *  The algorithm remains, but the code has been re-arranged to facilitate
+ *  porting to other precisions.
+ */
+
 /* @(#)gamma.c	8.1 (Berkeley) 6/4/93 */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+/* Used in b_log.c and below. */
+struct Double {
+	double a;
+	double b;
+};
+
+#include "b_log.c"
+#include "b_exp.c"
+
 /*
- * This code by P. McIlroy, Oct 1992;
+ * The range is broken into several subranges.  Each is handled by its
+ * helper functions.
  *
- * The financial support of UUNET Communications Services is greatfully
- * acknowledged.
- */
-
-#include <math.h>
-#include "mathimpl.h"
-
-/* METHOD:
- * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
- * 	At negative integers, return NaN and raise invalid.
- *
- * x < 6.5:
- *	Use argument reduction G(x+1) = xG(x) to reach the
- *	range [1.066124,2.066124].  Use a rational
- *	approximation centered at the minimum (x0+1) to
- *	ensure monotonicity.
- *
- * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
- *	adjusted for equal-ripples:
- *
- *	log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
- *
- *	Keep extra precision in multiplying (x-.5)(log(x)-1), to
- *	avoid premature round-off.
+ *         x >=   6.0: large_gam(x)
+ *   6.0 > x >= xleft: small_gam(x) where xleft = 1 + left + x0.
+ * xleft > x >   iota: smaller_gam(x) where iota = 1e-17.
+ *  iota > x >  -itoa: Handle x near 0.
+ * -iota > x         : neg_gam
  *
  * Special values:
  *	-Inf:			return NaN and raise invalid;
@@ -77,201 +86,224 @@
  *	Maximum observed error < 4ulp in 1,000,000 trials.
  */
 
-static double neg_gam(double);
-static double small_gam(double);
-static double smaller_gam(double);
-static struct Double large_gam(double);
-static struct Double ratfun_gam(double, double);
-
-/*
- * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
- * [1.066.., 2.066..] accurate to 4.25e-19.
- */
-#define LEFT -.3955078125	/* left boundary for rat. approx */
-#define x0 .461632144968362356785	/* xmin - 1 */
-
-#define a0_hi 0.88560319441088874992
-#define a0_lo -.00000000000000004996427036469019695
-#define P0	 6.21389571821820863029017800727e-01
-#define P1	 2.65757198651533466104979197553e-01
-#define P2	 5.53859446429917461063308081748e-03
-#define P3	 1.38456698304096573887145282811e-03
-#define P4	 2.40659950032711365819348969808e-03
-#define Q0	 1.45019531250000000000000000000e+00
-#define Q1	 1.06258521948016171343454061571e+00
-#define Q2	-2.07474561943859936441469926649e-01
-#define Q3	-1.46734131782005422506287573015e-01
-#define Q4	 3.07878176156175520361557573779e-02
-#define Q5	 5.12449347980666221336054633184e-03
-#define Q6	-1.76012741431666995019222898833e-03
-#define Q7	 9.35021023573788935372153030556e-05
-#define Q8	 6.13275507472443958924745652239e-06
 /*
  * Constants for large x approximation (x in [6, Inf])
  * (Accurate to 2.8*10^-19 absolute)
  */
-#define lns2pi_hi 0.418945312500000
-#define lns2pi_lo -.000006779295327258219670263595
-#define Pa0	 8.33333333333333148296162562474e-02
-#define Pa1	-2.77777777774548123579378966497e-03
-#define Pa2	 7.93650778754435631476282786423e-04
-#define Pa3	-5.95235082566672847950717262222e-04
-#define Pa4	 8.41428560346653702135821806252e-04
-#define Pa5	-1.89773526463879200348872089421e-03
-#define Pa6	 5.69394463439411649408050664078e-03
-#define Pa7	-1.44705562421428915453880392761e-02
 
-static const double zero = 0., one = 1.0, tiny = 1e-300;
-
-double
-tgamma(x)
-	double x;
-{
-	struct Double u;
-
-	if (x >= 6) {
-		if(x > 171.63)
-			return (x / zero);
-		u = large_gam(x);
-		return(__exp__D(u.a, u.b));
-	} else if (x >= 1.0 + LEFT + x0)
-		return (small_gam(x));
-	else if (x > 1.e-17)
-		return (smaller_gam(x));
-	else if (x > -1.e-17) {
-		if (x != 0.0)
-			u.a = one - tiny;	/* raise inexact */
-		return (one/x);
-	} else if (!finite(x))
-		return (x - x);		/* x is NaN or -Inf */
-	else
-		return (neg_gam(x));
-}
+static const double zero = 0.;
+static const volatile double tiny = 1e-300;
 /*
+ * x >= 6
+ *
+ * Use the asymptotic approximation (Stirling's formula) adjusted fof
+ * equal-ripples:
+ *
+ * log(G(x)) ~= (x-0.5)*(log(x)-1) + 0.5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ * Keep extra precision in multiplying (x-.5)(log(x)-1), to avoid
+ * premature round-off.
+ *
  * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
  */
-static struct Double
-large_gam(x)
-	double x;
-{
-	double z, p;
-	struct Double t, u, v;
+static const double
+    ln2pi_hi =  0.41894531250000000,
+    ln2pi_lo = -6.7792953272582197e-6,
+    Pa0 =  8.3333333333333329e-02, /* 0x3fb55555, 0x55555555 */
+    Pa1 = -2.7777777777735404e-03, /* 0xbf66c16c, 0x16c145ec */
+    Pa2 =  7.9365079044114095e-04, /* 0x3f4a01a0, 0x183de82d */
+    Pa3 = -5.9523715464225254e-04, /* 0xbf438136, 0x0e681f62 */
+    Pa4 =  8.4161391899445698e-04, /* 0x3f4b93f8, 0x21042a13 */
+    Pa5 = -1.9065246069191080e-03, /* 0xbf5f3c8b, 0x357cb64e */
+    Pa6 =  5.9047708485785158e-03, /* 0x3f782f99, 0xdaf5d65f */
+    Pa7 = -1.6484018705183290e-02; /* 0xbf90e12f, 0xc4fb4df0 */
 
-	z = one/(x*x);
-	p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
-	p = p/x;
+static struct Double
+large_gam(double x)
+{
+	double p, z, thi, tlo, xhi, xlo;
+	struct Double u;
+
+	z = 1 / (x * x);
+	p = Pa0 + z * (Pa1 + z * (Pa2 + z * (Pa3 + z * (Pa4 + z * (Pa5 +
+	    z * (Pa6 + z * Pa7))))));
+	p = p / x;
 
 	u = __log__D(x);
-	u.a -= one;
-	v.a = (x -= .5);
-	TRUNC(v.a);
-	v.b = x - v.a;
-	t.a = v.a*u.a;			/* t = (x-.5)*(log(x)-1) */
-	t.b = v.b*u.a + x*u.b;
-	/* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
-	t.b += lns2pi_lo; t.b += p;
-	u.a = lns2pi_hi + t.b; u.a += t.a;
-	u.b = t.a - u.a;
-	u.b += lns2pi_hi; u.b += t.b;
+	u.a -= 1;
+
+	/* Split (x - 0.5) in high and low parts. */
+	x -= 0.5;
+	xhi = (float)x;
+	xlo = x - xhi;
+
+	/* Compute  t = (x-.5)*(log(x)-1) in extra precision. */
+	thi = xhi * u.a;
+	tlo = xlo * u.a + x * u.b;
+
+	/* Compute thi + tlo + ln2pi_hi + ln2pi_lo + p. */
+	tlo += ln2pi_lo;
+	tlo += p;
+	u.a = ln2pi_hi + tlo;
+	u.a += thi;
+	u.b = thi - u.a;
+	u.b += ln2pi_hi;
+	u.b += tlo;
 	return (u);
 }
 /*
+ * Rational approximation, A0 + x * x * P(x) / Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ *
+ * Returns r.a + r.b = a0 + (z + c)^2 * p / q, with r.a truncated.
+ */
+static const double
+#if 0
+    a0_hi =  8.8560319441088875e-1,
+    a0_lo = -4.9964270364690197e-17,
+#else
+    a0_hi =  8.8560319441088875e-01, /* 0x3fec56dc, 0x82a74aef */
+    a0_lo = -4.9642368725563397e-17, /* 0xbc8c9deb, 0xaa64afc3 */
+#endif
+    P0 =  6.2138957182182086e-1,
+    P1 =  2.6575719865153347e-1,
+    P2 =  5.5385944642991746e-3,
+    P3 =  1.3845669830409657e-3,
+    P4 =  2.4065995003271137e-3,
+    Q0 =  1.4501953125000000e+0,
+    Q1 =  1.0625852194801617e+0,
+    Q2 = -2.0747456194385994e-1,
+    Q3 = -1.4673413178200542e-1,
+    Q4 =  3.0787817615617552e-2,
+    Q5 =  5.1244934798066622e-3,
+    Q6 = -1.7601274143166700e-3,
+    Q7 =  9.3502102357378894e-5,
+    Q8 =  6.1327550747244396e-6;
+
+static struct Double
+ratfun_gam(double z, double c)
+{
+	double p, q, thi, tlo;
+	struct Double r;
+
+	q = Q0 + z * (Q1 + z * (Q2 + z * (Q3 + z * (Q4 + z * (Q5 + 
+	    z * (Q6 + z * (Q7 + z * Q8)))))));
+	p = P0 + z * (P1 + z * (P2 + z * (P3 + z * P4)));
+	p = p / q;
+
+	/* Split z into high and low parts. */
+	thi = (float)z;
+	tlo = (z - thi) + c;
+	tlo *= (thi + z);
+
+	/* Split (z+c)^2 into high and low parts. */
+	thi *= thi;
+	q = thi;
+	thi = (float)thi;
+	tlo += (q - thi);
+
+	/* Split p/q into high and low parts. */
+	r.a = (float)p;
+	r.b = p - r.a;
+
+	tlo = tlo * p + thi * r.b + a0_lo;
+	thi *= r.a;				/* t = (z+c)^2*(P/Q) */
+	r.a = (float)(thi + a0_hi);
+	r.b = ((a0_hi - r.a) + thi) + tlo;
+	return (r);				/* r = a0 + t */
+}
+/*
+ * x < 6
+ *
+ * Use argument reduction G(x+1) = xG(x) to reach the range [1.066124,
+ * 2.066124].  Use a rational approximation centered at the minimum
+ * (x0+1) to ensure monotonicity.
+ *
  * Good to < 1 ulp.  (provably .90 ulp; .87 ulp on 1,000,000 runs.)
  * It also has correct monotonicity.
  */
+static const double
+    left = -0.3955078125,	/* left boundary for rat. approx */
+    x0 = 4.6163214496836236e-1;	/* xmin - 1 */
+
 static double
-small_gam(x)
-	double x;
+small_gam(double x)
 {
-	double y, ym1, t;
+	double t, y, ym1;
 	struct Double yy, r;
-	y = x - one;
-	ym1 = y - one;
-	if (y <= 1.0 + (LEFT + x0)) {
+
+	y = x - 1;
+	if (y <= 1 + (left + x0)) {
 		yy = ratfun_gam(y - x0, 0);
 		return (yy.a + yy.b);
 	}
-	r.a = y;
-	TRUNC(r.a);
-	yy.a = r.a - one;
-	y = ym1;
-	yy.b = r.b = y - yy.a;
+
+	r.a = (float)y;
+	yy.a = r.a - 1;
+	y = y - 1 ;
+	r.b = yy.b = y - yy.a;
+
 	/* Argument reduction: G(x+1) = x*G(x) */
-	for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
-		t = r.a*yy.a;
-		r.b = r.a*yy.b + y*r.b;
-		r.a = t;
-		TRUNC(r.a);
+	for (ym1 = y - 1; ym1 > left + x0; y = ym1--, yy.a--) {
+		t = r.a * yy.a;
+		r.b = r.a * yy.b + y * r.b;
+		r.a = (float)t;
 		r.b += (t - r.a);
 	}
+
 	/* Return r*tgamma(y). */
 	yy = ratfun_gam(y - x0, 0);
-	y = r.b*(yy.a + yy.b) + r.a*yy.b;
-	y += yy.a*r.a;
+	y = r.b * (yy.a + yy.b) + r.a * yy.b;
+	y += yy.a * r.a;
 	return (y);
 }
 /*
- * Good on (0, 1+x0+LEFT].  Accurate to 1ulp.
+ * Good on (0, 1+x0+left].  Accurate to 1 ulp.
  */
 static double
-smaller_gam(x)
-	double x;
+smaller_gam(double x)
 {
-	double t, d;
-	struct Double r, xx;
-	if (x < x0 + LEFT) {
-		t = x, TRUNC(t);
-		d = (t+x)*(x-t);
+	double d, rhi, rlo, t, xhi, xlo;
+	struct Double r;
+
+	if (x < x0 + left) {
+		t = (float)x;
+		d = (t + x) * (x - t);
 		t *= t;
-		xx.a = (t + x), TRUNC(xx.a);
-		xx.b = x - xx.a; xx.b += t; xx.b += d;
-		t = (one-x0); t += x;
-		d = (one-x0); d -= t; d += x;
-		x = xx.a + xx.b;
+		xhi = (float)(t + x);
+		xlo = x - xhi;
+		xlo += t;
+		xlo += d;
+		t = 1 - x0;
+		t += x;
+		d = 1 - x0;
+		d -= t;
+		d += x;
+		x = xhi + xlo;
 	} else {
-		xx.a =  x, TRUNC(xx.a);
-		xx.b = x - xx.a;
+		xhi = (float)x;
+		xlo = x - xhi;
 		t = x - x0;
-		d = (-x0 -t); d += x;
+		d = - x0 - t;
+		d += x;
 	}
+
 	r = ratfun_gam(t, d);
-	d = r.a/x, TRUNC(d);
-	r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
-	return (d + r.a/x);
+	d = (float)(r.a / x);
+	r.a -= d * xhi;
+	r.a -= d * xlo;
+	r.a += r.b;
+
+	return (d + r.a / x);
 }
 /*
- * returns (z+c)^2 * P(z)/Q(z) + a0
+ * x < 0
+ *
+ * Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x)).
+ * At negative integers, return NaN and raise invalid.
  */
-static struct Double
-ratfun_gam(z, c)
-	double z, c;
-{
-	double p, q;
-	struct Double r, t;
-
-	q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
-	p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
-
-	/* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
-	p = p/q;
-	t.a = z, TRUNC(t.a);		/* t ~= z + c */
-	t.b = (z - t.a) + c;
-	t.b *= (t.a + z);
-	q = (t.a *= t.a);		/* t = (z+c)^2 */
-	TRUNC(t.a);
-	t.b += (q - t.a);
-	r.a = p, TRUNC(r.a);		/* r = P/Q */
-	r.b = p - r.a;
-	t.b = t.b*p + t.a*r.b + a0_lo;
-	t.a *= r.a;			/* t = (z+c)^2*(P/Q) */
-	r.a = t.a + a0_hi, TRUNC(r.a);
-	r.b = ((a0_hi-r.a) + t.a) + t.b;
-	return (r);			/* r = a0 + t */
-}
-
 static double
-neg_gam(x)
-	double x;
+neg_gam(double x)
 {
 	int sgn = 1;
 	struct Double lg, lsine;
@@ -280,23 +312,29 @@
 	y = ceil(x);
 	if (y == x)		/* Negative integer. */
 		return ((x - x) / zero);
+
 	z = y - x;
 	if (z > 0.5)
-		z = one - z;
-	y = 0.5 * y;
+		z = 1 - z;
+
+	y = y / 2;
 	if (y == ceil(y))
 		sgn = -1;
-	if (z < .25)
-		z = sin(M_PI*z);
+
+	if (z < 0.25)
+		z = sinpi(z);
 	else
-		z = cos(M_PI*(0.5-z));
+		z = cospi(0.5 - z);
+
 	/* Special case: G(1-x) = Inf; G(x) may be nonzero. */
 	if (x < -170) {
+
 		if (x < -190)
-			return ((double)sgn*tiny*tiny);
-		y = one - x;		/* exact: 128 < |x| < 255 */
+			return (sgn * tiny * tiny);
+
+		y = 1 - x;			/* exact: 128 < |x| < 255 */
 		lg = large_gam(y);
-		lsine = __log__D(M_PI/z);	/* = TRUNC(log(u)) + small */
+		lsine = __log__D(M_PI / z);	/* = TRUNC(log(u)) + small */
 		lg.a -= lsine.a;		/* exact (opposite signs) */
 		lg.b -= lsine.b;
 		y = -(lg.a + lg.b);
@@ -305,11 +343,58 @@
 		if (sgn < 0) y = -y;
 		return (y);
 	}
-	y = one-x;
-	if (one-y == x)
+
+	y = 1 - x;
+	if (1 - y == x)
 		y = tgamma(y);
 	else		/* 1-x is inexact */
-		y = -x*tgamma(-x);
+		y = - x * tgamma(-x);
+
 	if (sgn < 0) y = -y;
-	return (M_PI / (y*z));
+	return (M_PI / (y * z));
 }
+/*
+ * xmax comes from lgamma(xmax) - emax * log(2) = 0.
+ * static const float  xmax = 35.040095f
+ * static const double xmax = 171.624376956302725;
+ * ld80: LD80C(0xdb718c066b352e20, 10, 1.75554834290446291689e+03L),
+ * ld128: 1.75554834290446291700388921607020320e+03L,
+ *
+ * iota is a sloppy threshold to isolate x = 0.
+ */
+static const double xmax = 171.624376956302725;
+static const double iota = 0x1p-56;
+
+double
+tgamma(double x)
+{
+	struct Double u;
+
+	if (x >= 6) {
+		if (x > xmax)
+			return (x / zero);
+		u = large_gam(x);
+		return (__exp__D(u.a, u.b));
+	}
+
+	if (x >= 1 + left + x0)
+		return (small_gam(x));
+
+	if (x > iota)
+		return (smaller_gam(x));
+
+	if (x > -iota) {
+		if (x != 0.)
+			u.a = 1 - tiny;	/* raise inexact */
+		return (1 / x);
+	}
+
+	if (!isfinite(x))
+		return (x - x);		/* x is NaN or -Inf */
+
+	return (neg_gam(x));
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(tgamma, tgammal);
+#endif