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