Browse Source

Import long double versions from OpenBSD.

Viral B. Shah 10 years ago
parent
commit
52c901a68c

+ 58 - 0
ld128/e_acoshl.c

@@ -0,0 +1,58 @@
+/* @(#)e_acosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* acoshl(x)
+ * Method :
+ *	Based on
+ *		acoshl(x) = logl [ x + sqrtl(x*x-1) ]
+ *	we have
+ *		acoshl(x) := logl(x)+ln2,	if x is large; else
+ *		acoshl(x) := logl(2x-1/(sqrtl(x*x-1)+x)) if x>2; else
+ *		acoshl(x) := log1pl(t+sqrtl(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ *	acoshl(x) is NaN with signal if x<1.
+ *	acoshl(NaN) is NaN without signal.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+one	= 1.0,
+ln2	= 0.6931471805599453094172321214581766L;
+
+long double
+acoshl(long double x)
+{
+	long double t;
+	u_int64_t lx;
+	int64_t hx;
+	GET_LDOUBLE_WORDS64(hx,lx,x);
+	if(hx<0x3fff000000000000LL) {		/* x < 1 */
+	    return (x-x)/(x-x);
+	} else if(hx >=0x4035000000000000LL) {	/* x > 2**54 */
+	    if(hx >=0x7fff000000000000LL) {	/* x is inf of NaN */
+		return x+x;
+	    } else
+		return logl(x)+ln2;	/* acoshl(huge)=logl(2x) */
+	} else if(((hx-0x3fff000000000000LL)|lx)==0) {
+	    return 0.0L;			/* acosh(1) = 0 */
+	} else if (hx > 0x4000000000000000LL) {	/* 2**28 > x > 2 */
+	    t=x*x;
+	    return logl(2.0L*x-one/(x+sqrtl(t-one)));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    return log1pl(t+sqrtl(2.0L*t+t*t));
+	}
+}

+ 65 - 0
ld128/e_atanhl.c

@@ -0,0 +1,65 @@
+/* @(#)e_atanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* atanhl(x)
+ * Method :
+ *    1.Reduced x to positive by atanh(-x) = -atanh(x)
+ *    2.For x>=0.5
+ *                   1              2x                          x
+ *	atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ *                   2             1 - x                      1 - x
+ *
+ * 	For x<0.5
+ *	atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ *	atanhl(x) is NaN if |x| > 1 with signal;
+ *	atanhl(NaN) is that NaN with no signal;
+ *	atanhl(+-1) is +-INF with signal.
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0L, huge = 1e4900L;
+
+static const long double zero = 0.0L;
+
+long double
+atanhl(long double x)
+{
+	long double t;
+	u_int32_t jx, ix;
+	ieee_quad_shape_type u;
+
+	u.value = x;
+	jx = u.parts32.mswhi;
+	ix = jx & 0x7fffffff;
+	u.parts32.mswhi = ix;
+	if (ix >= 0x3fff0000) /* |x| >= 1.0 or infinity or NaN */
+	  {
+	    if (u.value == one)
+	      return x/zero;
+	    else
+	      return (x-x)/(x-x);
+	  }
+	if(ix<0x3fc60000 && (huge+x)>zero) return x;	/* x < 2^-57 */
+
+	if(ix<0x3ffe0000) {		/* x < 0.5 */
+	    t = u.value+u.value;
+	    t = 0.5*log1pl(t+t*u.value/(one-u.value));
+	} else
+	    t = 0.5*log1pl((u.value+u.value)/(one-u.value));
+	if(jx & 0x80000000) return -t; else return t;
+}

+ 105 - 0
ld128/e_coshl.c

@@ -0,0 +1,105 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* coshl(x)
+ * Method :
+ * mathematically coshl(x) if defined to be (exp(x)+exp(-x))/2
+ *      1. Replace x by |x| (coshl(x) = coshl(-x)).
+ *      2.
+ *                                                      [ exp(x) - 1 ]^2
+ *          0        <= x <= ln2/2  :  coshl(x) := 1 + -------------------
+ *                                                         2*exp(x)
+ *
+ *                                                 exp(x) +  1/exp(x)
+ *          ln2/2    <= x <= 22     :  coshl(x) := -------------------
+ *                                                         2
+ *          22       <= x <= lnovft :  coshl(x) := expl(x)/2
+ *          lnovft   <= x <= ln2ovft:  coshl(x) := expl(x/2)/2 * expl(x/2)
+ *          ln2ovft  <  x           :  coshl(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ *      coshl(x) is |x| if x is +INF, -INF, or NaN.
+ *      only coshl(0)=1 is exact for finite x.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, half = 0.5, huge = 1.0e4900L,
+ovf_thresh = 1.1357216553474703894801348310092223067821E4L;
+
+long double
+coshl(long double x)
+{
+  long double t, w;
+  int32_t ex;
+  ieee_quad_shape_type u;
+
+  u.value = x;
+  ex = u.parts32.mswhi & 0x7fffffff;
+
+  /* Absolute value of x.  */
+  u.parts32.mswhi = ex;
+
+  /* x is INF or NaN */
+  if (ex >= 0x7fff0000)
+    return x * x;
+
+  /* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expl(|x|)) */
+  if (ex < 0x3ffd62e4) /* 0.3465728759765625 */
+    {
+      t = expm1l (u.value);
+      w = one + t;
+      if (ex < 0x3fb80000) /* |x| < 2^-116 */
+	return w;		/* cosh(tiny) = 1 */
+
+      return one + (t * t) / (w + w);
+    }
+
+  /* |x| in [0.5*ln2,40], return (exp(|x|)+1/exp(|x|)/2; */
+  if (ex < 0x40044000)
+    {
+      t = expl (u.value);
+      return half * t + half / t;
+    }
+
+  /* |x| in [22, ln(maxdouble)] return half*exp(|x|) */
+  if (ex <= 0x400c62e3) /* 11356.375 */
+    return half * expl (u.value);
+
+  /* |x| in [log(maxdouble), overflowthresold] */
+  if (u.value <= ovf_thresh)
+    {
+      w = expl (half * u.value);
+      t = half * w;
+      return t * w;
+    }
+
+  /* |x| > overflowthresold, cosh(x) overflow */
+  return huge * huge;
+}

+ 145 - 0
ld128/e_expl.c

@@ -0,0 +1,145 @@
+/*	$OpenBSD: e_expl.c,v 1.3 2013/11/12 20:35:18 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							expl.c
+ *
+ *	Exponential function, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expl();
+ *
+ * y = expl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ *     x    k  f
+ *    e  = 2  e.
+ *
+ * A Pade' form of degree 2/3 is used to approximate exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      +-MAXLOG    100,000     2.6e-34     8.6e-35
+ *
+ *
+ * Error amplification in the exponential function can be
+ * a serious matter.  The error propagation involves
+ * exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
+ * which shows that a 1 lsb error in representing X produces
+ * a relative error of X times 1 lsb in the function.
+ * While the routine gives an accurate result for arguments
+ * that are exactly represented by a long double precision
+ * computer number, the result contains amplified roundoff
+ * error for large arguments not exactly represented.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ * exp underflow    x < MINLOG         0.0
+ * exp overflow     x > MAXLOG         MAXNUM
+ *
+ */
+
+/*	Exponential function	*/
+
+#include <float.h>
+#include <math.h>
+
+#include "math_private.h"
+
+/* Pade' coefficients for exp(x) - 1
+   Theoretical peak relative error = 2.2e-37,
+   relative peak error spread = 9.2e-38
+ */
+static long double P[5] = {
+ 3.279723985560247033712687707263393506266E-10L,
+ 6.141506007208645008909088812338454698548E-7L,
+ 2.708775201978218837374512615596512792224E-4L,
+ 3.508710990737834361215404761139478627390E-2L,
+ 9.999999999999999999999999999999999998502E-1L
+};
+static long double Q[6] = {
+ 2.980756652081995192255342779918052538681E-12L,
+ 1.771372078166251484503904874657985291164E-8L,
+ 1.504792651814944826817779302637284053660E-5L,
+ 3.611828913847589925056132680618007270344E-3L,
+ 2.368408864814233538909747618894558968880E-1L,
+ 2.000000000000000000000000000000000000150E0L
+};
+/* C1 + C2 = ln 2 */
+static const long double C1 = -6.93145751953125E-1L;
+static const long double C2 = -1.428606820309417232121458176568075500134E-6L;
+
+static const long double LOG2EL = 1.442695040888963407359924681001892137426646L;
+static const long double MAXLOGL = 1.1356523406294143949491931077970764891253E4L;
+static const long double MINLOGL = -1.143276959615573793352782661133116431383730e4L;
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+long double
+expl(long double x)
+{
+long double px, xx;
+int n;
+
+if( x > MAXLOGL)
+	return (huge*huge);		/* overflow */
+
+if( x < MINLOGL )
+	return (twom10000*twom10000);	/* underflow */
+
+/* Express e**x = e**g 2**n
+ *   = e**g e**( n loge(2) )
+ *   = e**( g + n loge(2) )
+ */
+px = floorl( LOG2EL * x + 0.5L ); /* floor() truncates toward -infinity. */
+n = px;
+x += px * C1;
+x += px * C2;
+/* rational approximation for exponential
+ * of the fractional part:
+ * e**x =  1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
+ */
+xx = x * x;
+px = x * __polevll( xx, P, 4 );
+xx = __polevll( xx, Q, 5 );
+x =  px/( xx - px );
+x = 1.0L + x + x;
+
+x = ldexpl( x, n );
+return(x);
+}

+ 129 - 0
ld128/e_fmodl.c

@@ -0,0 +1,129 @@
+/* @(#)e_fmod.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+long double
+fmodl(long double x, long double y)
+{
+	int64_t n,hx,hy,hz,ix,iy,sx,i;
+	u_int64_t lx,ly,lz;
+
+	GET_LDOUBLE_WORDS64(hx,lx,x);
+	GET_LDOUBLE_WORDS64(hy,ly,y);
+	sx = hx&0x8000000000000000ULL;		/* sign of x */
+	hx ^=sx;				/* |x| */
+	hy &= 0x7fffffffffffffffLL;		/* |y| */
+
+    /* purge off exception values */
+	if((hy|ly)==0||(hx>=0x7fff000000000000LL)|| /* y=0,or x not finite */
+	  ((hy|((ly|-ly)>>63))>0x7fff000000000000LL))	/* or y is NaN */
+	    return (x*y)/(x*y);
+	if(hx<=hy) {
+	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
+	    if(lx==ly)
+		return Zero[(u_int64_t)sx>>63];	/* |x|=|y| return x*0*/
+	}
+
+    /* determine ix = ilogb(x) */
+	if(hx<0x0001000000000000LL) {	/* subnormal x */
+	    if(hx==0) {
+		for (ix = -16431, i=lx; i>0; i<<=1) ix -=1;
+	    } else {
+		for (ix = -16382, i=hx<<15; i>0; i<<=1) ix -=1;
+	    }
+	} else ix = (hx>>48)-0x3fff;
+
+    /* determine iy = ilogb(y) */
+	if(hy<0x0001000000000000LL) {	/* subnormal y */
+	    if(hy==0) {
+		for (iy = -16431, i=ly; i>0; i<<=1) iy -=1;
+	    } else {
+		for (iy = -16382, i=hy<<15; i>0; i<<=1) iy -=1;
+	    }
+	} else iy = (hy>>48)-0x3fff;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	if(ix >= -16382)
+	    hx = 0x0001000000000000LL|(0x0000ffffffffffffLL&hx);
+	else {		/* subnormal x, shift x to normal */
+	    n = -16382-ix;
+	    if(n<=63) {
+		hx = (hx<<n)|(lx>>(64-n));
+		lx <<= n;
+	    } else {
+		hx = lx<<(n-64);
+		lx = 0;
+	    }
+	}
+	if(iy >= -16382)
+	    hy = 0x0001000000000000LL|(0x0000ffffffffffffLL&hy);
+	else {		/* subnormal y, shift y to normal */
+	    n = -16382-iy;
+	    if(n<=63) {
+		hy = (hy<<n)|(ly>>(64-n));
+		ly <<= n;
+	    } else {
+		hy = ly<<(n-64);
+		ly = 0;
+	    }
+	}
+
+    /* fix point fmod */
+	n = ix - iy;
+	while(n--) {
+	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
+	    else {
+		if((hz|lz)==0)		/* return sign(x)*0 */
+		    return Zero[(u_int64_t)sx>>63];
+		hx = hz+hz+(lz>>63); lx = lz+lz;
+	    }
+	}
+	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {hx=hz;lx=lz;}
+
+    /* convert back to floating value and restore the sign */
+	if((hx|lx)==0)			/* return sign(x)*0 */
+	    return Zero[(u_int64_t)sx>>63];	
+	while(hx<0x0001000000000000LL) {	/* normalize x */
+	    hx = hx+hx+(lx>>63); lx = lx+lx;
+	    iy -= 1;
+	}
+	if(iy>= -16382) {	/* normalize output */
+	    hx = ((hx-0x0001000000000000LL)|((iy+16383)<<48));
+	    SET_LDOUBLE_WORDS64(x,hx|sx,lx);
+	} else {		/* subnormal output */
+	    n = -16382 - iy;
+	    if(n<=48) {
+		lx = (lx>>n)|((u_int64_t)hx<<(64-n));
+		hx >>= n;
+	    } else if (n<=63) {
+		lx = (hx<<(64-n))|(lx>>n); hx = sx;
+	    } else {
+		lx = hx>>(n-64); hx = sx;
+	    }
+	    SET_LDOUBLE_WORDS64(x,hx|sx,lx);
+	    x *= one;		/* create necessary signal */
+	}
+	return x;		/* exact output */
+}

+ 122 - 0
ld128/e_hypotl.c

@@ -0,0 +1,122 @@
+/* @(#)e_hypot.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* hypotl(x,y)
+ *
+ * Method :
+ *	If (assume round-to-nearest) z=x*x+y*y
+ *	has error less than sqrtl(2)/2 ulp, than
+ *	sqrtl(z) has error less than 1 ulp (exercise).
+ *
+ *	So, compute sqrtl(x*x+y*y) with some care as
+ *	follows to get the error below 1 ulp:
+ *
+ *	Assume x>y>0;
+ *	(if possible, set rounding to round-to-nearest)
+ *	1. if x > 2y  use
+ *		x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ *	where x1 = x with lower 64 bits cleared, x2 = x-x1; else
+ *	2. if x <= 2y use
+ *		t1*yy1+((x-y)*(x-y)+(t1*y2+t2*y))
+ *	where t1 = 2x with lower 64 bits cleared, t2 = 2x-t1,
+ *	yy1= y with lower 64 bits chopped, y2 = y-yy1.
+ *
+ *	NOTE: scaling may be necessary if some argument is too
+ *	      large or too tiny
+ *
+ * Special cases:
+ *	hypotl(x,y) is INF if x or y is +INF or -INF; else
+ *	hypotl(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * 	hypotl(x,y) returns sqrtl(x^2+y^2) with error less
+ * 	than 1 ulps (units in the last place)
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+long double
+hypotl(long double x, long double y)
+{
+	long double a,b,t1,t2,yy1,y2,w;
+	int64_t j,k,ha,hb;
+
+	GET_LDOUBLE_MSW64(ha,x);
+	ha &= 0x7fffffffffffffffLL;
+	GET_LDOUBLE_MSW64(hb,y);
+	hb &= 0x7fffffffffffffffLL;
+	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+	SET_LDOUBLE_MSW64(a,ha);	/* a <- |a| */
+	SET_LDOUBLE_MSW64(b,hb);	/* b <- |b| */
+	if((ha-hb)>0x78000000000000LL) {return a+b;} /* x/y > 2**120 */
+	k=0;
+	if(ha > 0x5f3f000000000000LL) {	/* a>2**8000 */
+	   if(ha >= 0x7fff000000000000LL) {	/* Inf or NaN */
+	       u_int64_t low;
+	       w = a+b;			/* for sNaN */
+	       GET_LDOUBLE_LSW64(low,a);
+	       if(((ha&0xffffffffffffLL)|low)==0) w = a;
+	       GET_LDOUBLE_LSW64(low,b);
+	       if(((hb^0x7fff000000000000LL)|low)==0) w = b;
+	       return w;
+	   }
+	   /* scale a and b by 2**-9600 */
+	   ha -= 0x2580000000000000LL;
+	   hb -= 0x2580000000000000LL;	k += 9600;
+	   SET_LDOUBLE_MSW64(a,ha);
+	   SET_LDOUBLE_MSW64(b,hb);
+	}
+	if(hb < 0x20bf000000000000LL) {	/* b < 2**-8000 */
+	    if(hb <= 0x0000ffffffffffffLL) {	/* subnormal b or 0 */
+		u_int64_t low;
+		GET_LDOUBLE_LSW64(low,b);
+		if((hb|low)==0) return a;
+		t1=0;
+		SET_LDOUBLE_MSW64(t1,0x7ffd000000000000LL); /* t1=2^16382 */
+		b *= t1;
+		a *= t1;
+		k -= 16382;
+	    } else {		/* scale a and b by 2^9600 */
+		ha += 0x2580000000000000LL;	/* a *= 2^9600 */
+		hb += 0x2580000000000000LL;	/* b *= 2^9600 */
+		k -= 9600;
+		SET_LDOUBLE_MSW64(a,ha);
+		SET_LDOUBLE_MSW64(b,hb);
+	    }
+	}
+    /* medium size a and b */
+	w = a-b;
+	if (w>b) {
+	    t1 = 0;
+	    SET_LDOUBLE_MSW64(t1,ha);
+	    t2 = a-t1;
+	    w  = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+	} else {
+	    a  = a+a;
+	    yy1 = 0;
+	    SET_LDOUBLE_MSW64(yy1,hb);
+	    y2 = b - yy1;
+	    t1 = 0;
+	    SET_LDOUBLE_MSW64(t1,ha+0x0001000000000000LL);
+	    t2 = a - t1;
+	    w  = sqrtl(t1*yy1-(w*(-w)-(t1*y2+t2*b)));
+	}
+	if(k!=0) {
+	    u_int64_t high;
+	    t1 = 1.0L;
+	    GET_LDOUBLE_MSW64(high,t1);
+	    SET_LDOUBLE_MSW64(t1,high+(k<<48));
+	    return t1*w;
+	} else return w;
+}

+ 1038 - 0
ld128/e_lgammal.c

@@ -0,0 +1,1038 @@
+/*	$OpenBSD: e_lgammal.c,v 1.3 2011/07/09 05:29:06 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*                                                      lgammal
+ *
+ *      Natural logarithm of gamma function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, lgammal();
+ * extern int signgam;
+ *
+ * y = lgammal(x);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of the absolute
+ * value of the gamma function of the argument.
+ * The sign (+1 or -1) of the gamma function is returned in a
+ * global (extern) variable named signgam.
+ *
+ * The positive domain is partitioned into numerous segments for approximation.
+ * For x > 10,
+ *   log gamma(x) = (x - 0.5) log(x) - x + log sqrt(2 pi) + 1/x R(1/x^2)
+ * Near the minimum at x = x0 = 1.46... the approximation is
+ *   log gamma(x0 + z) = log gamma(x0) + z^2 P(z)/Q(z)
+ * for small z.
+ * Elsewhere between 0 and 10,
+ *   log gamma(n + z) = log gamma(n) + z P(z)/Q(z)
+ * for various selected n and small z.
+ *
+ * The cosecant reflection formula is employed for negative arguments.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *
+ * arithmetic      domain        # trials     peak         rms
+ *                                            Relative error:
+ *    IEEE         10, 30         100000     3.9e-34     9.8e-35
+ *    IEEE          0, 10         100000     3.8e-34     5.3e-35
+ *                                            Absolute error:
+ *    IEEE         -10, 0         100000     8.0e-34     8.0e-35
+ *    IEEE         -30, -10       100000     4.4e-34     1.0e-34
+ *    IEEE        -100, 100       100000                 1.0e-34
+ *
+ * The absolute error criterion is the same as relative error
+ * when the function magnitude is greater than one but it is absolute
+ * when the magnitude is less than one.
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double PIL = 3.1415926535897932384626433832795028841972E0L;
+static const long double MAXLGM = 1.0485738685148938358098967157129705071571E4928L;
+static const long double one = 1.0L;
+static const long double huge = 1.0e4000L;
+
+/* log gamma(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x P(1/x^2)
+   1/x <= 0.0741 (x >= 13.495...)
+   Peak relative error 1.5e-36  */
+static const long double ls2pi = 9.1893853320467274178032973640561763986140E-1L;
+#define NRASY 12
+static const long double RASY[NRASY + 1] =
+{
+  8.333333333333333333333333333310437112111E-2L,
+ -2.777777777777777777777774789556228296902E-3L,
+  7.936507936507936507795933938448586499183E-4L,
+ -5.952380952380952041799269756378148574045E-4L,
+  8.417508417507928904209891117498524452523E-4L,
+ -1.917526917481263997778542329739806086290E-3L,
+  6.410256381217852504446848671499409919280E-3L,
+ -2.955064066900961649768101034477363301626E-2L,
+  1.796402955865634243663453415388336954675E-1L,
+ -1.391522089007758553455753477688592767741E0L,
+  1.326130089598399157988112385013829305510E1L,
+ -1.420412699593782497803472576479997819149E2L,
+  1.218058922427762808938869872528846787020E3L
+};
+
+
+/* log gamma(x+13) = log gamma(13) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   12.5 <= x+13 <= 13.5
+   Peak relative error 1.1e-36  */
+static const long double lgam13a = 1.9987213134765625E1L;
+static const long double lgam13b = 1.3608962611495173623870550785125024484248E-6L;
+#define NRN13 7
+static const long double RN13[NRN13 + 1] =
+{
+  8.591478354823578150238226576156275285700E11L,
+  2.347931159756482741018258864137297157668E11L,
+  2.555408396679352028680662433943000804616E10L,
+  1.408581709264464345480765758902967123937E9L,
+  4.126759849752613822953004114044451046321E7L,
+  6.133298899622688505854211579222889943778E5L,
+  3.929248056293651597987893340755876578072E3L,
+  6.850783280018706668924952057996075215223E0L
+};
+#define NRD13 6
+static const long double RD13[NRD13 + 1] =
+{
+  3.401225382297342302296607039352935541669E11L,
+  8.756765276918037910363513243563234551784E10L,
+  8.873913342866613213078554180987647243903E9L,
+  4.483797255342763263361893016049310017973E8L,
+  1.178186288833066430952276702931512870676E7L,
+  1.519928623743264797939103740132278337476E5L,
+  7.989298844938119228411117593338850892311E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+12) = log gamma(12) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   11.5 <= x+12 <= 12.5
+   Peak relative error 4.1e-36  */
+static const long double lgam12a = 1.75023040771484375E1L;
+static const long double lgam12b = 3.7687254483392876529072161996717039575982E-6L;
+#define NRN12 7
+static const long double RN12[NRN12 + 1] =
+{
+  4.709859662695606986110997348630997559137E11L,
+  1.398713878079497115037857470168777995230E11L,
+  1.654654931821564315970930093932954900867E10L,
+  9.916279414876676861193649489207282144036E8L,
+  3.159604070526036074112008954113411389879E7L,
+  5.109099197547205212294747623977502492861E5L,
+  3.563054878276102790183396740969279826988E3L,
+  6.769610657004672719224614163196946862747E0L
+};
+#define NRD12 6
+static const long double RD12[NRD12 + 1] =
+{
+  1.928167007860968063912467318985802726613E11L,
+  5.383198282277806237247492369072266389233E10L,
+  5.915693215338294477444809323037871058363E9L,
+  3.241438287570196713148310560147925781342E8L,
+  9.236680081763754597872713592701048455890E6L,
+  1.292246897881650919242713651166596478850E5L,
+  7.366532445427159272584194816076600211171E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+11) = log gamma(11) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   10.5 <= x+11 <= 11.5
+   Peak relative error 1.8e-35  */
+static const long double lgam11a = 1.5104400634765625E1L;
+static const long double lgam11b = 1.1938309890295225709329251070371882250744E-5L;
+#define NRN11 7
+static const long double RN11[NRN11 + 1] =
+{
+  2.446960438029415837384622675816736622795E11L,
+  7.955444974446413315803799763901729640350E10L,
+  1.030555327949159293591618473447420338444E10L,
+  6.765022131195302709153994345470493334946E8L,
+  2.361892792609204855279723576041468347494E7L,
+  4.186623629779479136428005806072176490125E5L,
+  3.202506022088912768601325534149383594049E3L,
+  6.681356101133728289358838690666225691363E0L
+};
+#define NRD11 6
+static const long double RD11[NRD11 + 1] =
+{
+  1.040483786179428590683912396379079477432E11L,
+  3.172251138489229497223696648369823779729E10L,
+  3.806961885984850433709295832245848084614E9L,
+  2.278070344022934913730015420611609620171E8L,
+  7.089478198662651683977290023829391596481E6L,
+  1.083246385105903533237139380509590158658E5L,
+  6.744420991491385145885727942219463243597E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+10) = log gamma(10) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   9.5 <= x+10 <= 10.5
+   Peak relative error 5.4e-37  */
+static const long double lgam10a = 1.280181884765625E1L;
+static const long double lgam10b = 8.6324252196112077178745667061642811492557E-6L;
+#define NRN10 7
+static const long double RN10[NRN10 + 1] =
+{
+  -1.239059737177249934158597996648808363783E14L,
+  -4.725899566371458992365624673357356908719E13L,
+  -7.283906268647083312042059082837754850808E12L,
+  -5.802855515464011422171165179767478794637E11L,
+  -2.532349691157548788382820303182745897298E10L,
+  -5.884260178023777312587193693477072061820E8L,
+  -6.437774864512125749845840472131829114906E6L,
+  -2.350975266781548931856017239843273049384E4L
+};
+#define NRD10 7
+static const long double RD10[NRD10 + 1] =
+{
+  -5.502645997581822567468347817182347679552E13L,
+  -1.970266640239849804162284805400136473801E13L,
+  -2.819677689615038489384974042561531409392E12L,
+  -2.056105863694742752589691183194061265094E11L,
+  -8.053670086493258693186307810815819662078E9L,
+  -1.632090155573373286153427982504851867131E8L,
+  -1.483575879240631280658077826889223634921E6L,
+  -4.002806669713232271615885826373550502510E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+9) = log gamma(9) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   8.5 <= x+9 <= 9.5
+   Peak relative error 3.6e-36  */
+static const long double lgam9a = 1.06045989990234375E1L;
+static const long double lgam9b = 3.9037218127284172274007216547549861681400E-6L;
+#define NRN9 7
+static const long double RN9[NRN9 + 1] =
+{
+  -4.936332264202687973364500998984608306189E13L,
+  -2.101372682623700967335206138517766274855E13L,
+  -3.615893404644823888655732817505129444195E12L,
+  -3.217104993800878891194322691860075472926E11L,
+  -1.568465330337375725685439173603032921399E10L,
+  -4.073317518162025744377629219101510217761E8L,
+  -4.983232096406156139324846656819246974500E6L,
+  -2.036280038903695980912289722995505277253E4L
+};
+#define NRD9 7
+static const long double RD9[NRD9 + 1] =
+{
+  -2.306006080437656357167128541231915480393E13L,
+  -9.183606842453274924895648863832233799950E12L,
+  -1.461857965935942962087907301194381010380E12L,
+  -1.185728254682789754150068652663124298303E11L,
+  -5.166285094703468567389566085480783070037E9L,
+  -1.164573656694603024184768200787835094317E8L,
+  -1.177343939483908678474886454113163527909E6L,
+  -3.529391059783109732159524500029157638736E3L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+8) = log gamma(8) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   7.5 <= x+8 <= 8.5
+   Peak relative error 2.4e-37  */
+static const long double lgam8a = 8.525146484375E0L;
+static const long double lgam8b = 1.4876690414300165531036347125050759667737E-5L;
+#define NRN8 8
+static const long double RN8[NRN8 + 1] =
+{
+  6.600775438203423546565361176829139703289E11L,
+  3.406361267593790705240802723914281025800E11L,
+  7.222460928505293914746983300555538432830E10L,
+  8.102984106025088123058747466840656458342E9L,
+  5.157620015986282905232150979772409345927E8L,
+  1.851445288272645829028129389609068641517E7L,
+  3.489261702223124354745894067468953756656E5L,
+  2.892095396706665774434217489775617756014E3L,
+  6.596977510622195827183948478627058738034E0L
+};
+#define NRD8 7
+static const long double RD8[NRD8 + 1] =
+{
+  3.274776546520735414638114828622673016920E11L,
+  1.581811207929065544043963828487733970107E11L,
+  3.108725655667825188135393076860104546416E10L,
+  3.193055010502912617128480163681842165730E9L,
+  1.830871482669835106357529710116211541839E8L,
+  5.790862854275238129848491555068073485086E6L,
+  9.305213264307921522842678835618803553589E4L,
+  6.216974105861848386918949336819572333622E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+7) = log gamma(7) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   6.5 <= x+7 <= 7.5
+   Peak relative error 3.2e-36  */
+static const long double lgam7a = 6.5792388916015625E0L;
+static const long double lgam7b = 1.2320408538495060178292903945321122583007E-5L;
+#define NRN7 8
+static const long double RN7[NRN7 + 1] =
+{
+  2.065019306969459407636744543358209942213E11L,
+  1.226919919023736909889724951708796532847E11L,
+  2.996157990374348596472241776917953749106E10L,
+  3.873001919306801037344727168434909521030E9L,
+  2.841575255593761593270885753992732145094E8L,
+  1.176342515359431913664715324652399565551E7L,
+  2.558097039684188723597519300356028511547E5L,
+  2.448525238332609439023786244782810774702E3L,
+  6.460280377802030953041566617300902020435E0L
+};
+#define NRD7 7
+static const long double RD7[NRD7 + 1] =
+{
+  1.102646614598516998880874785339049304483E11L,
+  6.099297512712715445879759589407189290040E10L,
+  1.372898136289611312713283201112060238351E10L,
+  1.615306270420293159907951633566635172343E9L,
+  1.061114435798489135996614242842561967459E8L,
+  3.845638971184305248268608902030718674691E6L,
+  7.081730675423444975703917836972720495507E4L,
+  5.423122582741398226693137276201344096370E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+6) = log gamma(6) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   5.5 <= x+6 <= 6.5
+   Peak relative error 6.2e-37  */
+static const long double lgam6a = 4.7874908447265625E0L;
+static const long double lgam6b = 8.9805548349424770093452324304839959231517E-7L;
+#define NRN6 8
+static const long double RN6[NRN6 + 1] =
+{
+  -3.538412754670746879119162116819571823643E13L,
+  -2.613432593406849155765698121483394257148E13L,
+  -8.020670732770461579558867891923784753062E12L,
+  -1.322227822931250045347591780332435433420E12L,
+  -1.262809382777272476572558806855377129513E11L,
+  -7.015006277027660872284922325741197022467E9L,
+  -2.149320689089020841076532186783055727299E8L,
+  -3.167210585700002703820077565539658995316E6L,
+  -1.576834867378554185210279285358586385266E4L
+};
+#define NRD6 8
+static const long double RD6[NRD6 + 1] =
+{
+  -2.073955870771283609792355579558899389085E13L,
+  -1.421592856111673959642750863283919318175E13L,
+  -4.012134994918353924219048850264207074949E12L,
+  -6.013361045800992316498238470888523722431E11L,
+  -5.145382510136622274784240527039643430628E10L,
+  -2.510575820013409711678540476918249524123E9L,
+  -6.564058379709759600836745035871373240904E7L,
+  -7.861511116647120540275354855221373571536E5L,
+  -2.821943442729620524365661338459579270561E3L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+5) = log gamma(5) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   4.5 <= x+5 <= 5.5
+   Peak relative error 3.4e-37  */
+static const long double lgam5a = 3.17803955078125E0L;
+static const long double lgam5b = 1.4279566695619646941601297055408873990961E-5L;
+#define NRN5 9
+static const long double RN5[NRN5 + 1] =
+{
+  2.010952885441805899580403215533972172098E11L,
+  1.916132681242540921354921906708215338584E11L,
+  7.679102403710581712903937970163206882492E10L,
+  1.680514903671382470108010973615268125169E10L,
+  2.181011222911537259440775283277711588410E9L,
+  1.705361119398837808244780667539728356096E8L,
+  7.792391565652481864976147945997033946360E6L,
+  1.910741381027985291688667214472560023819E5L,
+  2.088138241893612679762260077783794329559E3L,
+  6.330318119566998299106803922739066556550E0L
+};
+#define NRD5 8
+static const long double RD5[NRD5 + 1] =
+{
+  1.335189758138651840605141370223112376176E11L,
+  1.174130445739492885895466097516530211283E11L,
+  4.308006619274572338118732154886328519910E10L,
+  8.547402888692578655814445003283720677468E9L,
+  9.934628078575618309542580800421370730906E8L,
+  6.847107420092173812998096295422311820672E7L,
+  2.698552646016599923609773122139463150403E6L,
+  5.526516251532464176412113632726150253215E4L,
+  4.772343321713697385780533022595450486932E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+4) = log gamma(4) +  x P(x)/Q(x)
+   -0.5 <= x <= 0.5
+   3.5 <= x+4 <= 4.5
+   Peak relative error 6.7e-37  */
+static const long double lgam4a = 1.791748046875E0L;
+static const long double lgam4b = 1.1422353055000812477358380702272722990692E-5L;
+#define NRN4 9
+static const long double RN4[NRN4 + 1] =
+{
+  -1.026583408246155508572442242188887829208E13L,
+  -1.306476685384622809290193031208776258809E13L,
+  -7.051088602207062164232806511992978915508E12L,
+  -2.100849457735620004967624442027793656108E12L,
+  -3.767473790774546963588549871673843260569E11L,
+  -4.156387497364909963498394522336575984206E10L,
+  -2.764021460668011732047778992419118757746E9L,
+  -1.036617204107109779944986471142938641399E8L,
+  -1.895730886640349026257780896972598305443E6L,
+  -1.180509051468390914200720003907727988201E4L
+};
+#define NRD4 9
+static const long double RD4[NRD4 + 1] =
+{
+  -8.172669122056002077809119378047536240889E12L,
+  -9.477592426087986751343695251801814226960E12L,
+  -4.629448850139318158743900253637212801682E12L,
+  -1.237965465892012573255370078308035272942E12L,
+  -1.971624313506929845158062177061297598956E11L,
+  -1.905434843346570533229942397763361493610E10L,
+  -1.089409357680461419743730978512856675984E9L,
+  -3.416703082301143192939774401370222822430E7L,
+  -4.981791914177103793218433195857635265295E5L,
+  -2.192507743896742751483055798411231453733E3L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+3) = log gamma(3) +  x P(x)/Q(x)
+   -0.25 <= x <= 0.5
+   2.75 <= x+3 <= 3.5
+   Peak relative error 6.0e-37  */
+static const long double lgam3a = 6.93145751953125E-1L;
+static const long double lgam3b = 1.4286068203094172321214581765680755001344E-6L;
+
+#define NRN3 9
+static const long double RN3[NRN3 + 1] =
+{
+  -4.813901815114776281494823863935820876670E11L,
+  -8.425592975288250400493910291066881992620E11L,
+  -6.228685507402467503655405482985516909157E11L,
+  -2.531972054436786351403749276956707260499E11L,
+  -6.170200796658926701311867484296426831687E10L,
+  -9.211477458528156048231908798456365081135E9L,
+  -8.251806236175037114064561038908691305583E8L,
+  -4.147886355917831049939930101151160447495E7L,
+  -1.010851868928346082547075956946476932162E6L,
+  -8.333374463411801009783402800801201603736E3L
+};
+#define NRD3 9
+static const long double RD3[NRD3 + 1] =
+{
+  -5.216713843111675050627304523368029262450E11L,
+  -8.014292925418308759369583419234079164391E11L,
+  -5.180106858220030014546267824392678611990E11L,
+  -1.830406975497439003897734969120997840011E11L,
+  -3.845274631904879621945745960119924118925E10L,
+  -4.891033385370523863288908070309417710903E9L,
+  -3.670172254411328640353855768698287474282E8L,
+  -1.505316381525727713026364396635522516989E7L,
+  -2.856327162923716881454613540575964890347E5L,
+  -1.622140448015769906847567212766206894547E3L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+2.5) = log gamma(2.5) +  x P(x)/Q(x)
+   -0.125 <= x <= 0.25
+   2.375 <= x+2.5 <= 2.75  */
+static const long double lgam2r5a = 2.8466796875E-1L;
+static const long double lgam2r5b = 1.4901722919159632494669682701924320137696E-5L;
+#define NRN2r5 8
+static const long double RN2r5[NRN2r5 + 1] =
+{
+  -4.676454313888335499356699817678862233205E9L,
+  -9.361888347911187924389905984624216340639E9L,
+  -7.695353600835685037920815799526540237703E9L,
+  -3.364370100981509060441853085968900734521E9L,
+  -8.449902011848163568670361316804900559863E8L,
+  -1.225249050950801905108001246436783022179E8L,
+  -9.732972931077110161639900388121650470926E6L,
+  -3.695711763932153505623248207576425983573E5L,
+  -4.717341584067827676530426007495274711306E3L
+};
+#define NRD2r5 8
+static const long double RD2r5[NRD2r5 + 1] =
+{
+  -6.650657966618993679456019224416926875619E9L,
+  -1.099511409330635807899718829033488771623E10L,
+  -7.482546968307837168164311101447116903148E9L,
+  -2.702967190056506495988922973755870557217E9L,
+  -5.570008176482922704972943389590409280950E8L,
+  -6.536934032192792470926310043166993233231E7L,
+  -4.101991193844953082400035444146067511725E6L,
+  -1.174082735875715802334430481065526664020E5L,
+  -9.932840389994157592102947657277692978511E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+2) = x P(x)/Q(x)
+   -0.125 <= x <= +0.375
+   1.875 <= x+2 <= 2.375
+   Peak relative error 4.6e-36  */
+#define NRN2 9
+static const long double RN2[NRN2 + 1] =
+{
+  -3.716661929737318153526921358113793421524E9L,
+  -1.138816715030710406922819131397532331321E10L,
+  -1.421017419363526524544402598734013569950E10L,
+  -9.510432842542519665483662502132010331451E9L,
+  -3.747528562099410197957514973274474767329E9L,
+  -8.923565763363912474488712255317033616626E8L,
+  -1.261396653700237624185350402781338231697E8L,
+  -9.918402520255661797735331317081425749014E6L,
+  -3.753996255897143855113273724233104768831E5L,
+  -4.778761333044147141559311805999540765612E3L
+};
+#define NRD2 9
+static const long double RD2[NRD2 + 1] =
+{
+  -8.790916836764308497770359421351673950111E9L,
+  -2.023108608053212516399197678553737477486E10L,
+  -1.958067901852022239294231785363504458367E10L,
+  -1.035515043621003101254252481625188704529E10L,
+  -3.253884432621336737640841276619272224476E9L,
+  -6.186383531162456814954947669274235815544E8L,
+  -6.932557847749518463038934953605969951466E7L,
+  -4.240731768287359608773351626528479703758E6L,
+  -1.197343995089189188078944689846348116630E5L,
+  -1.004622911670588064824904487064114090920E3L
+/* 1.0E0 */
+};
+
+
+/* log gamma(x+1.75) = log gamma(1.75) +  x P(x)/Q(x)
+   -0.125 <= x <= +0.125
+   1.625 <= x+1.75 <= 1.875
+   Peak relative error 9.2e-37 */
+static const long double lgam1r75a = -8.441162109375E-2L;
+static const long double lgam1r75b = 1.0500073264444042213965868602268256157604E-5L;
+#define NRN1r75 8
+static const long double RN1r75[NRN1r75 + 1] =
+{
+  -5.221061693929833937710891646275798251513E7L,
+  -2.052466337474314812817883030472496436993E8L,
+  -2.952718275974940270675670705084125640069E8L,
+  -2.132294039648116684922965964126389017840E8L,
+  -8.554103077186505960591321962207519908489E7L,
+  -1.940250901348870867323943119132071960050E7L,
+  -2.379394147112756860769336400290402208435E6L,
+  -1.384060879999526222029386539622255797389E5L,
+  -2.698453601378319296159355612094598695530E3L
+};
+#define NRD1r75 8
+static const long double RD1r75[NRD1r75 + 1] =
+{
+  -2.109754689501705828789976311354395393605E8L,
+  -5.036651829232895725959911504899241062286E8L,
+  -4.954234699418689764943486770327295098084E8L,
+  -2.589558042412676610775157783898195339410E8L,
+  -7.731476117252958268044969614034776883031E7L,
+  -1.316721702252481296030801191240867486965E7L,
+  -1.201296501404876774861190604303728810836E6L,
+  -5.007966406976106636109459072523610273928E4L,
+  -6.155817990560743422008969155276229018209E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+x0) = y0 +  x^2 P(x)/Q(x)
+   -0.0867 <= x <= +0.1634
+   1.374932... <= x+x0 <= 1.625032...
+   Peak relative error 4.0e-36  */
+static const long double x0a = 1.4616241455078125L;
+static const long double x0b = 7.9994605498412626595423257213002588621246E-6L;
+static const long double y0a = -1.21490478515625E-1L;
+static const long double y0b = 4.1879797753919044854428223084178486438269E-6L;
+#define NRN1r5 8
+static const long double RN1r5[NRN1r5 + 1] =
+{
+  6.827103657233705798067415468881313128066E5L,
+  1.910041815932269464714909706705242148108E6L,
+  2.194344176925978377083808566251427771951E6L,
+  1.332921400100891472195055269688876427962E6L,
+  4.589080973377307211815655093824787123508E5L,
+  8.900334161263456942727083580232613796141E4L,
+  9.053840838306019753209127312097612455236E3L,
+  4.053367147553353374151852319743594873771E2L,
+  5.040631576303952022968949605613514584950E0L
+};
+#define NRD1r5 8
+static const long double RD1r5[NRD1r5 + 1] =
+{
+  1.411036368843183477558773688484699813355E6L,
+  4.378121767236251950226362443134306184849E6L,
+  5.682322855631723455425929877581697918168E6L,
+  3.999065731556977782435009349967042222375E6L,
+  1.653651390456781293163585493620758410333E6L,
+  4.067774359067489605179546964969435858311E5L,
+  5.741463295366557346748361781768833633256E4L,
+  4.226404539738182992856094681115746692030E3L,
+  1.316980975410327975566999780608618774469E2L,
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x+1.25) = log gamma(1.25) +  x P(x)/Q(x)
+   -.125 <= x <= +.125
+   1.125 <= x+1.25 <= 1.375
+   Peak relative error = 4.9e-36 */
+static const long double lgam1r25a = -9.82818603515625E-2L;
+static const long double lgam1r25b = 1.0023929749338536146197303364159774377296E-5L;
+#define NRN1r25 9
+static const long double RN1r25[NRN1r25 + 1] =
+{
+  -9.054787275312026472896002240379580536760E4L,
+  -8.685076892989927640126560802094680794471E4L,
+  2.797898965448019916967849727279076547109E5L,
+  6.175520827134342734546868356396008898299E5L,
+  5.179626599589134831538516906517372619641E5L,
+  2.253076616239043944538380039205558242161E5L,
+  5.312653119599957228630544772499197307195E4L,
+  6.434329437514083776052669599834938898255E3L,
+  3.385414416983114598582554037612347549220E2L,
+  4.907821957946273805080625052510832015792E0L
+};
+#define NRD1r25 8
+static const long double RD1r25[NRD1r25 + 1] =
+{
+  3.980939377333448005389084785896660309000E5L,
+  1.429634893085231519692365775184490465542E6L,
+  2.145438946455476062850151428438668234336E6L,
+  1.743786661358280837020848127465970357893E6L,
+  8.316364251289743923178092656080441655273E5L,
+  2.355732939106812496699621491135458324294E5L,
+  3.822267399625696880571810137601310855419E4L,
+  3.228463206479133236028576845538387620856E3L,
+  1.152133170470059555646301189220117965514E2L
+  /* 1.0E0L */
+};
+
+
+/* log gamma(x + 1) = x P(x)/Q(x)
+   0.0 <= x <= +0.125
+   1.0 <= x+1 <= 1.125
+   Peak relative error 1.1e-35  */
+#define NRN1 8
+static const long double RN1[NRN1 + 1] =
+{
+  -9.987560186094800756471055681088744738818E3L,
+  -2.506039379419574361949680225279376329742E4L,
+  -1.386770737662176516403363873617457652991E4L,
+  1.439445846078103202928677244188837130744E4L,
+  2.159612048879650471489449668295139990693E4L,
+  1.047439813638144485276023138173676047079E4L,
+  2.250316398054332592560412486630769139961E3L,
+  1.958510425467720733041971651126443864041E2L,
+  4.516830313569454663374271993200291219855E0L
+};
+#define NRD1 7
+static const long double RD1[NRD1 + 1] =
+{
+  1.730299573175751778863269333703788214547E4L,
+  6.807080914851328611903744668028014678148E4L,
+  1.090071629101496938655806063184092302439E5L,
+  9.124354356415154289343303999616003884080E4L,
+  4.262071638655772404431164427024003253954E4L,
+  1.096981664067373953673982635805821283581E4L,
+  1.431229503796575892151252708527595787588E3L,
+  7.734110684303689320830401788262295992921E1L
+ /* 1.0E0 */
+};
+
+
+/* log gamma(x + 1) = x P(x)/Q(x)
+   -0.125 <= x <= 0
+   0.875 <= x+1 <= 1.0
+   Peak relative error 7.0e-37  */
+#define NRNr9 8
+static const long double RNr9[NRNr9 + 1] =
+{
+  4.441379198241760069548832023257571176884E5L,
+  1.273072988367176540909122090089580368732E6L,
+  9.732422305818501557502584486510048387724E5L,
+  -5.040539994443998275271644292272870348684E5L,
+  -1.208719055525609446357448132109723786736E6L,
+  -7.434275365370936547146540554419058907156E5L,
+  -2.075642969983377738209203358199008185741E5L,
+  -2.565534860781128618589288075109372218042E4L,
+  -1.032901669542994124131223797515913955938E3L,
+};
+#define NRDr9 8
+static const long double RDr9[NRDr9 + 1] =
+{
+  -7.694488331323118759486182246005193998007E5L,
+  -3.301918855321234414232308938454112213751E6L,
+  -5.856830900232338906742924836032279404702E6L,
+  -5.540672519616151584486240871424021377540E6L,
+  -3.006530901041386626148342989181721176919E6L,
+  -9.350378280513062139466966374330795935163E5L,
+  -1.566179100031063346901755685375732739511E5L,
+  -1.205016539620260779274902967231510804992E4L,
+  -2.724583156305709733221564484006088794284E2L
+/* 1.0E0 */
+};
+
+
+/* Evaluate P[n] x^n  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+/* Evaluate x^n+1  +  P[n] x^(n)  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = x + *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+long double
+lgammal(long double x)
+{
+  long double p, q, w, z, nx;
+  int i, nn;
+
+  signgam = 1;
+
+  if (! finite (x))
+    return x * x;
+
+  if (x == 0.0L)
+    {
+      if (signbit (x))
+	signgam = -1;
+      return one / fabsl (x);
+    }
+
+  if (x < 0.0L)
+    {
+      q = -x;
+      p = floorl (q);
+      if (p == q)
+	return (one / (p - p));
+      i = p;
+      if ((i & 1) == 0)
+	signgam = -1;
+      else
+	signgam = 1;
+      z = q - p;
+      if (z > 0.5L)
+	{
+	  p += 1.0L;
+	  z = p - q;
+	}
+      z = q * sinl (PIL * z);
+      if (z == 0.0L)
+	return (signgam * huge * huge);
+      w = lgammal (q);
+      z = logl (PIL / z) - w;
+      return (z);
+    }
+
+  if (x < 13.5L)
+    {
+      p = 0.0L;
+      nx = floorl (x + 0.5L);
+      nn = nx;
+      switch (nn)
+	{
+	case 0:
+	  /* log gamma (x + 1) = log(x) + log gamma(x) */
+	  if (x <= 0.125)
+	    {
+	      p = x * neval (x, RN1, NRN1) / deval (x, RD1, NRD1);
+	    }
+	  else if (x <= 0.375)
+	    {
+	      z = x - 0.25L;
+	      p = z * neval (z, RN1r25, NRN1r25) / deval (z, RD1r25, NRD1r25);
+	      p += lgam1r25b;
+	      p += lgam1r25a;
+	    }
+	  else if (x <= 0.625)
+	    {
+	      z = x + (1.0L - x0a);
+	      z = z - x0b;
+	      p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+	      p = p * z * z;
+	      p = p + y0b;
+	      p = p + y0a;
+	    }
+	  else if (x <= 0.875)
+	    {
+	      z = x - 0.75L;
+	      p = z * neval (z, RN1r75, NRN1r75) / deval (z, RD1r75, NRD1r75);
+	      p += lgam1r75b;
+	      p += lgam1r75a;
+	    }
+	  else
+	    {
+	      z = x - 1.0L;
+	      p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+	    }
+	  p = p - logl (x);
+	  break;
+
+	case 1:
+	  if (x < 0.875L)
+	    {
+	      if (x <= 0.625)
+		{
+		  z = x + (1.0L - x0a);
+		  z = z - x0b;
+		  p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+		  p = p * z * z;
+		  p = p + y0b;
+		  p = p + y0a;
+		}
+	      else if (x <= 0.875)
+		{
+		  z = x - 0.75L;
+		  p = z * neval (z, RN1r75, NRN1r75)
+			/ deval (z, RD1r75, NRD1r75);
+		  p += lgam1r75b;
+		  p += lgam1r75a;
+		}
+	      else
+		{
+		  z = x - 1.0L;
+		  p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+		}
+	      p = p - logl (x);
+	    }
+	  else if (x < 1.0L)
+	    {
+	      z = x - 1.0L;
+	      p = z * neval (z, RNr9, NRNr9) / deval (z, RDr9, NRDr9);
+	    }
+	  else if (x == 1.0L)
+	    p = 0.0L;
+	  else if (x <= 1.125L)
+	    {
+	      z = x - 1.0L;
+	      p = z * neval (z, RN1, NRN1) / deval (z, RD1, NRD1);
+	    }
+	  else if (x <= 1.375)
+	    {
+	      z = x - 1.25L;
+	      p = z * neval (z, RN1r25, NRN1r25) / deval (z, RD1r25, NRD1r25);
+	      p += lgam1r25b;
+	      p += lgam1r25a;
+	    }
+	  else
+	    {
+	      /* 1.375 <= x+x0 <= 1.625 */
+	      z = x - x0a;
+	      z = z - x0b;
+	      p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+	      p = p * z * z;
+	      p = p + y0b;
+	      p = p + y0a;
+	    }
+	  break;
+
+	case 2:
+	  if (x < 1.625L)
+	    {
+	      z = x - x0a;
+	      z = z - x0b;
+	      p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+	      p = p * z * z;
+	      p = p + y0b;
+	      p = p + y0a;
+	    }
+	  else if (x < 1.875L)
+	    {
+	      z = x - 1.75L;
+	      p = z * neval (z, RN1r75, NRN1r75) / deval (z, RD1r75, NRD1r75);
+	      p += lgam1r75b;
+	      p += lgam1r75a;
+	    }
+	  else if (x == 2.0L)
+	    p = 0.0L;
+	  else if (x < 2.375L)
+	    {
+	      z = x - 2.0L;
+	      p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+	    }
+	  else
+	    {
+	      z = x - 2.5L;
+	      p = z * neval (z, RN2r5, NRN2r5) / deval (z, RD2r5, NRD2r5);
+	      p += lgam2r5b;
+	      p += lgam2r5a;
+	    }
+	  break;
+
+	case 3:
+	  if (x < 2.75)
+	    {
+	      z = x - 2.5L;
+	      p = z * neval (z, RN2r5, NRN2r5) / deval (z, RD2r5, NRD2r5);
+	      p += lgam2r5b;
+	      p += lgam2r5a;
+	    }
+	  else
+	    {
+	      z = x - 3.0L;
+	      p = z * neval (z, RN3, NRN3) / deval (z, RD3, NRD3);
+	      p += lgam3b;
+	      p += lgam3a;
+	    }
+	  break;
+
+	case 4:
+	  z = x - 4.0L;
+	  p = z * neval (z, RN4, NRN4) / deval (z, RD4, NRD4);
+	  p += lgam4b;
+	  p += lgam4a;
+	  break;
+
+	case 5:
+	  z = x - 5.0L;
+	  p = z * neval (z, RN5, NRN5) / deval (z, RD5, NRD5);
+	  p += lgam5b;
+	  p += lgam5a;
+	  break;
+
+	case 6:
+	  z = x - 6.0L;
+	  p = z * neval (z, RN6, NRN6) / deval (z, RD6, NRD6);
+	  p += lgam6b;
+	  p += lgam6a;
+	  break;
+
+	case 7:
+	  z = x - 7.0L;
+	  p = z * neval (z, RN7, NRN7) / deval (z, RD7, NRD7);
+	  p += lgam7b;
+	  p += lgam7a;
+	  break;
+
+	case 8:
+	  z = x - 8.0L;
+	  p = z * neval (z, RN8, NRN8) / deval (z, RD8, NRD8);
+	  p += lgam8b;
+	  p += lgam8a;
+	  break;
+
+	case 9:
+	  z = x - 9.0L;
+	  p = z * neval (z, RN9, NRN9) / deval (z, RD9, NRD9);
+	  p += lgam9b;
+	  p += lgam9a;
+	  break;
+
+	case 10:
+	  z = x - 10.0L;
+	  p = z * neval (z, RN10, NRN10) / deval (z, RD10, NRD10);
+	  p += lgam10b;
+	  p += lgam10a;
+	  break;
+
+	case 11:
+	  z = x - 11.0L;
+	  p = z * neval (z, RN11, NRN11) / deval (z, RD11, NRD11);
+	  p += lgam11b;
+	  p += lgam11a;
+	  break;
+
+	case 12:
+	  z = x - 12.0L;
+	  p = z * neval (z, RN12, NRN12) / deval (z, RD12, NRD12);
+	  p += lgam12b;
+	  p += lgam12a;
+	  break;
+
+	case 13:
+	  z = x - 13.0L;
+	  p = z * neval (z, RN13, NRN13) / deval (z, RD13, NRD13);
+	  p += lgam13b;
+	  p += lgam13a;
+	  break;
+	}
+      return p;
+    }
+
+  if (x > MAXLGM)
+    return (signgam * huge * huge);
+
+  q = ls2pi - x;
+  q = (x - 0.5L) * logl (x) + q;
+  if (x > 1.0e18L)
+    return (q);
+
+  p = 1.0L / (x * x);
+  q += neval (p, RASY, NRASY) / x;
+  return (q);
+}

+ 255 - 0
ld128/e_log10l.c

@@ -0,0 +1,255 @@
+/*	$OpenBSD: e_log10l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							log10l.c
+ *
+ *	Common logarithm, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log10l();
+ *
+ * y = log10l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 10 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0.5, 2.0     30000      2.3e-34     4.9e-35
+ *    IEEE     exp(+-10000)  30000      1.0e-34     4.1e-35
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double P[13] =
+{
+  1.313572404063446165910279910527789794488E4L,
+  7.771154681358524243729929227226708890930E4L,
+  2.014652742082537582487669938141683759923E5L,
+  3.007007295140399532324943111654767187848E5L,
+  2.854829159639697837788887080758954924001E5L,
+  1.797628303815655343403735250238293741397E5L,
+  7.594356839258970405033155585486712125861E4L,
+  2.128857716871515081352991964243375186031E4L,
+  3.824952356185897735160588078446136783779E3L,
+  4.114517881637811823002128927449878962058E2L,
+  2.321125933898420063925789532045674660756E1L,
+  4.998469661968096229986658302195402690910E-1L,
+  1.538612243596254322971797716843006400388E-6L
+};
+static const long double Q[12] =
+{
+  3.940717212190338497730839731583397586124E4L,
+  2.626900195321832660448791748036714883242E5L,
+  7.777690340007566932935753241556479363645E5L,
+  1.347518538384329112529391120390701166528E6L,
+  1.514882452993549494932585972882995548426E6L,
+  1.158019977462989115839826904108208787040E6L,
+  6.132189329546557743179177159925690841200E5L,
+  2.248234257620569139969141618556349415120E5L,
+  5.605842085972455027590989944010492125825E4L,
+  9.147150349299596453976674231612674085381E3L,
+  9.104928120962988414618126155557301584078E2L,
+  4.839208193348159620282142911143429644326E1L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double R[6] =
+{
+  1.418134209872192732479751274970992665513E5L,
+ -8.977257995689735303686582344659576526998E4L,
+  2.048819892795278657810231591630928516206E4L,
+ -2.024301798136027039250415126250455056397E3L,
+  8.057002716646055371965756206836056074715E1L,
+ -8.828896441624934385266096344596648080902E-1L
+};
+static const long double S[6] =
+{
+  1.701761051846631278975701529965589676574E6L,
+ -1.332535117259762928288745111081235577029E6L,
+  4.001557694070773974936904547424676279307E5L,
+ -5.748542087379434595104154610899551484314E4L,
+  3.998526750980007367835804959888064681098E3L,
+ -1.186359407982897997337150403816839480438E2L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+static const long double
+/* log10(2) */
+L102A = 0.3125L,
+L102B = -1.14700043360188047862611052755069732318101185E-2L,
+/* log10(e) */
+L10EA = 0.5L,
+L10EB = -6.570551809674817234887108108339491770560299E-2L,
+/* sqrt(2)/2 */
+SQRTH = 7.071067811865475244008443621048490392848359E-1L;
+
+
+
+/* Evaluate P[n] x^n  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+/* Evaluate x^n+1  +  P[n] x^(n)  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = x + *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+
+long double
+log10l(long double x)
+{
+  long double z;
+  long double y;
+  int e;
+  int64_t hx, lx;
+
+/* Test for domain */
+  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
+    return (-1.0L / (x - x));
+  if (hx < 0)
+    return (x - x) / (x - x);
+  if (hx >= 0x7fff000000000000LL)
+    return (x + x);
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+  x = frexpl (x, &e);
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+  if ((e > 2) || (e < -2))
+    {
+      if (x < SQRTH)
+	{			/* 2( 2x-1 )/( 2x+1 ) */
+	  e -= 1;
+	  z = x - 0.5L;
+	  y = 0.5L * z + 0.5L;
+	}
+      else
+	{			/*  2 (x-1)/(x+1)   */
+	  z = x - 0.5L;
+	  z -= 0.5L;
+	  y = 0.5L * x + 0.5L;
+	}
+      x = z / y;
+      z = x * x;
+      y = x * (z * neval (z, R, 5) / deval (z, S, 5));
+      goto done;
+    }
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+  if (x < SQRTH)
+    {
+      e -= 1;
+      x = 2.0 * x - 1.0L;	/*  2x - 1  */
+    }
+  else
+    {
+      x = x - 1.0L;
+    }
+  z = x * x;
+  y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
+  y = y - 0.5 * z;
+
+done:
+
+  /* Multiply log of fraction by log10(e)
+   * and base 2 exponent by log10(2).
+   */
+  z = y * L10EB;
+  z += x * L10EB;
+  z += e * L102B;
+  z += y * L10EA;
+  z += x * L10EA;
+  z += e * L102A;
+  return (z);
+}

+ 248 - 0
ld128/e_log2l.c

@@ -0,0 +1,248 @@
+/*	$OpenBSD: e_log2l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*                                                      log2l.c
+ *      Base 2 logarithm, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log2l();
+ *
+ * y = log2l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 2 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the (natural)
+ * logarithm of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0.5, 2.0     100,000    2.6e-34     4.9e-35
+ *    IEEE     exp(+-10000)  100,000    9.6e-35     4.0e-35
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double P[13] =
+{
+  1.313572404063446165910279910527789794488E4L,
+  7.771154681358524243729929227226708890930E4L,
+  2.014652742082537582487669938141683759923E5L,
+  3.007007295140399532324943111654767187848E5L,
+  2.854829159639697837788887080758954924001E5L,
+  1.797628303815655343403735250238293741397E5L,
+  7.594356839258970405033155585486712125861E4L,
+  2.128857716871515081352991964243375186031E4L,
+  3.824952356185897735160588078446136783779E3L,
+  4.114517881637811823002128927449878962058E2L,
+  2.321125933898420063925789532045674660756E1L,
+  4.998469661968096229986658302195402690910E-1L,
+  1.538612243596254322971797716843006400388E-6L
+};
+static const long double Q[12] =
+{
+  3.940717212190338497730839731583397586124E4L,
+  2.626900195321832660448791748036714883242E5L,
+  7.777690340007566932935753241556479363645E5L,
+  1.347518538384329112529391120390701166528E6L,
+  1.514882452993549494932585972882995548426E6L,
+  1.158019977462989115839826904108208787040E6L,
+  6.132189329546557743179177159925690841200E5L,
+  2.248234257620569139969141618556349415120E5L,
+  5.605842085972455027590989944010492125825E4L,
+  9.147150349299596453976674231612674085381E3L,
+  9.104928120962988414618126155557301584078E2L,
+  4.839208193348159620282142911143429644326E1L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double R[6] =
+{
+  1.418134209872192732479751274970992665513E5L,
+ -8.977257995689735303686582344659576526998E4L,
+  2.048819892795278657810231591630928516206E4L,
+ -2.024301798136027039250415126250455056397E3L,
+  8.057002716646055371965756206836056074715E1L,
+ -8.828896441624934385266096344596648080902E-1L
+};
+static const long double S[6] =
+{
+  1.701761051846631278975701529965589676574E6L,
+ -1.332535117259762928288745111081235577029E6L,
+  4.001557694070773974936904547424676279307E5L,
+ -5.748542087379434595104154610899551484314E4L,
+  3.998526750980007367835804959888064681098E3L,
+ -1.186359407982897997337150403816839480438E2L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+static const long double
+/* log2(e) - 1 */
+LOG2EA = 4.4269504088896340735992468100189213742664595E-1L,
+/* sqrt(2)/2 */
+SQRTH = 7.071067811865475244008443621048490392848359E-1L;
+
+
+/* Evaluate P[n] x^n  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+/* Evaluate x^n+1  +  P[n] x^(n)  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = x + *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+
+long double
+log2l(long double x)
+{
+  long double z;
+  long double y;
+  int e;
+  int64_t hx, lx;
+
+/* Test for domain */
+  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
+    return (-1.0L / (x - x));
+  if (hx < 0)
+    return (x - x) / (x - x);
+  if (hx >= 0x7fff000000000000LL)
+    return (x + x);
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+  x = frexpl (x, &e);
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+  if ((e > 2) || (e < -2))
+    {
+      if (x < SQRTH)
+	{			/* 2( 2x-1 )/( 2x+1 ) */
+	  e -= 1;
+	  z = x - 0.5L;
+	  y = 0.5L * z + 0.5L;
+	}
+      else
+	{			/*  2 (x-1)/(x+1)   */
+	  z = x - 0.5L;
+	  z -= 0.5L;
+	  y = 0.5L * x + 0.5L;
+	}
+      x = z / y;
+      z = x * x;
+      y = x * (z * neval (z, R, 5) / deval (z, S, 5));
+      goto done;
+    }
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+  if (x < SQRTH)
+    {
+      e -= 1;
+      x = 2.0 * x - 1.0L;	/*  2x - 1  */
+    }
+  else
+    {
+      x = x - 1.0L;
+    }
+  z = x * x;
+  y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
+  y = y - 0.5 * z;
+
+done:
+
+/* Multiply log of fraction by log2(e)
+ * and base 2 exponent by 1
+ */
+  z = y * LOG2EA;
+  z += x * LOG2EA;
+  z += y;
+  z += x;
+  z += e;
+  return (z);
+}

+ 283 - 0
ld128/e_logl.c

@@ -0,0 +1,283 @@
+/*	$OpenBSD: e_logl.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							logl.c
+ *
+ * Natural logarithm for 128-bit long double precision.
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, logl();
+ *
+ * y = logl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  Use of a lookup table increases the speed of the routine.
+ * The program uses logarithms tabulated at intervals of 1/128 to
+ * cover the domain from approximately 0.7 to 1.4.
+ *
+ * On the interval [-1/128, +1/128] the logarithm of 1+x is approximated by
+ *     log(1+x) = x - 0.5 x^2 + x^3 P(x) .
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE   0.875, 1.125   100000      1.2e-34    4.1e-35
+ *    IEEE   0.125, 8       100000      1.2e-34    4.1e-35
+ *
+ *
+ * WARNING:
+ *
+ * This program uses integer operations on bit fields of floating-point
+ * numbers.  It does not work with data structures other than the
+ * structure assumed.
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* log(1+x) = x - .5 x^2 + x^3 l(x)
+   -.0078125 <= x <= +.0078125
+   peak relative error 1.2e-37 */
+static const long double
+l3 =   3.333333333333333333333333333333336096926E-1L,
+l4 =  -2.499999999999999999999999999486853077002E-1L,
+l5 =   1.999999999999999999999999998515277861905E-1L,
+l6 =  -1.666666666666666666666798448356171665678E-1L,
+l7 =   1.428571428571428571428808945895490721564E-1L,
+l8 =  -1.249999999999999987884655626377588149000E-1L,
+l9 =   1.111111111111111093947834982832456459186E-1L,
+l10 = -1.000000000000532974938900317952530453248E-1L,
+l11 =  9.090909090915566247008015301349979892689E-2L,
+l12 = -8.333333211818065121250921925397567745734E-2L,
+l13 =  7.692307559897661630807048686258659316091E-2L,
+l14 = -7.144242754190814657241902218399056829264E-2L,
+l15 =  6.668057591071739754844678883223432347481E-2L;
+
+/* Lookup table of ln(t) - (t-1)
+    t = 0.5 + (k+26)/128)
+    k = 0, ..., 91   */
+static const long double logtbl[92] = {
+-5.5345593589352099112142921677820359632418E-2L,
+-5.2108257402767124761784665198737642086148E-2L,
+-4.8991686870576856279407775480686721935120E-2L,
+-4.5993270766361228596215288742353061431071E-2L,
+-4.3110481649613269682442058976885699556950E-2L,
+-4.0340872319076331310838085093194799765520E-2L,
+-3.7682072451780927439219005993827431503510E-2L,
+-3.5131785416234343803903228503274262719586E-2L,
+-3.2687785249045246292687241862699949178831E-2L,
+-3.0347913785027239068190798397055267411813E-2L,
+-2.8110077931525797884641940838507561326298E-2L,
+-2.5972247078357715036426583294246819637618E-2L,
+-2.3932450635346084858612873953407168217307E-2L,
+-2.1988775689981395152022535153795155900240E-2L,
+-2.0139364778244501615441044267387667496733E-2L,
+-1.8382413762093794819267536615342902718324E-2L,
+-1.6716169807550022358923589720001638093023E-2L,
+-1.5138929457710992616226033183958974965355E-2L,
+-1.3649036795397472900424896523305726435029E-2L,
+-1.2244881690473465543308397998034325468152E-2L,
+-1.0924898127200937840689817557742469105693E-2L,
+-9.6875626072830301572839422532631079809328E-3L,
+-8.5313926245226231463436209313499745894157E-3L,
+-7.4549452072765973384933565912143044991706E-3L,
+-6.4568155251217050991200599386801665681310E-3L,
+-5.5356355563671005131126851708522185605193E-3L,
+-4.6900728132525199028885749289712348829878E-3L,
+-3.9188291218610470766469347968659624282519E-3L,
+-3.2206394539524058873423550293617843896540E-3L,
+-2.5942708080877805657374888909297113032132E-3L,
+-2.0385211375711716729239156839929281289086E-3L,
+-1.5522183228760777967376942769773768850872E-3L,
+-1.1342191863606077520036253234446621373191E-3L,
+-7.8340854719967065861624024730268350459991E-4L,
+-4.9869831458030115699628274852562992756174E-4L,
+-2.7902661731604211834685052867305795169688E-4L,
+-1.2335696813916860754951146082826952093496E-4L,
+-3.0677461025892873184042490943581654591817E-5L,
+#define ZERO logtbl[38]
+ 0.0000000000000000000000000000000000000000E0L,
+-3.0359557945051052537099938863236321874198E-5L,
+-1.2081346403474584914595395755316412213151E-4L,
+-2.7044071846562177120083903771008342059094E-4L,
+-4.7834133324631162897179240322783590830326E-4L,
+-7.4363569786340080624467487620270965403695E-4L,
+-1.0654639687057968333207323853366578860679E-3L,
+-1.4429854811877171341298062134712230604279E-3L,
+-1.8753781835651574193938679595797367137975E-3L,
+-2.3618380914922506054347222273705859653658E-3L,
+-2.9015787624124743013946600163375853631299E-3L,
+-3.4938307889254087318399313316921940859043E-3L,
+-4.1378413103128673800485306215154712148146E-3L,
+-4.8328735414488877044289435125365629849599E-3L,
+-5.5782063183564351739381962360253116934243E-3L,
+-6.3731336597098858051938306767880719015261E-3L,
+-7.2169643436165454612058905294782949315193E-3L,
+-8.1090214990427641365934846191367315083867E-3L,
+-9.0486422112807274112838713105168375482480E-3L,
+-1.0035177140880864314674126398350812606841E-2L,
+-1.1067990155502102718064936259435676477423E-2L,
+-1.2146457974158024928196575103115488672416E-2L,
+-1.3269969823361415906628825374158424754308E-2L,
+-1.4437927104692837124388550722759686270765E-2L,
+-1.5649743073340777659901053944852735064621E-2L,
+-1.6904842527181702880599758489058031645317E-2L,
+-1.8202661505988007336096407340750378994209E-2L,
+-1.9542647000370545390701192438691126552961E-2L,
+-2.0924256670080119637427928803038530924742E-2L,
+-2.2346958571309108496179613803760727786257E-2L,
+-2.3810230892650362330447187267648486279460E-2L,
+-2.5313561699385640380910474255652501521033E-2L,
+-2.6856448685790244233704909690165496625399E-2L,
+-2.8438398935154170008519274953860128449036E-2L,
+-3.0058928687233090922411781058956589863039E-2L,
+-3.1717563112854831855692484086486099896614E-2L,
+-3.3413836095418743219397234253475252001090E-2L,
+-3.5147290019036555862676702093393332533702E-2L,
+-3.6917475563073933027920505457688955423688E-2L,
+-3.8723951502862058660874073462456610731178E-2L,
+-4.0566284516358241168330505467000838017425E-2L,
+-4.2444048996543693813649967076598766917965E-2L,
+-4.4356826869355401653098777649745233339196E-2L,
+-4.6304207416957323121106944474331029996141E-2L,
+-4.8285787106164123613318093945035804818364E-2L,
+-5.0301169421838218987124461766244507342648E-2L,
+-5.2349964705088137924875459464622098310997E-2L,
+-5.4431789996103111613753440311680967840214E-2L,
+-5.6546268881465384189752786409400404404794E-2L,
+-5.8693031345788023909329239565012647817664E-2L,
+-6.0871713627532018185577188079210189048340E-2L,
+-6.3081958078862169742820420185833800925568E-2L,
+-6.5323413029406789694910800219643791556918E-2L,
+-6.7595732653791419081537811574227049288168E-2L
+};
+
+/* ln(2) = ln2a + ln2b with extended precision. */
+static const long double
+  ln2a = 6.93145751953125e-1L,
+  ln2b = 1.4286068203094172321214581765680755001344E-6L;
+
+long double
+logl(long double x)
+{
+  long double z, y, w;
+  ieee_quad_shape_type u, t;
+  unsigned int m;
+  int k, e;
+
+  u.value = x;
+  m = u.parts32.mswhi;
+
+  /* Check for IEEE special cases.  */
+  k = m & 0x7fffffff;
+  /* log(0) = -infinity. */
+  if ((k | u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+    {
+      return -0.5L / ZERO;
+    }
+  /* log ( x < 0 ) = NaN */
+  if (m & 0x80000000)
+    {
+      return (x - x) / ZERO;
+    }
+  /* log (infinity or NaN) */
+  if (k >= 0x7fff0000)
+    {
+      return x + x;
+    }
+
+  /* Extract exponent and reduce domain to 0.703125 <= u < 1.40625  */
+  e = (int) (m >> 16) - (int) 0x3ffe;
+  m &= 0xffff;
+  u.parts32.mswhi = m | 0x3ffe0000;
+  m |= 0x10000;
+  /* Find lookup table index k from high order bits of the significand. */
+  if (m < 0x16800)
+    {
+      k = (m - 0xff00) >> 9;
+      /* t is the argument 0.5 + (k+26)/128
+	 of the nearest item to u in the lookup table.  */
+      t.parts32.mswhi = 0x3fff0000 + (k << 9);
+      t.parts32.mswlo = 0;
+      t.parts32.lswhi = 0;
+      t.parts32.lswlo = 0;
+      u.parts32.mswhi += 0x10000;
+      e -= 1;
+      k += 64;
+    }
+  else
+    {
+      k = (m - 0xfe00) >> 10;
+      t.parts32.mswhi = 0x3ffe0000 + (k << 10);
+      t.parts32.mswlo = 0;
+      t.parts32.lswhi = 0;
+      t.parts32.lswlo = 0;
+    }
+  /* On this interval the table is not used due to cancellation error.  */
+  if ((x <= 1.0078125L) && (x >= 0.9921875L))
+    {
+      z = x - 1.0L;
+      k = 64;
+      t.value  = 1.0L;
+      e = 0;
+    }
+  else
+    {
+      /* log(u) = log( t u/t ) = log(t) + log(u/t)
+	 log(t) is tabulated in the lookup table.
+	 Express log(u/t) = log(1+z),  where z = u/t - 1 = (u-t)/t.
+	cf. Cody & Waite. */
+      z = (u.value - t.value) / t.value;
+    }
+  /* Series expansion of log(1+z).  */
+  w = z * z;
+  y = ((((((((((((l15 * z
+		  + l14) * z
+		 + l13) * z
+		+ l12) * z
+	       + l11) * z
+	      + l10) * z
+	     + l9) * z
+	    + l8) * z
+	   + l7) * z
+	  + l6) * z
+	 + l5) * z
+	+ l4) * z
+       + l3) * z * w;
+  y -= 0.5 * w;
+  y += e * ln2b;  /* Base 2 exponent offset times ln(2).  */
+  y += z;
+  y += logtbl[k-26]; /* log(t) - (t-1) */
+  y += (t.value - 1.0L);
+  y += e * ln2a;
+  return y;
+}

+ 439 - 0
ld128/e_powl.c

@@ -0,0 +1,439 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* powl(x,y) return x**y
+ *
+ *		      n
+ * Method:  Let x =  2   * (1+f)
+ *	1. Compute and return log2(x) in two pieces:
+ *		log2(x) = w1 + w2,
+ *	   where w1 has 113-53 = 60 bit trailing zeros.
+ *	2. Perform y*log2(x) = n+y' by simulating muti-precision
+ *	   arithmetic, where |y'|<=0.5.
+ *	3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *	1.  (anything) ** 0  is 1
+ *	2.  (anything) ** 1  is itself
+ *	3.  (anything) ** NAN is NAN
+ *	4.  NAN ** (anything except 0) is NAN
+ *	5.  +-(|x| > 1) **  +INF is +INF
+ *	6.  +-(|x| > 1) **  -INF is +0
+ *	7.  +-(|x| < 1) **  +INF is +0
+ *	8.  +-(|x| < 1) **  -INF is +INF
+ *	9.  +-1         ** +-INF is NAN
+ *	10. +0 ** (+anything except 0, NAN)               is +0
+ *	11. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *	12. +0 ** (-anything except 0, NAN)               is +INF
+ *	13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *	14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *	15. +INF ** (+anything except 0,NAN) is +INF
+ *	16. +INF ** (-anything except 0,NAN) is +0
+ *	17. -INF ** (anything)  = -0 ** (-anything)
+ *	18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *	19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double bp[] = {
+  1.0L,
+  1.5L,
+};
+
+/* log_2(1.5) */
+static const long double dp_h[] = {
+  0.0,
+  5.8496250072115607565592654282227158546448E-1L
+};
+
+/* Low part of log_2(1.5) */
+static const long double dp_l[] = {
+  0.0,
+  1.0579781240112554492329533686862998106046E-16L
+};
+
+static const long double zero = 0.0L,
+  one = 1.0L,
+  two = 2.0L,
+  two113 = 1.0384593717069655257060992658440192E34L,
+  huge = 1.0e3000L,
+  tiny = 1.0e-3000L;
+
+/* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
+   z = (x-1)/(x+1)
+   1 <= x <= 1.25
+   Peak relative error 2.3e-37 */
+static const long double LN[] =
+{
+ -3.0779177200290054398792536829702930623200E1L,
+  6.5135778082209159921251824580292116201640E1L,
+ -4.6312921812152436921591152809994014413540E1L,
+  1.2510208195629420304615674658258363295208E1L,
+ -9.9266909031921425609179910128531667336670E-1L
+};
+static const long double LD[] =
+{
+ -5.129862866715009066465422805058933131960E1L,
+  1.452015077564081884387441590064272782044E2L,
+ -1.524043275549860505277434040464085593165E2L,
+  7.236063513651544224319663428634139768808E1L,
+ -1.494198912340228235853027849917095580053E1L
+  /* 1.0E0 */
+};
+
+/* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
+   0 <= x <= 0.5
+   Peak relative error 5.7e-38  */
+static const long double PN[] =
+{
+  5.081801691915377692446852383385968225675E8L,
+  9.360895299872484512023336636427675327355E6L,
+  4.213701282274196030811629773097579432957E4L,
+  5.201006511142748908655720086041570288182E1L,
+  9.088368420359444263703202925095675982530E-3L,
+};
+static const long double PD[] =
+{
+  3.049081015149226615468111430031590411682E9L,
+  1.069833887183886839966085436512368982758E8L,
+  8.259257717868875207333991924545445705394E5L,
+  1.872583833284143212651746812884298360922E3L,
+  /* 1.0E0 */
+};
+
+static const long double
+  /* ln 2 */
+  lg2 = 6.9314718055994530941723212145817656807550E-1L,
+  lg2_h = 6.9314718055994528622676398299518041312695E-1L,
+  lg2_l = 2.3190468138462996154948554638754786504121E-17L,
+  ovt = 8.0085662595372944372e-0017L,
+  /* 2/(3*log(2)) */
+  cp = 9.6179669392597560490661645400126142495110E-1L,
+  cp_h = 9.6179669392597555432899980587535537779331E-1L,
+  cp_l = 5.0577616648125906047157785230014751039424E-17L;
+
+long double
+powl(long double x, long double y)
+{
+  long double z, ax, z_h, z_l, p_h, p_l;
+  long double yy1, t1, t2, r, s, t, u, v, w;
+  long double s2, s_h, s_l, t_h, t_l;
+  int32_t i, j, k, yisint, n;
+  u_int32_t ix, iy;
+  int32_t hx, hy;
+  ieee_quad_shape_type o, p, q;
+
+  p.value = x;
+  hx = p.parts32.mswhi;
+  ix = hx & 0x7fffffff;
+
+  q.value = y;
+  hy = q.parts32.mswhi;
+  iy = hy & 0x7fffffff;
+
+
+  /* y==zero: x**0 = 1 */
+  if ((iy | q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+    return one;
+
+  /* 1.0**y = 1; -1.0**+-Inf = 1 */
+  if (x == one)
+    return one;
+  if (x == -1.0L && iy == 0x7fff0000
+      && (q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+    return one;
+
+  /* +-NaN return x+y */
+  if ((ix > 0x7fff0000)
+      || ((ix == 0x7fff0000)
+	  && ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) != 0))
+      || (iy > 0x7fff0000)
+      || ((iy == 0x7fff0000)
+	  && ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) != 0)))
+    return x + y;
+
+  /* determine if y is an odd int when x < 0
+   * yisint = 0       ... y is not an integer
+   * yisint = 1       ... y is an odd int
+   * yisint = 2       ... y is an even int
+   */
+  yisint = 0;
+  if (hx < 0)
+    {
+      if (iy >= 0x40700000)	/* 2^113 */
+	yisint = 2;		/* even integer y */
+      else if (iy >= 0x3fff0000)	/* 1.0 */
+	{
+	  if (floorl (y) == y)
+	    {
+	      z = 0.5 * y;
+	      if (floorl (z) == z)
+		yisint = 2;
+	      else
+		yisint = 1;
+	    }
+	}
+    }
+
+  /* special value of y */
+  if ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+    {
+      if (iy == 0x7fff0000)	/* y is +-inf */
+	{
+	  if (((ix - 0x3fff0000) | p.parts32.mswlo | p.parts32.lswhi |
+	    p.parts32.lswlo) == 0)
+	    return y - y;	/* +-1**inf is NaN */
+	  else if (ix >= 0x3fff0000)	/* (|x|>1)**+-inf = inf,0 */
+	    return (hy >= 0) ? y : zero;
+	  else			/* (|x|<1)**-,+inf = inf,0 */
+	    return (hy < 0) ? -y : zero;
+	}
+      if (iy == 0x3fff0000)
+	{			/* y is  +-1 */
+	  if (hy < 0)
+	    return one / x;
+	  else
+	    return x;
+	}
+      if (hy == 0x40000000)
+	return x * x;		/* y is  2 */
+      if (hy == 0x3ffe0000)
+	{			/* y is  0.5 */
+	  if (hx >= 0)		/* x >= +0 */
+	    return sqrtl (x);
+	}
+    }
+
+  ax = fabsl (x);
+  /* special value of x */
+  if ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) == 0)
+    {
+      if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
+	{
+	  z = ax;		/*x is +-0,+-inf,+-1 */
+	  if (hy < 0)
+	    z = one / z;	/* z = (1/|x|) */
+	  if (hx < 0)
+	    {
+	      if (((ix - 0x3fff0000) | yisint) == 0)
+		{
+		  z = (z - z) / (z - z);	/* (-1)**non-int is NaN */
+		}
+	      else if (yisint == 1)
+		z = -z;		/* (x<0)**odd = -(|x|**odd) */
+	    }
+	  return z;
+	}
+    }
+
+  /* (x<0)**(non-int) is NaN */
+  if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0)
+    return (x - x) / (x - x);
+
+  /* |y| is huge.
+     2^-16495 = 1/2 of smallest representable value.
+     If (1 - 1/131072)^y underflows, y > 1.4986e9 */
+  if (iy > 0x401d654b)
+    {
+      /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
+      if (iy > 0x407d654b)
+	{
+	  if (ix <= 0x3ffeffff)
+	    return (hy < 0) ? huge * huge : tiny * tiny;
+	  if (ix >= 0x3fff0000)
+	    return (hy > 0) ? huge * huge : tiny * tiny;
+	}
+      /* over/underflow if x is not close to one */
+      if (ix < 0x3ffeffff)
+	return (hy < 0) ? huge * huge : tiny * tiny;
+      if (ix > 0x3fff0000)
+	return (hy > 0) ? huge * huge : tiny * tiny;
+    }
+
+  n = 0;
+  /* take care subnormal number */
+  if (ix < 0x00010000)
+    {
+      ax *= two113;
+      n -= 113;
+      o.value = ax;
+      ix = o.parts32.mswhi;
+    }
+  n += ((ix) >> 16) - 0x3fff;
+  j = ix & 0x0000ffff;
+  /* determine interval */
+  ix = j | 0x3fff0000;		/* normalize ix */
+  if (j <= 0x3988)
+    k = 0;			/* |x|<sqrt(3/2) */
+  else if (j < 0xbb67)
+    k = 1;			/* |x|<sqrt(3)   */
+  else
+    {
+      k = 0;
+      n += 1;
+      ix -= 0x00010000;
+    }
+
+  o.value = ax;
+  o.parts32.mswhi = ix;
+  ax = o.value;
+
+  /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+  u = ax - bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
+  v = one / (ax + bp[k]);
+  s = u * v;
+  s_h = s;
+
+  o.value = s_h;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  s_h = o.value;
+  /* t_h=ax+bp[k] High */
+  t_h = ax + bp[k];
+  o.value = t_h;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  t_h = o.value;
+  t_l = ax - (t_h - bp[k]);
+  s_l = v * ((u - s_h * t_h) - s_h * t_l);
+  /* compute log(ax) */
+  s2 = s * s;
+  u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
+  v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
+  r = s2 * s2 * u / v;
+  r += s_l * (s_h + s);
+  s2 = s_h * s_h;
+  t_h = 3.0 + s2 + r;
+  o.value = t_h;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  t_h = o.value;
+  t_l = r - ((t_h - 3.0) - s2);
+  /* u+v = s*(1+...) */
+  u = s_h * t_h;
+  v = s_l * t_h + t_l * s;
+  /* 2/(3log2)*(s+...) */
+  p_h = u + v;
+  o.value = p_h;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  p_h = o.value;
+  p_l = v - (p_h - u);
+  z_h = cp_h * p_h;		/* cp_h+cp_l = 2/(3*log2) */
+  z_l = cp_l * p_h + p_l * cp + dp_l[k];
+  /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+  t = (long double) n;
+  t1 = (((z_h + z_l) + dp_h[k]) + t);
+  o.value = t1;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  t1 = o.value;
+  t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
+
+  /* s (sign of result -ve**odd) = -1 else = 1 */
+  s = one;
+  if (((((u_int32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
+    s = -one;			/* (-ve)**(odd int) */
+
+  /* split up y into yy1+y2 and compute (yy1+y2)*(t1+t2) */
+  yy1 = y;
+  o.value = yy1;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  yy1 = o.value;
+  p_l = (y - yy1) * t1 + y * t2;
+  p_h = yy1 * t1;
+  z = p_l + p_h;
+  o.value = z;
+  j = o.parts32.mswhi;
+  if (j >= 0x400d0000) /* z >= 16384 */
+    {
+      /* if z > 16384 */
+      if (((j - 0x400d0000) | o.parts32.mswlo | o.parts32.lswhi |
+	o.parts32.lswlo) != 0)
+	return s * huge * huge;	/* overflow */
+      else
+	{
+	  if (p_l + ovt > z - p_h)
+	    return s * huge * huge;	/* overflow */
+	}
+    }
+  else if ((j & 0x7fffffff) >= 0x400d01b9)	/* z <= -16495 */
+    {
+      /* z < -16495 */
+      if (((j - 0xc00d01bc) | o.parts32.mswlo | o.parts32.lswhi |
+	o.parts32.lswlo)
+	  != 0)
+	return s * tiny * tiny;	/* underflow */
+      else
+	{
+	  if (p_l <= z - p_h)
+	    return s * tiny * tiny;	/* underflow */
+	}
+    }
+  /* compute 2**(p_h+p_l) */
+  i = j & 0x7fffffff;
+  k = (i >> 16) - 0x3fff;
+  n = 0;
+  if (i > 0x3ffe0000)
+    {				/* if |z| > 0.5, set n = [z+0.5] */
+      n = floorl (z + 0.5L);
+      t = n;
+      p_h -= t;
+    }
+  t = p_l + p_h;
+  o.value = t;
+  o.parts32.lswlo = 0;
+  o.parts32.lswhi &= 0xf8000000;
+  t = o.value;
+  u = t * lg2_h;
+  v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
+  z = u + v;
+  w = v - (z - u);
+  /*  exp(z) */
+  t = z * z;
+  u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
+  v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
+  t1 = z - t * u / v;
+  r = (z * t1) / (t1 - two) - (w + z * w);
+  z = one - (r - z);
+  o.value = z;
+  j = o.parts32.mswhi;
+  j += (n << 16);
+  if ((j >> 16) <= 0)
+    z = scalbnl (z, n);	/* subnormal output */
+  else
+    {
+      o.parts32.mswhi = j;
+      z = o.value;
+    }
+  return s * z;
+}

+ 104 - 0
ld128/e_sinhl.c

@@ -0,0 +1,104 @@
+/* @(#)e_sinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* sinhl(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ *      1. Replace x by |x| (sinhl(-x) = -sinhl(x)).
+ *      2.
+ *                                                   E + E/(E+1)
+ *          0        <= x <= 25     :  sinhl(x) := --------------, E=expm1l(x)
+ *                                                       2
+ *
+ *          25       <= x <= lnovft :  sinhl(x) := expl(x)/2
+ *          lnovft   <= x <= ln2ovft:  sinhl(x) := expl(x/2)/2 * expl(x/2)
+ *          ln2ovft  <  x           :  sinhl(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ *      sinhl(x) is |x| if x is +INF, -INF, or NaN.
+ *      only sinhl(0)=0 is exact for finite x.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, shuge = 1.0e4931L,
+ovf_thresh = 1.1357216553474703894801348310092223067821E4L;
+
+long double
+sinhl(long double x)
+{
+  long double t, w, h;
+  u_int32_t jx, ix;
+  ieee_quad_shape_type u;
+
+  /* Words of |x|. */
+  u.value = x;
+  jx = u.parts32.mswhi;
+  ix = jx & 0x7fffffff;
+
+  /* x is INF or NaN */
+  if (ix >= 0x7fff0000)
+    return x + x;
+
+  h = 0.5;
+  if (jx & 0x80000000)
+    h = -h;
+
+  /* Absolute value of x.  */
+  u.parts32.mswhi = ix;
+
+  /* |x| in [0,40], return sign(x)*0.5*(E+E/(E+1))) */
+  if (ix <= 0x40044000)
+    {
+      if (ix < 0x3fc60000) /* |x| < 2^-57 */
+	if (shuge + x > one)
+	  return x;		/* sinh(tiny) = tiny with inexact */
+      t = expm1l (u.value);
+      if (ix < 0x3fff0000)
+	return h * (2.0 * t - t * t / (t + one));
+      return h * (t + t / (t + one));
+    }
+
+  /* |x| in [40, log(maxdouble)] return 0.5*exp(|x|) */
+  if (ix <= 0x400c62e3) /* 11356.375 */
+    return h * expl (u.value);
+
+  /* |x| in [log(maxdouble), overflowthreshold]
+     Overflow threshold is log(2 * maxdouble).  */
+  if (u.value <= ovf_thresh)
+    {
+      w = expl (0.5 * u.value);
+      t = h * w;
+      return t * w;
+    }
+
+  /* |x| > overflowthreshold, sinhl(x) overflow */
+  return x * shuge;
+}

+ 45 - 0
ld128/e_tgammal.c

@@ -0,0 +1,45 @@
+/*	$OpenBSD: e_tgammal.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2011 Martynas Venckus <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+long double
+tgammal(long double x)
+{
+	int64_t i0,i1;
+
+	GET_LDOUBLE_WORDS64(i0,i1,x);
+	if (((i0&0x7fffffffffffffffLL)|i1) == 0) {
+		signgam = 0;
+		return (1.0/x);
+	}
+
+	if (i0<0 && (u_int64_t)i0<0xffff000000000000ULL && rintl(x)==x) {
+		signgam = 0;
+		return (x-x)/(x-x);
+	}
+
+	if (i0==0xffff000000000000ULL && i1==0) {
+		signgam = 0;
+		return (x-x);
+	}
+
+	return expl(lgammal(x));
+}

+ 69 - 0
ld128/s_asinhl.c

@@ -0,0 +1,69 @@
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* asinhl(x)
+ * Method :
+ *      Based on
+ *              asinhl(x) = signl(x) * logl [ |x| + sqrtl(x*x+1) ]
+ *      we have
+ *      asinhl(x) := x  if  1+x*x=1,
+ *                := signl(x)*(logl(x)+ln2)) for large |x|, else
+ *                := signl(x)*logl(2|x|+1/(|x|+sqrtl(x*x+1))) if|x|>2, else
+ *                := signl(x)*log1pl(|x| + x^2/(1 + sqrtl(1+x^2)))
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+  one = 1.0L,
+  ln2 = 6.931471805599453094172321214581765681e-1L,
+  huge = 1.0e+4900L;
+
+long double
+asinhl(long double x)
+{
+  long double t, w;
+  int32_t ix, sign;
+  ieee_quad_shape_type u;
+
+  u.value = x;
+  sign = u.parts32.mswhi;
+  ix = sign & 0x7fffffff;
+  if (ix == 0x7fff0000)
+    return x + x;		/* x is inf or NaN */
+  if (ix < 0x3fc70000)
+    {				/* |x| < 2^ -56 */
+      if (huge + x > one)
+	return x;		/* return x inexact except 0 */
+    }
+  u.parts32.mswhi = ix;
+  if (ix > 0x40350000)
+    {				/* |x| > 2 ^ 54 */
+      w = logl (u.value) + ln2;
+    }
+  else if (ix >0x40000000)
+    {				/* 2^ 54 > |x| > 2.0 */
+      t = u.value;
+      w = logl (2.0 * t + one / (sqrtl (x * x + one) + t));
+    }
+  else
+    {				/* 2.0 > |x| > 2 ^ -56 */
+      t = x * x;
+      w = log1pl (u.value + t / (one + sqrtl (one + t)));
+    }
+  if (sign & 0x80000000)
+    return -w;
+  else
+    return w;
+}

+ 69 - 0
ld128/s_ceill.c

@@ -0,0 +1,69 @@
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+ceill(long double x)
+{
+	int64_t i0,i1,jj0;
+	u_int64_t i,j;
+	GET_LDOUBLE_WORDS64(i0,i1,x);
+	jj0 = ((i0>>48)&0x7fff)-0x3fff;
+	if(jj0<48) {
+	    if(jj0<0) {		/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
+		    else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
+		}
+	    } else {
+		i = (0x0000ffffffffffffULL)>>jj0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(i0>0) i0 += (0x0001000000000000LL)>>jj0;
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (jj0>111) {
+	    if(jj0==0x4000) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = -1ULL>>(jj0-48);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) {		/* raise inexact flag */
+		if(i0>0) {
+		    if(jj0==48) i0+=1;
+		    else {
+			j = i1+(1LL<<(112-jj0));
+			if(j<i1) i0 +=1 ;	/* got a carry */
+			i1=j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	SET_LDOUBLE_WORDS64(x,i0,i1);
+	return x;
+}

+ 926 - 0
ld128/s_erfl.c

@@ -0,0 +1,926 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ *			     x
+ *		      2      |\
+ *     erf(x)  =  ---------  | exp(-t*t)dt
+ *		   sqrt(pi) \|
+ *			     0
+ *
+ *     erfc(x) =  1-erf(x)
+ *  Note that
+ *		erf(-x) = -erf(x)
+ *		erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ *	1.  erf(x)  = x + x*R(x^2) for |x| in [0, 7/8]
+ *	   Remark. The formula is derived by noting
+ *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ *	   and that
+ *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ *	   is close to one.
+ *
+ *      1a. erf(x)  = 1 - erfc(x), for |x| > 1.0
+ *          erfc(x) = 1 - erf(x)  if |x| < 1/4
+ *
+ *      2. For |x| in [7/8, 1], let s = |x| - 1, and
+ *         c = 0.84506291151 rounded to single (24 bits)
+ *	erf(s + c)  = sign(x) * (c  + P1(s)/Q1(s))
+ *	   Remark: here we use the taylor series expansion at x=1.
+ *		erf(1+s) = erf(1) + s*Poly(s)
+ *			 = 0.845.. + P1(s)/Q1(s)
+ *	   Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *
+ *      3. For x in [1/4, 5/4],
+ *	erfc(s + const)  = erfc(const)  + s P1(s)/Q1(s)
+ *              for const = 1/4, 3/8, ..., 9/8
+ *              and 0 <= s <= 1/8 .
+ *
+ *      4. For x in [5/4, 107],
+ *	erfc(x) = (1/x)*exp(-x*x-0.5625 + R(z))
+ *              z=1/x^2
+ *         The interval is partitioned into several segments
+ *         of width 1/8 in 1/x.
+ *
+ *      Note1:
+ *	   To compute exp(-x*x-0.5625+R/S), let s be a single
+ *	   precision number and s := x; then
+ *		-x*x = -s*s + (s-x)*(s+x)
+ *	        exp(-x*x-0.5626+R/S) =
+ *			exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ *      Note2:
+ *	   Here 4 and 5 make use of the asymptotic series
+ *			  exp(-x*x)
+ *		erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ *			  x*sqrt(pi)
+ *
+ *      5. For inf > x >= 107
+ *	erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+ *	erfc(x) = tiny*tiny (raise underflow) if x > 0
+ *			= 2 - tiny if x<0
+ *
+ *      7. Special case:
+ *	erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+ *	erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ *		erfc/erf(NaN) is NaN
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Evaluate P[n] x^n  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+/* Evaluate x^n+1  +  P[n] x^(n)  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+  long double y;
+
+  p += n;
+  y = x + *p--;
+  do
+    {
+      y = y * x + *p--;
+    }
+  while (--n > 0);
+  return y;
+}
+
+
+
+static const long double
+tiny = 1e-4931L,
+  one = 1.0L,
+  two = 2.0L,
+  /* 2/sqrt(pi) - 1 */
+  efx = 1.2837916709551257389615890312154517168810E-1L,
+  /* 8 * (2/sqrt(pi) - 1) */
+  efx8 = 1.0270333367641005911692712249723613735048E0L;
+
+
+/* erf(x)  = x  + x R(x^2)
+   0 <= x <= 7/8
+   Peak relative error 1.8e-35  */
+#define NTN1 8
+static const long double TN1[NTN1 + 1] =
+{
+ -3.858252324254637124543172907442106422373E10L,
+  9.580319248590464682316366876952214879858E10L,
+  1.302170519734879977595901236693040544854E10L,
+  2.922956950426397417800321486727032845006E9L,
+  1.764317520783319397868923218385468729799E8L,
+  1.573436014601118630105796794840834145120E7L,
+  4.028077380105721388745632295157816229289E5L,
+  1.644056806467289066852135096352853491530E4L,
+  3.390868480059991640235675479463287886081E1L
+};
+#define NTD1 8
+static const long double TD1[NTD1 + 1] =
+{
+  -3.005357030696532927149885530689529032152E11L,
+  -1.342602283126282827411658673839982164042E11L,
+  -2.777153893355340961288511024443668743399E10L,
+  -3.483826391033531996955620074072768276974E9L,
+  -2.906321047071299585682722511260895227921E8L,
+  -1.653347985722154162439387878512427542691E7L,
+  -6.245520581562848778466500301865173123136E5L,
+  -1.402124304177498828590239373389110545142E4L,
+  -1.209368072473510674493129989468348633579E2L
+/* 1.0E0 */
+};
+
+
+/* erf(z+1)  = erf_const + P(z)/Q(z)
+   -.125 <= z <= 0
+   Peak relative error 7.3e-36  */
+static const long double erf_const = 0.845062911510467529296875L;
+#define NTN2 8
+static const long double TN2[NTN2 + 1] =
+{
+ -4.088889697077485301010486931817357000235E1L,
+  7.157046430681808553842307502826960051036E3L,
+ -2.191561912574409865550015485451373731780E3L,
+  2.180174916555316874988981177654057337219E3L,
+  2.848578658049670668231333682379720943455E2L,
+  1.630362490952512836762810462174798925274E2L,
+  6.317712353961866974143739396865293596895E0L,
+  2.450441034183492434655586496522857578066E1L,
+  5.127662277706787664956025545897050896203E-1L
+};
+#define NTD2 8
+static const long double TD2[NTD2 + 1] =
+{
+  1.731026445926834008273768924015161048885E4L,
+  1.209682239007990370796112604286048173750E4L,
+  1.160950290217993641320602282462976163857E4L,
+  5.394294645127126577825507169061355698157E3L,
+  2.791239340533632669442158497532521776093E3L,
+  8.989365571337319032943005387378993827684E2L,
+  2.974016493766349409725385710897298069677E2L,
+  6.148192754590376378740261072533527271947E1L,
+  1.178502892490738445655468927408440847480E1L
+ /* 1.0E0 */
+};
+
+
+/* erfc(x + 0.25) = erfc(0.25) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 1.4e-35  */
+#define NRNr13 8
+static const long double RNr13[NRNr13 + 1] =
+{
+ -2.353707097641280550282633036456457014829E3L,
+  3.871159656228743599994116143079870279866E2L,
+ -3.888105134258266192210485617504098426679E2L,
+ -2.129998539120061668038806696199343094971E1L,
+ -8.125462263594034672468446317145384108734E1L,
+  8.151549093983505810118308635926270319660E0L,
+ -5.033362032729207310462422357772568553670E0L,
+ -4.253956621135136090295893547735851168471E-2L,
+ -8.098602878463854789780108161581050357814E-2L
+};
+#define NRDr13 7
+static const long double RDr13[NRDr13 + 1] =
+{
+  2.220448796306693503549505450626652881752E3L,
+  1.899133258779578688791041599040951431383E2L,
+  1.061906712284961110196427571557149268454E3L,
+  7.497086072306967965180978101974566760042E1L,
+  2.146796115662672795876463568170441327274E2L,
+  1.120156008362573736664338015952284925592E1L,
+  2.211014952075052616409845051695042741074E1L,
+  6.469655675326150785692908453094054988938E-1L
+ /* 1.0E0 */
+};
+/* erfc(0.25) = C13a + C13b to extra precision.  */
+static const long double C13a = 0.723663330078125L;
+static const long double C13b = 1.0279753638067014931732235184287934646022E-5L;
+
+
+/* erfc(x + 0.375) = erfc(0.375) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 1.2e-35  */
+#define NRNr14 8
+static const long double RNr14[NRNr14 + 1] =
+{
+ -2.446164016404426277577283038988918202456E3L,
+  6.718753324496563913392217011618096698140E2L,
+ -4.581631138049836157425391886957389240794E2L,
+ -2.382844088987092233033215402335026078208E1L,
+ -7.119237852400600507927038680970936336458E1L,
+  1.313609646108420136332418282286454287146E1L,
+ -6.188608702082264389155862490056401365834E0L,
+ -2.787116601106678287277373011101132659279E-2L,
+ -2.230395570574153963203348263549700967918E-2L
+};
+#define NRDr14 7
+static const long double RDr14[NRDr14 + 1] =
+{
+  2.495187439241869732696223349840963702875E3L,
+  2.503549449872925580011284635695738412162E2L,
+  1.159033560988895481698051531263861842461E3L,
+  9.493751466542304491261487998684383688622E1L,
+  2.276214929562354328261422263078480321204E2L,
+  1.367697521219069280358984081407807931847E1L,
+  2.276988395995528495055594829206582732682E1L,
+  7.647745753648996559837591812375456641163E-1L
+ /* 1.0E0 */
+};
+/* erfc(0.375) = C14a + C14b to extra precision.  */
+static const long double C14a = 0.5958709716796875L;
+static const long double C14b = 1.2118885490201676174914080878232469565953E-5L;
+
+/* erfc(x + 0.5) = erfc(0.5) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 4.7e-36  */
+#define NRNr15 8
+static const long double RNr15[NRNr15 + 1] =
+{
+ -2.624212418011181487924855581955853461925E3L,
+  8.473828904647825181073831556439301342756E2L,
+ -5.286207458628380765099405359607331669027E2L,
+ -3.895781234155315729088407259045269652318E1L,
+ -6.200857908065163618041240848728398496256E1L,
+  1.469324610346924001393137895116129204737E1L,
+ -6.961356525370658572800674953305625578903E0L,
+  5.145724386641163809595512876629030548495E-3L,
+  1.990253655948179713415957791776180406812E-2L
+};
+#define NRDr15 7
+static const long double RDr15[NRDr15 + 1] =
+{
+  2.986190760847974943034021764693341524962E3L,
+  5.288262758961073066335410218650047725985E2L,
+  1.363649178071006978355113026427856008978E3L,
+  1.921707975649915894241864988942255320833E2L,
+  2.588651100651029023069013885900085533226E2L,
+  2.628752920321455606558942309396855629459E1L,
+  2.455649035885114308978333741080991380610E1L,
+  1.378826653595128464383127836412100939126E0L
+  /* 1.0E0 */
+};
+/* erfc(0.5) = C15a + C15b to extra precision.  */
+static const long double C15a = 0.4794921875L;
+static const long double C15b = 7.9346869534623172533461080354712635484242E-6L;
+
+/* erfc(x + 0.625) = erfc(0.625) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 5.1e-36  */
+#define NRNr16 8
+static const long double RNr16[NRNr16 + 1] =
+{
+ -2.347887943200680563784690094002722906820E3L,
+  8.008590660692105004780722726421020136482E2L,
+ -5.257363310384119728760181252132311447963E2L,
+ -4.471737717857801230450290232600243795637E1L,
+ -4.849540386452573306708795324759300320304E1L,
+  1.140885264677134679275986782978655952843E1L,
+ -6.731591085460269447926746876983786152300E0L,
+  1.370831653033047440345050025876085121231E-1L,
+  2.022958279982138755020825717073966576670E-2L,
+};
+#define NRDr16 7
+static const long double RDr16[NRDr16 + 1] =
+{
+  3.075166170024837215399323264868308087281E3L,
+  8.730468942160798031608053127270430036627E2L,
+  1.458472799166340479742581949088453244767E3L,
+  3.230423687568019709453130785873540386217E2L,
+  2.804009872719893612081109617983169474655E2L,
+  4.465334221323222943418085830026979293091E1L,
+  2.612723259683205928103787842214809134746E1L,
+  2.341526751185244109722204018543276124997E0L,
+  /* 1.0E0 */
+};
+/* erfc(0.625) = C16a + C16b to extra precision.  */
+static const long double C16a = 0.3767547607421875L;
+static const long double C16b = 4.3570693945275513594941232097252997287766E-6L;
+
+/* erfc(x + 0.75) = erfc(0.75) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 1.7e-35  */
+#define NRNr17 8
+static const long double RNr17[NRNr17 + 1] =
+{
+  -1.767068734220277728233364375724380366826E3L,
+  6.693746645665242832426891888805363898707E2L,
+  -4.746224241837275958126060307406616817753E2L,
+  -2.274160637728782675145666064841883803196E1L,
+  -3.541232266140939050094370552538987982637E1L,
+  6.988950514747052676394491563585179503865E0L,
+  -5.807687216836540830881352383529281215100E0L,
+  3.631915988567346438830283503729569443642E-1L,
+  -1.488945487149634820537348176770282391202E-2L
+};
+#define NRDr17 7
+static const long double RDr17[NRDr17 + 1] =
+{
+  2.748457523498150741964464942246913394647E3L,
+  1.020213390713477686776037331757871252652E3L,
+  1.388857635935432621972601695296561952738E3L,
+  3.903363681143817750895999579637315491087E2L,
+  2.784568344378139499217928969529219886578E2L,
+  5.555800830216764702779238020065345401144E1L,
+  2.646215470959050279430447295801291168941E1L,
+  2.984905282103517497081766758550112011265E0L,
+  /* 1.0E0 */
+};
+/* erfc(0.75) = C17a + C17b to extra precision.  */
+static const long double C17a = 0.2888336181640625L;
+static const long double C17b = 1.0748182422368401062165408589222625794046E-5L;
+
+
+/* erfc(x + 0.875) = erfc(0.875) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 2.2e-35  */
+#define NRNr18 8
+static const long double RNr18[NRNr18 + 1] =
+{
+ -1.342044899087593397419622771847219619588E3L,
+  6.127221294229172997509252330961641850598E2L,
+ -4.519821356522291185621206350470820610727E2L,
+  1.223275177825128732497510264197915160235E1L,
+ -2.730789571382971355625020710543532867692E1L,
+  4.045181204921538886880171727755445395862E0L,
+ -4.925146477876592723401384464691452700539E0L,
+  5.933878036611279244654299924101068088582E-1L,
+ -5.557645435858916025452563379795159124753E-2L
+};
+#define NRDr18 7
+static const long double RDr18[NRDr18 + 1] =
+{
+  2.557518000661700588758505116291983092951E3L,
+  1.070171433382888994954602511991940418588E3L,
+  1.344842834423493081054489613250688918709E3L,
+  4.161144478449381901208660598266288188426E2L,
+  2.763670252219855198052378138756906980422E2L,
+  5.998153487868943708236273854747564557632E1L,
+  2.657695108438628847733050476209037025318E1L,
+  3.252140524394421868923289114410336976512E0L,
+  /* 1.0E0 */
+};
+/* erfc(0.875) = C18a + C18b to extra precision.  */
+static const long double C18a = 0.215911865234375L;
+static const long double C18b = 1.3073705765341685464282101150637224028267E-5L;
+
+/* erfc(x + 1.0) = erfc(1.0) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 1.6e-35  */
+#define NRNr19 8
+static const long double RNr19[NRNr19 + 1] =
+{
+ -1.139180936454157193495882956565663294826E3L,
+  6.134903129086899737514712477207945973616E2L,
+ -4.628909024715329562325555164720732868263E2L,
+  4.165702387210732352564932347500364010833E1L,
+ -2.286979913515229747204101330405771801610E1L,
+  1.870695256449872743066783202326943667722E0L,
+ -4.177486601273105752879868187237000032364E0L,
+  7.533980372789646140112424811291782526263E-1L,
+ -8.629945436917752003058064731308767664446E-2L
+};
+#define NRDr19 7
+static const long double RDr19[NRDr19 + 1] =
+{
+  2.744303447981132701432716278363418643778E3L,
+  1.266396359526187065222528050591302171471E3L,
+  1.466739461422073351497972255511919814273E3L,
+  4.868710570759693955597496520298058147162E2L,
+  2.993694301559756046478189634131722579643E2L,
+  6.868976819510254139741559102693828237440E1L,
+  2.801505816247677193480190483913753613630E1L,
+  3.604439909194350263552750347742663954481E0L,
+  /* 1.0E0 */
+};
+/* erfc(1.0) = C19a + C19b to extra precision.  */
+static const long double C19a = 0.15728759765625L;
+static const long double C19b = 1.1609394035130658779364917390740703933002E-5L;
+
+/* erfc(x + 1.125) = erfc(1.125) + x R(x)
+   0 <= x < 0.125
+   Peak relative error 3.6e-36  */
+#define NRNr20 8
+static const long double RNr20[NRNr20 + 1] =
+{
+ -9.652706916457973956366721379612508047640E2L,
+  5.577066396050932776683469951773643880634E2L,
+ -4.406335508848496713572223098693575485978E2L,
+  5.202893466490242733570232680736966655434E1L,
+ -1.931311847665757913322495948705563937159E1L,
+ -9.364318268748287664267341457164918090611E-2L,
+ -3.306390351286352764891355375882586201069E0L,
+  7.573806045289044647727613003096916516475E-1L,
+ -9.611744011489092894027478899545635991213E-2L
+};
+#define NRDr20 7
+static const long double RDr20[NRDr20 + 1] =
+{
+  3.032829629520142564106649167182428189014E3L,
+  1.659648470721967719961167083684972196891E3L,
+  1.703545128657284619402511356932569292535E3L,
+  6.393465677731598872500200253155257708763E2L,
+  3.489131397281030947405287112726059221934E2L,
+  8.848641738570783406484348434387611713070E1L,
+  3.132269062552392974833215844236160958502E1L,
+  4.430131663290563523933419966185230513168E0L
+ /* 1.0E0 */
+};
+/* erfc(1.125) = C20a + C20b to extra precision.  */
+static const long double C20a = 0.111602783203125L;
+static const long double C20b = 8.9850951672359304215530728365232161564636E-6L;
+
+/* erfc(1/x) = 1/x exp (-1/x^2 - 0.5625 + R(1/x^2))
+   7/8 <= 1/x < 1
+   Peak relative error 1.4e-35  */
+#define NRNr8 9
+static const long double RNr8[NRNr8 + 1] =
+{
+  3.587451489255356250759834295199296936784E1L,
+  5.406249749087340431871378009874875889602E2L,
+  2.931301290625250886238822286506381194157E3L,
+  7.359254185241795584113047248898753470923E3L,
+  9.201031849810636104112101947312492532314E3L,
+  5.749697096193191467751650366613289284777E3L,
+  1.710415234419860825710780802678697889231E3L,
+  2.150753982543378580859546706243022719599E2L,
+  8.740953582272147335100537849981160931197E0L,
+  4.876422978828717219629814794707963640913E-2L
+};
+#define NRDr8 8
+static const long double RDr8[NRDr8 + 1] =
+{
+  6.358593134096908350929496535931630140282E1L,
+  9.900253816552450073757174323424051765523E2L,
+  5.642928777856801020545245437089490805186E3L,
+  1.524195375199570868195152698617273739609E4L,
+  2.113829644500006749947332935305800887345E4L,
+  1.526438562626465706267943737310282977138E4L,
+  5.561370922149241457131421914140039411782E3L,
+  9.394035530179705051609070428036834496942E2L,
+  6.147019596150394577984175188032707343615E1L
+  /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp (-1/x^2 - 0.5625 + R(1/x^2))
+   0.75 <= 1/x <= 0.875
+   Peak relative error 2.0e-36  */
+#define NRNr7 9
+static const long double RNr7[NRNr7 + 1] =
+{
+ 1.686222193385987690785945787708644476545E1L,
+ 1.178224543567604215602418571310612066594E3L,
+ 1.764550584290149466653899886088166091093E4L,
+ 1.073758321890334822002849369898232811561E5L,
+ 3.132840749205943137619839114451290324371E5L,
+ 4.607864939974100224615527007793867585915E5L,
+ 3.389781820105852303125270837910972384510E5L,
+ 1.174042187110565202875011358512564753399E5L,
+ 1.660013606011167144046604892622504338313E4L,
+ 6.700393957480661937695573729183733234400E2L
+};
+#define NRDr7 9
+static const long double RDr7[NRDr7 + 1] =
+{
+-1.709305024718358874701575813642933561169E3L,
+-3.280033887481333199580464617020514788369E4L,
+-2.345284228022521885093072363418750835214E5L,
+-8.086758123097763971926711729242327554917E5L,
+-1.456900414510108718402423999575992450138E6L,
+-1.391654264881255068392389037292702041855E6L,
+-6.842360801869939983674527468509852583855E5L,
+-1.597430214446573566179675395199807533371E5L,
+-1.488876130609876681421645314851760773480E4L,
+-3.511762950935060301403599443436465645703E2L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   5/8 <= 1/x < 3/4
+   Peak relative error 1.9e-35  */
+#define NRNr6 9
+static const long double RNr6[NRNr6 + 1] =
+{
+ 1.642076876176834390623842732352935761108E0L,
+ 1.207150003611117689000664385596211076662E2L,
+ 2.119260779316389904742873816462800103939E3L,
+ 1.562942227734663441801452930916044224174E4L,
+ 5.656779189549710079988084081145693580479E4L,
+ 1.052166241021481691922831746350942786299E5L,
+ 9.949798524786000595621602790068349165758E4L,
+ 4.491790734080265043407035220188849562856E4L,
+ 8.377074098301530326270432059434791287601E3L,
+ 4.506934806567986810091824791963991057083E2L
+};
+#define NRDr6 9
+static const long double RDr6[NRDr6 + 1] =
+{
+-1.664557643928263091879301304019826629067E2L,
+-3.800035902507656624590531122291160668452E3L,
+-3.277028191591734928360050685359277076056E4L,
+-1.381359471502885446400589109566587443987E5L,
+-3.082204287382581873532528989283748656546E5L,
+-3.691071488256738343008271448234631037095E5L,
+-2.300482443038349815750714219117566715043E5L,
+-6.873955300927636236692803579555752171530E4L,
+-8.262158817978334142081581542749986845399E3L,
+-2.517122254384430859629423488157361983661E2L
+ /* 1.00 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   1/2 <= 1/x < 5/8
+   Peak relative error 4.6e-36  */
+#define NRNr5 10
+static const long double RNr5[NRNr5 + 1] =
+{
+-3.332258927455285458355550878136506961608E-3L,
+-2.697100758900280402659586595884478660721E-1L,
+-6.083328551139621521416618424949137195536E0L,
+-6.119863528983308012970821226810162441263E1L,
+-3.176535282475593173248810678636522589861E2L,
+-8.933395175080560925809992467187963260693E2L,
+-1.360019508488475978060917477620199499560E3L,
+-1.075075579828188621541398761300910213280E3L,
+-4.017346561586014822824459436695197089916E2L,
+-5.857581368145266249509589726077645791341E1L,
+-2.077715925587834606379119585995758954399E0L
+};
+#define NRDr5 9
+static const long double RDr5[NRDr5 + 1] =
+{
+ 3.377879570417399341550710467744693125385E-1L,
+ 1.021963322742390735430008860602594456187E1L,
+ 1.200847646592942095192766255154827011939E2L,
+ 7.118915528142927104078182863387116942836E2L,
+ 2.318159380062066469386544552429625026238E3L,
+ 4.238729853534009221025582008928765281620E3L,
+ 4.279114907284825886266493994833515580782E3L,
+ 2.257277186663261531053293222591851737504E3L,
+ 5.570475501285054293371908382916063822957E2L,
+ 5.142189243856288981145786492585432443560E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   3/8 <= 1/x < 1/2
+   Peak relative error 2.0e-36  */
+#define NRNr4 10
+static const long double RNr4[NRNr4 + 1] =
+{
+ 3.258530712024527835089319075288494524465E-3L,
+ 2.987056016877277929720231688689431056567E-1L,
+ 8.738729089340199750734409156830371528862E0L,
+ 1.207211160148647782396337792426311125923E2L,
+ 8.997558632489032902250523945248208224445E2L,
+ 3.798025197699757225978410230530640879762E3L,
+ 9.113203668683080975637043118209210146846E3L,
+ 1.203285891339933238608683715194034900149E4L,
+ 8.100647057919140328536743641735339740855E3L,
+ 2.383888249907144945837976899822927411769E3L,
+ 2.127493573166454249221983582495245662319E2L
+};
+#define NRDr4 10
+static const long double RDr4[NRDr4 + 1] =
+{
+-3.303141981514540274165450687270180479586E-1L,
+-1.353768629363605300707949368917687066724E1L,
+-2.206127630303621521950193783894598987033E2L,
+-1.861800338758066696514480386180875607204E3L,
+-8.889048775872605708249140016201753255599E3L,
+-2.465888106627948210478692168261494857089E4L,
+-3.934642211710774494879042116768390014289E4L,
+-3.455077258242252974937480623730228841003E4L,
+-1.524083977439690284820586063729912653196E4L,
+-2.810541887397984804237552337349093953857E3L,
+-1.343929553541159933824901621702567066156E2L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   1/4 <= 1/x < 3/8
+   Peak relative error 8.4e-37  */
+#define NRNr3 11
+static const long double RNr3[NRNr3 + 1] =
+{
+-1.952401126551202208698629992497306292987E-6L,
+-2.130881743066372952515162564941682716125E-4L,
+-8.376493958090190943737529486107282224387E-3L,
+-1.650592646560987700661598877522831234791E-1L,
+-1.839290818933317338111364667708678163199E0L,
+-1.216278715570882422410442318517814388470E1L,
+-4.818759344462360427612133632533779091386E1L,
+-1.120994661297476876804405329172164436784E2L,
+-1.452850765662319264191141091859300126931E2L,
+-9.485207851128957108648038238656777241333E1L,
+-2.563663855025796641216191848818620020073E1L,
+-1.787995944187565676837847610706317833247E0L
+};
+#define NRDr3 10
+static const long double RDr3[NRDr3 + 1] =
+{
+ 1.979130686770349481460559711878399476903E-4L,
+ 1.156941716128488266238105813374635099057E-2L,
+ 2.752657634309886336431266395637285974292E-1L,
+ 3.482245457248318787349778336603569327521E0L,
+ 2.569347069372696358578399521203959253162E1L,
+ 1.142279000180457419740314694631879921561E2L,
+ 3.056503977190564294341422623108332700840E2L,
+ 4.780844020923794821656358157128719184422E2L,
+ 4.105972727212554277496256802312730410518E2L,
+ 1.724072188063746970865027817017067646246E2L,
+ 2.815939183464818198705278118326590370435E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   1/8 <= 1/x < 1/4
+   Peak relative error 1.5e-36  */
+#define NRNr2 11
+static const long double RNr2[NRNr2 + 1] =
+{
+-2.638914383420287212401687401284326363787E-8L,
+-3.479198370260633977258201271399116766619E-6L,
+-1.783985295335697686382487087502222519983E-4L,
+-4.777876933122576014266349277217559356276E-3L,
+-7.450634738987325004070761301045014986520E-2L,
+-7.068318854874733315971973707247467326619E-1L,
+-4.113919921935944795764071670806867038732E0L,
+-1.440447573226906222417767283691888875082E1L,
+-2.883484031530718428417168042141288943905E1L,
+-2.990886974328476387277797361464279931446E1L,
+-1.325283914915104866248279787536128997331E1L,
+-1.572436106228070195510230310658206154374E0L
+};
+#define NRDr2 10
+static const long double RDr2[NRDr2 + 1] =
+{
+ 2.675042728136731923554119302571867799673E-6L,
+ 2.170997868451812708585443282998329996268E-4L,
+ 7.249969752687540289422684951196241427445E-3L,
+ 1.302040375859768674620410563307838448508E-1L,
+ 1.380202483082910888897654537144485285549E0L,
+ 8.926594113174165352623847870299170069350E0L,
+ 3.521089584782616472372909095331572607185E1L,
+ 8.233547427533181375185259050330809105570E1L,
+ 1.072971579885803033079469639073292840135E2L,
+ 6.943803113337964469736022094105143158033E1L,
+ 1.775695341031607738233608307835017282662E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+   1/128 <= 1/x < 1/8
+   Peak relative error 2.2e-36  */
+#define NRNr1 9
+static const long double RNr1[NRNr1 + 1] =
+{
+-4.250780883202361946697751475473042685782E-8L,
+-5.375777053288612282487696975623206383019E-6L,
+-2.573645949220896816208565944117382460452E-4L,
+-6.199032928113542080263152610799113086319E-3L,
+-8.262721198693404060380104048479916247786E-2L,
+-6.242615227257324746371284637695778043982E-1L,
+-2.609874739199595400225113299437099626386E0L,
+-5.581967563336676737146358534602770006970E0L,
+-5.124398923356022609707490956634280573882E0L,
+-1.290865243944292370661544030414667556649E0L
+};
+#define NRDr1 8
+static const long double RDr1[NRDr1 + 1] =
+{
+ 4.308976661749509034845251315983612976224E-6L,
+ 3.265390126432780184125233455960049294580E-4L,
+ 9.811328839187040701901866531796570418691E-3L,
+ 1.511222515036021033410078631914783519649E-1L,
+ 1.289264341917429958858379585970225092274E0L,
+ 6.147640356182230769548007536914983522270E0L,
+ 1.573966871337739784518246317003956180750E1L,
+ 1.955534123435095067199574045529218238263E1L,
+ 9.472613121363135472247929109615785855865E0L
+  /* 1.0E0 */
+};
+
+
+long double
+erfl(long double x)
+{
+  long double a, y, z;
+  int32_t i, ix, sign;
+  ieee_quad_shape_type u;
+
+  u.value = x;
+  sign = u.parts32.mswhi;
+  ix = sign & 0x7fffffff;
+
+  if (ix >= 0x7fff0000)
+    {				/* erf(nan)=nan */
+      i = ((sign & 0xffff0000) >> 31) << 1;
+      return (long double) (1 - i) + one / x;	/* erf(+-inf)=+-1 */
+    }
+
+  if (ix >= 0x3fff0000) /* |x| >= 1.0 */
+    {
+      y = erfcl (x);
+      return (one - y);
+      /*    return (one - erfcl (x)); */
+    }
+  u.parts32.mswhi = ix;
+  a = u.value;
+  z = x * x;
+  if (ix < 0x3ffec000)  /* a < 0.875 */
+    {
+      if (ix < 0x3fc60000) /* |x|<2**-57 */
+	{
+	  if (ix < 0x00080000)
+	    return 0.125 * (8.0 * x + efx8 * x);	/*avoid underflow */
+	  return x + efx * x;
+	}
+      y = a + a * neval (z, TN1, NTN1) / deval (z, TD1, NTD1);
+    }
+  else
+    {
+      a = a - one;
+      y = erf_const + neval (a, TN2, NTN2) / deval (a, TD2, NTD2);
+    }
+
+  if (sign & 0x80000000) /* x < 0 */
+    y = -y;
+  return( y );
+}
+
+long double
+erfcl(long double x)
+{
+  long double y, z, p, r;
+  int32_t i, ix, sign;
+  ieee_quad_shape_type u;
+
+  u.value = x;
+  sign = u.parts32.mswhi;
+  ix = sign & 0x7fffffff;
+  u.parts32.mswhi = ix;
+
+  if (ix >= 0x7fff0000)
+    {				/* erfc(nan)=nan */
+      /* erfc(+-inf)=0,2 */
+      return (long double) (((u_int32_t) sign >> 31) << 1) + one / x;
+    }
+
+  if (ix < 0x3ffd0000) /* |x| <1/4 */
+    {
+      if (ix < 0x3f8d0000) /* |x|<2**-114 */
+	return one - x;
+      return one - erfl (x);
+    }
+  if (ix < 0x3fff4000) /* 1.25 */
+    {
+      x = u.value;
+      i = 8.0 * x;
+      switch (i)
+	{
+	case 2:
+	  z = x - 0.25L;
+	  y = C13b + z * neval (z, RNr13, NRNr13) / deval (z, RDr13, NRDr13);
+	  y += C13a;
+	  break;
+	case 3:
+	  z = x - 0.375L;
+	  y = C14b + z * neval (z, RNr14, NRNr14) / deval (z, RDr14, NRDr14);
+	  y += C14a;
+	  break;
+	case 4:
+	  z = x - 0.5L;
+	  y = C15b + z * neval (z, RNr15, NRNr15) / deval (z, RDr15, NRDr15);
+	  y += C15a;
+	  break;
+	case 5:
+	  z = x - 0.625L;
+	  y = C16b + z * neval (z, RNr16, NRNr16) / deval (z, RDr16, NRDr16);
+	  y += C16a;
+	  break;
+	case 6:
+	  z = x - 0.75L;
+	  y = C17b + z * neval (z, RNr17, NRNr17) / deval (z, RDr17, NRDr17);
+	  y += C17a;
+	  break;
+	case 7:
+	  z = x - 0.875L;
+	  y = C18b + z * neval (z, RNr18, NRNr18) / deval (z, RDr18, NRDr18);
+	  y += C18a;
+	  break;
+	case 8:
+	  z = x - 1.0L;
+	  y = C19b + z * neval (z, RNr19, NRNr19) / deval (z, RDr19, NRDr19);
+	  y += C19a;
+	  break;
+	case 9:
+	  z = x - 1.125L;
+	  y = C20b + z * neval (z, RNr20, NRNr20) / deval (z, RDr20, NRDr20);
+	  y += C20a;
+	  break;
+	}
+      if (sign & 0x80000000)
+	y = 2.0L - y;
+      return y;
+    }
+  /* 1.25 < |x| < 107 */
+  if (ix < 0x4005ac00)
+    {
+      /* x < -9 */
+      if ((ix >= 0x40022000) && (sign & 0x80000000))
+	return two - tiny;
+
+      x = fabsl (x);
+      z = one / (x * x);
+      i = 8.0 / x;
+      switch (i)
+	{
+	default:
+	case 0:
+	  p = neval (z, RNr1, NRNr1) / deval (z, RDr1, NRDr1);
+	  break;
+	case 1:
+	  p = neval (z, RNr2, NRNr2) / deval (z, RDr2, NRDr2);
+	  break;
+	case 2:
+	  p = neval (z, RNr3, NRNr3) / deval (z, RDr3, NRDr3);
+	  break;
+	case 3:
+	  p = neval (z, RNr4, NRNr4) / deval (z, RDr4, NRDr4);
+	  break;
+	case 4:
+	  p = neval (z, RNr5, NRNr5) / deval (z, RDr5, NRDr5);
+	  break;
+	case 5:
+	  p = neval (z, RNr6, NRNr6) / deval (z, RDr6, NRDr6);
+	  break;
+	case 6:
+	  p = neval (z, RNr7, NRNr7) / deval (z, RDr7, NRDr7);
+	  break;
+	case 7:
+	  p = neval (z, RNr8, NRNr8) / deval (z, RDr8, NRDr8);
+	  break;
+	}
+      u.value = x;
+      u.parts32.lswlo = 0;
+      u.parts32.lswhi &= 0xfe000000;
+      z = u.value;
+      r = expl (-z * z - 0.5625) *
+	expl ((z - x) * (z + x) + p);
+      if ((sign & 0x80000000) == 0)
+	return r / x;
+      else
+	return two - r / x;
+    }
+  else
+    {
+      if ((sign & 0x80000000) == 0)
+	return tiny * tiny;
+      else
+	return two - tiny;
+    }
+}

+ 162 - 0
ld128/s_expm1l.c

@@ -0,0 +1,162 @@
+/*	$OpenBSD: s_expm1l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							expm1l.c
+ *
+ *	Exponential function, minus 1
+ *      128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expm1l();
+ *
+ * y = expm1l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power, minus one.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ *     x    k  f
+ *    e  = 2  e.
+ *
+ * An expansion x + .5 x^2 + x^3 R(x) approximates exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE    -79,+MAXLOG    100,000     1.7e-34     4.5e-35
+ *
+ */
+
+#include <errno.h>
+#include <math.h>
+
+#include "math_private.h"
+
+/* exp(x) - 1 = x + 0.5 x^2 + x^3 P(x)/Q(x)
+   -.5 ln 2  <  x  <  .5 ln 2
+   Theoretical peak relative error = 8.1e-36  */
+
+static const long double
+  P0 = 2.943520915569954073888921213330863757240E8L,
+  P1 = -5.722847283900608941516165725053359168840E7L,
+  P2 = 8.944630806357575461578107295909719817253E6L,
+  P3 = -7.212432713558031519943281748462837065308E5L,
+  P4 = 4.578962475841642634225390068461943438441E4L,
+  P5 = -1.716772506388927649032068540558788106762E3L,
+  P6 = 4.401308817383362136048032038528753151144E1L,
+  P7 = -4.888737542888633647784737721812546636240E-1L,
+  Q0 = 1.766112549341972444333352727998584753865E9L,
+  Q1 = -7.848989743695296475743081255027098295771E8L,
+  Q2 = 1.615869009634292424463780387327037251069E8L,
+  Q3 = -2.019684072836541751428967854947019415698E7L,
+  Q4 = 1.682912729190313538934190635536631941751E6L,
+  Q5 = -9.615511549171441430850103489315371768998E4L,
+  Q6 = 3.697714952261803935521187272204485251835E3L,
+  Q7 = -8.802340681794263968892934703309274564037E1L,
+  /* Q8 = 1.000000000000000000000000000000000000000E0 */
+/* C1 + C2 = ln 2 */
+
+  C1 = 6.93145751953125E-1L,
+  C2 = 1.428606820309417232121458176568075500134E-6L,
+/* ln (2^16384 * (1 - 2^-113)) */
+  maxlog = 1.1356523406294143949491931077970764891253E4L,
+/* ln 2^-114 */
+  minarg = -7.9018778583833765273564461846232128760607E1L, big = 1e4932L;
+
+
+long double
+expm1l(long double x)
+{
+  long double px, qx, xx;
+  int32_t ix, sign;
+  ieee_quad_shape_type u;
+  int k;
+
+  /* Detect infinity and NaN.  */
+  u.value = x;
+  ix = u.parts32.mswhi;
+  sign = ix & 0x80000000;
+  ix &= 0x7fffffff;
+  if (ix >= 0x7fff0000)
+    {
+      /* Infinity. */
+      if (((ix & 0xffff) | u.parts32.mswlo | u.parts32.lswhi |
+	u.parts32.lswlo) == 0)
+	{
+	  if (sign)
+	    return -1.0L;
+	  else
+	    return x;
+	}
+      /* NaN. No invalid exception. */
+      return x;
+    }
+
+  /* expm1(+- 0) = +- 0.  */
+  if ((ix == 0) && (u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+    return x;
+
+  /* Overflow.  */
+  if (x > maxlog)
+      return (big * big);
+
+  /* Minimum value.  */
+  if (x < minarg)
+    return (4.0/big - 1.0L);
+
+  /* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
+  xx = C1 + C2;			/* ln 2. */
+  px = floorl (0.5 + x / xx);
+  k = px;
+  /* remainder times ln 2 */
+  x -= px * C1;
+  x -= px * C2;
+
+  /* Approximate exp(remainder ln 2).  */
+  px = (((((((P7 * x
+	      + P6) * x
+	     + P5) * x + P4) * x + P3) * x + P2) * x + P1) * x + P0) * x;
+
+  qx = (((((((x
+	      + Q7) * x
+	     + Q6) * x + Q5) * x + Q4) * x + Q3) * x + Q2) * x + Q1) * x + Q0;
+
+  xx = x * x;
+  qx = x + (0.5 * xx + xx * px / qx);
+
+  /* exp(x) = exp(k ln 2) exp(remainder ln 2) = 2^k exp(remainder ln 2).
+
+  We have qx = exp(remainder ln 2) - 1, so
+  exp(x) - 1 = 2^k (qx + 1) - 1
+	     = 2^k qx + 2^k - 1.  */
+
+  px = ldexpl (1.0L, k);
+  x = px * qx + (px - 1.0);
+  return x;
+}

+ 71 - 0
ld128/s_floorl.c

@@ -0,0 +1,71 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+floorl(long double x)
+{
+	int64_t i0,i1,jj0;
+	u_int64_t i,j;
+	GET_LDOUBLE_WORDS64(i0,i1,x);
+	jj0 = ((i0>>48)&0x7fff)-0x3fff;
+	if(jj0<48) {
+	    if(jj0<0) {		/* raise inexact if x != 0 */
+		if(huge+x>0.0) {
+		    if(i0>=0)
+			return 0.0L;
+		    else if(((i0&0x7fffffffffffffffLL)|i1)!=0)
+			return -1.0L;
+		}
+	    } else {
+		i = (0x0000ffffffffffffULL)>>jj0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(i0<0) i0 += (0x0001000000000000LL)>>jj0;
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (jj0>111) {
+	    if(jj0==0x4000) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = -1ULL>>(jj0-48);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) {		/* raise inexact flag */
+		if(i0<0) {
+		    if(jj0==48) i0+=1;
+		    else {
+			j = i1+(1LL<<(112-jj0));
+			if(j<i1) i0 +=1 ;	/* got a carry */
+			i1=j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	SET_LDOUBLE_WORDS64(x,i0,i1);
+	return x;
+}

+ 247 - 0
ld128/s_log1pl.c

@@ -0,0 +1,247 @@
+/*	$OpenBSD: s_log1pl.c,v 1.1 2011/07/06 00:02:42 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							log1pl.c
+ *
+ *      Relative error logarithm
+ *	Natural logarithm of 1+x, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log1pl();
+ *
+ * y = log1pl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of 1+x.
+ *
+ * The argument 1+x is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(w-1)/(w+1),
+ *
+ *     log(w) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      -1, 8       100000      1.9e-34     4.3e-35
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
+ * 1/sqrt(2) <= 1+x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double
+  P12 = 1.538612243596254322971797716843006400388E-6L,
+  P11 = 4.998469661968096229986658302195402690910E-1L,
+  P10 = 2.321125933898420063925789532045674660756E1L,
+  P9 = 4.114517881637811823002128927449878962058E2L,
+  P8 = 3.824952356185897735160588078446136783779E3L,
+  P7 = 2.128857716871515081352991964243375186031E4L,
+  P6 = 7.594356839258970405033155585486712125861E4L,
+  P5 = 1.797628303815655343403735250238293741397E5L,
+  P4 = 2.854829159639697837788887080758954924001E5L,
+  P3 = 3.007007295140399532324943111654767187848E5L,
+  P2 = 2.014652742082537582487669938141683759923E5L,
+  P1 = 7.771154681358524243729929227226708890930E4L,
+  P0 = 1.313572404063446165910279910527789794488E4L,
+  /* Q12 = 1.000000000000000000000000000000000000000E0L, */
+  Q11 = 4.839208193348159620282142911143429644326E1L,
+  Q10 = 9.104928120962988414618126155557301584078E2L,
+  Q9 = 9.147150349299596453976674231612674085381E3L,
+  Q8 = 5.605842085972455027590989944010492125825E4L,
+  Q7 = 2.248234257620569139969141618556349415120E5L,
+  Q6 = 6.132189329546557743179177159925690841200E5L,
+  Q5 = 1.158019977462989115839826904108208787040E6L,
+  Q4 = 1.514882452993549494932585972882995548426E6L,
+  Q3 = 1.347518538384329112529391120390701166528E6L,
+  Q2 = 7.777690340007566932935753241556479363645E5L,
+  Q1 = 2.626900195321832660448791748036714883242E5L,
+  Q0 = 3.940717212190338497730839731583397586124E4L;
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double
+  R5 = -8.828896441624934385266096344596648080902E-1L,
+  R4 = 8.057002716646055371965756206836056074715E1L,
+  R3 = -2.024301798136027039250415126250455056397E3L,
+  R2 = 2.048819892795278657810231591630928516206E4L,
+  R1 = -8.977257995689735303686582344659576526998E4L,
+  R0 = 1.418134209872192732479751274970992665513E5L,
+  /* S6 = 1.000000000000000000000000000000000000000E0L, */
+  S5 = -1.186359407982897997337150403816839480438E2L,
+  S4 = 3.998526750980007367835804959888064681098E3L,
+  S3 = -5.748542087379434595104154610899551484314E4L,
+  S2 = 4.001557694070773974936904547424676279307E5L,
+  S1 = -1.332535117259762928288745111081235577029E6L,
+  S0 = 1.701761051846631278975701529965589676574E6L;
+
+/* C1 + C2 = ln 2 */
+static const long double C1 = 6.93145751953125E-1L;
+static const long double C2 = 1.428606820309417232121458176568075500134E-6L;
+
+static const long double sqrth = 0.7071067811865475244008443621048490392848L;
+/* ln (2^16384 * (1 - 2^-113)) */
+static const long double zero = 0.0L;
+
+long double
+log1pl(long double xm1)
+{
+  long double x, y, z, r, s;
+  ieee_quad_shape_type u;
+  int32_t hx;
+  int e;
+
+  /* Test for NaN or infinity input. */
+  u.value = xm1;
+  hx = u.parts32.mswhi;
+  if (hx >= 0x7fff0000)
+    return xm1;
+
+  /* log1p(+- 0) = +- 0.  */
+  if (((hx & 0x7fffffff) == 0)
+      && (u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+    return xm1;
+
+  x = xm1 + 1.0L;
+
+  /* log1p(-1) = -inf */
+  if (x <= 0.0L)
+    {
+      if (x == 0.0L)
+	return (-1.0L / (x - x));
+      else
+	return (zero / (x - x));
+    }
+
+  /* Separate mantissa from exponent.  */
+
+  /* Use frexp used so that denormal numbers will be handled properly.  */
+  x = frexpl (x, &e);
+
+  /* Logarithm using log(x) = z + z^3 P(z^2)/Q(z^2),
+     where z = 2(x-1)/x+1).  */
+  if ((e > 2) || (e < -2))
+    {
+      if (x < sqrth)
+	{			/* 2( 2x-1 )/( 2x+1 ) */
+	  e -= 1;
+	  z = x - 0.5L;
+	  y = 0.5L * z + 0.5L;
+	}
+      else
+	{			/*  2 (x-1)/(x+1)   */
+	  z = x - 0.5L;
+	  z -= 0.5L;
+	  y = 0.5L * x + 0.5L;
+	}
+      x = z / y;
+      z = x * x;
+      r = ((((R5 * z
+	      + R4) * z
+	     + R3) * z
+	    + R2) * z
+	   + R1) * z
+	+ R0;
+      s = (((((z
+	       + S5) * z
+	      + S4) * z
+	     + S3) * z
+	    + S2) * z
+	   + S1) * z
+	+ S0;
+      z = x * (z * r / s);
+      z = z + e * C2;
+      z = z + x;
+      z = z + e * C1;
+      return (z);
+    }
+
+
+  /* Logarithm using log(1+x) = x - .5x^2 + x^3 P(x)/Q(x). */
+
+  if (x < sqrth)
+    {
+      e -= 1;
+      if (e != 0)
+	x = 2.0L * x - 1.0L;	/*  2x - 1  */
+      else
+	x = xm1;
+    }
+  else
+    {
+      if (e != 0)
+	x = x - 1.0L;
+      else
+	x = xm1;
+    }
+  z = x * x;
+  r = (((((((((((P12 * x
+		 + P11) * x
+		+ P10) * x
+	       + P9) * x
+	      + P8) * x
+	     + P7) * x
+	    + P6) * x
+	   + P5) * x
+	  + P4) * x
+	 + P3) * x
+	+ P2) * x
+       + P1) * x
+    + P0;
+  s = (((((((((((x
+		 + Q11) * x
+		+ Q10) * x
+	       + Q9) * x
+	      + Q8) * x
+	     + Q7) * x
+	    + Q6) * x
+	   + Q5) * x
+	  + Q4) * x
+	 + Q3) * x
+	+ Q2) * x
+       + Q1) * x
+    + Q0;
+  y = x * (z * r / s);
+  y = y + e * C2;
+  z = y - 0.5L * z;
+  z = z + x;
+  z = z + e * C1;
+  return (z);
+}

+ 73 - 0
ld128/s_modfl.c

@@ -0,0 +1,73 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modfl(long double x, long double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *	Bit twiddling.
+ *
+ * Exception:
+ *	No exception.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0;
+
+long double
+modfl(long double x, long double *iptr)
+{
+	int64_t i0,i1,jj0;
+	u_int64_t i;
+	GET_LDOUBLE_WORDS64(i0,i1,x);
+	jj0 = ((i0>>48)&0x7fff)-0x3fff;	/* exponent of x */
+	if(jj0<48) {			/* integer part in high x */
+	    if(jj0<0) {			/* |x|<1 */
+		/* *iptr = +-0 */
+		SET_LDOUBLE_WORDS64(*iptr,i0&0x8000000000000000ULL,0);
+		return x;
+	    } else {
+		i = (0x0000ffffffffffffLL)>>jj0;
+		if(((i0&i)|i1)==0) {		/* x is integral */
+		    *iptr = x;
+		    /* return +-0 */
+		    SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+		    return x;
+		} else {
+		    SET_LDOUBLE_WORDS64(*iptr,i0&(~i),0);
+		    return x - *iptr;
+		}
+	    }
+	} else if (jj0>111) {		/* no fraction part */
+	    *iptr = x*one;
+	    /* We must handle NaNs separately.  */
+	    if (jj0 == 0x4000 && ((i0 & 0x0000ffffffffffffLL) | i1))
+	      return x*one;
+	    /* return +-0 */
+	    SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+	    return x;
+	} else {			/* fraction part in low x */
+	    i = -1ULL>>(jj0-48);
+	    if((i1&i)==0) {		/* x is integral */
+		*iptr = x;
+		/* return +-0 */
+		SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+		return x;
+	    } else {
+		SET_LDOUBLE_WORDS64(*iptr,i0,i1&(~i));
+		return x - *iptr;
+	    }
+	}
+}

+ 72 - 0
ld128/s_nextafterl.c

@@ -0,0 +1,72 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *	nextafterl(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+long double
+nextafterl(long double x, long double y)
+{
+	int64_t hx,hy,ix,iy;
+	u_int64_t lx,ly;
+
+	GET_LDOUBLE_WORDS64(hx,lx,x);
+	GET_LDOUBLE_WORDS64(hy,ly,y);
+	ix = hx&0x7fffffffffffffffLL;		/* |x| */
+	iy = hy&0x7fffffffffffffffLL;		/* |y| */
+
+	if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) ||   /* x is nan */
+	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))     /* y is nan */
+	   return x+y;
+	if(x==y) return y;		/* x=y, return y */
+	if((ix|lx)==0) {			/* x == 0 */
+	    volatile long double u;
+	    SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(hx>=0) {			/* x > 0 */
+	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
+		if(lx==0) hx--;
+		lx--;
+	    } else {				/* x < y, x += ulp */
+		lx++;
+		if(lx==0) hx++;
+	    }
+	} else {				/* x < 0 */
+	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+		if(lx==0) hx--;
+		lx--;
+	    } else {				/* x > y, x += ulp */
+		lx++;
+		if(lx==0) hx++;
+	    }
+	}
+	hy = hx&0x7fff000000000000LL;
+	if(hy==0x7fff000000000000LL) return x+x;/* overflow  */
+	if(hy==0) {
+	    volatile long double u = x*x;	/* underflow */
+	}
+	SET_LDOUBLE_WORDS64(x,hx,lx);
+	return x;
+}
+
+__strong_alias(nexttowardl, nextafterl);

+ 85 - 0
ld128/s_nexttoward.c

@@ -0,0 +1,85 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *	nexttoward(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <math.h>
+#include <float.h>
+
+#include "math_private.h"
+
+double
+nexttoward(double x, long double y)
+{
+	int32_t hx,ix;
+	int64_t hy,iy;
+	u_int32_t lx;
+	u_int64_t ly;
+
+	EXTRACT_WORDS(hx,lx,x);
+	GET_LDOUBLE_WORDS64(hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = hy&0x7fffffffffffffffLL;	/* |y| */
+
+	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
+	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
+							    /* y is nan */
+	   return x+y;
+	if((long double) x==y) return y;	/* x=y, return y */
+	if((ix|lx)==0) {			/* x == 0 */
+	    volatile double u;
+	    INSERT_WORDS(x,(u_int32_t)((hy>>32)&0x80000000),1);/* return +-minsub */
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if (hy<0||(ix>>20)>(iy>>48)-0x3c00
+		|| ((ix>>20)==(iy>>48)-0x3c00
+		    && (((((int64_t)hx)<<28)|(lx>>4))>(hy&0x0000ffffffffffffLL)
+			|| (((((int64_t)hx)<<28)|(lx>>4))==(hy&0x0000ffffffffffffLL)
+			    && (lx&0xf)>(ly>>60))))) {	/* x > y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x < y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if (hy>=0||(ix>>20)>(iy>>48)-0x3c00
+		|| ((ix>>20)==(iy>>48)-0x3c00
+		    && (((((int64_t)hx)<<28)|(lx>>4))>(hy&0x0000ffffffffffffLL)
+			|| (((((int64_t)hx)<<28)|(lx>>4))==(hy&0x0000ffffffffffffLL)
+			    && (lx&0xf)>(ly>>60))))) {	/* x < y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x > y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	}
+	hy = hx&0x7ff00000;
+	if(hy>=0x7ff00000) {
+	  x = x+x;	/* overflow  */
+	  return x;
+	}
+	if(hy<0x00100000) {
+	    volatile double u = x*x;		/* underflow */
+	}
+	INSERT_WORDS(x,hx,lx);
+	return x;
+}

+ 65 - 0
ld128/s_nexttowardf.c

@@ -0,0 +1,65 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+float
+nexttowardf(float x, long double y)
+{
+	int32_t hx,ix;
+	int64_t hy,iy;
+	u_int64_t ly;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_LDOUBLE_WORDS64(hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = hy&0x7fffffffffffffffLL;	/* |y| */
+
+	if((ix>0x7f800000) ||   /* x is nan */
+	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
+				/* y is nan */
+	   return x+y;
+	if((long double) x==y) return y;	/* x=y, return y */
+	if(ix==0) {				/* x == 0 */
+	    volatile float u;
+	    SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if(hy<0||(ix>>23)>(iy>>48)-0x3f80
+	       || ((ix>>23)==(iy>>48)-0x3f80
+		   && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x > y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x < y, x += ulp */
+		hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if(hy>=0||(ix>>23)>(iy>>48)-0x3f80
+	       || ((ix>>23)==(iy>>48)-0x3f80
+		   && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x < y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x > y, x += ulp */
+		hx += 1;
+	    }
+	}
+	hy = hx&0x7f800000;
+	if(hy>=0x7f800000) return x+x;	/* overflow  */
+	if(hy<0x00800000) {
+	    volatile float u = x*x;	/* underflow */
+	}
+	SET_FLOAT_WORD(x,hx);
+	return x;
+}

+ 168 - 0
ld128/s_remquol.c

@@ -0,0 +1,168 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define	BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define	LDBL_NBIT	0
+#define	SET_NBIT(hx)	((hx) | (1ULL << LDBL_MANH_SIZE))
+#define	HFRAC_BITS	(EXT_FRACHBITS + EXT_FRACHMBITS)
+#else
+#define	LDBL_NBIT	0x80000000
+#define	SET_NBIT(hx)	(hx)
+#define	HFRAC_BITS	(EXT_FRACHBITS + EXT_FRACHMBITS - 1)
+#endif
+
+#define	MANL_SHIFT	(EXT_FRACLMBITS + EXT_FRACLBITS - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ *   for an explicit integer bit in front of the fractional bits.
+ */
+long double
+remquol(long double x, long double y, int *quo)
+{
+	int64_t hx,hz,hy,_hx;
+	uint64_t lx,ly,lz;
+	uint64_t sx,sxy;
+	int ix,iy,n,q;
+
+	GET_LDOUBLE_WORDS64(hx,lx,x);
+	GET_LDOUBLE_WORDS64(hy,ly,y);
+	sx = (hx>>48)&0x8000;
+	sxy = sx ^ ((hy>>48)&0x8000);
+	hx &= 0x7fffffffffffffffLL;	/* |x| */
+	hy &= 0x7fffffffffffffffLL;	/* |y| */
+	SET_LDOUBLE_WORDS64(x,hx,lx);
+	SET_LDOUBLE_WORDS64(y,hy,ly);
+
+    /* purge off exception values */
+	if((hy|ly)==0 || /* y=0 */
+	   ((hx>>48) == BIAS + LDBL_MAX_EXP) ||	 /* or x not finite */
+	   ((hy>>48) == BIAS + LDBL_MAX_EXP &&
+	    (((hy&0x0000ffffffffffffLL)&~LDBL_NBIT)|ly)!=0)) /* or y is NaN */
+	    return (x*y)/(x*y);
+	if((hx>>48)<=(hy>>48)) {
+	    if(((hx>>48)<(hy>>48)) ||
+	       ((hx&0x0000ffffffffffffLL)<=(hy&0x0000ffffffffffffLL) &&
+		((hx&0x0000ffffffffffffLL)<(hy&0x0000ffffffffffffLL) ||
+		 lx<ly))) {
+		q = 0;
+		goto fixup;	/* |x|<|y| return x or x-y */
+	    }
+	    if((hx&0x0000ffffffffffffLL)==(hy&0x0000ffffffffffffLL) &&
+		lx==ly) {
+		*quo = 1;
+		return Zero[sx!=0];	/* |x|=|y| return x*0*/
+	    }
+	}
+
+    /* determine ix = ilogb(x) */
+	if((hx>>48) == 0) {	/* subnormal x */
+	    x *= 0x1.0p512;
+	    GET_LDOUBLE_WORDS64(hx,lx,x);
+	    ix = (hx>>48) - (BIAS + 512);
+	} else {
+	    ix = (hx>>48) - BIAS;
+	}
+
+    /* determine iy = ilogb(y) */
+	if((hy>>48) == 0) {	/* subnormal y */
+	    y *= 0x1.0p512;
+	    GET_LDOUBLE_WORDS64(hy,ly,y);
+	    iy = (hy>>48) - (BIAS + 512);
+	} else {
+	    iy = (hy>>48) - BIAS;
+	}
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	_hx = SET_NBIT(hx) & 0x0000ffffffffffffLL;
+	hy = SET_NBIT(hy);
+
+    /* fix point fmod */
+	n = ix - iy;
+	q = 0;
+
+	while(n--) {
+	    hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){_hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+	    else {_hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+	    q <<= 1;
+	}
+	hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {_hx=hz;lx=lz;q++;}
+
+    /* convert back to floating value and restore the sign */
+	if((_hx|lx)==0) {			/* return sign(x)*0 */
+	    *quo = (sxy ? -q : q);
+	    return Zero[sx!=0];
+	}
+	while(_hx<(1ULL<<HFRAC_BITS)) {	/* normalize x */
+	    _hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;
+	    iy -= 1;
+	}
+	hx = (hx&0xffff000000000000LL) | (_hx&0x0000ffffffffffffLL);
+	if (iy < LDBL_MIN_EXP) {
+	    hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS + 512)<<48;
+	    SET_LDOUBLE_WORDS64(x,hx,lx);
+	    x *= 0x1p-512;
+	    GET_LDOUBLE_WORDS64(hx,lx,x);
+	} else {
+	    hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS)<<48;
+	}
+	hx &= 0x7fffffffffffffffLL;
+	SET_LDOUBLE_WORDS64(x,hx,lx);
+fixup:
+	y = fabsl(y);
+	if (y < LDBL_MIN * 2) {
+	    if (x+x>y || (x+x==y && (q & 1))) {
+		q++;
+		x-=y;
+	    }
+	} else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+	    q++;
+	    x-=y;
+	}
+
+	GET_LDOUBLE_MSW64(hx,x);
+	hx ^= sx;
+	SET_LDOUBLE_MSW64(x,hx);
+
+	q &= 0x7fffffff;
+	*quo = (sxy ? -q : q);
+	return x;
+}

+ 104 - 0
ld128/s_tanhl.c

@@ -0,0 +1,104 @@
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* tanhl(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ *                                      x    -x
+ *                                     e  - e
+ *      0. tanhl(x) is defined to be -----------
+ *                                      x    -x
+ *                                     e  + e
+ *      1. reduce x to non-negative by tanhl(-x) = -tanhl(x).
+ *      2.  0      <= x <= 2**-57 : tanhl(x) := x*(one+x)
+ *                                               -t
+ *          2**-57 <  x <=  1     : tanhl(x) := -----; t = expm1l(-2x)
+ *                                              t + 2
+ *                                                    2
+ *          1      <= x <=  40.0  : tanhl(x) := 1-  ----- ; t=expm1l(2x)
+ *                                                  t + 2
+ *          40.0   <  x <= INF    : tanhl(x) := 1.
+ *
+ * Special cases:
+ *      tanhl(NaN) is NaN;
+ *      only tanhl(0)=0 is exact for finite argument.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const long double one = 1.0, two = 2.0, tiny = 1.0e-4900L;
+
+long double
+tanhl(long double x)
+{
+  long double t, z;
+  u_int32_t jx, ix;
+  ieee_quad_shape_type u;
+
+  /* Words of |x|. */
+  u.value = x;
+  jx = u.parts32.mswhi;
+  ix = jx & 0x7fffffff;
+  /* x is INF or NaN */
+  if (ix >= 0x7fff0000)
+    {
+      /* for NaN it's not important which branch: tanhl(NaN) = NaN */
+      if (jx & 0x80000000)
+	return one / x - one;	/* tanhl(-inf)= -1; */
+      else
+	return one / x + one;	/* tanhl(+inf)=+1 */
+    }
+
+  /* |x| < 40 */
+  if (ix < 0x40044000)
+    {
+      if (u.value == 0)
+	return x;		/* x == +- 0 */
+      if (ix < 0x3fc60000)	/* |x| < 2^-57 */
+	return x * (one + tiny); /* tanh(small) = small */
+      u.parts32.mswhi = ix;	/* Absolute value of x.  */
+      if (ix >= 0x3fff0000)
+	{			/* |x| >= 1  */
+	  t = expm1l (two * u.value);
+	  z = one - two / (t + two);
+	}
+      else
+	{
+	  t = expm1l (-two * u.value);
+	  z = -t / (t + two);
+	}
+      /* |x| > 40, return +-1 */
+    }
+  else
+    {
+      z = one - tiny;		/* raised inexact flag */
+    }
+  return (jx & 0x80000000) ? -z : z;
+}

+ 72 - 0
ld128/s_truncl.c

@@ -0,0 +1,72 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define	MANH_SIZE	(EXT_FRACHBITS + EXT_FRACHMBITS + 1)
+#else
+#define	MANH_SIZE	(EXT_FRACHBITS + EXT_FRACHMBITS)
+#endif
+
+static const long double huge = 1.0e300;
+static const float zero[] = { 0.0, -0.0 };
+
+long double
+truncl(long double x)
+{
+	int e;
+	int64_t ix0, ix1;
+
+	GET_LDOUBLE_WORDS64(ix0,ix1,x);
+	e = ((ix0>>48)&0x7fff) - LDBL_MAX_EXP + 1;
+
+	if (e < MANH_SIZE - 1) {
+		if (e < 0) {			/* raise inexact if x != 0 */
+			if (huge + x > 0.0)
+				return (zero[((ix0>>48)&0x8000)!=0]);
+		} else {
+			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+			if (((ix0 & m) | ix1) == 0)
+				return (x);	/* x is integral */
+			if (huge + x > 0.0) {	/* raise inexact flag */
+				ix0 &= ~m;
+				ix1 = 0;
+			}
+		}
+	} else if (e < LDBL_MANT_DIG - 1) {
+		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+		if ((ix1 & m) == 0)
+			return (x);	/* x is integral */
+		if (huge + x > 0.0)		/* raise inexact flag */
+			ix1 &= ~m;
+	}
+	SET_LDOUBLE_WORDS64(x,ix0,ix1);
+	return (x);
+}

+ 8 - 3
ld80/Make.files

@@ -1,6 +1,11 @@
-$(CUR_SRCS) += 	invtrig.c k_cosl.c k_sinl.c\
-		k_tanl.c s_exp2l.c
+$(CUR_SRCS) += 	invtrig.c \
+            e_acoshl.c     e_hypotl.c     e_powl.c       k_tanl.c       s_exp2l.c      s_nanl.c \
+            e_atanhl.c     e_lgammal.c    e_sinhl.c      s_asinhl.c     s_expm1l.c \
+            e_coshl.c      e_log10l.c     e_tgammal.c    s_floorl.c     s_nextafterl.c \
+            e_expl.c       e_log2l.c      k_cosl.c       s_ceill.c      s_log1pl.c     s_tanhl.c \
+            e_fmodl.c      e_logl.c       k_sinl.c       s_erfl.c       s_modfl.c      s_truncl.c
+#           s_remquol.c
 
 ifneq ($(OS), WINNT)
 $(CUR_SRCS) += s_nanl.c
-endif		
+endif

+ 57 - 0
ld80/e_acoshl.c

@@ -0,0 +1,57 @@
+/* @(#)e_acosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* acoshl(x)
+ * Method :
+ *	Based on
+ *		acoshl(x) = logl [ x + sqrtl(x*x-1) ]
+ *	we have
+ *		acoshl(x) := logl(x)+ln2,	if x is large; else
+ *		acoshl(x) := logl(2x-1/(sqrtl(x*x-1)+x)) if x>2; else
+ *		acoshl(x) := log1pl(t+sqrtl(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ *	acoshl(x) is NaN with signal if x<1.
+ *	acoshl(NaN) is NaN without signal.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+one	= 1.0,
+ln2	= 6.931471805599453094287e-01L; /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */
+
+long double
+acoshl(long double x)
+{
+	long double t;
+	u_int32_t se,i0,i1;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	if(se<0x3fff || se & 0x8000) {	/* x < 1 */
+	    return (x-x)/(x-x);
+	} else if(se >=0x401d) {	/* x > 2**30 */
+	    if(se >=0x7fff) {		/* x is inf of NaN */
+		return x+x;
+	    } else
+		return logl(x)+ln2;	/* acoshl(huge)=logl(2x) */
+	} else if(((se-0x3fff)|i0|i1)==0) {
+	    return 0.0;			/* acosh(1) = 0 */
+	} else if (se > 0x4000) {	/* 2**28 > x > 2 */
+	    t=x*x;
+	    return logl(2.0*x-one/(x+sqrtl(t-one)));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    return log1pl(t+sqrtl(2.0*t+t*t));
+	}
+}

+ 60 - 0
ld80/e_atanhl.c

@@ -0,0 +1,60 @@
+/* @(#)e_atanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* atanhl(x)
+ * Method :
+ *    1.Reduced x to positive by atanh(-x) = -atanh(x)
+ *    2.For x>=0.5
+ *                   1              2x                          x
+ *	atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ *                   2             1 - x                      1 - x
+ *
+ * 	For x<0.5
+ *	atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ *	atanhl(x) is NaN if |x| > 1 with signal;
+ *	atanhl(NaN) is that NaN with no signal;
+ *	atanhl(+-1) is +-INF with signal.
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, huge = 1e4900L;
+
+static const long double zero = 0.0;
+
+long double
+atanhl(long double x)
+{
+	long double t;
+	int32_t ix;
+	u_int32_t se,i0,i1;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	ix = se&0x7fff;
+	if ((ix+((((i0&0x7fffffff)|i1)|(-((i0&0x7fffffff)|i1)))>>31))>0x3fff)
+	  /* |x|>1 */
+	    return (x-x)/(x-x);
+	if(ix==0x3fff)
+	    return x/zero;
+	if(ix<0x3fe3&&(huge+x)>zero) return x;	/* x<2**-28 */
+	SET_LDOUBLE_EXP(x,ix);
+	if(ix<0x3ffe) {		/* x < 0.5 */
+	    t = x+x;
+	    t = 0.5*log1pl(t+t*x/(one-x));
+	} else
+	    t = 0.5*log1pl((x+x)/(one-x));
+	if(se<=0x7fff) return t; else return -t;
+}

+ 82 - 0
ld80/e_coshl.c

@@ -0,0 +1,82 @@
+/* @(#)e_cosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* coshl(x)
+ * Method :
+ * mathematically coshl(x) if defined to be (exp(x)+exp(-x))/2
+ *	1. Replace x by |x| (coshl(x) = coshl(-x)).
+ *	2.
+ *		                                        [ exp(x) - 1 ]^2
+ *	    0        <= x <= ln2/2  :  coshl(x) := 1 + -------------------
+ *			       			           2*exp(x)
+ *
+ *		                                   exp(x) +  1/exp(x)
+ *	    ln2/2    <= x <= 22     :  coshl(x) := -------------------
+ *			       			           2
+ *	    22       <= x <= lnovft :  coshl(x) := expl(x)/2
+ *	    lnovft   <= x <= ln2ovft:  coshl(x) := expl(x/2)/2 * expl(x/2)
+ *	    ln2ovft  <  x	    :  coshl(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ *	coshl(x) is |x| if x is +INF, -INF, or NaN.
+ *	only coshl(0)=1 is exact for finite x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const long double one = 1.0, half=0.5, huge = 1.0e4900L;
+
+long double
+coshl(long double x)
+{
+	long double t,w;
+	int32_t ex;
+	u_int32_t mx,lx;
+
+    /* High word of |x|. */
+	GET_LDOUBLE_WORDS(ex,mx,lx,x);
+	ex &= 0x7fff;
+
+    /* x is INF or NaN */
+	if(ex==0x7fff) return x*x;
+
+    /* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expl(|x|)) */
+	if(ex < 0x3ffd || (ex == 0x3ffd && mx < 0xb17217f7u)) {
+	    t = expm1l(fabsl(x));
+	    w = one+t;
+	    if (ex<0x3fbc) return w;	/* cosh(tiny) = 1 */
+	    return one+(t*t)/(w+w);
+	}
+
+    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+	if (ex < 0x4003 || (ex == 0x4003 && mx < 0xb0000000u)) {
+		t = expl(fabsl(x));
+		return half*t+half/t;
+	}
+
+    /* |x| in [22, ln(maxdouble)] return half*exp(|x|) */
+	if (ex < 0x400c || (ex == 0x400c && mx < 0xb1700000u))
+		return half*expl(fabsl(x));
+
+    /* |x| in [log(maxdouble), log(2*maxdouble)) */
+	if (ex == 0x400c && (mx < 0xb174ddc0u
+			     || (mx == 0xb174ddc0u && lx < 0x31aec0ebu)))
+	{
+	    w = expl(half*fabsl(x));
+	    t = half*w;
+	    return t*w;
+	}
+
+    /* |x| >= log(2*maxdouble), cosh(x) overflow */
+	return huge*huge;
+}

+ 131 - 0
ld80/e_expl.c

@@ -0,0 +1,131 @@
+/*	$OpenBSD: e_expl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							expl.c
+ *
+ *	Exponential function, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expl();
+ *
+ * y = expl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ *     x    k  f
+ *    e  = 2  e.
+ *
+ * A Pade' form of degree 2/3 is used to approximate exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      +-10000     50000       1.12e-19    2.81e-20
+ *
+ *
+ * Error amplification in the exponential function can be
+ * a serious matter.  The error propagation involves
+ * exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
+ * which shows that a 1 lsb error in representing X produces
+ * a relative error of X times 1 lsb in the function.
+ * While the routine gives an accurate result for arguments
+ * that are exactly represented by a long double precision
+ * computer number, the result contains amplified roundoff
+ * error for large arguments not exactly represented.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ * exp underflow    x < MINLOG         0.0
+ * exp overflow     x > MAXLOG         MAXNUM
+ *
+ */
+
+/*	Exponential function	*/
+
+#include <math.h>
+
+#include "math_private.h"
+
+static long double P[3] = {
+ 1.2617719307481059087798E-4L,
+ 3.0299440770744196129956E-2L,
+ 9.9999999999999999991025E-1L,
+};
+static long double Q[4] = {
+ 3.0019850513866445504159E-6L,
+ 2.5244834034968410419224E-3L,
+ 2.2726554820815502876593E-1L,
+ 2.0000000000000000000897E0L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+static const long double MINLOGL = -1.13994985314888605586758E4L;
+static const long double LOG2EL = 1.4426950408889634073599E0L;
+
+long double
+expl(long double x)
+{
+long double px, xx;
+int n;
+
+if( isnan(x) )
+	return(x);
+if( x > MAXLOGL)
+	return( INFINITY );
+
+if( x < MINLOGL )
+	return(0.0L);
+
+/* Express e**x = e**g 2**n
+ *   = e**g e**( n loge(2) )
+ *   = e**( g + n loge(2) )
+ */
+px = floorl( LOG2EL * x + 0.5L ); /* floor() truncates toward -infinity. */
+n = px;
+x -= px * C1;
+x -= px * C2;
+
+
+/* rational approximation for exponential
+ * of the fractional part:
+ * e**x =  1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
+ */
+xx = x * x;
+px = x * __polevll( xx, P, 2 );
+x =  px/( __polevll( xx, Q, 3 ) - px );
+x = 1.0L + ldexpl( x, 1 );
+
+x = ldexpl( x, n );
+return(x);
+}

+ 142 - 0
ld80/e_fmodl.c

@@ -0,0 +1,142 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+//#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define	BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define	LDBL_NBIT	0
+#define	SET_NBIT(hx)	((hx) | (1ULL << LDBL_MANH_SIZE))
+#define	HFRAC_BITS	EXT_FRACHBITS
+#else
+#define	LDBL_NBIT	0x80000000
+#define	SET_NBIT(hx)	(hx)
+#define	HFRAC_BITS	(EXT_FRACHBITS - 1)
+#endif
+
+#define	MANL_SHIFT	(EXT_FRACLBITS - 1)
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ *   for an explicit integer bit in front of the fractional bits.
+ */
+long double
+fmodl(long double x, long double y)
+{
+	union {
+		long double e;
+		struct ieee_ext bits;
+	} ux, uy;
+	int64_t hx,hz;	/* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+	uint32_t hy;
+	uint32_t lx,ly,lz;
+	int ix,iy,n,sx;
+
+	ux.e = x;
+	uy.e = y;
+	sx = ux.bits.ext_sign;
+
+    /* purge off exception values */
+	if((uy.bits.ext_exp|uy.bits.ext_frach|uy.bits.ext_fracl)==0 || /* y=0 */
+	   (ux.bits.ext_exp == BIAS + LDBL_MAX_EXP) ||	 /* or x not finite */
+	   (uy.bits.ext_exp == BIAS + LDBL_MAX_EXP &&
+	    ((uy.bits.ext_frach&~LDBL_NBIT)|uy.bits.ext_fracl)!=0)) /* or y is NaN */
+	    return (x*y)/(x*y);
+	if(ux.bits.ext_exp<=uy.bits.ext_exp) {
+	    if((ux.bits.ext_exp<uy.bits.ext_exp) ||
+	       (ux.bits.ext_frach<=uy.bits.ext_frach &&
+		(ux.bits.ext_frach<uy.bits.ext_frach ||
+		 ux.bits.ext_fracl<uy.bits.ext_fracl))) {
+		return x;		/* |x|<|y| return x or x-y */
+	    }
+	    if(ux.bits.ext_frach==uy.bits.ext_frach &&
+		ux.bits.ext_fracl==uy.bits.ext_fracl) {
+		return Zero[sx];	/* |x|=|y| return x*0*/
+	    }
+	}
+
+    /* determine ix = ilogb(x) */
+	if(ux.bits.ext_exp == 0) {	/* subnormal x */
+	    ux.e *= 0x1.0p512;
+	    ix = ux.bits.ext_exp - (BIAS + 512);
+	} else {
+	    ix = ux.bits.ext_exp - BIAS;
+	}
+
+    /* determine iy = ilogb(y) */
+	if(uy.bits.ext_exp == 0) {	/* subnormal y */
+	    uy.e *= 0x1.0p512;
+	    iy = uy.bits.ext_exp - (BIAS + 512);
+	} else {
+	    iy = uy.bits.ext_exp - BIAS;
+	}
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	hx = SET_NBIT(ux.bits.ext_frach);
+	hy = SET_NBIT(uy.bits.ext_frach);
+	lx = ux.bits.ext_fracl;
+	ly = uy.bits.ext_fracl;
+
+    /* fix point fmod */
+	n = ix - iy;
+
+	while(n--) {
+	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+	    else {
+		if ((hz|lz)==0)		/* return sign(x)*0 */
+		    return Zero[sx];
+		hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz;
+	    }
+	}
+	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {hx=hz;lx=lz;}
+
+    /* convert back to floating value and restore the sign */
+	if((hx|lx)==0)			/* return sign(x)*0 */
+	    return Zero[sx];
+	while(hx<(1ULL<<HFRAC_BITS)) {	/* normalize x */
+	    hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+	    iy -= 1;
+	}
+	ux.bits.ext_frach = hx; /* The mantissa is truncated here if needed. */
+	ux.bits.ext_fracl = lx;
+	if (iy < LDBL_MIN_EXP) {
+	    ux.bits.ext_exp = iy + (BIAS + 512);
+	    ux.e *= 0x1p-512;
+	} else {
+	    ux.bits.ext_exp = iy + BIAS;
+	}
+	x = ux.e * one;		/* create necessary signal */
+	return x;		/* exact output */
+}

+ 122 - 0
ld80/e_hypotl.c

@@ -0,0 +1,122 @@
+/* @(#)e_hypot.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* hypotl(x,y)
+ *
+ * Method :
+ *	If (assume round-to-nearest) z=x*x+y*y
+ *	has error less than sqrt(2)/2 ulp, than
+ *	sqrt(z) has error less than 1 ulp (exercise).
+ *
+ *	So, compute sqrt(x*x+y*y) with some care as
+ *	follows to get the error below 1 ulp:
+ *
+ *	Assume x>y>0;
+ *	(if possible, set rounding to round-to-nearest)
+ *	1. if x > 2y  use
+ *		x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ *	where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ *	2. if x <= 2y use
+ *		t1*yy1+((x-y)*(x-y)+(t1*y2+t2*y))
+ *	where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
+ *	yy1= y with lower 32 bits chopped, y2 = y-yy1.
+ *
+ *	NOTE: scaling may be necessary if some argument is too
+ *	      large or too tiny
+ *
+ * Special cases:
+ *	hypot(x,y) is INF if x or y is +INF or -INF; else
+ *	hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * 	hypot(x,y) returns sqrt(x^2+y^2) with error less
+ * 	than 1 ulps (units in the last place)
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+long double
+hypotl(long double x, long double y)
+{
+	long double a,b,t1,t2,yy1,y2,w;
+	u_int32_t j,k,ea,eb;
+
+	GET_LDOUBLE_EXP(ea,x);
+	ea &= 0x7fff;
+	GET_LDOUBLE_EXP(eb,y);
+	eb &= 0x7fff;
+	if(eb > ea) {a=y;b=x;j=ea; ea=eb;eb=j;} else {a=x;b=y;}
+	SET_LDOUBLE_EXP(a,ea);	/* a <- |a| */
+	SET_LDOUBLE_EXP(b,eb);	/* b <- |b| */
+	if((ea-eb)>0x46) {return a+b;} /* x/y > 2**70 */
+	k=0;
+	if(ea > 0x5f3f) {	/* a>2**8000 */
+	   if(ea == 0x7fff) {	/* Inf or NaN */
+	       u_int32_t es,high,low;
+	       w = a+b;			/* for sNaN */
+	       GET_LDOUBLE_WORDS(es,high,low,a);
+	       if(((high&0x7fffffff)|low)==0) w = a;
+	       GET_LDOUBLE_WORDS(es,high,low,b);
+	       if(((eb^0x7fff)|(high&0x7fffffff)|low)==0) w = b;
+	       return w;
+	   }
+	   /* scale a and b by 2**-9600 */
+	   ea -= 0x2580; eb -= 0x2580;	k += 9600;
+	   SET_LDOUBLE_EXP(a,ea);
+	   SET_LDOUBLE_EXP(b,eb);
+	}
+	if(eb < 0x20bf) {	/* b < 2**-8000 */
+	    if(eb == 0) {	/* subnormal b or 0 */
+		u_int32_t es,high,low;
+		GET_LDOUBLE_WORDS(es,high,low,b);
+		if((high|low)==0) return a;
+		SET_LDOUBLE_WORDS(t1, 0x7ffd, 0, 0);	/* t1=2^16382 */
+		b *= t1;
+		a *= t1;
+		k -= 16382;
+	    } else {		/* scale a and b by 2^9600 */
+		ea += 0x2580;	/* a *= 2^9600 */
+		eb += 0x2580;	/* b *= 2^9600 */
+		k -= 9600;
+		SET_LDOUBLE_EXP(a,ea);
+		SET_LDOUBLE_EXP(b,eb);
+	    }
+	}
+    /* medium size a and b */
+	w = a-b;
+	if (w>b) {
+	    u_int32_t high;
+	    GET_LDOUBLE_MSW(high,a);
+	    SET_LDOUBLE_WORDS(t1,ea,high,0);
+	    t2 = a-t1;
+	    w  = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+	} else {
+	    u_int32_t high;
+	    GET_LDOUBLE_MSW(high,b);
+	    a  = a+a;
+	    SET_LDOUBLE_WORDS(yy1,eb,high,0);
+	    y2 = b - yy1;
+	    GET_LDOUBLE_MSW(high,a);
+	    SET_LDOUBLE_WORDS(t1,ea+1,high,0);
+	    t2 = a - t1;
+	    w  = sqrtl(t1*yy1-(w*(-w)-(t1*y2+t2*b)));
+	}
+	if(k!=0) {
+	    u_int32_t es;
+	    t1 = 1.0;
+	    GET_LDOUBLE_EXP(es,t1);
+	    SET_LDOUBLE_EXP(t1,es+k);
+	    return t1*w;
+	} else return w;
+}

+ 425 - 0
ld80/e_lgammal.c

@@ -0,0 +1,425 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* lgammal(x)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ *   1. Argument Reduction for 0 < x <= 8
+ *	Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ *	reduce x to a number in [1.5,2.5] by
+ *		lgamma(1+s) = log(s) + lgamma(s)
+ *	for example,
+ *		lgamma(7.3) = log(6.3) + lgamma(6.3)
+ *			    = log(6.3*5.3) + lgamma(5.3)
+ *			    = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ *   2. Polynomial approximation of lgamma around its
+ *	minimun ymin=1.461632144968362245 to maintain monotonicity.
+ *	On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ *		Let z = x-ymin;
+ *		lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ *   2. Rational approximation in the primary interval [2,3]
+ *	We use the following approximation:
+ *		s = x-2.0;
+ *		lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ *	Our algorithms are based on the following observation
+ *
+ *                             zeta(2)-1    2    zeta(3)-1    3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s  -  --------- * s  + ...
+ *                                 2                 3
+ *
+ *	where Euler = 0.5771... is the Euler constant, which is very
+ *	close to 0.5.
+ *
+ *   3. For x>=8, we have
+ *	lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ *	(better formula:
+ *	   lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ *	Let z = 1/x, then we approximation
+ *		f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ *	by
+ *				    3       5             11
+ *		w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z
+ *
+ *   4. For negative x, since (G is gamma function)
+ *		-x*G(-x)*G(x) = pi/sin(pi*x),
+ *	we have
+ *		G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ *	since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ *	Hence, for x<0, signgam = sign(sin(pi*x)) and
+ *		lgamma(x) = log(|Gamma(x)|)
+ *			  = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ *	Note: one should avoid compute pi*(-x) directly in the
+ *	      computation of sin(pi*(-x)).
+ *
+ *   5. Special Cases
+ *		lgamma(2+s) ~ s*(1-Euler) for tiny s
+ *		lgamma(1)=lgamma(2)=0
+ *		lgamma(x) ~ -log(x) for tiny x
+ *		lgamma(0) = lgamma(inf) = inf
+ *		lgamma(-integer) = +-inf
+ *
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+  half = 0.5L,
+  one = 1.0L,
+  pi = 3.14159265358979323846264L,
+  two63 = 9.223372036854775808e18L,
+
+  /* lgam(1+x) = 0.5 x + x a(x)/b(x)
+     -0.268402099609375 <= x <= 0
+     peak relative error 6.6e-22 */
+  a0 = -6.343246574721079391729402781192128239938E2L,
+  a1 =  1.856560238672465796768677717168371401378E3L,
+  a2 =  2.404733102163746263689288466865843408429E3L,
+  a3 =  8.804188795790383497379532868917517596322E2L,
+  a4 =  1.135361354097447729740103745999661157426E2L,
+  a5 =  3.766956539107615557608581581190400021285E0L,
+
+  b0 =  8.214973713960928795704317259806842490498E3L,
+  b1 =  1.026343508841367384879065363925870888012E4L,
+  b2 =  4.553337477045763320522762343132210919277E3L,
+  b3 =  8.506975785032585797446253359230031874803E2L,
+  b4 =  6.042447899703295436820744186992189445813E1L,
+  /* b5 =  1.000000000000000000000000000000000000000E0 */
+
+
+  tc =  1.4616321449683623412626595423257213284682E0L,
+  tf = -1.2148629053584961146050602565082954242826E-1,/* double precision */
+/* tt = (tail of tf), i.e. tf + tt has extended precision. */
+  tt = 3.3649914684731379602768989080467587736363E-18L,
+  /* lgam ( 1.4616321449683623412626595423257213284682E0 ) =
+-1.2148629053584960809551455717769158215135617312999903886372437313313530E-1 */
+
+  /* lgam (x + tc) = tf + tt + x g(x)/h(x)
+     - 0.230003726999612341262659542325721328468 <= x
+     <= 0.2699962730003876587373404576742786715318
+     peak relative error 2.1e-21 */
+  g0 = 3.645529916721223331888305293534095553827E-18L,
+  g1 = 5.126654642791082497002594216163574795690E3L,
+  g2 = 8.828603575854624811911631336122070070327E3L,
+  g3 = 5.464186426932117031234820886525701595203E3L,
+  g4 = 1.455427403530884193180776558102868592293E3L,
+  g5 = 1.541735456969245924860307497029155838446E2L,
+  g6 = 4.335498275274822298341872707453445815118E0L,
+
+  h0 = 1.059584930106085509696730443974495979641E4L,
+  h1 =  2.147921653490043010629481226937850618860E4L,
+  h2 = 1.643014770044524804175197151958100656728E4L,
+  h3 =  5.869021995186925517228323497501767586078E3L,
+  h4 =  9.764244777714344488787381271643502742293E2L,
+  h5 =  6.442485441570592541741092969581997002349E1L,
+  /* h6 = 1.000000000000000000000000000000000000000E0 */
+
+
+  /* lgam (x+1) = -0.5 x + x u(x)/v(x)
+     -0.100006103515625 <= x <= 0.231639862060546875
+     peak relative error 1.3e-21 */
+  u0 = -8.886217500092090678492242071879342025627E1L,
+  u1 =  6.840109978129177639438792958320783599310E2L,
+  u2 =  2.042626104514127267855588786511809932433E3L,
+  u3 =  1.911723903442667422201651063009856064275E3L,
+  u4 =  7.447065275665887457628865263491667767695E2L,
+  u5 =  1.132256494121790736268471016493103952637E2L,
+  u6 =  4.484398885516614191003094714505960972894E0L,
+
+  v0 =  1.150830924194461522996462401210374632929E3L,
+  v1 =  3.399692260848747447377972081399737098610E3L,
+  v2 =  3.786631705644460255229513563657226008015E3L,
+  v3 =  1.966450123004478374557778781564114347876E3L,
+  v4 =  4.741359068914069299837355438370682773122E2L,
+  v5 =  4.508989649747184050907206782117647852364E1L,
+  /* v6 =  1.000000000000000000000000000000000000000E0 */
+
+
+  /* lgam (x+2) = .5 x + x s(x)/r(x)
+     0 <= x <= 1
+     peak relative error 7.2e-22 */
+  s0 =  1.454726263410661942989109455292824853344E6L,
+  s1 = -3.901428390086348447890408306153378922752E6L,
+  s2 = -6.573568698209374121847873064292963089438E6L,
+  s3 = -3.319055881485044417245964508099095984643E6L,
+  s4 = -7.094891568758439227560184618114707107977E5L,
+  s5 = -6.263426646464505837422314539808112478303E4L,
+  s6 = -1.684926520999477529949915657519454051529E3L,
+
+  r0 = -1.883978160734303518163008696712983134698E7L,
+  r1 = -2.815206082812062064902202753264922306830E7L,
+  r2 = -1.600245495251915899081846093343626358398E7L,
+  r3 = -4.310526301881305003489257052083370058799E6L,
+  r4 = -5.563807682263923279438235987186184968542E5L,
+  r5 = -3.027734654434169996032905158145259713083E4L,
+  r6 = -4.501995652861105629217250715790764371267E2L,
+  /* r6 =  1.000000000000000000000000000000000000000E0 */
+
+
+/* lgam(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x w(1/x^2)
+   x >= 8
+   Peak relative error 1.51e-21
+   w0 = LS2PI - 0.5 */
+  w0 =  4.189385332046727417803e-1L,
+  w1 =  8.333333333333331447505E-2L,
+  w2 = -2.777777777750349603440E-3L,
+  w3 =  7.936507795855070755671E-4L,
+  w4 = -5.952345851765688514613E-4L,
+  w5 =  8.412723297322498080632E-4L,
+  w6 = -1.880801938119376907179E-3L,
+  w7 =  4.885026142432270781165E-3L;
+
+static const long double zero = 0.0L;
+
+static long double
+sin_pi(long double x)
+{
+  long double y, z;
+  int n, ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  ix = (ix << 16) | (i0 >> 16);
+  if (ix < 0x3ffd8000) /* 0.25 */
+    return sinl (pi * x);
+  y = -x;			/* x is assume negative */
+
+  /*
+   * argument reduction, make sure inexact flag not raised if input
+   * is an integer
+   */
+  z = floorl (y);
+  if (z != y)
+    {				/* inexact anyway */
+      y  *= 0.5;
+      y = 2.0*(y - floorl(y));		/* y = |x| mod 2.0 */
+      n = (int) (y*4.0);
+    }
+  else
+    {
+      if (ix >= 0x403f8000)  /* 2^64 */
+	{
+	  y = zero; n = 0;		/* y must be even */
+	}
+      else
+	{
+	if (ix < 0x403e8000)  /* 2^63 */
+	  z = y + two63;	/* exact */
+	GET_LDOUBLE_WORDS (se, i0, i1, z);
+	n = i1 & 1;
+	y  = n;
+	n <<= 2;
+      }
+    }
+
+  switch (n)
+    {
+    case 0:
+      y = sinl (pi * y);
+      break;
+    case 1:
+    case 2:
+      y = cosl (pi * (half - y));
+      break;
+    case 3:
+    case 4:
+      y = sinl (pi * (one - y));
+      break;
+    case 5:
+    case 6:
+      y = -cosl (pi * (y - 1.5));
+      break;
+    default:
+      y = sinl (pi * (y - 2.0));
+      break;
+    }
+  return -y;
+}
+
+
+long double
+lgammal(long double x)
+{
+  long double t, y, z, nadj, p, p1, p2, q, r, w;
+  int i, ix;
+  u_int32_t se, i0, i1;
+
+  signgam = 1;
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+
+  if ((ix | i0 | i1) == 0)
+    {
+      if (se & 0x8000)
+	signgam = -1;
+      return one / fabsl (x);
+    }
+
+  ix = (ix << 16) | (i0 >> 16);
+
+  /* purge off +-inf, NaN, +-0, and negative arguments */
+  if (ix >= 0x7fff0000)
+    return x * x;
+
+  if (ix < 0x3fc08000) /* 2^-63 */
+    {				/* |x|<2**-63, return -log(|x|) */
+      if (se & 0x8000)
+	{
+	  signgam = -1;
+	  return -logl (-x);
+	}
+      else
+	return -logl (x);
+    }
+  if (se & 0x8000)
+    {
+      t = sin_pi (x);
+      if (t == zero)
+	return one / fabsl (t);	/* -integer */
+      nadj = logl (pi / fabsl (t * x));
+      if (t < zero)
+	signgam = -1;
+      x = -x;
+    }
+
+  /* purge off 1 and 2 */
+  if ((((ix - 0x3fff8000) | i0 | i1) == 0)
+      || (((ix - 0x40008000) | i0 | i1) == 0))
+    r = 0;
+  else if (ix < 0x40008000) /* 2.0 */
+    {
+      /* x < 2.0 */
+      if (ix <= 0x3ffee666) /* 8.99993896484375e-1 */
+	{
+	  /* lgamma(x) = lgamma(x+1) - log(x) */
+	  r = -logl (x);
+	  if (ix >= 0x3ffebb4a) /* 7.31597900390625e-1 */
+	    {
+	      y = x - one;
+	      i = 0;
+	    }
+	  else if (ix >= 0x3ffced33)/* 2.31639862060546875e-1 */
+	    {
+	      y = x - (tc - one);
+	      i = 1;
+	    }
+	  else
+	    {
+	      /* x < 0.23 */
+	      y = x;
+	      i = 2;
+	    }
+	}
+      else
+	{
+	  r = zero;
+	  if (ix >= 0x3fffdda6) /* 1.73162841796875 */
+	    {
+	      /* [1.7316,2] */
+	      y = x - 2.0;
+	      i = 0;
+	    }
+	  else if (ix >= 0x3fff9da6)/* 1.23162841796875 */
+	    {
+	      /* [1.23,1.73] */
+	      y = x - tc;
+	      i = 1;
+	    }
+	  else
+	    {
+	      /* [0.9, 1.23] */
+	      y = x - one;
+	      i = 2;
+	    }
+	}
+      switch (i)
+	{
+	case 0:
+	  p1 = a0 + y * (a1 + y * (a2 + y * (a3 + y * (a4 + y * a5))));
+	  p2 = b0 + y * (b1 + y * (b2 + y * (b3 + y * (b4 + y))));
+	  r += half * y + y * p1/p2;
+	  break;
+	case 1:
+    p1 = g0 + y * (g1 + y * (g2 + y * (g3 + y * (g4 + y * (g5 + y * g6)))));
+    p2 = h0 + y * (h1 + y * (h2 + y * (h3 + y * (h4 + y * (h5 + y)))));
+    p = tt + y * p1/p2;
+	  r += (tf + p);
+	  break;
+	case 2:
+ p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * (u5 + y * u6))))));
+      p2 = v0 + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * (v5 + y)))));
+	  r += (-half * y + p1 / p2);
+	}
+    }
+  else if (ix < 0x40028000) /* 8.0 */
+    {
+      /* x < 8.0 */
+      i = (int) x;
+      t = zero;
+      y = x - (double) i;
+  p = y *
+     (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
+  q = r0 + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * (r6 + y))))));
+      r = half * y + p / q;
+      z = one;			/* lgamma(1+s) = log(s) + lgamma(s) */
+      switch (i)
+	{
+	case 7:
+	  z *= (y + 6.0);	/* FALLTHRU */
+	case 6:
+	  z *= (y + 5.0);	/* FALLTHRU */
+	case 5:
+	  z *= (y + 4.0);	/* FALLTHRU */
+	case 4:
+	  z *= (y + 3.0);	/* FALLTHRU */
+	case 3:
+	  z *= (y + 2.0);	/* FALLTHRU */
+	  r += logl (z);
+	  break;
+	}
+    }
+  else if (ix < 0x40418000) /* 2^66 */
+    {
+      /* 8.0 <= x < 2**66 */
+      t = logl (x);
+      z = one / x;
+      y = z * z;
+      w = w0 + z * (w1
+	  + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * (w6 + y * w7))))));
+      r = (x - half) * (t - one) + w;
+    }
+  else
+    /* 2**66 <= x <= inf */
+    r = x * (logl (x) - one);
+  if (se & 0x8000)
+    r = nadj - r;
+  return r;
+}

+ 205 - 0
ld80/e_log10l.c

@@ -0,0 +1,205 @@
+/*	$OpenBSD: e_log10l.c,v 1.2 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							log10l.c
+ *
+ *	Common logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log10l();
+ *
+ * y = log10l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 10 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0.5, 2.0     30000      9.0e-20     2.6e-20
+ *    IEEE     exp(+-10000)  30000      6.0e-20     2.3e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity:  x = 0; returns MINLOG
+ * log domain:       x < 0; returns MINLOG
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.2e-22
+ */
+static long double P[] = {
+ 4.9962495940332550844739E-1L,
+ 1.0767376367209449010438E1L,
+ 7.7671073698359539859595E1L,
+ 2.5620629828144409632571E2L,
+ 4.2401812743503691187826E2L,
+ 3.4258224542413922935104E2L,
+ 1.0747524399916215149070E2L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 2.3479774160285863271658E1L,
+ 1.9444210022760132894510E2L,
+ 7.7952888181207260646090E2L,
+ 1.6911722418503949084863E3L,
+ 2.0307734695595183428202E3L,
+ 1.2695660352705325274404E3L,
+ 3.2242573199748645407652E2L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+/* log10(2) */
+#define L102A 0.3125L
+#define L102B -1.1470004336018804786261e-2L
+/* log10(e) */
+#define L10EA 0.5L
+#define L10EB -6.5705518096748172348871e-2L
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log10l(long double x)
+{
+long double y;
+volatile long double z;
+int e;
+
+if( isnan(x) )
+	return(x);
+/* Test for domain */
+if( x <= 0.0L )
+	{
+	if( x == 0.0L )
+		return (-1.0L / (x - x));
+	else
+		return (x - x) / (x - x);
+	}
+if( x == INFINITY )
+	return(INFINITY);
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+	{ /* 2( 2x-1 )/( 2x+1 ) */
+	e -= 1;
+	z = x - 0.5L;
+	y = 0.5L * z + 0.5L;
+	}	
+else
+	{ /*  2 (x-1)/(x+1)   */
+	z = x - 0.5L;
+	z -= 0.5L;
+	y = 0.5L * x  + 0.5L;
+	}
+x = z / y;
+z = x*x;
+y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+goto done;
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+	{
+	e -= 1;
+	x = ldexpl( x, 1 ) - 1.0L; /*  2x - 1  */
+	}	
+else
+	{
+	x = x - 1.0L;
+	}
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) );
+y = y - ldexpl( z, -1 );   /* -0.5x^2 + ... */
+
+done:
+
+/* Multiply log of fraction by log10(e)
+ * and base 2 exponent by log10(2).
+ *
+ * ***CAUTION***
+ *
+ * This sequence of operations is critical and it may
+ * be horribly defeated by some compiler optimizers.
+ */
+z = y * (L10EB);
+z += x * (L10EB);
+z += e * (L102B);
+z += y * (L10EA);
+z += x * (L10EA);
+z += e * (L102A);
+
+return( z );
+}

+ 199 - 0
ld80/e_log2l.c

@@ -0,0 +1,199 @@
+/*	$OpenBSD: e_log2l.c,v 1.2 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							log2l.c
+ *
+ *	Base 2 logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log2l();
+ *
+ * y = log2l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 2 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the (natural)
+ * logarithm of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0.5, 2.0     30000      9.8e-20     2.7e-20
+ *    IEEE     exp(+-10000)  70000      5.4e-20     2.3e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity:  x = 0; returns -INFINITY
+ * log domain:       x < 0; returns NAN
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.2e-22
+ */
+static long double P[] = {
+ 4.9962495940332550844739E-1L,
+ 1.0767376367209449010438E1L,
+ 7.7671073698359539859595E1L,
+ 2.5620629828144409632571E2L,
+ 4.2401812743503691187826E2L,
+ 3.4258224542413922935104E2L,
+ 1.0747524399916215149070E2L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 2.3479774160285863271658E1L,
+ 1.9444210022760132894510E2L,
+ 7.7952888181207260646090E2L,
+ 1.6911722418503949084863E3L,
+ 2.0307734695595183428202E3L,
+ 1.2695660352705325274404E3L,
+ 3.2242573199748645407652E2L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+/* log2(e) - 1 */
+#define LOG2EA 4.4269504088896340735992e-1L
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log2l(long double x)
+{
+volatile long double z;
+long double y;
+int e;
+
+if( isnan(x) )
+	return(x);
+if( x == INFINITY )
+	return(x);
+/* Test for domain */
+if( x <= 0.0L )
+	{
+	if( x == 0.0L )
+		return( -INFINITY );
+	else
+		return( NAN );
+	}
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+	{ /* 2( 2x-1 )/( 2x+1 ) */
+	e -= 1;
+	z = x - 0.5L;
+	y = 0.5L * z + 0.5L;
+	}	
+else
+	{ /*  2 (x-1)/(x+1)   */
+	z = x - 0.5L;
+	z -= 0.5L;
+	y = 0.5L * x  + 0.5L;
+	}
+x = z / y;
+z = x*x;
+y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+goto done;
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+	{
+	e -= 1;
+	x = ldexpl( x, 1 ) - 1.0L; /*  2x - 1  */
+	}	
+else
+	{
+	x = x - 1.0L;
+	}
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) );
+y = y - ldexpl( z, -1 );   /* -0.5x^2 + ... */
+
+done:
+
+/* Multiply log of fraction by log2(e)
+ * and base 2 exponent by 1
+ *
+ * ***CAUTION***
+ *
+ * This sequence of operations is critical and it may
+ * be horribly defeated by some compiler optimizers.
+ */
+z = y * LOG2EA;
+z += x * LOG2EA;
+z += y;
+z += x;
+z += e;
+return( z );
+}

+ 190 - 0
ld80/e_logl.c

@@ -0,0 +1,190 @@
+/*	$OpenBSD: e_logl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							logl.c
+ *
+ *	Natural logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, logl();
+ *
+ * y = logl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0.5, 2.0    150000      8.71e-20    2.75e-20
+ *    IEEE     exp(+-10000) 100000      5.39e-20    2.34e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity:  x = 0; returns -INFINITY
+ * log domain:       x < 0; returns NAN
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 2.32e-20
+ */
+static long double P[] = {
+ 4.5270000862445199635215E-5L,
+ 4.9854102823193375972212E-1L,
+ 6.5787325942061044846969E0L,
+ 2.9911919328553073277375E1L,
+ 6.0949667980987787057556E1L,
+ 5.7112963590585538103336E1L,
+ 2.0039553499201281259648E1L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 1.5062909083469192043167E1L,
+ 8.3047565967967209469434E1L,
+ 2.2176239823732856465394E2L,
+ 3.0909872225312059774938E2L,
+ 2.1642788614495947685003E2L,
+ 6.0118660497603843919306E1L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+logl(long double x)
+{
+long double y, z;
+int e;
+
+if( isnan(x) )
+	return(x);
+if( x == INFINITY )
+	return(x);
+/* Test for domain */
+if( x <= 0.0L )
+	{
+	if( x == 0.0L )
+		return( -INFINITY );
+	else
+		return( NAN );
+	}
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+	{ /* 2( 2x-1 )/( 2x+1 ) */
+	e -= 1;
+	z = x - 0.5L;
+	y = 0.5L * z + 0.5L;
+	}	
+else
+	{ /*  2 (x-1)/(x+1)   */
+	z = x - 0.5L;
+	z -= 0.5L;
+	y = 0.5L * x  + 0.5L;
+	}
+x = z / y;
+z = x*x;
+z = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+z = z + e * C2;
+z = z + x;
+z = z + e * C1;
+return( z );
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+	{
+	e -= 1;
+	x = ldexpl( x, 1 ) - 1.0L; /*  2x - 1  */
+	}	
+else
+	{
+	x = x - 1.0L;
+	}
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 6 ) );
+y = y + e * C2;
+z = y - ldexpl( z, -1 );   /*  y - 0.5 * z  */
+/* Note, the sum of above terms does not exceed x/4,
+ * so it contributes at most about 1/4 lsb to the error.
+ */
+z = z + x;
+z = z + e * C1; /* This sum has an error of 1/2 lsb. */
+return( z );
+}

+ 615 - 0
ld80/e_powl.c

@@ -0,0 +1,615 @@
+/*	$OpenBSD: e_powl.c,v 1.5 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							powl.c
+ *
+ *	Power function, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, z, powl();
+ *
+ * z = powl( x, y );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Computes x raised to the yth power.  Analytically,
+ *
+ *      x**y  =  exp( y log(x) ).
+ *
+ * Following Cody and Waite, this program uses a lookup table
+ * of 2**-i/32 and pseudo extended precision arithmetic to
+ * obtain several extra bits of accuracy in both the logarithm
+ * and the exponential.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * The relative error of pow(x,y) can be estimated
+ * by   y dl ln(2),   where dl is the absolute error of
+ * the internally computed base 2 logarithm.  At the ends
+ * of the approximation interval the logarithm equal 1/32
+ * and its relative error is about 1 lsb = 1.1e-19.  Hence
+ * the predicted relative error in the result is 2.3e-21 y .
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *
+ *    IEEE     +-1000       40000      2.8e-18      3.7e-19
+ * .001 < x < 1000, with log(x) uniformly distributed.
+ * -1000 < y < 1000, y uniformly distributed.
+ *
+ *    IEEE     0,8700       60000      6.5e-18      1.0e-18
+ * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ * pow overflow     x**y > MAXNUM      INFINITY
+ * pow underflow   x**y < 1/MAXNUM       0.0
+ * pow domain      x<0 and y noninteger  0.0
+ *
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "math_private.h"
+
+/* Table size */
+#define NXT 32
+/* log2(Table size) */
+#define LNXT 5
+
+/* log(1+x) =  x - .5x^2 + x^3 *  P(z)/Q(z)
+ * on the domain  2^(-1/32) - 1  <=  x  <=  2^(1/32) - 1
+ */
+static long double P[] = {
+ 8.3319510773868690346226E-4L,
+ 4.9000050881978028599627E-1L,
+ 1.7500123722550302671919E0L,
+ 1.4000100839971580279335E0L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0L,*/
+ 5.2500282295834889175431E0L,
+ 8.4000598057587009834666E0L,
+ 4.2000302519914740834728E0L,
+};
+/* A[i] = 2^(-i/32), rounded to IEEE long double precision.
+ * If i is even, A[i] + B[i/2] gives additional accuracy.
+ */
+static long double A[33] = {
+ 1.0000000000000000000000E0L,
+ 9.7857206208770013448287E-1L,
+ 9.5760328069857364691013E-1L,
+ 9.3708381705514995065011E-1L,
+ 9.1700404320467123175367E-1L,
+ 8.9735453750155359320742E-1L,
+ 8.7812608018664974155474E-1L,
+ 8.5930964906123895780165E-1L,
+ 8.4089641525371454301892E-1L,
+ 8.2287773907698242225554E-1L,
+ 8.0524516597462715409607E-1L,
+ 7.8799042255394324325455E-1L,
+ 7.7110541270397041179298E-1L,
+ 7.5458221379671136985669E-1L,
+ 7.3841307296974965571198E-1L,
+ 7.2259040348852331001267E-1L,
+ 7.0710678118654752438189E-1L,
+ 6.9195494098191597746178E-1L,
+ 6.7712777346844636413344E-1L,
+ 6.6261832157987064729696E-1L,
+ 6.4841977732550483296079E-1L,
+ 6.3452547859586661129850E-1L,
+ 6.2092890603674202431705E-1L,
+ 6.0762367999023443907803E-1L,
+ 5.9460355750136053334378E-1L,
+ 5.8186242938878875689693E-1L,
+ 5.6939431737834582684856E-1L,
+ 5.5719337129794626814472E-1L,
+ 5.4525386633262882960438E-1L,
+ 5.3357020033841180906486E-1L,
+ 5.2213689121370692017331E-1L,
+ 5.1094857432705833910408E-1L,
+ 5.0000000000000000000000E-1L,
+};
+static long double B[17] = {
+ 0.0000000000000000000000E0L,
+ 2.6176170809902549338711E-20L,
+-1.0126791927256478897086E-20L,
+ 1.3438228172316276937655E-21L,
+ 1.2207982955417546912101E-20L,
+-6.3084814358060867200133E-21L,
+ 1.3164426894366316434230E-20L,
+-1.8527916071632873716786E-20L,
+ 1.8950325588932570796551E-20L,
+ 1.5564775779538780478155E-20L,
+ 6.0859793637556860974380E-21L,
+-2.0208749253662532228949E-20L,
+ 1.4966292219224761844552E-20L,
+ 3.3540909728056476875639E-21L,
+-8.6987564101742849540743E-22L,
+-1.2327176863327626135542E-20L,
+ 0.0000000000000000000000E0L,
+};
+
+/* 2^x = 1 + x P(x),
+ * on the interval -1/32 <= x <= 0
+ */
+static long double R[] = {
+ 1.5089970579127659901157E-5L,
+ 1.5402715328927013076125E-4L,
+ 1.3333556028915671091390E-3L,
+ 9.6181291046036762031786E-3L,
+ 5.5504108664798463044015E-2L,
+ 2.4022650695910062854352E-1L,
+ 6.9314718055994530931447E-1L,
+};
+
+#define douba(k) A[k]
+#define doubb(k) B[k]
+#define MEXP (NXT*16384.0L)
+/* The following if denormal numbers are supported, else -MEXP: */
+#define MNEXP (-NXT*(16384.0L+64.0L))
+/* log2(e) - 1 */
+#define LOG2EA 0.44269504088896340735992L
+
+#define F W
+#define Fa Wa
+#define Fb Wb
+#define G W
+#define Ga Wa
+#define Gb u
+#define H W
+#define Ha Wb
+#define Hb Wb
+
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+static const long double MINLOGL = -1.13994985314888605586758E4L;
+static const long double LOGE2L = 6.9314718055994530941723E-1L;
+static volatile long double z;
+static long double w, W, Wa, Wb, ya, yb, u;
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+static long double reducl( long double );
+static long double powil ( long double, int );
+
+long double
+powl(long double x, long double y)
+{
+/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */
+int i, nflg, iyflg, yoddint;
+long e;
+
+if( y == 0.0L )
+	return( 1.0L );
+
+if( x == 1.0L )
+	return( 1.0L );
+
+if( isnan(x) )
+	return( x );
+if( isnan(y) )
+	return( y );
+
+if( y == 1.0L )
+	return( x );
+
+if( !isfinite(y) && x == -1.0L )
+	return( 1.0L );
+
+if( y >= LDBL_MAX )
+	{
+	if( x > 1.0L )
+		return( INFINITY );
+	if( x > 0.0L && x < 1.0L )
+		return( 0.0L );
+	if( x < -1.0L )
+		return( INFINITY );
+	if( x > -1.0L && x < 0.0L )
+		return( 0.0L );
+	}
+if( y <= -LDBL_MAX )
+	{
+	if( x > 1.0L )
+		return( 0.0L );
+	if( x > 0.0L && x < 1.0L )
+		return( INFINITY );
+	if( x < -1.0L )
+		return( 0.0L );
+	if( x > -1.0L && x < 0.0L )
+		return( INFINITY );
+	}
+if( x >= LDBL_MAX )
+	{
+	if( y > 0.0L )
+		return( INFINITY );
+	return( 0.0L );
+	}
+
+w = floorl(y);
+/* Set iyflg to 1 if y is an integer.  */
+iyflg = 0;
+if( w == y )
+	iyflg = 1;
+
+/* Test for odd integer y.  */
+yoddint = 0;
+if( iyflg )
+	{
+	ya = fabsl(y);
+	ya = floorl(0.5L * ya);
+	yb = 0.5L * fabsl(w);
+	if( ya != yb )
+		yoddint = 1;
+	}
+
+if( x <= -LDBL_MAX )
+	{
+	if( y > 0.0L )
+		{
+		if( yoddint )
+			return( -INFINITY );
+		return( INFINITY );
+		}
+	if( y < 0.0L )
+		{
+		if( yoddint )
+			return( -0.0L );
+		return( 0.0 );
+		}
+	}
+
+
+nflg = 0;	/* flag = 1 if x<0 raised to integer power */
+if( x <= 0.0L )
+	{
+	if( x == 0.0L )
+		{
+		if( y < 0.0 )
+			{
+			if( signbit(x) && yoddint )
+				return( -INFINITY );
+			return( INFINITY );
+			}
+		if( y > 0.0 )
+			{
+			if( signbit(x) && yoddint )
+				return( -0.0L );
+			return( 0.0 );
+			}
+		if( y == 0.0L )
+			return( 1.0L );  /*   0**0   */
+		else
+			return( 0.0L );  /*   0**y   */
+		}
+	else
+		{
+		if( iyflg == 0 )
+			return (x - x) / (x - x); /* (x<0)**(non-int) is NaN */
+		nflg = 1;
+		}
+	}
+
+/* Integer power of an integer.  */
+
+if( iyflg )
+	{
+	i = w;
+	w = floorl(x);
+	if( (w == x) && (fabsl(y) < 32768.0) )
+		{
+		w = powil( x, (int) y );
+		return( w );
+		}
+	}
+
+
+if( nflg )
+	x = fabsl(x);
+
+/* separate significand from exponent */
+x = frexpl( x, &i );
+e = i;
+
+/* find significand in antilog table A[] */
+i = 1;
+if( x <= douba(17) )
+	i = 17;
+if( x <= douba(i+8) )
+	i += 8;
+if( x <= douba(i+4) )
+	i += 4;
+if( x <= douba(i+2) )
+	i += 2;
+if( x >= douba(1) )
+	i = -1;
+i += 1;
+
+
+/* Find (x - A[i])/A[i]
+ * in order to compute log(x/A[i]):
+ *
+ * log(x) = log( a x/a ) = log(a) + log(x/a)
+ *
+ * log(x/a) = log(1+v),  v = x/a - 1 = (x-a)/a
+ */
+x -= douba(i);
+x -= doubb(i/2);
+x /= douba(i);
+
+
+/* rational approximation for log(1+v):
+ *
+ * log(1+v)  =  v  -  v**2/2  +  v**3 P(v) / Q(v)
+ */
+z = x*x;
+w = x * ( z * __polevll( x, P, 3 ) / __p1evll( x, Q, 3 ) );
+w = w - ldexpl( z, -1 );   /*  w - 0.5 * z  */
+
+/* Convert to base 2 logarithm:
+ * multiply by log2(e) = 1 + LOG2EA
+ */
+z = LOG2EA * w;
+z += w;
+z += LOG2EA * x;
+z += x;
+
+/* Compute exponent term of the base 2 logarithm. */
+w = -i;
+w = ldexpl( w, -LNXT );	/* divide by NXT */
+w += e;
+/* Now base 2 log of x is w + z. */
+
+/* Multiply base 2 log by y, in extended precision. */
+
+/* separate y into large part ya
+ * and small part yb less than 1/NXT
+ */
+ya = reducl(y);
+yb = y - ya;
+
+/* (w+z)(ya+yb)
+ * = w*ya + w*yb + z*y
+ */
+F = z * y  +  w * yb;
+Fa = reducl(F);
+Fb = F - Fa;
+
+G = Fa + w * ya;
+Ga = reducl(G);
+Gb = G - Ga;
+
+H = Fb + Gb;
+Ha = reducl(H);
+w = ldexpl( Ga+Ha, LNXT );
+
+/* Test the power of 2 for overflow */
+if( w > MEXP )
+	return (huge * huge);		/* overflow */
+
+if( w < MNEXP )
+	return (twom10000 * twom10000);	/* underflow */
+
+e = w;
+Hb = H - Ha;
+
+if( Hb > 0.0L )
+	{
+	e += 1;
+	Hb -= (1.0L/NXT);  /*0.0625L;*/
+	}
+
+/* Now the product y * log2(x)  =  Hb + e/NXT.
+ *
+ * Compute base 2 exponential of Hb,
+ * where -0.0625 <= Hb <= 0.
+ */
+z = Hb * __polevll( Hb, R, 6 );  /*    z  =  2**Hb - 1    */
+
+/* Express e/NXT as an integer plus a negative number of (1/NXT)ths.
+ * Find lookup table entry for the fractional power of 2.
+ */
+if( e < 0 )
+	i = 0;
+else
+	i = 1;
+i = e/NXT + i;
+e = NXT*i - e;
+w = douba( e );
+z = w * z;      /*    2**-e * ( 1 + (2**Hb-1) )    */
+z = z + w;
+z = ldexpl( z, i );  /* multiply by integer power of 2 */
+
+if( nflg )
+	{
+/* For negative x,
+ * find out if the integer exponent
+ * is odd or even.
+ */
+	w = ldexpl( y, -1 );
+	w = floorl(w);
+	w = ldexpl( w, 1 );
+	if( w != y )
+		z = -z; /* odd exponent */
+	}
+
+return( z );
+}
+
+
+/* Find a multiple of 1/NXT that is within 1/NXT of x. */
+static long double
+reducl(long double x)
+{
+long double t;
+
+t = ldexpl( x, LNXT );
+t = floorl( t );
+t = ldexpl( t, -LNXT );
+return(t);
+}
+
+/*							powil.c
+ *
+ *	Real raised to integer power, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, powil();
+ * int n;
+ *
+ * y = powil( x, n );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns argument x raised to the nth power.
+ * The routine efficiently decomposes n as a sum of powers of
+ * two. The desired power is a product of two-to-the-kth
+ * powers of x.  Thus to compute the 32767 power of x requires
+ * 28 multiplications instead of 32767 multiplications.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *
+ *                      Relative error:
+ * arithmetic   x domain   n domain  # trials      peak         rms
+ *    IEEE     .001,1000  -1022,1023  50000       4.3e-17     7.8e-18
+ *    IEEE        1,2     -1022,1023  20000       3.9e-17     7.6e-18
+ *    IEEE     .99,1.01     0,8700    10000       3.6e-16     7.2e-17
+ *
+ * Returns MAXNUM on overflow, zero on underflow.
+ *
+ */
+
+static long double
+powil(long double x, int nn)
+{
+long double ww, y;
+long double s;
+int n, e, sign, asign, lx;
+
+if( x == 0.0L )
+	{
+	if( nn == 0 )
+		return( 1.0L );
+	else if( nn < 0 )
+		return( LDBL_MAX );
+	else
+		return( 0.0L );
+	}
+
+if( nn == 0 )
+	return( 1.0L );
+
+
+if( x < 0.0L )
+	{
+	asign = -1;
+	x = -x;
+	}
+else
+	asign = 0;
+
+
+if( nn < 0 )
+	{
+	sign = -1;
+	n = -nn;
+	}
+else
+	{
+	sign = 1;
+	n = nn;
+	}
+
+/* Overflow detection */
+
+/* Calculate approximate logarithm of answer */
+s = x;
+s = frexpl( s, &lx );
+e = (lx - 1)*n;
+if( (e == 0) || (e > 64) || (e < -64) )
+	{
+	s = (s - 7.0710678118654752e-1L) / (s +  7.0710678118654752e-1L);
+	s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L;
+	}
+else
+	{
+	s = LOGE2L * e;
+	}
+
+if( s > MAXLOGL )
+	return (huge * huge);		/* overflow */
+
+if( s < MINLOGL )
+	return (twom10000 * twom10000);	/* underflow */
+/* Handle tiny denormal answer, but with less accuracy
+ * since roundoff error in 1.0/x will be amplified.
+ * The precise demarcation should be the gradual underflow threshold.
+ */
+if( s < (-MAXLOGL+2.0L) )
+	{
+	x = 1.0L/x;
+	sign = -sign;
+	}
+
+/* First bit of the power */
+if( n & 1 )
+	y = x;
+		
+else
+	{
+	y = 1.0L;
+	asign = 0;
+	}
+
+ww = x;
+n >>= 1;
+while( n )
+	{
+	ww = ww * ww;	/* arg to the 2-to-the-kth power */
+	if( n & 1 )	/* if that bit is set, then include in product */
+		y *= ww;
+	n >>= 1;
+	}
+
+if( asign )
+	y = -y; /* odd power of negative number */
+if( sign < 0 )
+	y = 1.0L/y;
+return(y);
+}

+ 76 - 0
ld80/e_sinhl.c

@@ -0,0 +1,76 @@
+/* @(#)e_sinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* sinhl(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ *	1. Replace x by |x| (sinhl(-x) = -sinhl(x)).
+ *	2.
+ *		                                     E + E/(E+1)
+ *	    0        <= x <= 25     :  sinhl(x) := --------------, E=expm1l(x)
+ *			       			         2
+ *
+ *	    25       <= x <= lnovft :  sinhl(x) := expl(x)/2
+ *	    lnovft   <= x <= ln2ovft:  sinhl(x) := expl(x/2)/2 * expl(x/2)
+ *	    ln2ovft  <  x	    :  sinhl(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ *	sinhl(x) is |x| if x is +INF, -INF, or NaN.
+ *	only sinhl(0)=0 is exact for finite x.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, shuge = 1.0e4931L;
+
+long double
+sinhl(long double x)
+{
+	long double t,w,h;
+	u_int32_t jx,ix,i0,i1;
+
+    /* Words of |x|. */
+	GET_LDOUBLE_WORDS(jx,i0,i1,x);
+	ix = jx&0x7fff;
+
+    /* x is INF or NaN */
+	if(ix==0x7fff) return x+x;
+
+	h = 0.5;
+	if (jx & 0x8000) h = -h;
+    /* |x| in [0,25], return sign(x)*0.5*(E+E/(E+1))) */
+	if (ix < 0x4003 || (ix == 0x4003 && i0 <= 0xc8000000)) { /* |x|<25 */
+	    if (ix<0x3fdf)		 /* |x|<2**-32 */
+		if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+	    t = expm1l(fabsl(x));
+	    if(ix<0x3fff) return h*(2.0*t-t*t/(t+one));
+	    return h*(t+t/(t+one));
+	}
+
+    /* |x| in [25, log(maxdouble)] return 0.5*exp(|x|) */
+	if (ix < 0x400c || (ix == 0x400c && i0 < 0xb17217f7))
+		return h*expl(fabsl(x));
+
+    /* |x| in [log(maxdouble), overflowthreshold] */
+	if (ix<0x400c || (ix == 0x400c && (i0 < 0xb174ddc0
+					   || (i0 == 0xb174ddc0
+					       && i1 <= 0x31aec0ea)))) {
+	    w = expl(0.5*fabsl(x));
+	    t = h*w;
+	    return t*w;
+	}
+
+    /* |x| > overflowthreshold, sinhl(x) overflow */
+	return x*shuge;
+}

+ 319 - 0
ld80/e_tgammal.c

@@ -0,0 +1,319 @@
+/*	$OpenBSD: e_tgammal.c,v 1.4 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							tgammal.c
+ *
+ *	Gamma function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, tgammal();
+ * extern int signgam;
+ *
+ * y = tgammal( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns gamma function of the argument.  The result is
+ * correctly signed, and the sign (+1 or -1) is also
+ * returned in a global (extern) variable named signgam.
+ * This variable is also filled in by the logarithmic gamma
+ * function lgamma().
+ *
+ * Arguments |x| <= 13 are reduced by recurrence and the function
+ * approximated by a rational function of degree 7/8 in the
+ * interval (2,3).  Large arguments are handled by Stirling's
+ * formula. Large negative arguments are made positive using
+ * a reflection formula.
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE     -40,+40      10000       3.6e-19     7.9e-20
+ *    IEEE    -1755,+1755   10000       4.8e-18     6.5e-19
+ *
+ * Accuracy for large arguments is dominated by error in powl().
+ *
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "math_private.h"
+
+/*
+tgamma(x+2)  = tgamma(x+2) P(x)/Q(x)
+0 <= x <= 1
+Relative error
+n=7, d=8
+Peak error =  1.83e-20
+Relative error spread =  8.4e-23
+*/
+
+static long double P[8] = {
+ 4.212760487471622013093E-5L,
+ 4.542931960608009155600E-4L,
+ 4.092666828394035500949E-3L,
+ 2.385363243461108252554E-2L,
+ 1.113062816019361559013E-1L,
+ 3.629515436640239168939E-1L,
+ 8.378004301573126728826E-1L,
+ 1.000000000000000000009E0L,
+};
+static long double Q[9] = {
+-1.397148517476170440917E-5L,
+ 2.346584059160635244282E-4L,
+-1.237799246653152231188E-3L,
+-7.955933682494738320586E-4L,
+ 2.773706565840072979165E-2L,
+-4.633887671244534213831E-2L,
+-2.243510905670329164562E-1L,
+ 4.150160950588455434583E-1L,
+ 9.999999999999999999908E-1L,
+};
+
+/*
+static long double P[] = {
+-3.01525602666895735709e0L,
+-3.25157411956062339893e1L,
+-2.92929976820724030353e2L,
+-1.70730828800510297666e3L,
+-7.96667499622741999770e3L,
+-2.59780216007146401957e4L,
+-5.99650230220855581642e4L,
+-7.15743521530849602425e4L
+};
+static long double Q[] = {
+ 1.00000000000000000000e0L,
+-1.67955233807178858919e1L,
+ 8.85946791747759881659e1L,
+ 5.69440799097468430177e1L,
+-1.98526250512761318471e3L,
+ 3.31667508019495079814e3L,
+ 1.60577839621734713377e4L,
+-2.97045081369399940529e4L,
+-7.15743521530849602412e4L
+};
+*/
+#define MAXGAML 1755.455L
+/*static const long double LOGPI = 1.14472988584940017414L;*/
+
+/* Stirling's formula for the gamma function
+tgamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x))
+z(x) = x
+13 <= x <= 1024
+Relative error
+n=8, d=0
+Peak error =  9.44e-21
+Relative error spread =  8.8e-4
+*/
+
+static long double STIR[9] = {
+ 7.147391378143610789273E-4L,
+-2.363848809501759061727E-5L,
+-5.950237554056330156018E-4L,
+ 6.989332260623193171870E-5L,
+ 7.840334842744753003862E-4L,
+-2.294719747873185405699E-4L,
+-2.681327161876304418288E-3L,
+ 3.472222222230075327854E-3L,
+ 8.333333333333331800504E-2L,
+};
+
+#define MAXSTIR 1024.0L
+static const long double SQTPI = 2.50662827463100050242E0L;
+
+/* 1/tgamma(x) = z P(z)
+ * z(x) = 1/x
+ * 0 < x < 0.03125
+ * Peak relative error 4.2e-23
+ */
+
+static long double S[9] = {
+-1.193945051381510095614E-3L,
+ 7.220599478036909672331E-3L,
+-9.622023360406271645744E-3L,
+-4.219773360705915470089E-2L,
+ 1.665386113720805206758E-1L,
+-4.200263503403344054473E-2L,
+-6.558780715202540684668E-1L,
+ 5.772156649015328608253E-1L,
+ 1.000000000000000000000E0L,
+};
+
+/* 1/tgamma(-x) = z P(z)
+ * z(x) = 1/x
+ * 0 < x < 0.03125
+ * Peak relative error 5.16e-23
+ * Relative error spread =  2.5e-24
+ */
+
+static long double SN[9] = {
+ 1.133374167243894382010E-3L,
+ 7.220837261893170325704E-3L,
+ 9.621911155035976733706E-3L,
+-4.219773343731191721664E-2L,
+-1.665386113944413519335E-1L,
+-4.200263503402112910504E-2L,
+ 6.558780715202536547116E-1L,
+ 5.772156649015328608727E-1L,
+-1.000000000000000000000E0L,
+};
+
+static const long double PIL = 3.1415926535897932384626L;
+
+static long double stirf ( long double );
+
+/* Gamma function computed by Stirling's formula.
+ */
+static long double stirf(long double x)
+{
+long double y, w, v;
+
+w = 1.0L/x;
+/* For large x, use rational coefficients from the analytical expansion.  */
+if( x > 1024.0L )
+	w = (((((6.97281375836585777429E-5L * w
+		+ 7.84039221720066627474E-4L) * w
+		- 2.29472093621399176955E-4L) * w
+		- 2.68132716049382716049E-3L) * w
+		+ 3.47222222222222222222E-3L) * w
+		+ 8.33333333333333333333E-2L) * w
+		+ 1.0L;
+else
+	w = 1.0L + w * __polevll( w, STIR, 8 );
+y = expl(x);
+if( x > MAXSTIR )
+	{ /* Avoid overflow in pow() */
+	v = powl( x, 0.5L * x - 0.25L );
+	y = v * (v / y);
+	}
+else
+	{
+	y = powl( x, x - 0.5L ) / y;
+	}
+y = SQTPI * y * w;
+return( y );
+}
+
+long double
+tgammal(long double x)
+{
+long double p, q, z;
+int i;
+
+signgam = 1;
+if( isnan(x) )
+	return(NAN);
+if(x == INFINITY)
+	return(INFINITY);
+if(x == -INFINITY)
+	return(x - x);
+if( x == 0.0L )
+	return( 1.0L / x );
+q = fabsl(x);
+
+if( q > 13.0L )
+	{
+	if( q > MAXGAML )
+		goto goverf;
+	if( x < 0.0L )
+		{
+		p = floorl(q);
+		if( p == q )
+			return (x - x) / (x - x);
+		i = p;
+		if( (i & 1) == 0 )
+			signgam = -1;
+		z = q - p;
+		if( z > 0.5L )
+			{
+			p += 1.0L;
+			z = q - p;
+			}
+		z = q * sinl( PIL * z );
+		z = fabsl(z) * stirf(q);
+		if( z <= PIL/LDBL_MAX )
+			{
+goverf:
+			return( signgam * INFINITY);
+			}
+		z = PIL/z;
+		}
+	else
+		{
+		z = stirf(x);
+		}
+	return( signgam * z );
+	}
+
+z = 1.0L;
+while( x >= 3.0L )
+	{
+	x -= 1.0L;
+	z *= x;
+	}
+
+while( x < -0.03125L )
+	{
+	z /= x;
+	x += 1.0L;
+	}
+
+if( x <= 0.03125L )
+	goto small;
+
+while( x < 2.0L )
+	{
+	z /= x;
+	x += 1.0L;
+	}
+
+if( x == 2.0L )
+	return(z);
+
+x -= 2.0L;
+p = __polevll( x, P, 7 );
+q = __polevll( x, Q, 8 );
+z = z * p / q;
+if( z < 0 )
+	signgam = -1;
+return z;
+
+small:
+if( x == 0.0L )
+	return (x - x) / (x - x);
+else
+	{
+	if( x < 0.0L )
+		{
+		x = -x;
+		q = z / (x * __polevll( x, SN, 8 ));
+		signgam = -1;
+		}
+	else
+		q = z / (x * __polevll( x, S, 8 ));
+	}
+return q;
+}

+ 54 - 0
ld80/s_asinhl.c

@@ -0,0 +1,54 @@
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* asinhl(x)
+ * Method :
+ *	Based on
+ *		asinhl(x) = signl(x) * logl [ |x| + sqrtl(x*x+1) ]
+ *	we have
+ *	asinhl(x) := x  if  1+x*x=1,
+ *		  := signl(x)*(logl(x)+ln2)) for large |x|, else
+ *		  := signl(x)*logl(2|x|+1/(|x|+sqrtl(x*x+1))) if|x|>2, else
+ *		  := signl(x)*log1pl(|x| + x^2/(1 + sqrtl(1+x^2)))
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+one =  1.000000000000000000000e+00L, /* 0x3FFF, 0x00000000, 0x00000000 */
+ln2 =  6.931471805599453094287e-01L, /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */
+huge=  1.000000000000000000e+4900L;
+
+long double
+asinhl(long double x)
+{
+	long double t,w;
+	int32_t hx,ix;
+	GET_LDOUBLE_EXP(hx,x);
+	ix = hx&0x7fff;
+	if(ix==0x7fff) return x+x;	/* x is inf or NaN */
+	if(ix< 0x3fde) {	/* |x|<2**-34 */
+	    if(huge+x>one) return x;	/* return x inexact except 0 */
+	}
+	if(ix>0x4020) {		/* |x| > 2**34 */
+	    w = logl(fabsl(x))+ln2;
+	} else if (ix>0x4000) {	/* 2**34 > |x| > 2.0 */
+	    t = fabsl(x);
+	    w = logl(2.0*t+one/(sqrtl(x*x+one)+t));
+	} else {		/* 2.0 > |x| > 2**-28 */
+	    t = x*x;
+	    w =log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
+	}
+	if(hx&0x8000) return -w; else return w;
+}

+ 78 - 0
ld80/s_ceill.c

@@ -0,0 +1,78 @@
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+ceill(long double x)
+{
+	int32_t i1,jj0;
+	u_int32_t i,j,se,i0,sx;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	sx = (se>>15)&1;
+	jj0 = (se&0x7fff)-0x3fff;
+	if(jj0<31) {
+	    if(jj0<0) {	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(sx) {se=0x8000;i0=0;i1=0;}
+		    else if((i0|i1)!=0) { se=0x3fff;i0=0;i1=0;}
+		}
+	    } else {
+		i = (0x7fffffff)>>jj0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(sx==0) {
+			if (jj0>0 && (i0+(0x80000000>>jj0))>i0)
+			  i0+=0x80000000>>jj0;
+			else
+			  {
+			    i = 0x7fffffff;
+			    ++se;
+			  }
+		    }
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (jj0>62) {
+	    if(jj0==0x4000) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(jj0-31);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) {		/* raise inexact flag */
+		if(sx==0) {
+		    if(jj0==31) i0+=1;
+		    else {
+			j = i1 + (1<<(63-jj0));
+			if(j<i1) i0+=1;	/* got a carry */
+			i1 = j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	SET_LDOUBLE_WORDS(x,se,i0,i1);
+	return x;
+}

+ 430 - 0
ld80/s_erfl.c

@@ -0,0 +1,430 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ *			     x
+ *		      2      |\
+ *     erf(x)  =  ---------  | exp(-t*t)dt
+ *		   sqrt(pi) \|
+ *			     0
+ *
+ *     erfc(x) =  1-erf(x)
+ *  Note that
+ *		erf(-x) = -erf(x)
+ *		erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ *	1. For |x| in [0, 0.84375]
+ *	    erf(x)  = x + x*R(x^2)
+ *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+ *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+ *	   Remark. The formula is derived by noting
+ *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ *	   and that
+ *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ *	   is close to one. The interval is chosen because the fix
+ *	   point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ *	   near 0.6174), and by some experiment, 0.84375 is chosen to
+ *	   guarantee the error is less than one ulp for erf.
+ *
+ *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ *         c = 0.84506291151 rounded to single (24 bits)
+ *	erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+ *	erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+ *			  1+(c+P1(s)/Q1(s))    if x < 0
+ *	   Remark: here we use the taylor series expansion at x=1.
+ *		erf(1+s) = erf(1) + s*Poly(s)
+ *			 = 0.845.. + P1(s)/Q1(s)
+ *	   Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *
+ *      3. For x in [1.25,1/0.35(~2.857143)],
+ *	erfc(x) = (1/x)*exp(-x*x-0.5625+R1(z)/S1(z))
+ *              z=1/x^2
+ *	erf(x)  = 1 - erfc(x)
+ *
+ *      4. For x in [1/0.35,107]
+ *	erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ *			= 2.0 - (1/x)*exp(-x*x-0.5625+R2(z)/S2(z))
+ *                             if -6.666<x<0
+ *			= 2.0 - tiny		(if x <= -6.666)
+ *              z=1/x^2
+ *	erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6.666, else
+ *	erf(x)  = sign(x)*(1.0 - tiny)
+ *      Note1:
+ *	   To compute exp(-x*x-0.5625+R/S), let s be a single
+ *	   precision number and s := x; then
+ *		-x*x = -s*s + (s-x)*(s+x)
+ *	        exp(-x*x-0.5626+R/S) =
+ *			exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ *      Note2:
+ *	   Here 4 and 5 make use of the asymptotic series
+ *			  exp(-x*x)
+ *		erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ *			  x*sqrt(pi)
+ *
+ *      5. For inf > x >= 107
+ *	erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+ *	erfc(x) = tiny*tiny (raise underflow) if x > 0
+ *			= 2 - tiny if x<0
+ *
+ *      7. Special case:
+ *	erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+ *	erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ *		erfc/erf(NaN) is NaN
+ */
+
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double
+tiny = 1e-4931L,
+  half = 0.5L,
+  one = 1.0L,
+  two = 2.0L,
+	/* c = (float)0.84506291151 */
+  erx = 0.845062911510467529296875L,
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+  /* 2/sqrt(pi) - 1 */
+  efx = 1.2837916709551257389615890312154517168810E-1L,
+  /* 8 * (2/sqrt(pi) - 1) */
+  efx8 = 1.0270333367641005911692712249723613735048E0L,
+
+  pp[6] = {
+    1.122751350964552113068262337278335028553E6L,
+    -2.808533301997696164408397079650699163276E6L,
+    -3.314325479115357458197119660818768924100E5L,
+    -6.848684465326256109712135497895525446398E4L,
+    -2.657817695110739185591505062971929859314E3L,
+    -1.655310302737837556654146291646499062882E2L,
+  },
+
+  qq[6] = {
+    8.745588372054466262548908189000448124232E6L,
+    3.746038264792471129367533128637019611485E6L,
+    7.066358783162407559861156173539693900031E5L,
+    7.448928604824620999413120955705448117056E4L,
+    4.511583986730994111992253980546131408924E3L,
+    1.368902937933296323345610240009071254014E2L,
+    /* 1.000000000000000000000000000000000000000E0 */
+  },
+
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25]
+ */
+/* erf(x+1) = 0.845062911510467529296875 + pa(x)/qa(x)
+   -0.15625 <= x <= +.25
+   Peak relative error 8.5e-22  */
+
+  pa[8] = {
+    -1.076952146179812072156734957705102256059E0L,
+     1.884814957770385593365179835059971587220E2L,
+    -5.339153975012804282890066622962070115606E1L,
+     4.435910679869176625928504532109635632618E1L,
+     1.683219516032328828278557309642929135179E1L,
+    -2.360236618396952560064259585299045804293E0L,
+     1.852230047861891953244413872297940938041E0L,
+     9.394994446747752308256773044667843200719E-2L,
+  },
+
+  qa[7] =  {
+    4.559263722294508998149925774781887811255E2L,
+    3.289248982200800575749795055149780689738E2L,
+    2.846070965875643009598627918383314457912E2L,
+    1.398715859064535039433275722017479994465E2L,
+    6.060190733759793706299079050985358190726E1L,
+    2.078695677795422351040502569964299664233E1L,
+    4.641271134150895940966798357442234498546E0L,
+    /* 1.000000000000000000000000000000000000000E0 */
+  },
+
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + ra(x^2)/sa(x^2))
+   1/2.85711669921875 < 1/x < 1/1.25
+   Peak relative error 3.1e-21  */
+
+    ra[] = {
+      1.363566591833846324191000679620738857234E-1L,
+      1.018203167219873573808450274314658434507E1L,
+      1.862359362334248675526472871224778045594E2L,
+      1.411622588180721285284945138667933330348E3L,
+      5.088538459741511988784440103218342840478E3L,
+      8.928251553922176506858267311750789273656E3L,
+      7.264436000148052545243018622742770549982E3L,
+      2.387492459664548651671894725748959751119E3L,
+      2.220916652813908085449221282808458466556E2L,
+    },
+
+    sa[] = {
+      -1.382234625202480685182526402169222331847E1L,
+      -3.315638835627950255832519203687435946482E2L,
+      -2.949124863912936259747237164260785326692E3L,
+      -1.246622099070875940506391433635999693661E4L,
+      -2.673079795851665428695842853070996219632E4L,
+      -2.880269786660559337358397106518918220991E4L,
+      -1.450600228493968044773354186390390823713E4L,
+      -2.874539731125893533960680525192064277816E3L,
+      -1.402241261419067750237395034116942296027E2L,
+      /* 1.000000000000000000000000000000000000000E0 */
+    },
+/*
+ * Coefficients for approximation to  erfc in [1/.35,107]
+ */
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + rb(x^2)/sb(x^2))
+   1/6.6666259765625 < 1/x < 1/2.85711669921875
+   Peak relative error 4.2e-22  */
+    rb[] = {
+      -4.869587348270494309550558460786501252369E-5L,
+      -4.030199390527997378549161722412466959403E-3L,
+      -9.434425866377037610206443566288917589122E-2L,
+      -9.319032754357658601200655161585539404155E-1L,
+      -4.273788174307459947350256581445442062291E0L,
+      -8.842289940696150508373541814064198259278E0L,
+      -7.069215249419887403187988144752613025255E0L,
+      -1.401228723639514787920274427443330704764E0L,
+    },
+
+    sb[] = {
+      4.936254964107175160157544545879293019085E-3L,
+      1.583457624037795744377163924895349412015E-1L,
+      1.850647991850328356622940552450636420484E0L,
+      9.927611557279019463768050710008450625415E0L,
+      2.531667257649436709617165336779212114570E1L,
+      2.869752886406743386458304052862814690045E1L,
+      1.182059497870819562441683560749192539345E1L,
+      /* 1.000000000000000000000000000000000000000E0 */
+    },
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + rc(x^2)/sc(x^2))
+   1/107 <= 1/x <= 1/6.6666259765625
+   Peak relative error 1.1e-21  */
+    rc[] = {
+      -8.299617545269701963973537248996670806850E-5L,
+      -6.243845685115818513578933902532056244108E-3L,
+      -1.141667210620380223113693474478394397230E-1L,
+      -7.521343797212024245375240432734425789409E-1L,
+      -1.765321928311155824664963633786967602934E0L,
+      -1.029403473103215800456761180695263439188E0L,
+    },
+
+    sc[] = {
+      8.413244363014929493035952542677768808601E-3L,
+      2.065114333816877479753334599639158060979E-1L,
+      1.639064941530797583766364412782135680148E0L,
+      4.936788463787115555582319302981666347450E0L,
+      5.005177727208955487404729933261347679090E0L,
+      /* 1.000000000000000000000000000000000000000E0 */
+    };
+
+long double
+erfl(long double x)
+{
+  long double R, S, P, Q, s, y, z, r;
+  int32_t ix, i;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+
+  if (ix >= 0x7fff)
+    {				/* erf(nan)=nan */
+      i = ((se & 0xffff) >> 15) << 1;
+      return (long double) (1 - i) + one / x;	/* erf(+-inf)=+-1 */
+    }
+
+  ix = (ix << 16) | (i0 >> 16);
+  if (ix < 0x3ffed800) /* |x|<0.84375 */
+    {
+      if (ix < 0x3fde8000) /* |x|<2**-33 */
+	{
+	  if (ix < 0x00080000)
+	    return 0.125 * (8.0 * x + efx8 * x);	/*avoid underflow */
+	  return x + efx * x;
+	}
+      z = x * x;
+      r = pp[0] + z * (pp[1]
+	+ z * (pp[2] + z * (pp[3] + z * (pp[4] + z * pp[5]))));
+      s = qq[0] + z * (qq[1]
+	+ z * (qq[2] + z * (qq[3] + z * (qq[4] + z * (qq[5] + z)))));
+      y = r / s;
+      return x + x * y;
+    }
+  if (ix < 0x3fffa000) /* 1.25 */
+    {				/* 0.84375 <= |x| < 1.25 */
+      s = fabsl (x) - one;
+      P = pa[0] + s * (pa[1] + s * (pa[2]
+	+ s * (pa[3] + s * (pa[4] + s * (pa[5] + s * (pa[6] + s * pa[7]))))));
+      Q = qa[0] + s * (qa[1] + s * (qa[2]
+	+ s * (qa[3] + s * (qa[4] + s * (qa[5] + s * (qa[6] + s))))));
+      if ((se & 0x8000) == 0)
+	return erx + P / Q;
+      else
+	return -erx - P / Q;
+    }
+  if (ix >= 0x4001d555) /* 6.6666259765625 */
+    {				/* inf>|x|>=6.666 */
+      if ((se & 0x8000) == 0)
+	return one - tiny;
+      else
+	return tiny - one;
+    }
+  x = fabsl (x);
+  s = one / (x * x);
+  if (ix < 0x4000b6db) /* 2.85711669921875 */
+    {
+      R = ra[0] + s * (ra[1] + s * (ra[2] + s * (ra[3] + s * (ra[4] +
+	s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8])))))));
+      S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] +
+	s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s))))))));
+    }
+  else
+    {				/* |x| >= 1/0.35 */
+      R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] +
+	s * (rb[5] + s * (rb[6] + s * rb[7]))))));
+      S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] +
+	s * (sb[5] + s * (sb[6] + s))))));
+    }
+  z = x;
+  GET_LDOUBLE_WORDS (i, i0, i1, z);
+  i1 = 0;
+  SET_LDOUBLE_WORDS (z, i, i0, i1);
+  r =
+    expl (-z * z - 0.5625) * expl ((z - x) * (z + x) + R / S);
+  if ((se & 0x8000) == 0)
+    return one - r / x;
+  else
+    return r / x - one;
+}
+
+long double
+erfcl(long double x)
+{
+  int32_t hx, ix;
+  long double R, S, P, Q, s, y, z, r;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x7fff)
+    {				/* erfc(nan)=nan */
+      /* erfc(+-inf)=0,2 */
+      return (long double) (((se & 0xffff) >> 15) << 1) + one / x;
+    }
+
+  ix = (ix << 16) | (i0 >> 16);
+  if (ix < 0x3ffed800) /* |x|<0.84375 */
+    {
+      if (ix < 0x3fbe0000) /* |x|<2**-65 */
+	return one - x;
+      z = x * x;
+      r = pp[0] + z * (pp[1]
+	+ z * (pp[2] + z * (pp[3] + z * (pp[4] + z * pp[5]))));
+      s = qq[0] + z * (qq[1]
+	+ z * (qq[2] + z * (qq[3] + z * (qq[4] + z * (qq[5] + z)))));
+      y = r / s;
+      if (ix < 0x3ffd8000) /* x<1/4 */
+	{
+	  return one - (x + x * y);
+	}
+      else
+	{
+	  r = x * y;
+	  r += (x - half);
+	  return half - r;
+	}
+    }
+  if (ix < 0x3fffa000) /* 1.25 */
+    {				/* 0.84375 <= |x| < 1.25 */
+      s = fabsl (x) - one;
+      P = pa[0] + s * (pa[1] + s * (pa[2]
+	+ s * (pa[3] + s * (pa[4] + s * (pa[5] + s * (pa[6] + s * pa[7]))))));
+      Q = qa[0] + s * (qa[1] + s * (qa[2]
+	+ s * (qa[3] + s * (qa[4] + s * (qa[5] + s * (qa[6] + s))))));
+      if ((se & 0x8000) == 0)
+	{
+	  z = one - erx;
+	  return z - P / Q;
+	}
+      else
+	{
+	  z = erx + P / Q;
+	  return one + z;
+	}
+    }
+  if (ix < 0x4005d600) /* 107 */
+    {				/* |x|<107 */
+      x = fabsl (x);
+      s = one / (x * x);
+      if (ix < 0x4000b6db) /* 2.85711669921875 */
+	{			/* |x| < 1/.35 ~ 2.857143 */
+	  R = ra[0] + s * (ra[1] + s * (ra[2] + s * (ra[3] + s * (ra[4] +
+	    s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8])))))));
+	  S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] +
+	    s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s))))))));
+	}
+      else if (ix < 0x4001d555) /* 6.6666259765625 */
+	{			/* 6.666 > |x| >= 1/.35 ~ 2.857143 */
+	  R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] +
+	    s * (rb[5] + s * (rb[6] + s * rb[7]))))));
+	  S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] +
+	    s * (sb[5] + s * (sb[6] + s))))));
+	}
+      else
+	{			/* |x| >= 6.666 */
+	  if (se & 0x8000)
+	    return two - tiny;	/* x < -6.666 */
+
+	  R = rc[0] + s * (rc[1] + s * (rc[2] + s * (rc[3] +
+						    s * (rc[4] + s * rc[5]))));
+	  S = sc[0] + s * (sc[1] + s * (sc[2] + s * (sc[3] +
+						    s * (sc[4] + s))));
+	}
+      z = x;
+      GET_LDOUBLE_WORDS (hx, i0, i1, z);
+      i1 = 0;
+      i0 &= 0xffffff00;
+      SET_LDOUBLE_WORDS (z, hx, i0, i1);
+      r = expl (-z * z - 0.5625) *
+	expl ((z - x) * (z + x) + R / S);
+      if ((se & 0x8000) == 0)
+	return r / x;
+      else
+	return two - r / x;
+    }
+  else
+    {
+      if ((se & 0x8000) == 0)
+	return tiny * tiny;
+      else
+	return two - tiny;
+    }
+}

+ 138 - 0
ld80/s_expm1l.c

@@ -0,0 +1,138 @@
+/*	$OpenBSD: s_expm1l.c,v 1.2 2011/07/20 21:02:51 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							expm1l.c
+ *
+ *	Exponential function, minus 1
+ *      Long double precision
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expm1l();
+ *
+ * y = expm1l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power, minus 1.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ *     x    k  f
+ *    e  = 2  e.
+ *
+ * An expansion x + .5 x^2 + x^3 R(x) approximates exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE    -45,+MAXLOG   200,000     1.2e-19     2.5e-20
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ * expm1l overflow   x > MAXLOG         MAXNUM
+ *
+ */
+
+#include <math.h>
+
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+
+/* exp(x) - 1 = x + 0.5 x^2 + x^3 P(x)/Q(x)
+   -.5 ln 2  <  x  <  .5 ln 2
+   Theoretical peak relative error = 3.4e-22  */
+
+static const long double
+  P0 = -1.586135578666346600772998894928250240826E4L,
+  P1 =  2.642771505685952966904660652518429479531E3L,
+  P2 = -3.423199068835684263987132888286791620673E2L,
+  P3 =  1.800826371455042224581246202420972737840E1L,
+  P4 = -5.238523121205561042771939008061958820811E-1L,
+
+  Q0 = -9.516813471998079611319047060563358064497E4L,
+  Q1 =  3.964866271411091674556850458227710004570E4L,
+  Q2 = -7.207678383830091850230366618190187434796E3L,
+  Q3 =  7.206038318724600171970199625081491823079E2L,
+  Q4 = -4.002027679107076077238836622982900945173E1L,
+  /* Q5 = 1.000000000000000000000000000000000000000E0 */
+
+/* C1 + C2 = ln 2 */
+C1 = 6.93145751953125E-1L,
+C2 = 1.428606820309417232121458176568075500134E-6L,
+/* ln 2^-65 */
+minarg = -4.5054566736396445112120088E1L;
+static const long double huge = 0x1p10000L;
+
+long double
+expm1l(long double x)
+{
+long double px, qx, xx;
+int k;
+
+/* Overflow.  */
+if (x > MAXLOGL)
+  return (huge*huge);	/* overflow */
+
+if (x == 0.0)
+  return x;
+
+/* Minimum value.  */
+if (x < minarg)
+  return -1.0L;
+
+xx = C1 + C2;
+
+/* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
+px = floorl (0.5 + x / xx);
+k = px;
+/* remainder times ln 2 */
+x -= px * C1;
+x -= px * C2;
+
+/* Approximate exp(remainder ln 2).  */
+px = (((( P4 * x
+	 + P3) * x
+	+ P2) * x
+       + P1) * x
+      + P0) * x;
+
+qx = (((( x
+	 + Q4) * x
+	+ Q3) * x
+       + Q2) * x
+      + Q1) * x
+     + Q0;
+
+xx = x * x;
+qx = x + (0.5 * xx + xx * px / qx);
+
+/* exp(x) = exp(k ln 2) exp(remainder ln 2) = 2^k exp(remainder ln 2).
+   We have qx = exp(remainder ln 2) - 1, so
+   exp(x) - 1  =  2^k (qx + 1) - 1  =  2^k qx + 2^k - 1.  */
+px = ldexpl(1.0L, k);
+x = px * qx + (px - 1.0);
+return x;
+}

+ 80 - 0
ld80/s_floorl.c

@@ -0,0 +1,80 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+floorl(long double x)
+{
+	int32_t i1,jj0;
+	u_int32_t i,j,se,i0,sx;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	sx = (se>>15)&1;
+	jj0 = (se&0x7fff)-0x3fff;
+	if(jj0<31) {
+	    if(jj0<0) {	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {
+		    if(sx==0)
+			return 0.0L;
+		    else if(((se&0x7fff)|i0|i1)!=0)
+			return -1.0L;
+		}
+	    } else {
+		i = (0x7fffffff)>>jj0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(sx) {
+			if (jj0>0 && (i0+(0x80000000>>jj0))>i0)
+			  i0 += (0x80000000)>>jj0;
+			else
+			  {
+			    i = 0x7fffffff;
+			    ++se;
+			  }
+		    }
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (jj0>62) {
+	    if(jj0==0x4000) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(jj0-31);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) {		/* raise inexact flag */
+		if(sx) {
+		    if(jj0==31) i0+=1;
+		    else {
+			j = i1+(1<<(63-jj0));
+			if(j<i1) i0 +=1 ;	/* got a carry */
+			i1=j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	SET_LDOUBLE_WORDS(x,se,i0,i1);
+	return x;
+}

+ 191 - 0
ld80/s_log1pl.c

@@ -0,0 +1,191 @@
+/*	$OpenBSD: s_log1pl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*							log1pl.c
+ *
+ *      Relative error logarithm
+ *	Natural logarithm of 1+x, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log1pl();
+ *
+ * y = log1pl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of 1+x.
+ *
+ * The argument 1+x is separated into its exponent and fractional
+ * parts.  If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ *     log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting  z = 2(x-1)/x+1),
+ *
+ *     log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE     -1.0, 9.0    100000      8.2e-20    2.5e-20
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity:  x-1 = 0; returns -INFINITY
+ * log domain:       x-1 < 0; returns NAN
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 2.32e-20
+ */
+
+static long double P[] = {
+ 4.5270000862445199635215E-5L,
+ 4.9854102823193375972212E-1L,
+ 6.5787325942061044846969E0L,
+ 2.9911919328553073277375E1L,
+ 6.0949667980987787057556E1L,
+ 5.7112963590585538103336E1L,
+ 2.0039553499201281259648E1L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 1.5062909083469192043167E1L,
+ 8.3047565967967209469434E1L,
+ 2.2176239823732856465394E2L,
+ 3.0909872225312059774938E2L,
+ 2.1642788614495947685003E2L,
+ 6.0118660497603843919306E1L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log1pl(long double xm1)
+{
+long double x, y, z;
+int e;
+
+if( isnan(xm1) )
+	return(xm1);
+if( xm1 == INFINITY )
+	return(xm1);
+if(xm1 == 0.0)
+	return(xm1);
+
+x = xm1 + 1.0L;
+
+/* Test for domain errors.  */
+if( x <= 0.0L )
+	{
+	if( x == 0.0L )
+		return( -INFINITY );
+	else
+		return( NAN );
+	}
+
+/* Separate mantissa from exponent.
+   Use frexp so that denormal numbers will be handled properly.  */
+x = frexpl( x, &e );
+
+/* logarithm using log(x) = z + z^3 P(z)/Q(z),
+   where z = 2(x-1)/x+1)  */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+	{ /* 2( 2x-1 )/( 2x+1 ) */
+	e -= 1;
+	z = x - 0.5L;
+	y = 0.5L * z + 0.5L;
+	}	
+else
+	{ /*  2 (x-1)/(x+1)   */
+	z = x - 0.5L;
+	z -= 0.5L;
+	y = 0.5L * x  + 0.5L;
+	}
+x = z / y;
+z = x*x;
+z = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+z = z + e * C2;
+z = z + x;
+z = z + e * C1;
+return( z );
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+	{
+	e -= 1;
+	if (e != 0)
+	  x = 2.0 * x - 1.0L;
+	else
+	  x = xm1;
+	}	
+else
+	{
+	  if (e != 0)
+	    x = x - 1.0L;
+	  else
+	    x = xm1;
+	}
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 6 ) );
+y = y + e * C2;
+z = y - 0.5 * z;
+z = z + x;
+z = z + e * C1;
+return( z );
+}

+ 69 - 0
ld80/s_modfl.c

@@ -0,0 +1,69 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modfl(long double x, long double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *	Bit twiddling.
+ *
+ * Exception:
+ *	No exception.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0;
+
+long double
+modfl(long double x, long double *iptr)
+{
+	int32_t i0,i1,jj0;
+	u_int32_t i,se;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	jj0 = (se&0x7fff)-0x3fff;	/* exponent of x */
+	if(jj0<32) {			/* integer part in high x */
+	    if(jj0<0) {			/* |x|<1 */
+		SET_LDOUBLE_WORDS(*iptr,se&0x8000,0,0);	/* *iptr = +-0 */
+		return x;
+	    } else {
+		i = (0x7fffffff)>>jj0;
+		if(((i0&i)|i1)==0) {		/* x is integral */
+		    *iptr = x;
+		    SET_LDOUBLE_WORDS(x,se&0x8000,0,0);	/* return +-0 */
+		    return x;
+		} else {
+		    SET_LDOUBLE_WORDS(*iptr,se,i0&(~i),0);
+		    return x - *iptr;
+		}
+	    }
+	} else if (jj0>63) {		/* no fraction part */
+	    *iptr = x*one;
+	    /* We must handle NaNs separately.  */
+	    if (jj0 == 0x4000 && ((i0 & 0x7fffffff) | i1))
+	      return x*one;
+	    SET_LDOUBLE_WORDS(x,se&0x8000,0,0);	/* return +-0 */
+	    return x;
+	} else {			/* fraction part in low x */
+	    i = ((u_int32_t)(0x7fffffff))>>(jj0-32);
+	    if((i1&i)==0) {		/* x is integral */
+		*iptr = x;
+		SET_LDOUBLE_WORDS(x,se&0x8000,0,0);	/* return +-0 */
+		return x;
+	    } else {
+		SET_LDOUBLE_WORDS(*iptr,se,i0,i1&(~i));
+		return x - *iptr;
+	    }
+	}
+}

+ 90 - 0
ld80/s_nextafterl.c

@@ -0,0 +1,90 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *	nextafterl(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+long double
+nextafterl(long double x, long double y)
+{
+	int32_t hx,hy,ix,iy;
+	u_int32_t lx,ly,esx,esy;
+
+	GET_LDOUBLE_WORDS(esx,hx,lx,x);
+	GET_LDOUBLE_WORDS(esy,hy,ly,y);
+	ix = esx&0x7fff;		/* |x| */
+	iy = esy&0x7fff;		/* |y| */
+
+	if (((ix==0x7fff)&&((hx&0x7fffffff|lx)!=0)) ||   /* x is nan */
+	    ((iy==0x7fff)&&((hy&0x7fffffff|ly)!=0)))     /* y is nan */
+	   return x+y;
+	if(x==y) return y;		/* x=y, return y */
+	if((ix|hx|lx)==0) {			/* x == 0 */
+	    volatile long double u;
+	    SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(esx<0x8000) {			/* x > 0 */
+	    if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) {
+	      /* x > y, x -= ulp */
+		if(lx==0) {
+		    if ((hx&0x7fffffff)==0) esx -= 1;
+		    hx = (hx - 1) | (hx & 0x80000000);
+		}
+		lx -= 1;
+	    } else {				/* x < y, x += ulp */
+		lx += 1;
+		if(lx==0) {
+		    hx = (hx + 1) | (hx & 0x80000000);
+		    if ((hx&0x7fffffff)==0) esx += 1;
+		}
+	    }
+	} else {				/* x < 0 */
+	    if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
+	      /* x < y, x -= ulp */
+		if(lx==0) {
+		    if ((hx&0x7fffffff)==0) esx -= 1;
+		    hx = (hx - 1) | (hx & 0x80000000);
+		}
+		lx -= 1;
+	    } else {				/* x > y, x += ulp */
+		lx += 1;
+		if(lx==0) {
+		    hx = (hx + 1) | (hx & 0x80000000);
+		    if ((hx&0x7fffffff)==0) esx += 1;
+		}
+	    }
+	}
+	esy = esx&0x7fff;
+	if(esy==0x7fff) return x+x;		/* overflow  */
+	if(esy==0) {
+	    volatile long double u = x*x;	/* underflow */
+	    if(u==x) {
+		SET_LDOUBLE_WORDS(x,esx,hx,lx);
+		return x;
+	    }
+	}
+	SET_LDOUBLE_WORDS(x,esx,hx,lx);
+	return x;
+}
+
+__strong_alias(nexttowardl, nextafterl);

+ 86 - 0
ld80/s_nexttoward.c

@@ -0,0 +1,86 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *	nexttoward(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <math.h>
+#include <float.h>
+
+#include "math_private.h"
+
+double
+nexttoward(double x, long double y)
+{
+	int32_t hx,ix,iy;
+	u_int32_t lx,hy,ly,esy;
+
+	EXTRACT_WORDS(hx,lx,x);
+	GET_LDOUBLE_WORDS(esy,hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = esy&0x7fff;		/* |y| */
+
+	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
+	   ((iy>=0x7fff)&&(hy|ly)!=0))		/* y is nan */
+	   return x+y;
+	if((long double) x==y) return y;	/* x=y, return y */
+	if((ix|lx)==0) {			/* x == 0 */
+	    volatile double u;
+	    INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00
+		|| (((ix>>20)&0x7ff)==iy-0x3c00
+		    && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
+			|| (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
+			    && (lx<<11)>ly)))) {	/* x > y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x < y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00
+		|| (((ix>>20)&0x7ff)==iy-0x3c00
+		    && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
+			|| (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
+			    && (lx<<11)>ly))))	{/* x < y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x > y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	}
+	hy = hx&0x7ff00000;
+	if(hy>=0x7ff00000) {
+	  x = x+x;	/* overflow  */
+	  return x;
+	}
+	if(hy<0x00100000) {
+	    volatile double u = x*x;		/* underflow */
+	    if(u==x) {
+		INSERT_WORDS(x,hx,lx);
+		return x;
+	    }
+	}
+	INSERT_WORDS(x,hx,lx);
+	return x;
+}

+ 67 - 0
ld80/s_nexttowardf.c

@@ -0,0 +1,67 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include <float.h>
+
+#include "math_private.h"
+
+float
+nexttowardf(float x, long double y)
+{
+	int32_t hx,ix,iy;
+	u_int32_t hy,ly,esy;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_LDOUBLE_WORDS(esy,hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = esy&0x7fff;		/* |y| */
+
+	if((ix>0x7f800000) ||			/* x is nan */
+	   (iy>=0x7fff&&((hy|ly)!=0)))		/* y is nan */
+	   return x+y;
+	if((long double) x==y) return y;	/* x=y, return y */
+	if(ix==0) {				/* x == 0 */
+	    volatile float u;
+	    SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/
+	    u = x;
+	    u = u * u;				/* raise underflow flag */
+	    return x;
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80
+	       || (((ix>>23)&0xff)==iy-0x3f80
+		   && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x < y, x += ulp */
+		hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80
+	       || (((ix>>23)&0xff)==iy-0x3f80
+		   && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x > y, x += ulp */
+		hx += 1;
+	    }
+	}
+	hy = hx&0x7f800000;
+	if(hy>=0x7f800000) {
+	  x = x+x;	/* overflow  */
+	  return x;
+	}
+	if(hy<0x00800000) {
+	    volatile float u = x*x;		/* underflow */
+	}
+	SET_FLOAT_WORD(x,hx);
+	return x;
+}

+ 166 - 0
ld80/s_remquol.c

@@ -0,0 +1,166 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define	BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define	LDBL_NBIT	0
+#define	SET_NBIT(hx)	((hx) | (1ULL << LDBL_MANH_SIZE))
+#define	HFRAC_BITS	EXT_FRACHBITS
+#else
+#define	LDBL_NBIT	0x80000000
+#define	SET_NBIT(hx)	(hx)
+#define	HFRAC_BITS	(EXT_FRACHBITS - 1)
+#endif
+
+#define	MANL_SHIFT	(EXT_FRACLBITS - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ *   for an explicit integer bit in front of the fractional bits.
+ */
+long double
+remquol(long double x, long double y, int *quo)
+{
+	int64_t hx,hz;	/* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+	uint32_t hy;
+	uint32_t lx,ly,lz;
+	uint32_t esx, esy;
+	int ix,iy,n,q,sx,sxy;
+
+	GET_LDOUBLE_WORDS(esx,hx,lx,x);
+	GET_LDOUBLE_WORDS(esy,hy,ly,y);
+	sx = esx & 0x8000;
+	sxy = sx ^ (esy & 0x8000);
+	esx &= 0x7fff;				/* |x| */
+	esy &= 0x7fff;				/* |y| */
+	SET_LDOUBLE_EXP(x,esx);
+	SET_LDOUBLE_EXP(y,esy);
+
+    /* purge off exception values */
+	if((esy|hy|ly)==0 ||			/* y=0 */
+	   (esx == BIAS + LDBL_MAX_EXP) ||	/* or x not finite */
+	   (esy == BIAS + LDBL_MAX_EXP &&
+	    ((hy&~LDBL_NBIT)|ly)!=0))		/* or y is NaN */
+	    return (x*y)/(x*y);
+	if(esx<=esy) {
+	    if((esx<esy) ||
+	       (hx<=hy &&
+		(hx<hy ||
+		 lx<ly))) {
+		q = 0;
+		goto fixup;			/* |x|<|y| return x or x-y */
+	    }
+	    if(hx==hy && lx==ly) {
+		*quo = 1;
+		return Zero[sx!=0];		/* |x|=|y| return x*0*/
+	    }
+	}
+
+    /* determine ix = ilogb(x) */
+	if(esx == 0) {				/* subnormal x */
+	    x *= 0x1.0p512;
+	    GET_LDOUBLE_WORDS(esx,hx,lx,x);
+	    ix = esx - (BIAS + 512);
+	} else {
+	    ix = esx - BIAS;
+	}
+
+    /* determine iy = ilogb(y) */
+	if(esy == 0) {				/* subnormal y */
+	    y *= 0x1.0p512;
+	    GET_LDOUBLE_WORDS(esy,hy,ly,y);
+	    iy = esy - (BIAS + 512);
+	} else {
+	    iy = esy - BIAS;
+	}
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	hx = SET_NBIT(hx);
+	lx = SET_NBIT(lx);
+
+    /* fix point fmod */
+	n = ix - iy;
+	q = 0;
+
+	while(n--) {
+	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+	    else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+	    q <<= 1;
+	}
+	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {hx=hz;lx=lz;q++;}
+
+    /* convert back to floating value and restore the sign */
+	if((hx|lx)==0) {			/* return sign(x)*0 */
+	    *quo = (sxy ? -q : q);
+	    return Zero[sx!=0];
+	}
+	while(hx<(1ULL<<HFRAC_BITS)) {	/* normalize x */
+	    hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+	    iy -= 1;
+	}
+	if (iy < LDBL_MIN_EXP) {
+	    esx = (iy + BIAS + 512) & 0x7fff;
+	    SET_LDOUBLE_WORDS(x,esx,hx,lx);
+	    x *= 0x1p-512;
+	    GET_LDOUBLE_WORDS(esx,hx,lx,x);
+	} else {
+	    esx = (iy + BIAS) & 0x7fff;
+	}
+	SET_LDOUBLE_WORDS(x,esx,hx,lx);
+fixup:
+	y = fabsl(y);
+	if (y < LDBL_MIN * 2) {
+	    if (x+x>y || (x+x==y && (q & 1))) {
+		q++;
+		x-=y;
+	    }
+	} else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+	    q++;
+	    x-=y;
+	}
+
+	GET_LDOUBLE_EXP(esx,x);
+	esx ^= sx;
+	SET_LDOUBLE_EXP(x,esx);
+
+	q &= 0x7fffffff;
+	*quo = (sxy ? -q : q);
+	return x;
+}

+ 79 - 0
ld80/s_tanhl.c

@@ -0,0 +1,79 @@
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* tanhl(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ *				        x    -x
+ *				       e  - e
+ *	0. tanhl(x) is defined to be -----------
+ *				        x    -x
+ *				       e  + e
+ *	1. reduce x to non-negative by tanhl(-x) = -tanhl(x).
+ *	2.  0      <= x <= 2**-55 : tanhl(x) := x*(one+x)
+ *					         -t
+ *	    2**-55 <  x <=  1     : tanhl(x) := -----; t = expm1l(-2x)
+ *					        t + 2
+ *						      2
+ *	    1      <= x <=  23.0  : tanhl(x) := 1-  ----- ; t=expm1l(2x)
+ *						    t + 2
+ *	    23.0   <  x <= INF    : tanhl(x) := 1.
+ *
+ * Special cases:
+ *	tanhl(NaN) is NaN;
+ *	only tanhl(0)=0 is exact for finite argument.
+ */
+
+#include <math.h>
+
+#include "math_private.h"
+
+static const long double one=1.0, two=2.0, tiny = 1.0e-4900L;
+
+long double
+tanhl(long double x)
+{
+	long double t,z;
+	int32_t se;
+	u_int32_t jj0,jj1,ix;
+
+    /* High word of |x|. */
+	GET_LDOUBLE_WORDS(se,jj0,jj1,x);
+	ix = se&0x7fff;
+
+    /* x is INF or NaN */
+	if(ix==0x7fff) {
+	    /* for NaN it's not important which branch: tanhl(NaN) = NaN */
+	    if (se&0x8000) return one/x-one;	/* tanhl(-inf)= -1; */
+	    else	   return one/x+one;	/* tanhl(+inf)=+1 */
+	}
+
+    /* |x| < 23 */
+	if (ix < 0x4003 || (ix == 0x4003 && jj0 < 0xb8000000u)) {/* |x|<23 */
+	    if ((ix|jj0|jj1) == 0)
+		return x;		/* x == +- 0 */
+	    if (ix<0x3fc8)		/* |x|<2**-55 */
+		return x*(one+tiny);	/* tanh(small) = small */
+	    if (ix>=0x3fff) {	/* |x|>=1  */
+		t = expm1l(two*fabsl(x));
+		z = one - two/(t+two);
+	    } else {
+		t = expm1l(-two*fabsl(x));
+		z= -t/(t+two);
+	    }
+    /* |x| > 23, return +-1 */
+	} else {
+	    z = one - tiny;		/* raised inexact flag */
+	}
+	return (se&0x8000)? -z: z;
+}

+ 72 - 0
ld80/s_truncl.c

@@ -0,0 +1,72 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define	MANH_SIZE	(EXT_FRACHBITS + 1)
+#else
+#define	MANH_SIZE	EXT_FRACHBITS
+#endif
+
+static const long double huge = 1.0e300;
+static const float zero[] = { 0.0, -0.0 };
+
+long double
+truncl(long double x)
+{
+	int e, es;
+	uint32_t ix0, ix1;
+
+	GET_LDOUBLE_WORDS(es,ix0,ix1,x);
+	e = (es&0x7fff) - LDBL_MAX_EXP + 1;
+
+	if (e < MANH_SIZE - 1) {
+		if (e < 0) {			/* raise inexact if x != 0 */
+			if (huge + x > 0.0)
+				return (zero[(es&0x8000)!=0]);
+		} else {
+			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+			if (((ix0 & m) | ix1) == 0)
+				return (x);	/* x is integral */
+			if (huge + x > 0.0) {	/* raise inexact flag */
+				ix0 &= ~m;
+				ix1 = 0;
+			}
+		}
+	} else if (e < LDBL_MANT_DIG - 1) {
+		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+		if ((ix1 & m) == 0)
+			return (x);	/* x is integral */
+		if (huge + x > 0.0)		/* raise inexact flag */
+			ix1 &= ~m;
+	}
+	SET_LDOUBLE_WORDS(x,es,ix0,ix1);
+	return (x);
+}