Browse Source

Merge pull request #69 from JuliaLang/vs/longdouble

Long double versions of math functions
Viral B. Shah 10 năm trước cách đây
mục cha
commit
f876e59885
62 tập tin đã thay đổi với 9795 bổ sung21 xóa
  1. 3 3
      Make.inc
  2. 58 0
      ld128/e_acoshl.c
  3. 65 0
      ld128/e_atanhl.c
  4. 105 0
      ld128/e_coshl.c
  5. 145 0
      ld128/e_expl.c
  6. 129 0
      ld128/e_fmodl.c
  7. 122 0
      ld128/e_hypotl.c
  8. 1038 0
      ld128/e_lgammal.c
  9. 255 0
      ld128/e_log10l.c
  10. 248 0
      ld128/e_log2l.c
  11. 283 0
      ld128/e_logl.c
  12. 439 0
      ld128/e_powl.c
  13. 104 0
      ld128/e_sinhl.c
  14. 45 0
      ld128/e_tgammal.c
  15. 69 0
      ld128/s_asinhl.c
  16. 69 0
      ld128/s_ceill.c
  17. 926 0
      ld128/s_erfl.c
  18. 162 0
      ld128/s_expm1l.c
  19. 71 0
      ld128/s_floorl.c
  20. 247 0
      ld128/s_log1pl.c
  21. 73 0
      ld128/s_modfl.c
  22. 72 0
      ld128/s_nextafterl.c
  23. 85 0
      ld128/s_nexttoward.c
  24. 65 0
      ld128/s_nexttowardf.c
  25. 168 0
      ld128/s_remquol.c
  26. 104 0
      ld128/s_tanhl.c
  27. 72 0
      ld128/s_truncl.c
  28. 10 3
      ld80/Make.files
  29. 57 0
      ld80/e_acoshl.c
  30. 60 0
      ld80/e_atanhl.c
  31. 82 0
      ld80/e_coshl.c
  32. 131 0
      ld80/e_expl.c
  33. 142 0
      ld80/e_fmodl.c
  34. 122 0
      ld80/e_hypotl.c
  35. 426 0
      ld80/e_lgammal.c
  36. 205 0
      ld80/e_log10l.c
  37. 199 0
      ld80/e_log2l.c
  38. 190 0
      ld80/e_logl.c
  39. 615 0
      ld80/e_powl.c
  40. 10 10
      ld80/e_rem_pio2l.h
  41. 76 0
      ld80/e_sinhl.c
  42. 320 0
      ld80/e_tgammal.c
  43. 1 1
      ld80/invtrig.h
  44. 54 0
      ld80/s_asinhl.c
  45. 78 0
      ld80/s_ceill.c
  46. 430 0
      ld80/s_erfl.c
  47. 1 1
      ld80/s_exp2l.c
  48. 138 0
      ld80/s_expm1l.c
  49. 80 0
      ld80/s_floorl.c
  50. 191 0
      ld80/s_log1pl.c
  51. 69 0
      ld80/s_modfl.c
  52. 1 1
      ld80/s_nanl.c
  53. 90 0
      ld80/s_nextafterl.c
  54. 86 0
      ld80/s_nexttoward.c
  55. 67 0
      ld80/s_nexttowardf.c
  56. 166 0
      ld80/s_remquol.c
  57. 79 0
      ld80/s_tanhl.c
  58. 72 0
      ld80/s_truncl.c
  59. 1 1
      src/Make.files
  60. 2 1
      src/math_private.h
  61. 218 0
      src/math_private_openbsd.h
  62. 104 0
      src/polevll.c

+ 3 - 3
Make.inc

@@ -3,8 +3,8 @@
 OS := $(shell uname)
 # Do not forget to bump SOMINOR when changing VERSION,
 # and SOMAJOR when breaking ABI in a backward-incompatible way
-VERSION = 0.4
-SOMAJOR = 1
+VERSION = 0.5
+SOMAJOR = 2
 SOMINOR = 0
 DESTDIR =
 prefix = /usr/local
@@ -64,7 +64,7 @@ endif
 
 ifeq ($(ARCH),x86_64)
 override ARCH := amd64
-endif 
+endif
 
 ifneq (,$(findstring MINGW,$(OS)))
 override OS=WINNT

+ 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <martynas@openbsd.org>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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 <steve@moshier.net>
+ *
+ * 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);
+}

+ 10 - 3
ld80/Make.files

@@ -1,6 +1,13 @@
-$(CUR_SRCS) += 	invtrig.c k_cosl.c k_sinl.c\
-		k_tanl.c s_exp2l.c
+$(CUR_SRCS) += 	invtrig.c \
+            e_acoshl.c     e_powl.c       k_tanl.c       s_exp2l.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 \
+            e_expl.c       e_log2l.c      k_cosl.c       s_log1pl.c     s_tanhl.c \
+            e_logl.c       k_sinl.c       s_erfl.c
+
+#           s_remquol.c    e_fmodl.c      s_truncl.c
+#           e_hypotl.c     s_floorl.c     s_nextafterl.c s_ceill.c      s_modfl.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 <openlibm.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 <openlibm.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 "openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <openlibm.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;
+}

+ 426 - 0
ld80/e_lgammal.c

@@ -0,0 +1,426 @@
+/*
+ * ====================================================
+ * 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 <steve@moshier.net>
+ *
+ * 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 <openlibm.h>
+
+#include "math_private.h"
+extern int signgam;
+
+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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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);
+}

+ 10 - 10
ld80/e_rem_pio2l.h

@@ -6,7 +6,7 @@
  *
  * Developed at SunSoft, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
  *
@@ -17,8 +17,8 @@
 //__FBSDID("$FreeBSD: src/lib/msun/ld80/e_rem_pio2l.h,v 1.3 2011/06/18 13:56:33 benl Exp $");
 
 /* ld80 version of __ieee754_rem_pio2l(x,y)
- * 
- * return the remainder of x rem pi/2 in y[0]+y[1] 
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
  * use __kernel_rem_pio2()
  */
 
@@ -26,7 +26,7 @@
 
 #include "openlibm.h"
 #include "math_private.h"
-#include "fpmath.h"
+#include "openlibm.h"
 
 #define	BIAS	(LDBL_MAX_EXP - 1)
 
@@ -102,24 +102,24 @@ __ieee754_rem_pio2l(long double x, long double *y)
 		union IEEEl2bits u2;
 	        int ex1;
 	        j  = ex;
-	        y[0] = r-w; 
+	        y[0] = r-w;
 		u2.e = y[0];
 		ex1 = u2.xbits.expsign & 0x7fff;
 	        i = j-ex1;
 	        if(i>22) {  /* 2nd iteration needed, good to 141 */
 		    t  = r;
-		    w  = fn*pio2_2;	
+		    w  = fn*pio2_2;
 		    r  = t-w;
-		    w  = fn*pio2_2t-((t-r)-w);	
+		    w  = fn*pio2_2t-((t-r)-w);
 		    y[0] = r-w;
 		    u2.e = y[0];
 		    ex1 = u2.xbits.expsign & 0x7fff;
 		    i = j-ex1;
 		    if(i>61) {	/* 3rd iteration need, 180 bits acc */
 		    	t  = r;	/* will cover all possible cases */
-		    	w  = fn*pio2_3;	
+		    	w  = fn*pio2_3;
 		    	r  = t-w;
-		    	w  = fn*pio2_3t-((t-r)-w);	
+		    	w  = fn*pio2_3t-((t-r)-w);
 		    	y[0] = r-w;
 		    }
 		}
@@ -127,7 +127,7 @@ __ieee754_rem_pio2l(long double x, long double *y)
 	    y[1] = (r-y[0])-w;
 	    return n;
 	}
-    /* 
+    /*
      * all other (large) arguments
      */
 	if(ex==0x7fff) {		/* x is inf or NaN */

+ 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 <openlibm.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;
+}

+ 320 - 0
ld80/e_tgammal.c

@@ -0,0 +1,320 @@
+/*	$OpenBSD: e_tgammal.c,v 1.4 2013/11/12 20:35:19 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * 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 <openlibm.h>
+
+#include "math_private.h"
+extern int signgam;
+
+/*
+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;
+}

+ 1 - 1
ld80/invtrig.h

@@ -28,7 +28,7 @@
 
 #include <float.h>
 
-#include "fpmath.h"
+#include <openlibm.h>
 
 #define	BIAS		(LDBL_MAX_EXP - 1)
 #define	MANH_SIZE	LDBL_MANH_SIZE

+ 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 <openlibm.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 <openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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;
+    }
+}

+ 1 - 1
ld80/s_exp2l.c

@@ -32,7 +32,7 @@
 
 #include "amd64/bsd_ieeefp.h"
 
-#include "fpmath.h"
+#include "openlibm.h"
 #include "openlibm.h"
 #include "math_private.h"
 

+ 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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <openlibm.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 <steve@moshier.net>
+ *
+ * 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 <openlibm.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 <openlibm.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;
+	    }
+	}
+}

+ 1 - 1
ld80/s_nanl.c

@@ -28,7 +28,7 @@
 
 #include "openlibm.h"
 
-#include "fpmath.h"
+#include "openlibm.h"
 #include "math_private.h"
 
 DLLEXPORT long double

+ 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 <openlibm.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 <openlibm.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 <openlibm.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 <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 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 <openlibm.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 "openlibm.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);
+}

+ 1 - 1
src/Make.files

@@ -50,7 +50,7 @@ $(CUR_SRCS) +=	e_acosl.c e_asinl.c e_atan2l.c e_fmodl.c \
 	s_frexpl.c s_logbl.c s_nexttoward.c \
 	s_remquol.c \
 	s_sinl.c s_sincosl.c s_tanl.c s_truncl.c w_cabsl.c \
-	s_nextafterl.c s_rintl.c s_scalbnl.c
+	s_nextafterl.c s_rintl.c s_scalbnl.c polevll.c
 #	s_cbrtl.c
 endif
 

+ 2 - 1
src/math_private.h

@@ -22,6 +22,7 @@
 #include "fpmath.h"
 #include <complex.h>
 #include <stdint.h>
+#include "math_private_openbsd.h"
 
 /*
  * The original fdlibm code used statements like:
@@ -228,7 +229,7 @@ do {								\
  * Common routine to process the arguments to nan(), nanf(), and nanl().
  */
 void _scan_nan(u_int32_t *__words, int __num_words, const char *__s);
- 
+
 #ifdef __GNUCLIKE_ASM
 
 /* Asm versions of some functions. */

+ 218 - 0
src/math_private_openbsd.h

@@ -0,0 +1,218 @@
+/*	$OpenBSD: math_private.h,v 1.17 2014/06/02 19:31:17 kettenis Exp $	*/
+/*
+ * ====================================================
+ * 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: @(#)fdlibm.h 5.1 93/09/24
+ */
+
+#ifndef _MATH_PRIVATE_OPENBSD_H_
+#define _MATH_PRIVATE_OPENBSD_H_
+
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct {
+    u_int32_t mswhi;
+    u_int32_t mswlo;
+    u_int32_t lswhi;
+    u_int32_t lswlo;
+  } parts32;
+  struct {
+    u_int64_t msw;
+    u_int64_t lsw;
+  } parts64;
+} ieee_quad_shape_type;
+
+#endif
+
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct {
+    u_int32_t lswlo;
+    u_int32_t lswhi;
+    u_int32_t mswlo;
+    u_int32_t mswhi;
+  } parts32;
+  struct {
+    u_int64_t lsw;
+    u_int64_t msw;
+  } parts64;
+} ieee_quad_shape_type;
+
+#endif
+
+/* Get two 64 bit ints from a long double.  */
+
+#define GET_LDOUBLE_WORDS64(ix0,ix1,d)				\
+do {								\
+  ieee_quad_shape_type qw_u;					\
+  qw_u.value = (d);						\
+  (ix0) = qw_u.parts64.msw;					\
+  (ix1) = qw_u.parts64.lsw;					\
+} while (0)
+
+/* Set a long double from two 64 bit ints.  */
+
+#define SET_LDOUBLE_WORDS64(d,ix0,ix1)				\
+do {								\
+  ieee_quad_shape_type qw_u;					\
+  qw_u.parts64.msw = (ix0);					\
+  qw_u.parts64.lsw = (ix1);					\
+  (d) = qw_u.value;						\
+} while (0)
+
+/* Get the more significant 64 bits of a long double mantissa.  */
+
+#define GET_LDOUBLE_MSW64(v,d)					\
+do {								\
+  ieee_quad_shape_type sh_u;					\
+  sh_u.value = (d);						\
+  (v) = sh_u.parts64.msw;					\
+} while (0)
+
+/* Set the more significant 64 bits of a long double mantissa from an int.  */
+
+#define SET_LDOUBLE_MSW64(d,v)					\
+do {								\
+  ieee_quad_shape_type sh_u;					\
+  sh_u.value = (d);						\
+  sh_u.parts64.msw = (v);					\
+  (d) = sh_u.value;						\
+} while (0)
+
+/* Get the least significant 64 bits of a long double mantissa.  */
+
+#define GET_LDOUBLE_LSW64(v,d)					\
+do {								\
+  ieee_quad_shape_type sh_u;					\
+  sh_u.value = (d);						\
+  (v) = sh_u.parts64.lsw;					\
+} while (0)
+
+/* A union which permits us to convert between a long double and
+   three 32 bit ints.  */
+
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct {
+#ifdef __LP64__
+    int padh:32;
+#endif
+    int exp:16;
+    int padl:16;
+    u_int32_t msw;
+    u_int32_t lsw;
+  } parts;
+} ieee_extended_shape_type;
+
+#endif
+
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct {
+    u_int32_t lsw;
+    u_int32_t msw;
+    int exp:16;
+    int padl:16;
+#ifdef __LP64__
+    int padh:32;
+#endif
+  } parts;
+} ieee_extended_shape_type;
+
+#endif
+
+/* Get three 32 bit ints from a double.  */
+
+#define GET_LDOUBLE_WORDS(se,ix0,ix1,d)				\
+do {								\
+  ieee_extended_shape_type ew_u;				\
+  ew_u.value = (d);						\
+  (se) = ew_u.parts.exp;					\
+  (ix0) = ew_u.parts.msw;					\
+  (ix1) = ew_u.parts.lsw;					\
+} while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define SET_LDOUBLE_WORDS(d,se,ix0,ix1)				\
+do {								\
+  ieee_extended_shape_type iw_u;				\
+  iw_u.parts.exp = (se);					\
+  iw_u.parts.msw = (ix0);					\
+  iw_u.parts.lsw = (ix1);					\
+  (d) = iw_u.value;						\
+} while (0)
+
+/* Get the more significant 32 bits of a long double mantissa.  */
+
+#define GET_LDOUBLE_MSW(v,d)					\
+do {								\
+  ieee_extended_shape_type sh_u;				\
+  sh_u.value = (d);						\
+  (v) = sh_u.parts.msw;						\
+} while (0)
+
+/* Set the more significant 32 bits of a long double mantissa from an int.  */
+
+#define SET_LDOUBLE_MSW(d,v)					\
+do {								\
+  ieee_extended_shape_type sh_u;				\
+  sh_u.value = (d);						\
+  sh_u.parts.msw = (v);						\
+  (d) = sh_u.value;						\
+} while (0)
+
+/* Get int from the exponent of a long double.  */
+
+#define GET_LDOUBLE_EXP(se,d)					\
+do {								\
+  ieee_extended_shape_type ge_u;				\
+  ge_u.value = (d);						\
+  (se) = ge_u.parts.exp;					\
+} while (0)
+
+/* Set exponent of a long double from an int.  */
+
+#define SET_LDOUBLE_EXP(d,se)					\
+do {								\
+  ieee_extended_shape_type se_u;				\
+  se_u.value = (d);						\
+  se_u.parts.exp = (se);					\
+  (d) = se_u.value;						\
+} while (0)
+
+/*
+ * Common routine to process the arguments to nan(), nanf(), and nanl().
+ */
+void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+double __exp__D(double, double);
+struct Double __log__D(double);
+long double __p1evll(long double, void *, int);
+long double __polevll(long double, void *, int);
+
+#endif /* _MATH_PRIVATE_OPENBSD_H_ */

+ 104 - 0
src/polevll.c

@@ -0,0 +1,104 @@
+/*	$OpenBSD: polevll.c,v 1.2 2013/11/12 20:35:09 martynas Exp $	*/
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * 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.
+ */
+
+/*							polevll.c
+ *							p1evll.c
+ *
+ *	Evaluate polynomial
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * int N;
+ * long double x, y, coef[N+1], polevl[];
+ *
+ * y = polevll( x, coef, N );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Evaluates polynomial of degree N:
+ *
+ *                     2          N
+ * y  =  C  + C x + C x  +...+ C x
+ *        0    1     2          N
+ *
+ * Coefficients are stored in reverse order:
+ *
+ * coef[0] = C  , ..., coef[N] = C  .
+ *            N                   0
+ *
+ *  The function p1evll() assumes that coef[N] = 1.0 and is
+ * omitted from the array.  Its calling arguments are
+ * otherwise the same as polevll().
+ *
+ *
+ * SPEED:
+ *
+ * In the interest of speed, there are no checks for out
+ * of bounds arithmetic.  This routine is used by most of
+ * the functions in the library.  Depending on available
+ * equipment features, the user may wish to rewrite the
+ * program in microcode or assembly language.
+ *
+ */
+
+#include "openlibm.h"
+
+#include "math_private.h"
+
+/*
+ * Polynomial evaluator:
+ *  P[0] x^n  +  P[1] x^(n-1)  +  ...  +  P[n]
+ */
+long double
+__polevll(long double x, void *PP, int n)
+{
+	long double y;
+	long double *P;
+
+	P = (long double *)PP;
+	y = *P++;
+	do {
+		y = y * x + *P++;
+	} while (--n);
+
+	return (y);
+}
+
+/*
+ * Polynomial evaluator:
+ *  x^n  +  P[0] x^(n-1)  +  P[1] x^(n-2)  +  ...  +  P[n]
+ */
+long double
+__p1evll(long double x, void *PP, int n)
+{
+	long double y;
+	long double *P;
+
+	P = (long double *)PP;
+	n -= 1;
+	y = x + *P++;
+	do {
+		y = y * x + *P++;
+	} while (--n);
+
+	return (y);
+}