1 /* @(#)s_nextafter.c 5.1 93/09/24 */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12 
13 /* IEEE functions
14  *	nextafterl(x,y)
15  *	return the next machine floating-point number of x in the
16  *	direction toward y.
17  *   Special cases:
18  */
19 
20 
21 
22 long double
nextafterl(long double x,long double y)23 nextafterl(long double x, long double y)
24 {
25 	u_int32_t hx,hy,ix,iy;
26 	u_int32_t lx,ly;
27         int32_t esx,esy;
28 
29 	GET_LDOUBLE_WORDS(esx,hx,lx,x);
30 	GET_LDOUBLE_WORDS(esy,hy,ly,y);
31 	ix = esx&0x7fff;		/* |x| */
32 	iy = esy&0x7fff;		/* |y| */
33 
34 	if (((ix==0x7fff)&&(((hx&0x7fffffff)|lx)!=0)) ||   /* x is nan */
35 	    ((iy==0x7fff)&&(((hy&0x7fffffff)|ly)!=0)))     /* y is nan */
36 	   return x+y;
37 	if(x==y) return y;		/* x=y, return y */
38 	if((ix|hx|lx)==0) {			/* x == 0 */
39             SET_LDOUBLE_WORDS(x,esy & 0x8000,hx,1);
40             force_eval_long_double(opt_barrier_long_double(x)*x);
41             return x;
42 	}
43 	if(esx>=0) {			/* x > 0 */
44 	    if(esy<0||(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly)))))) {
45 	      /* x > y, x -= ulp */
46 		if(lx==0) {
47 		    if ((hx&0x7fffffff)==0) esx -= 1;
48 		    hx = (hx - 1) | (hx & 0x80000000);
49 		}
50 		lx -= 1;
51 	    } else {				/* x < y, x += ulp */
52 		lx += 1;
53 		if(lx==0) {
54 		    hx = (hx + 1) | (hx & 0x80000000);
55 		    if ((hx&0x7fffffff)==0) esx += 1;
56 		}
57 	    }
58 	} else {				/* x < 0 */
59 	    if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
60 	      /* x < y, x -= ulp */
61 		if(lx==0) {
62 		    if ((hx&0x7fffffff)==0) esx -= 1;
63 		    hx = (hx - 1) | (hx & 0x80000000);
64 		}
65 		lx -= 1;
66 	    } else {				/* x > y, x += ulp */
67 		lx += 1;
68 		if(lx==0) {
69 		    hx = (hx + 1) | (hx & 0x80000000);
70 		    if ((hx&0x7fffffff)==0) esx += 1;
71 		}
72 	    }
73 	}
74 	esy = esx&0x7fff;
75 	if(esy==0x7fff)
76             return __math_oflowl(esx & 0x8000);		/* overflow  */
77 	SET_LDOUBLE_WORDS(x,esx,hx,lx);
78 	if(esy==0)
79             return __math_denorml(x);
80 	return x;
81 }
82 
83 #ifdef _HAVE_ALIAS_ATTRIBUTE
84 __strong_reference(nextafterl, nexttowardl);
85 #else
86 long double
nexttowardl(long double x,long double y)87 nexttowardl(long double x, long double y)
88 {
89     return nextafterl(x, y);
90 }
91 #endif
92