xref: /openbsd-src/lib/libm/src/ld128/s_nextafterl.c (revision 2f2c00629eff6a304ebffb255fc56f4fa7a1833b)
149393c00Smartynas /* @(#)s_nextafter.c 5.1 93/09/24 */
249393c00Smartynas /*
349393c00Smartynas  * ====================================================
449393c00Smartynas  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
549393c00Smartynas  *
649393c00Smartynas  * Developed at SunPro, a Sun Microsystems, Inc. business.
749393c00Smartynas  * Permission to use, copy, modify, and distribute this
849393c00Smartynas  * software is freely granted, provided that this notice
949393c00Smartynas  * is preserved.
1049393c00Smartynas  * ====================================================
1149393c00Smartynas  */
1249393c00Smartynas 
1349393c00Smartynas /* IEEE functions
1449393c00Smartynas  *	nextafterl(x,y)
1549393c00Smartynas  *	return the next machine floating-point number of x in the
1649393c00Smartynas  *	direction toward y.
1749393c00Smartynas  *   Special cases:
1849393c00Smartynas  */
1949393c00Smartynas 
2049393c00Smartynas #include <math.h>
2149393c00Smartynas 
2249393c00Smartynas #include "math_private.h"
2349393c00Smartynas 
2449393c00Smartynas long double
nextafterl(long double x,long double y)2549393c00Smartynas nextafterl(long double x, long double y)
2649393c00Smartynas {
2749393c00Smartynas 	int64_t hx,hy,ix,iy;
2849393c00Smartynas 	u_int64_t lx,ly;
2949393c00Smartynas 
3049393c00Smartynas 	GET_LDOUBLE_WORDS64(hx,lx,x);
3149393c00Smartynas 	GET_LDOUBLE_WORDS64(hy,ly,y);
3249393c00Smartynas 	ix = hx&0x7fffffffffffffffLL;		/* |x| */
3349393c00Smartynas 	iy = hy&0x7fffffffffffffffLL;		/* |y| */
3449393c00Smartynas 
3549393c00Smartynas 	if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) ||   /* x is nan */
3649393c00Smartynas 	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))     /* y is nan */
3749393c00Smartynas 	   return x+y;
3849393c00Smartynas 	if(x==y) return y;		/* x=y, return y */
3949393c00Smartynas 	if((ix|lx)==0) {			/* x == 0 */
4049393c00Smartynas 	    volatile long double u;
4149393c00Smartynas 	    SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */
4249393c00Smartynas 	    u = x;
4349393c00Smartynas 	    u = u * u;				/* raise underflow flag */
4449393c00Smartynas 	    return x;
4549393c00Smartynas 	}
4649393c00Smartynas 	if(hx>=0) {			/* x > 0 */
4749393c00Smartynas 	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
4849393c00Smartynas 		if(lx==0) hx--;
4949393c00Smartynas 		lx--;
5049393c00Smartynas 	    } else {				/* x < y, x += ulp */
5149393c00Smartynas 		lx++;
5249393c00Smartynas 		if(lx==0) hx++;
5349393c00Smartynas 	    }
5449393c00Smartynas 	} else {				/* x < 0 */
5549393c00Smartynas 	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
5649393c00Smartynas 		if(lx==0) hx--;
5749393c00Smartynas 		lx--;
5849393c00Smartynas 	    } else {				/* x > y, x += ulp */
5949393c00Smartynas 		lx++;
6049393c00Smartynas 		if(lx==0) hx++;
6149393c00Smartynas 	    }
6249393c00Smartynas 	}
6349393c00Smartynas 	hy = hx&0x7fff000000000000LL;
6449393c00Smartynas 	if(hy==0x7fff000000000000LL) return x+x;/* overflow  */
6549393c00Smartynas 	if(hy==0) {
6649393c00Smartynas 	    volatile long double u = x*x;	/* underflow */
6749393c00Smartynas 	}
6849393c00Smartynas 	SET_LDOUBLE_WORDS64(x,hx,lx);
6949393c00Smartynas 	return x;
7049393c00Smartynas }
71*2f2c0062Sguenther DEF_STD(nextafterl);
72*2f2c0062Sguenther MAKE_UNUSED_CLONE(nexttowardl, nextafterl);
73