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