1130613Smlaier/* s_nextafterl.c -- long double version of s_nextafter.c. 2130610Smlaier * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz. 3133573Smlaier */ 4130610Smlaier 5130610Smlaier/* 6130610Smlaier * ==================================================== 7130610Smlaier * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 8130610Smlaier * 9130610Smlaier * Developed at SunPro, a Sun Microsystems, Inc. business. 10130610Smlaier * Permission to use, copy, modify, and distribute this 11130610Smlaier * software is freely granted, provided that this notice 12130610Smlaier * is preserved. 13130610Smlaier * ==================================================== 14130610Smlaier */ 15130610Smlaier 16130610Smlaier#if defined(LIBM_SCCS) && !defined(lint) 17130610Smlaierstatic char rcsid[] = "NetBSD: "; 18130610Smlaier#endif 19130610Smlaier 20130610Smlaier/* IEEE functions 21130610Smlaier * nextafterq(x,y) 22130610Smlaier * return the next machine floating-point number of x in the 23130610Smlaier * direction toward y. 24130610Smlaier * Special cases: 25130610Smlaier */ 26130610Smlaier 27130610Smlaier#include "quadmath-imp.h" 28130610Smlaier 29130610Smlaier__float128 nextafterq(__float128 x, __float128 y) 30130610Smlaier{ 31130610Smlaier int64_t hx,hy,ix,iy; 32130610Smlaier uint64_t lx,ly; 33130610Smlaier 34130610Smlaier GET_FLT128_WORDS64(hx,lx,x); 35130613Smlaier GET_FLT128_WORDS64(hy,ly,y); 36130613Smlaier ix = hx&0x7fffffffffffffffLL; /* |x| */ 37130613Smlaier iy = hy&0x7fffffffffffffffLL; /* |y| */ 38130613Smlaier 39130613Smlaier if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) || /* x is nan */ 40130610Smlaier ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0)) /* y is nan */ 41130610Smlaier return x+y; 42130613Smlaier if(x==y) return y; /* x=y, return y */ 43130613Smlaier if((ix|lx)==0) { /* x == 0 */ 44130613Smlaier __float128 u; 45130610Smlaier SET_FLT128_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */ 46130610Smlaier u = math_opt_barrier (x); 47130610Smlaier u = u * u; 48130610Smlaier math_force_eval (u); /* raise underflow flag */ 49130610Smlaier return x; 50130613Smlaier } 51130610Smlaier if(hx>=0) { /* x > 0 */ 52130613Smlaier if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ 53130610Smlaier if(lx==0) hx--; 54130610Smlaier lx--; 55130610Smlaier } else { /* x < y, x += ulp */ 56130610Smlaier lx++; 57133573Smlaier if(lx==0) hx++; 58130610Smlaier } 59130610Smlaier } else { /* x < 0 */ 60130610Smlaier if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ 61130610Smlaier if(lx==0) hx--; 62130610Smlaier lx--; 63130610Smlaier } else { /* x > y, x += ulp */ 64130610Smlaier lx++; 65130610Smlaier if(lx==0) hx++; 66130610Smlaier } 67130610Smlaier } 68130610Smlaier hy = hx&0x7fff000000000000LL; 69130610Smlaier if(hy==0x7fff000000000000LL) { 70130610Smlaier __float128 u = x + x; /* overflow */ 71130610Smlaier math_force_eval (u); 72130610Smlaier errno = ERANGE; 73130610Smlaier } 74130610Smlaier if(hy==0) { 75130610Smlaier __float128 u = x*x; /* underflow */ 76130610Smlaier math_force_eval (u); /* raise underflow flag */ 77130610Smlaier errno = ERANGE; 78130610Smlaier } 79130610Smlaier SET_FLT128_WORDS64(x,hx,lx); 80130610Smlaier return x; 81130613Smlaier} 82130610Smlaier