float __ieee754_hypotf(float x, float y) { double d_x, d_y; int32_t ha, hb; GET_FLOAT_WORD(ha,x); ha &= 0x7fffffff; GET_FLOAT_WORD(hb,y); hb &= 0x7fffffff; if (ha == 0x7f800000 && !issignaling (y)) return fabsf(x); else if (hb == 0x7f800000 && !issignaling (x)) return fabsf(y); else if (ha > 0x7f800000 || hb > 0x7f800000) return fabsf(x) * fabsf(y); else if (ha == 0) return fabsf(y); else if (hb == 0) return fabsf(x); d_x = (double) x; d_y = (double) y; return (float) __ieee754_sqrt(d_x * d_x + d_y * d_y); }
FLOAT M_DECL_FUNC (__fmin) (FLOAT x, FLOAT y) { if (islessequal (x, y)) return x; else if (isgreater (x, y)) return y; else if (issignaling (x) || issignaling (y)) return x + y; else return isnan (y) ? x : y; }
FLOAT M_DECL_FUNC (__fminmag) (FLOAT x, FLOAT y) { FLOAT ax = M_FABS (x); FLOAT ay = M_FABS (y); if (isless (ax, ay)) return x; else if (isgreater (ax, ay)) return y; else if (ax == ay) return x < y ? x : y; else if (issignaling (x) || issignaling (y)) return x + y; else return isnan (y) ? x : y; }
float __ieee754_powf(float x, float y) { float z,ax,z_h,z_l,p_h,p_l; float y1,t1,t2,r,s,t,u,v,w; int32_t i,j,k,yisint,n; int32_t hx,hy,ix,iy,is; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ if(iy==0 && !issignaling (x)) return one; /* x==+-1 */ if(x == 1.0 && !issignaling (y)) return one; if(x == -1.0 && isinf(y)) return one; /* +-NaN return x+y */ if(__builtin_expect(ix > 0x7f800000 || iy > 0x7f800000, 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>=0x4b800000) yisint = 2; /* even integer y */ else if(iy>=0x3f800000) { k = (iy>>23)-0x7f; /* exponent */ j = iy>>(23-k); if((j<<(23-k))==iy) yisint = 2-(j&1); } }
/* An ultimate power routine. Given two IEEE double machine numbers y, x it computes the correctly rounded (to nearest) value of X^y. */ double SECTION __ieee754_pow (double x, double y) { double z, a, aa, error, t, a1, a2, y1, y2; mynumber u, v; int k; int4 qx, qy; v.x = y; u.x = x; if (v.i[LOW_HALF] == 0) { /* of y */ qx = u.i[HIGH_HALF] & 0x7fffffff; /* Is x a NaN? */ if ((((qx == 0x7ff00000) && (u.i[LOW_HALF] != 0)) || (qx > 0x7ff00000)) && (y != 0 || issignaling (x))) return x + x; if (y == 1.0) return x; if (y == 2.0) return x * x; if (y == -1.0) return 1.0 / x; if (y == 0) return 1.0; } /* else */ if (((u.i[HIGH_HALF] > 0 && u.i[HIGH_HALF] < 0x7ff00000) || /* x>0 and not x->0 */ (u.i[HIGH_HALF] == 0 && u.i[LOW_HALF] != 0)) && /* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */ (v.i[HIGH_HALF] & 0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */ double retval; { SET_RESTORE_ROUND (FE_TONEAREST); /* Avoid internal underflow for tiny y. The exact value of y does not matter if |y| <= 2**-64. */ if (fabs (y) < 0x1p-64) y = y < 0 ? -0x1p-64 : 0x1p-64; z = log1 (x, &aa, &error); /* x^y =e^(y log (X)) */ t = y * CN; y1 = t - (t - y); y2 = y - y1; t = z * CN; a1 = t - (t - z); a2 = (z - a1) + aa; a = y1 * a1; aa = y2 * a1 + y * a2; a1 = a + aa; a2 = (a - a1) + aa; error = error * fabs (y); t = __exp1 (a1, a2, 1.9e16 * error); /* return -10 or 0 if wasn't computed exactly */ retval = (t > 0) ? t : power1 (x, y); } if (isinf (retval)) retval = huge * huge; else if (retval == 0) retval = tiny * tiny; else math_check_force_underflow_nonneg (retval); return retval; } if (x == 0) { if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] != 0) || (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000) /* NaN */ return y + y; if (fabs (y) > 1.0e20) return (y > 0) ? 0 : 1.0 / 0.0; k = checkint (y); if (k == -1) return y < 0 ? 1.0 / x : x; else return y < 0 ? 1.0 / 0.0 : 0.0; /* return 0 */ } qx = u.i[HIGH_HALF] & 0x7fffffff; /* no sign */ qy = v.i[HIGH_HALF] & 0x7fffffff; /* no sign */ if (qx >= 0x7ff00000 && (qx > 0x7ff00000 || u.i[LOW_HALF] != 0)) /* NaN */ return x + y; if (qy >= 0x7ff00000 && (qy > 0x7ff00000 || v.i[LOW_HALF] != 0)) /* NaN */ return x == 1.0 && !issignaling (y) ? 1.0 : y + y; /* if x<0 */ if (u.i[HIGH_HALF] < 0) { k = checkint (y); if (k == 0) { if (qy == 0x7ff00000) { if (x == -1.0) return 1.0; else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0; else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x; } else if (qx == 0x7ff00000) return y < 0 ? 0.0 : INF.x; return (x - x) / (x - x); /* y not integer and x<0 */ } else if (qx == 0x7ff00000) { if (k < 0) return y < 0 ? nZERO.x : nINF.x; else return y < 0 ? 0.0 : INF.x; } /* if y even or odd */ if (k == 1) return __ieee754_pow (-x, y); else { double retval; { SET_RESTORE_ROUND (FE_TONEAREST); retval = -__ieee754_pow (-x, y); } if (isinf (retval)) retval = -huge * huge; else if (retval == 0) retval = -tiny * tiny; return retval; } } /* x>0 */ if (qx == 0x7ff00000) /* x= 2^-0x3ff */ return y > 0 ? x : 0; if (qy > 0x45f00000 && qy < 0x7ff00000) { if (x == 1.0) return 1.0; if (y > 0) return (x > 1.0) ? huge * huge : tiny * tiny; if (y < 0) return (x < 1.0) ? huge * huge : tiny * tiny; } if (x == 1.0) return 1.0; if (y > 0) return (x > 1.0) ? INF.x : 0; if (y < 0) return (x < 1.0) ? INF.x : 0; return 0; /* unreachable, to make the compiler happy */ }
long double __ieee754_hypotl(long double x, long double y) { long double a,b,a1,a2,b1,b2,w,kld; int64_t j,k,ha,hb; double xhi, yhi, hi, lo; xhi = ldbl_high (x); EXTRACT_WORDS64 (ha, xhi); yhi = ldbl_high (y); EXTRACT_WORDS64 (hb, yhi); ha &= 0x7fffffffffffffffLL; hb &= 0x7fffffffffffffffLL; if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} a = fabsl(a); /* a <- |a| */ b = fabsl(b); /* b <- |b| */ if((ha-hb)>0x0780000000000000LL) {return a+b;} /* x/y > 2**120 */ k=0; kld = 1.0L; if(ha > 0x5f30000000000000LL) { /* a>2**500 */ if(ha >= 0x7ff0000000000000LL) { /* Inf or NaN */ w = a+b; /* for sNaN */ if (issignaling (a) || issignaling (b)) return w; if(ha == 0x7ff0000000000000LL) w = a; if(hb == 0x7ff0000000000000LL) w = b; return w; } /* scale a and b by 2**-600 */ a *= 0x1p-600L; b *= 0x1p-600L; k = 600; kld = 0x1p+600L; } else if(hb < 0x23d0000000000000LL) { /* b < 2**-450 */ if(hb <= 0x000fffffffffffffLL) { /* subnormal b or 0 */ if(hb==0) return a; a *= 0x1p+1022L; b *= 0x1p+1022L; k = -1022; kld = 0x1p-1022L; } else { /* scale a and b by 2^600 */ a *= 0x1p+600L; b *= 0x1p+600L; k = -600; kld = 0x1p-600L; } } /* medium size a and b */ w = a-b; if (w>b) { ldbl_unpack (a, &hi, &lo); a1 = hi; a2 = lo; /* a*a + b*b = (a1+a2)*a + b*b = a1*a + a2*a + b*b = a1*(a1+a2) + a2*a + b*b = a1*a1 + a1*a2 + a2*a + b*b = a1*a1 + a2*(a+a1) + b*b */ w = sqrtl(a1*a1-(b*(-b)-a2*(a+a1))); } else { a = a+a; ldbl_unpack (b, &hi, &lo); b1 = hi; b2 = lo; ldbl_unpack (a, &hi, &lo); a1 = hi; a2 = lo; /* a*a + b*b = a*a + (a-b)*(a-b) - (a-b)*(a-b) + b*b = a*a + w*w - (a*a - 2*a*b + b*b) + b*b = w*w + 2*a*b = w*w + (a1+a2)*b = w*w + a1*b + a2*b = w*w + a1*(b1+b2) + a2*b = w*w + a1*b1 + a1*b2 + a2*b */ w = sqrtl(a1*b1-(w*(-w)-(a1*b2+a2*b))); } if(k!=0) { w *= kld; math_check_force_underflow_nonneg (w); return w; } else return w; }
double __ieee754_hypot (double x, double y) { double a, b, t1, t2, y1, y2, w; int32_t j, k, ha, hb; GET_HIGH_WORD (ha, x); ha &= 0x7fffffff; GET_HIGH_WORD (hb, y); hb &= 0x7fffffff; if (hb > ha) { a = y; b = x; j = ha; ha = hb; hb = j; } else { a = x; b = y; } SET_HIGH_WORD (a, ha); /* a <- |a| */ SET_HIGH_WORD (b, hb); /* b <- |b| */ if ((ha - hb) > 0x3c00000) { return a + b; } /* x/y > 2**60 */ k = 0; if (__glibc_unlikely (ha > 0x5f300000)) /* a>2**500 */ { if (ha >= 0x7ff00000) /* Inf or NaN */ { u_int32_t low; w = a + b; /* for sNaN */ if (issignaling (a) || issignaling (b)) return w; GET_LOW_WORD (low, a); if (((ha & 0xfffff) | low) == 0) w = a; GET_LOW_WORD (low, b); if (((hb ^ 0x7ff00000) | low) == 0) w = b; return w; } /* scale a and b by 2**-600 */ ha -= 0x25800000; hb -= 0x25800000; k += 600; SET_HIGH_WORD (a, ha); SET_HIGH_WORD (b, hb); } if (__builtin_expect (hb < 0x23d00000, 0)) /* b < 2**-450 */ { if (hb <= 0x000fffff) /* subnormal b or 0 */ { u_int32_t low; GET_LOW_WORD (low, b); if ((hb | low) == 0) return a; t1 = 0; SET_HIGH_WORD (t1, 0x7fd00000); /* t1=2^1022 */ b *= t1; a *= t1; k -= 1022; GET_HIGH_WORD (ha, a); GET_HIGH_WORD (hb, b); if (hb > ha) { t1 = a; a = b; b = t1; j = ha; ha = hb; hb = j; } } else /* scale a and b by 2^600 */ { ha += 0x25800000; /* a *= 2^600 */ hb += 0x25800000; /* b *= 2^600 */ k -= 600; SET_HIGH_WORD (a, ha); SET_HIGH_WORD (b, hb); } } /* medium size a and b */ w = a - b; if (w > b) { t1 = 0; SET_HIGH_WORD (t1, ha); t2 = a - t1; w = __ieee754_sqrt (t1 * t1 - (b * (-b) - t2 * (a + t1))); } else { a = a + a; y1 = 0; SET_HIGH_WORD (y1, hb); y2 = b - y1; t1 = 0; SET_HIGH_WORD (t1, ha + 0x00100000); t2 = a - t1; w = __ieee754_sqrt (t1 * y1 - (w * (-w) - (t1 * y2 + t2 * b))); } if (k != 0) { u_int32_t high; t1 = 1.0; GET_HIGH_WORD (high, t1); SET_HIGH_WORD (t1, high + (k << 20)); w *= t1; math_check_force_underflow_nonneg (w); return w; } else return w; }
static int test (const char str[]) { char *endp; int result = 0; puts (str); double d = strtod (str, &endp); if (!isnan (d)) { puts ("strtod did not return NAN"); result = 1; } if (issignaling (d)) { puts ("strtod returned a sNAN"); result = 1; } if (strcmp (endp, "something") != 0) { puts ("strtod set incorrect end pointer"); result = 1; } float f = strtof (str, &endp); if (!isnanf (f)) { puts ("strtof did not return NAN"); result = 1; } if (issignaling (f)) { puts ("strtof returned a sNAN"); result = 1; } if (strcmp (endp, "something") != 0) { puts ("strtof set incorrect end pointer"); result = 1; } long double ld = strtold (str, &endp); if (!isnan (ld)) { puts ("strtold did not return NAN"); result = 1; } if (issignaling (ld)) { puts ("strtold returned a sNAN"); result = 1; } if (strcmp (endp, "something") != 0) { puts ("strtold set incorrect end pointer"); result = 1; } return result; }