2.5-18.1
[jlayton/glibc.git] / sysdeps / ieee754 / ldbl-96 / s_nextafterl.c
1 /* s_nextafterl.c -- long double version of s_nextafter.c.
2  * Conversion to long double by Ulrich Drepper,
3  * Cygnus Support, drepper@cygnus.com.
4  */
5
6 /*
7  * ====================================================
8  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9  *
10  * Developed at SunPro, a Sun Microsystems, Inc. business.
11  * Permission to use, copy, modify, and distribute this
12  * software is freely granted, provided that this notice
13  * is preserved.
14  * ====================================================
15  */
16
17 #if defined(LIBM_SCCS) && !defined(lint)
18 static char rcsid[] = "$NetBSD: $";
19 #endif
20
21 /* IEEE functions
22  *      nextafterl(x,y)
23  *      return the next machine floating-point number of x in the
24  *      direction toward y.
25  *   Special cases:
26  */
27
28 #include "math.h"
29 #include <math_private.h>
30
31 #ifdef __STDC__
32         long double __nextafterl(long double x, long double y)
33 #else
34         long double __nextafterl(x,y)
35         long double x,y;
36 #endif
37 {
38         int32_t hx,hy,ix,iy;
39         u_int32_t lx,ly,esx,esy;
40
41         GET_LDOUBLE_WORDS(esx,hx,lx,x);
42         GET_LDOUBLE_WORDS(esy,hy,ly,y);
43         ix = esx&0x7fff;                /* |x| */
44         iy = esy&0x7fff;                /* |y| */
45
46         if (((ix==0x7fff)&&((hx|lx)!=0)) ||   /* x is nan */
47             ((iy==0x7fff)&&((hy|ly)!=0)))     /* y is nan */
48            return x+y;
49         if(x==y) return y;              /* x=y, return y */
50         if((ix|hx|lx)==0) {                     /* x == 0 */
51             long double u;
52             SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */
53             u = math_opt_barrier (x);
54             u = u * u;
55             math_force_eval (u);                /* raise underflow flag */
56             return x;
57         }
58         if(esx<0x8000) {                        /* x > 0 */
59             if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) {
60               /* x > y, x -= ulp */
61                 if(lx==0) {
62                     if (hx==0) esx -= 1;
63                     hx -= 1;
64                 }
65                 lx -= 1;
66             } else {                            /* x < y, x += ulp */
67                 lx += 1;
68                 if(lx==0) {
69                     hx += 1;
70                     if (hx==0)
71                         esx += 1;
72                 }
73             }
74         } else {                                /* x < 0 */
75             if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
76               /* x < y, x -= ulp */
77                 if(lx==0) {
78                     if (hx==0) esx -= 1;
79                     hx -= 1;
80                 }
81                 lx -= 1;
82             } else {                            /* x > y, x += ulp */
83                 lx += 1;
84                 if(lx==0) {
85                     hx += 1;
86                     if (hx==0) esx += 1;
87                 }
88             }
89         }
90         esy = esx&0x7fff;
91         if(esy==0x7fff) return x+x;             /* overflow  */
92         if(esy==0) {
93             long double u = x*x;                /* underflow */
94             math_force_eval (u);                /* raise underflow flag */
95         }
96         SET_LDOUBLE_WORDS(x,esx,hx,lx);
97         return x;
98 }
99 weak_alias (__nextafterl, nextafterl)
100 strong_alias (__nextafterl, __nexttowardl)
101 weak_alias (__nextafterl, nexttowardl)