00db10
# commit 650ef4bd7976e36831cba22d838b567d3b5f6e8f
00db10
# Author: Alan Modra <amodra@gmail.com>
00db10
# Date:   Sat Aug 17 18:25:51 2013 +0930
00db10
# 
00db10
#     PowerPC floating point little-endian [4 of 15]
00db10
#     http://sourceware.org/ml/libc-alpha/2013-08/msg00084.html
00db10
#     
00db10
#     Another batch of ieee854 macros and union replacement.  These four
00db10
#     files also have bugs fixed with this patch.  The fact that the two
00db10
#     doubles in an IBM long double may have different signs means that
00db10
#     negation and absolute value operations can't just twiddle one sign bit
00db10
#     as you can with ieee864 style extended double.  fmodl, remainderl,
00db10
#     erfl and erfcl all had errors of this type.  erfl also returned +1 for
00db10
#     large magnitude negative input where it should return -1.  The hypotl
00db10
#     error is innocuous since the value adjusted twice is only used as a
00db10
#     flag.  The e_hypotl.c tests for large "a" and small "b" are mutually
00db10
#     exclusive because we've already exited when x/y > 2**120.  That allows
00db10
#     some further small simplifications.
00db10
#     
00db10
#         [BZ #15734], [BZ #15735]
00db10
#         * sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl): Rewrite
00db10
#         all uses of ieee875 long double macros and unions.  Simplify test
00db10
#         for 0.0L.  Correct |x|<|y| and |x|=|y| test.  Use
00db10
#         ldbl_extract_mantissa value for ix,iy exponents.  Properly
00db10
#         normalize after ldbl_extract_mantissa, and don't add hidden bit
00db10
#         already handled.  Don't treat low word of ieee854 mantissa like
00db10
#         low word of IBM long double and mask off bit when testing for
00db10
#         zero.
00db10
#         * sysdeps/ieee754/ldbl-128ibm/e_hypotl.c (__ieee754_hypotl): Rewrite
00db10
#         all uses of ieee875 long double macros and unions.  Simplify tests
00db10
#         for 0.0L and inf.  Correct double adjustment of k.  Delete dead code
00db10
#         adjusting ha,hb.  Simplify code setting kld.  Delete two600 and
00db10
#         two1022, instead use their values.  Recognise that tests for large
00db10
#         "a" and small "b" are mutually exclusive.  Rename vars.  Comment.
00db10
#         * sysdeps/ieee754/ldbl-128ibm/e_remainderl.c (__ieee754_remainderl):
00db10
#         Rewrite all uses of ieee875 long double macros and unions.  Simplify
00db10
#         test for 0.0L and nan.  Correct negation.
00db10
#         * sysdeps/ieee754/ldbl-128ibm/s_erfl.c (__erfl): Rewrite all uses of
00db10
#         ieee875 long double macros and unions.  Correct output for large
00db10
#         magnitude x.  Correct absolute value calculation.
00db10
#         (__erfcl): Likewise.
00db10
#         * math/libm-test.inc: Add tests for errors discovered in IBM long
00db10
#         double versions of fmodl, remainderl, erfl and erfcl.
00db10
# 
00db10
diff -urN glibc-2.17-c758a686/math/libm-test.inc glibc-2.17-c758a686/math/libm-test.inc
00db10
--- glibc-2.17-c758a686/math/libm-test.inc	2014-05-27 20:02:29.000000000 -0500
00db10
+++ glibc-2.17-c758a686/math/libm-test.inc	2014-05-27 20:09:59.000000000 -0500
00db10
@@ -4040,6 +4040,10 @@
00db10
   TEST_f_f (erf, 2.0L, 0.995322265018952734162069256367252929L);
00db10
   TEST_f_f (erf, 4.125L, 0.999999994576599200434933994687765914L);
00db10
   TEST_f_f (erf, 27.0L, 1.0L);
00db10
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 54
00db10
+  /* The input is not exactly representable as a double.  */
00db10
+  TEST_f_f (erf, -0x1.fffffffffffff8p-2L, -0.5204998778130465132916303345518417673509L);
00db10
+#endif
00db10
 
00db10
   END (erf);
00db10
 }
00db10
@@ -4071,6 +4075,10 @@
00db10
   TEST_f_f (erfc, 0x1.ffa002p+2L, 1.233585992097580296336099501489175967033e-29L);
00db10
   TEST_f_f (erfc, 0x1.ffffc8p+2L, 1.122671365033056305522366683719541099329e-29L);
00db10
 #ifdef TEST_LDOUBLE
00db10
+# if LDBL_MANT_DIG >= 54
00db10
+  /* The input is not exactly representable as a double.  */
00db10
+  TEST_f_f (erfc, -0x1.fffffffffffff8p-2L, 1.52049987781304651329163033455184176735L);
00db10
+# endif
00db10
   /* The result can only be represented in long double.  */
00db10
 # if LDBL_MIN_10_EXP < -319
00db10
   TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L);
00db10
@@ -5634,6 +5642,13 @@
00db10
 #if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381
00db10
   TEST_ff_f (fmod, 0x0.fffffffffffffffep-16382L, 0x1p-16445L, plus_zero);
00db10
 #endif
00db10
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56
00db10
+  TEST_ff_f (fmod, -0x1.00000000000004p+0L, 0x1.fffffffffffff8p-1L, -0x1p-53L);
00db10
+  TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, 0x1p-56L);
00db10
+  TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, -0x1p-56L);
00db10
+  TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, 0x1p-56L);
00db10
+  TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, -0x1p-56L);
00db10
+#endif
00db10
 
00db10
   END (fmod);
00db10
 }
00db10
@@ -8642,6 +8657,9 @@
00db10
   TEST_ff_f (remainder, -1.625, -1.0, 0.375);
00db10
   TEST_ff_f (remainder, 5.0, 2.0, 1.0);
00db10
   TEST_ff_f (remainder, 3.0, 2.0, -1.0);
00db10
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56
00db10
+  TEST_ff_f (remainder, -0x1.80000000000002p1L, 2.0, 0x1.fffffffffffff8p-1L);
00db10
+#endif
00db10
 
00db10
   END (remainder);
00db10
 }
00db10
diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
00db10
--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c	2014-05-27 20:02:27.000000000 -0500
00db10
+++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c	2014-05-27 20:04:08.000000000 -0500
00db10
@@ -27,76 +27,83 @@
00db10
 long double
00db10
 __ieee754_fmodl (long double x, long double y)
00db10
 {
00db10
-	int64_t n,hx,hy,hz,ix,iy,sx, i;
00db10
-	u_int64_t lx,ly,lz;
00db10
-	int temp;
00db10
-
00db10
-	GET_LDOUBLE_WORDS64(hx,lx,x);
00db10
-	GET_LDOUBLE_WORDS64(hy,ly,y);
00db10
+	int64_t hx, hy, hz, sx, sy;
00db10
+	uint64_t lx, ly, lz;
00db10
+	int n, ix, iy;
00db10
+	double xhi, xlo, yhi, ylo;
00db10
+
00db10
+	ldbl_unpack (x, &xhi, &xlo;;
00db10
+	EXTRACT_WORDS64 (hx, xhi);
00db10
+	EXTRACT_WORDS64 (lx, xlo);
00db10
+	ldbl_unpack (y, &yhi, &ylo);
00db10
+	EXTRACT_WORDS64 (hy, yhi);
00db10
+	EXTRACT_WORDS64 (ly, ylo);
00db10
 	sx = hx&0x8000000000000000ULL;		/* sign of x */
00db10
-	hx ^=sx;				/* |x| */
00db10
-	hy &= 0x7fffffffffffffffLL;		/* |y| */
00db10
+	hx ^= sx;				/* |x| */
00db10
+	sy = hy&0x8000000000000000ULL;		/* sign of y */
00db10
+	hy ^= sy;				/* |y| */
00db10
 
00db10
     /* purge off exception values */
00db10
-	if(__builtin_expect((hy|(ly&0x7fffffffffffffff))==0 ||
00db10
+	if(__builtin_expect(hy==0 ||
00db10
 			    (hx>=0x7ff0000000000000LL)|| /* y=0,or x not finite */
00db10
 			    (hy>0x7ff0000000000000LL),0))	/* or y is NaN */
00db10
 	    return (x*y)/(x*y);
00db10
-	if(__builtin_expect(hx<=hy,0)) {
00db10
-	    if((hx
00db10
-	    if(lx==ly)
00db10
-		return Zero[(u_int64_t)sx>>63];	/* |x|=|y| return x*0*/
00db10
+	if (__builtin_expect (hx <= hy, 0))
00db10
+	  {
00db10
+	    /* If |x| < |y| return x.  */
00db10
+	    if (hx < hy)
00db10
+	      return x;
00db10
+	    /* At this point the absolute value of the high doubles of
00db10
+	       x and y must be equal.  */
00db10
+	    /* If the low double of y is the same sign as the high
00db10
+	       double of y (ie. the low double increases |y|)...  */
00db10
+	    if (((ly ^ sy) & 0x8000000000000000LL) == 0
00db10
+		/* ... then a different sign low double to high double
00db10
+		   for x or same sign but lower magnitude...  */
00db10
+		&& (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy))
00db10
+	      /* ... means |x| < |y|.  */
00db10
+	      return x;
00db10
+	    /* If the low double of x differs in sign to the high
00db10
+	       double of x (ie. the low double decreases |x|)...  */
00db10
+	    if (((lx ^ sx) & 0x8000000000000000LL) != 0
00db10
+		/* ... then a different sign low double to high double
00db10
+		   for y with lower magnitude (we've already caught
00db10
+		   the same sign for y case above)...  */
00db10
+		&& (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy))
00db10
+	      /* ... means |x| < |y|.  */
00db10
+	      return x;
00db10
+	    /* If |x| == |y| return x*0.  */
00db10
+	    if ((lx ^ sx) == (ly ^ sy))
00db10
+	      return Zero[(uint64_t) sx >> 63];
00db10
 	}
00db10
 
00db10
-    /* determine ix = ilogb(x) */
00db10
-	if(__builtin_expect(hx<0x0010000000000000LL,0)) {	/* subnormal x */
00db10
-	    if(hx==0) {
00db10
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
00db10
-	    } else {
00db10
-		for (ix = -1022, i=(hx<<11); i>0; i<<=1) ix -=1;
00db10
-	    }
00db10
-	} else ix = (hx>>52)-0x3ff;
00db10
-
00db10
-    /* determine iy = ilogb(y) */
00db10
-	if(__builtin_expect(hy<0x0010000000000000LL,0)) {	/* subnormal y */
00db10
-	    if(hy==0) {
00db10
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
00db10
-	    } else {
00db10
-		for (iy = -1022, i=(hy<<11); i>0; i<<=1) iy -=1;
00db10
-	    }
00db10
-	} else iy = (hy>>52)-0x3ff;
00db10
-
00db10
     /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
00db10
        bit mantissa so the following operations will give the correct
00db10
        result.  */
00db10
-	ldbl_extract_mantissa(&hx, &lx, &temp, x);
00db10
-	ldbl_extract_mantissa(&hy, &ly, &temp, y);
00db10
+	ldbl_extract_mantissa(&hx, &lx, &ix, x);
00db10
+	ldbl_extract_mantissa(&hy, &ly, &iy, y);
00db10
 
00db10
-    /* set up {hx,lx}, {hy,ly} and align y to x */
00db10
-	if(__builtin_expect(ix >= -1022, 1))
00db10
-	    hx = 0x0001000000000000LL|(0x0000ffffffffffffLL&hx;;
00db10
-	else {		/* subnormal x, shift x to normal */
00db10
-	    n = -1022-ix;
00db10
-	    if(n<=63) {
00db10
-		hx = (hx<<n)|(lx>>(64-n));
00db10
-		lx <<= n;
00db10
-	    } else {
00db10
-		hx = lx<<(n-64);
00db10
-		lx = 0;
00db10
-	    }
00db10
-	}
00db10
-	if(__builtin_expect(iy >= -1022, 1))
00db10
-	    hy = 0x0001000000000000LL|(0x0000ffffffffffffLL&hy);
00db10
-	else {		/* subnormal y, shift y to normal */
00db10
-	    n = -1022-iy;
00db10
-	    if(n<=63) {
00db10
-		hy = (hy<<n)|(ly>>(64-n));
00db10
-		ly <<= n;
00db10
-	    } else {
00db10
-		hy = ly<<(n-64);
00db10
-		ly = 0;
00db10
-	    }
00db10
-	}
00db10
+	if (__builtin_expect (ix == -IEEE754_DOUBLE_BIAS, 0))
00db10
+	  {
00db10
+	    /* subnormal x, shift x to normal.  */
00db10
+	    while ((hx & (1LL << 48)) == 0)
00db10
+	      {
00db10
+		hx = (hx << 1) | (lx >> 63);
00db10
+		lx = lx << 1;
00db10
+		ix -= 1;
00db10
+	      }
00db10
+	  }
00db10
+
00db10
+	if (__builtin_expect (iy == -IEEE754_DOUBLE_BIAS, 0))
00db10
+	  {
00db10
+	    /* subnormal y, shift y to normal.  */
00db10
+	    while ((hy & (1LL << 48)) == 0)
00db10
+	      {
00db10
+		hy = (hy << 1) | (ly >> 63);
00db10
+		ly = ly << 1;
00db10
+		iy -= 1;
00db10
+	      }
00db10
+	  }
00db10
 
00db10
     /* fix point fmod */
00db10
 	n = ix - iy;
00db10
@@ -104,7 +111,7 @@
00db10
 	    hz=hx-hy;lz=lx-ly; if(lx
00db10
 	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
00db10
 	    else {
00db10
-		if((hz|(lz&0x7fffffffffffffff))==0)		/* return sign(x)*0 */
00db10
+		if((hz|lz)==0)		/* return sign(x)*0 */
00db10
 		    return Zero[(u_int64_t)sx>>63];
00db10
 		hx = hz+hz+(lz>>63); lx = lz+lz;
00db10
 	    }
00db10
@@ -113,7 +120,7 @@
00db10
 	if(hz>=0) {hx=hz;lx=lz;}
00db10
 
00db10
     /* convert back to floating value and restore the sign */
00db10
-	if((hx|(lx&0x7fffffffffffffff))==0)			/* return sign(x)*0 */
00db10
+	if((hx|lx)==0)			/* return sign(x)*0 */
00db10
 	    return Zero[(u_int64_t)sx>>63];
00db10
 	while(hx<0x0001000000000000LL) {	/* normalize x */
00db10
 	    hx = hx+hx+(lx>>63); lx = lx+lx;
00db10
diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c
00db10
--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c	2014-05-27 20:02:27.000000000 -0500
00db10
+++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c	2014-05-27 20:04:08.000000000 -0500
00db10
@@ -45,76 +45,84 @@
00db10
 #include <math.h>
00db10
 #include <math_private.h>
00db10
 
00db10
-static const long double two600 = 0x1.0p+600L;
00db10
-static const long double two1022 = 0x1.0p+1022L;
00db10
-
00db10
 long double
00db10
 __ieee754_hypotl(long double x, long double y)
00db10
 {
00db10
-	long double a,b,t1,t2,y1,y2,w,kld;
00db10
+	long double a,b,a1,a2,b1,b2,w,kld;
00db10
 	int64_t j,k,ha,hb;
00db10
+	double xhi, yhi, hi, lo;
00db10
 
00db10
-	GET_LDOUBLE_MSW64(ha,x);
00db10
+	xhi = ldbl_high (x);
00db10
+	EXTRACT_WORDS64 (ha, xhi);
00db10
+	yhi = ldbl_high (y);
00db10
+	EXTRACT_WORDS64 (hb, yhi);
00db10
 	ha &= 0x7fffffffffffffffLL;
00db10
-	GET_LDOUBLE_MSW64(hb,y);
00db10
 	hb &= 0x7fffffffffffffffLL;
00db10
 	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
00db10
 	a = fabsl(a);	/* a <- |a| */
00db10
 	b = fabsl(b);	/* b <- |b| */
00db10
-	if((ha-hb)>0x780000000000000LL) {return a+b;} /* x/y > 2**120 */
00db10
+	if((ha-hb)>0x0780000000000000LL) {return a+b;} /* x/y > 2**120 */
00db10
 	k=0;
00db10
 	kld = 1.0L;
00db10
 	if(ha > 0x5f30000000000000LL) {	/* a>2**500 */
00db10
 	   if(ha >= 0x7ff0000000000000LL) {	/* Inf or NaN */
00db10
-	       u_int64_t low;
00db10
 	       w = a+b;			/* for sNaN */
00db10
-	       GET_LDOUBLE_LSW64(low,a);
00db10
-	       if(((ha&0xfffffffffffffLL)|(low&0x7fffffffffffffffLL))==0)
00db10
+	       if(ha == 0x7ff0000000000000LL)
00db10
 		 w = a;
00db10
-	       GET_LDOUBLE_LSW64(low,b);
00db10
-	       if(((hb^0x7ff0000000000000LL)|(low&0x7fffffffffffffffLL))==0)
00db10
+	       if(hb == 0x7ff0000000000000LL)
00db10
 		 w = b;
00db10
 	       return w;
00db10
 	   }
00db10
 	   /* scale a and b by 2**-600 */
00db10
-	   ha -= 0x2580000000000000LL; hb -= 0x2580000000000000LL; k += 600;
00db10
-	   a /= two600;
00db10
-	   b /= two600;
00db10
-	   k += 600;
00db10
-	   kld = two600;
00db10
+	   a *= 0x1p-600L;
00db10
+	   b *= 0x1p-600L;
00db10
+	   k = 600;
00db10
+	   kld = 0x1p+600L;
00db10
 	}
00db10
-	if(hb < 0x23d0000000000000LL) {	/* b < 2**-450 */
00db10
+	else if(hb < 0x23d0000000000000LL) {	/* b < 2**-450 */
00db10
 	    if(hb <= 0x000fffffffffffffLL) {	/* subnormal b or 0 */
00db10
-		u_int64_t low;
00db10
-		GET_LDOUBLE_LSW64(low,b);
00db10
-		if((hb|(low&0x7fffffffffffffffLL))==0) return a;
00db10
-		t1=two1022;	/* t1=2^1022 */
00db10
-		b *= t1;
00db10
-		a *= t1;
00db10
-		k -= 1022;
00db10
-		kld = kld / two1022;
00db10
+		if(hb==0) return a;
00db10
+		a *= 0x1p+1022L;
00db10
+		b *= 0x1p+1022L;
00db10
+		k = -1022;
00db10
+		kld = 0x1p-1022L;
00db10
 	    } else {		/* scale a and b by 2^600 */
00db10
-		ha += 0x2580000000000000LL;	/* a *= 2^600 */
00db10
-		hb += 0x2580000000000000LL;	/* b *= 2^600 */
00db10
-		k -= 600;
00db10
-		a *= two600;
00db10
-		b *= two600;
00db10
-		kld = kld / two600;
00db10
+		a *= 0x1p+600L;
00db10
+		b *= 0x1p+600L;
00db10
+		k = -600;
00db10
+		kld = 0x1p-600L;
00db10
 	    }
00db10
 	}
00db10
     /* medium size a and b */
00db10
 	w = a-b;
00db10
 	if (w>b) {
00db10
-	    SET_LDOUBLE_WORDS64(t1,ha,0);
00db10
-	    t2 = a-t1;
00db10
-	    w  = __ieee754_sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
00db10
+	    ldbl_unpack (a, &hi, &lo);
00db10
+	    a1 = hi;
00db10
+	    a2 = lo;
00db10
+	    /* a*a + b*b
00db10
+	       = (a1+a2)*a + b*b
00db10
+	       = a1*a + a2*a + b*b
00db10
+	       = a1*(a1+a2) + a2*a + b*b
00db10
+	       = a1*a1 + a1*a2 + a2*a + b*b
00db10
+	       = a1*a1 + a2*(a+a1) + b*b  */
00db10
+	    w  = __ieee754_sqrtl(a1*a1-(b*(-b)-a2*(a+a1)));
00db10
 	} else {
00db10
 	    a  = a+a;
00db10
-	    SET_LDOUBLE_WORDS64(y1,hb,0);
00db10
-	    y2 = b - y1;
00db10
-	    SET_LDOUBLE_WORDS64(t1,ha+0x0010000000000000LL,0);
00db10
-	    t2 = a - t1;
00db10
-	    w  = __ieee754_sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b)));
00db10
+	    ldbl_unpack (b, &hi, &lo);
00db10
+	    b1 = hi;
00db10
+	    b2 = lo;
00db10
+	    ldbl_unpack (a, &hi, &lo);
00db10
+	    a1 = hi;
00db10
+	    a2 = lo;
00db10
+	    /* a*a + b*b
00db10
+	       = a*a + (a-b)*(a-b) - (a-b)*(a-b) + b*b
00db10
+	       = a*a + w*w  - (a*a - 2*a*b + b*b) + b*b
00db10
+	       = w*w + 2*a*b
00db10
+	       = w*w + (a1+a2)*b
00db10
+	       = w*w + a1*b + a2*b
00db10
+	       = w*w + a1*(b1+b2) + a2*b
00db10
+	       = w*w + a1*b1 + a1*b2 + a2*b  */
00db10
+	    w  = __ieee754_sqrtl(a1*b1-(w*(-w)-(a1*b2+a2*b)));
00db10
 	}
00db10
 	if(k!=0)
00db10
 	    return w*kld;
00db10
diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
00db10
--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c	2014-05-27 20:02:27.000000000 -0500
00db10
+++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c	2014-05-27 20:04:08.000000000 -0500
00db10
@@ -33,18 +33,22 @@
00db10
 	int64_t hx,hp;
00db10
 	u_int64_t sx,lx,lp;
00db10
 	long double p_half;
00db10
+	double xhi, xlo, phi, plo;
00db10
 
00db10
-	GET_LDOUBLE_WORDS64(hx,lx,x);
00db10
-	GET_LDOUBLE_WORDS64(hp,lp,p);
00db10
+	ldbl_unpack (x, &xhi, &xlo;;
00db10
+	EXTRACT_WORDS64 (hx, xhi);
00db10
+	EXTRACT_WORDS64 (lx, xlo);
00db10
+	ldbl_unpack (p, &phi, &plo;;
00db10
+	EXTRACT_WORDS64 (hp, phi);
00db10
+	EXTRACT_WORDS64 (lp, plo);
00db10
 	sx = hx&0x8000000000000000ULL;
00db10
 	hp &= 0x7fffffffffffffffLL;
00db10
 	hx &= 0x7fffffffffffffffLL;
00db10
 
00db10
     /* purge off exception values */
00db10
-	if((hp|(lp&0x7fffffffffffffff))==0) return (x*p)/(x*p);	/* p = 0 */
00db10
+	if(hp==0) return (x*p)/(x*p);	/* p = 0 */
00db10
 	if((hx>=0x7ff0000000000000LL)||			/* x not finite */
00db10
-	  ((hp>=0x7ff0000000000000LL)&&			/* p is NaN */
00db10
-	  (((hp-0x7ff0000000000000LL)|lp)!=0)))
00db10
+	   (hp>0x7ff0000000000000LL))			/* p is NaN */
00db10
 	    return (x*p)/(x*p);
00db10
 
00db10
 
00db10
@@ -64,8 +68,8 @@
00db10
 		if(x>=p_half) x -= p;
00db10
 	    }
00db10
 	}
00db10
-	GET_LDOUBLE_MSW64(hx,x);
00db10
-	SET_LDOUBLE_MSW64(x,hx^sx);
00db10
+	if (sx)
00db10
+	  x = -x;
00db10
 	return x;
00db10
 }
00db10
 strong_alias (__ieee754_remainderl, __remainderl_finite)
00db10
diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
00db10
--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c	2014-05-27 20:02:27.000000000 -0500
00db10
+++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c	2014-05-27 20:04:08.000000000 -0500
00db10
@@ -760,16 +760,16 @@
00db10
 __erfl (long double x)
00db10
 {
00db10
   long double a, y, z;
00db10
-  int32_t i, ix, sign;
00db10
-  ieee854_long_double_shape_type u;
00db10
+  int32_t i, ix, hx;
00db10
+  double xhi;
00db10
 
00db10
-  u.value = x;
00db10
-  sign = u.parts32.w0;
00db10
-  ix = sign & 0x7fffffff;
00db10
+  xhi = ldbl_high (x);
00db10
+  GET_HIGH_WORD (hx, xhi);
00db10
+  ix = hx & 0x7fffffff;
00db10
 
00db10
   if (ix >= 0x7ff00000)
00db10
     {				/* erf(nan)=nan */
00db10
-      i = ((sign & 0xfff00000) >> 31) << 1;
00db10
+      i = ((uint32_t) hx >> 31) << 1;
00db10
       return (long double) (1 - i) + one / x;	/* erf(+-inf)=+-1 */
00db10
     }
00db10
 
00db10
@@ -778,7 +778,7 @@
00db10
       if (ix >= 0x4039A0DE)
00db10
 	{
00db10
 	/* __erfcl (x) underflows if x > 25.6283 */
00db10
-	  if (sign)
00db10
+	  if ((hx & 0x80000000) == 0)
00db10
 	    return one-tiny;
00db10
 	  else
00db10
 	    return tiny-one;
00db10
@@ -789,8 +789,9 @@
00db10
 	  return (one - y);
00db10
 	}
00db10
     }
00db10
-  u.parts32.w0 = ix;
00db10
-  a = u.value;
00db10
+  a = x;
00db10
+  if ((hx & 0x80000000) != 0)
00db10
+    a = -a;
00db10
   z = x * x;
00db10
   if (ix < 0x3fec0000)  /* a < 0.875 */
00db10
     {
00db10
@@ -814,7 +815,7 @@
00db10
       y = erf_const + neval (a, TN2, NTN2) / deval (a, TD2, NTD2);
00db10
     }
00db10
 
00db10
-  if (sign & 0x80000000) /* x < 0 */
00db10
+  if (hx & 0x80000000) /* x < 0 */
00db10
     y = -y;
00db10
   return( y );
00db10
 }
00db10
@@ -824,18 +825,18 @@
00db10
 __erfcl (long double x)
00db10
 {
00db10
   long double y, z, p, r;
00db10
-  int32_t i, ix, sign;
00db10
-  ieee854_long_double_shape_type u;
00db10
-
00db10
-  u.value = x;
00db10
-  sign = u.parts32.w0;
00db10
-  ix = sign & 0x7fffffff;
00db10
-  u.parts32.w0 = ix;
00db10
+  int32_t i, ix;
00db10
+  uint32_t hx;
00db10
+  double xhi;
00db10
+
00db10
+  xhi = ldbl_high (x);
00db10
+  GET_HIGH_WORD (hx, xhi);
00db10
+  ix = hx & 0x7fffffff;
00db10
 
00db10
   if (ix >= 0x7ff00000)
00db10
     {				/* erfc(nan)=nan */
00db10
       /* erfc(+-inf)=0,2 */
00db10
-      return (long double) (((u_int32_t) sign >> 31) << 1) + one / x;
00db10
+      return (long double) ((hx >> 31) << 1) + one / x;
00db10
     }
00db10
 
00db10
   if (ix < 0x3fd00000) /* |x| <1/4 */
00db10
@@ -846,7 +847,8 @@
00db10
     }
00db10
   if (ix < 0x3ff40000) /* 1.25 */
00db10
     {
00db10
-      x = u.value;
00db10
+      if ((hx & 0x80000000) != 0)
00db10
+	x = -x;
00db10
       i = 8.0 * x;
00db10
       switch (i)
00db10
 	{
00db10
@@ -891,7 +893,7 @@
00db10
 	  y += C20a;
00db10
 	  break;
00db10
 	}
00db10
-      if (sign & 0x80000000)
00db10
+      if (hx & 0x80000000)
00db10
 	y = 2.0L - y;
00db10
       return y;
00db10
     }
00db10
@@ -899,10 +901,11 @@
00db10
   if (ix < 0x405ac000)
00db10
     {
00db10
       /* x < -9 */
00db10
-      if ((ix >= 0x40220000) && (sign & 0x80000000))
00db10
+      if (hx >= 0xc0220000)
00db10
 	return two - tiny;
00db10
 
00db10
-      x = fabsl (x);
00db10
+      if ((hx & 0x80000000) != 0)
00db10
+	x = -x;
00db10
       z = one / (x * x);
00db10
       i = 8.0 / x;
00db10
       switch (i)
00db10
@@ -933,21 +936,17 @@
00db10
 	  p = neval (z, RNr8, NRNr8) / deval (z, RDr8, NRDr8);
00db10
 	  break;
00db10
 	}
00db10
-      u.value = x;
00db10
-      u.parts32.w3 = 0;
00db10
-      u.parts32.w2 = 0;
00db10
-      u.parts32.w1 &= 0xf8000000;
00db10
-      z = u.value;
00db10
+      z = (float) x;
00db10
       r = __ieee754_expl (-z * z - 0.5625) *
00db10
 	__ieee754_expl ((z - x) * (z + x) + p);
00db10
-      if ((sign & 0x80000000) == 0)
00db10
+      if ((hx & 0x80000000) == 0)
00db10
 	return r / x;
00db10
       else
00db10
 	return two - r / x;
00db10
     }
00db10
   else
00db10
     {
00db10
-      if ((sign & 0x80000000) == 0)
00db10
+      if ((hx & 0x80000000) == 0)
00db10
 	return tiny * tiny;
00db10
       else
00db10
 	return two - tiny;