1 /* s_nextafterl.c -- long double version of s_nextafter.c.
2 * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
6 * ====================================================
7 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9 * Developed at SunPro, a Sun Microsystems, Inc. business.
10 * Permission to use, copy, modify, and distribute this
11 * software is freely granted, provided that this notice
13 * ====================================================
16 #if defined(LIBM_SCCS) && !defined(lint)
17 static char rcsid
[] = "$NetBSD: $";
22 * return the next machine floating-point number of x in the
28 #include <math_private.h>
29 #include <math_ldbl_opt.h>
31 long double __nextafterl(long double x
, long double y
)
33 int64_t hx
,hy
,ihx
,ihy
,ilx
;
35 u_int64_t ly
__attribute__ ((unused
));
37 GET_LDOUBLE_WORDS64(hx
,lx
,x
);
38 GET_LDOUBLE_WORDS64(hy
,ly
,y
);
39 ihx
= hx
&0x7fffffffffffffffLL
; /* |hx| */
40 ilx
= lx
&0x7fffffffffffffffLL
; /* |lx| */
41 ihy
= hy
&0x7fffffffffffffffLL
; /* |hy| */
43 if((((ihx
&0x7ff0000000000000LL
)==0x7ff0000000000000LL
)&&
44 ((ihx
&0x000fffffffffffffLL
)!=0)) || /* x is nan */
45 (((ihy
&0x7ff0000000000000LL
)==0x7ff0000000000000LL
)&&
46 ((ihy
&0x000fffffffffffffLL
)!=0))) /* y is nan */
47 return x
+y
; /* signal the nan */
49 return y
; /* x=y, return y */
50 if(ihx
== 0 && ilx
== 0) { /* x == 0 */
52 hy
= (hy
& 0x8000000000000000ULL
) | 1;
53 SET_LDOUBLE_WORDS64(x
,hy
,0ULL);/* return +-minsubnormal */
54 u
= math_opt_barrier (x
);
56 math_force_eval (u
); /* raise underflow flag */
61 if(x
> y
) { /* x > y, x -= ulp */
62 if((hx
==0xffefffffffffffffLL
)&&(lx
==0xfc8ffffffffffffeLL
))
63 return x
+x
; /* overflow, return -inf */
64 if (hx
>= 0x7ff0000000000000LL
) {
65 SET_LDOUBLE_WORDS64(u
,0x7fefffffffffffffLL
,0x7c8ffffffffffffeLL
);
68 if(ihx
<= 0x0360000000000000LL
) { /* x <= LDBL_MIN */
69 u
= math_opt_barrier (x
);
70 x
-= __LDBL_DENORM_MIN__
;
71 if (ihx
< 0x0360000000000000LL
72 || (hx
> 0 && (int64_t) lx
<= 0)
73 || (hx
< 0 && (int64_t) lx
> 1)) {
75 math_force_eval (u
); /* raise underflow flag */
79 if (ihx
< 0x06a0000000000000LL
) { /* ulp will denormal */
80 SET_LDOUBLE_WORDS64(u
,(hx
&0x7ff0000000000000LL
),0ULL);
81 u
*= 0x1.0000000000000p
-105L;
83 SET_LDOUBLE_WORDS64(u
,(hx
&0x7ff0000000000000LL
)-0x0690000000000000LL
,0ULL);
85 } else { /* x < y, x += ulp */
86 if((hx
==0x7fefffffffffffffLL
)&&(lx
==0x7c8ffffffffffffeLL
))
87 return x
+x
; /* overflow, return +inf */
88 if ((u_int64_t
) hx
>= 0xfff0000000000000ULL
) {
89 SET_LDOUBLE_WORDS64(u
,0xffefffffffffffffLL
,0xfc8ffffffffffffeLL
);
92 if(ihx
<= 0x0360000000000000LL
) { /* x <= LDBL_MIN */
93 u
= math_opt_barrier (x
);
94 x
+= __LDBL_DENORM_MIN__
;
95 if (ihx
< 0x0360000000000000LL
96 || (hx
> 0 && (int64_t) lx
< 0 && lx
!= 0x8000000000000001LL
)
97 || (hx
< 0 && (int64_t) lx
>= 0)) {
99 math_force_eval (u
); /* raise underflow flag */
101 if (x
== 0.0L) /* handle negative __LDBL_DENORM_MIN__ case */
105 if (ihx
< 0x06a0000000000000LL
) { /* ulp will denormal */
106 SET_LDOUBLE_WORDS64(u
,(hx
&0x7ff0000000000000LL
),0ULL);
107 u
*= 0x1.0000000000000p
-105L;
109 SET_LDOUBLE_WORDS64(u
,(hx
&0x7ff0000000000000LL
)-0x0690000000000000LL
,0ULL);
113 strong_alias (__nextafterl
, __nexttowardl
)
114 long_double_symbol (libm
, __nextafterl
, nextafterl
);
115 long_double_symbol (libm
, __nexttowardl
, nexttowardl
);