xref: /inferno-os/libmath/fdlibm/s_nextafter.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /* derived from /netlib/fdlibm */
2*37da2899SCharles.Forsyth 
3*37da2899SCharles.Forsyth /* @(#)s_nextafter.c 1.3 95/01/18 */
4*37da2899SCharles.Forsyth /*
5*37da2899SCharles.Forsyth  * ====================================================
6*37da2899SCharles.Forsyth  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7*37da2899SCharles.Forsyth  *
8*37da2899SCharles.Forsyth  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9*37da2899SCharles.Forsyth  * Permission to use, copy, modify, and distribute this
10*37da2899SCharles.Forsyth  * software is freely granted, provided that this notice
11*37da2899SCharles.Forsyth  * is preserved.
12*37da2899SCharles.Forsyth  * ====================================================
13*37da2899SCharles.Forsyth  */
14*37da2899SCharles.Forsyth 
15*37da2899SCharles.Forsyth /* IEEE functions
16*37da2899SCharles.Forsyth  *	nextafter(x,y)
17*37da2899SCharles.Forsyth  *	return the next machine floating-point number of x in the
18*37da2899SCharles.Forsyth  *	direction toward y.
19*37da2899SCharles.Forsyth  *   Special cases:
20*37da2899SCharles.Forsyth  */
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth #include "fdlibm.h"
23*37da2899SCharles.Forsyth 
nextafter(double x,double y)24*37da2899SCharles.Forsyth 	double nextafter(double x, double y)
25*37da2899SCharles.Forsyth {
26*37da2899SCharles.Forsyth 	int	hx,hy,ix,iy;
27*37da2899SCharles.Forsyth 	unsigned lx,ly;
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 	hx = __HI(x);		/* high word of x */
30*37da2899SCharles.Forsyth 	lx = __LO(x);		/* low  word of x */
31*37da2899SCharles.Forsyth 	hy = __HI(y);		/* high word of y */
32*37da2899SCharles.Forsyth 	ly = __LO(y);		/* low  word of y */
33*37da2899SCharles.Forsyth 	ix = hx&0x7fffffff;		/* |x| */
34*37da2899SCharles.Forsyth 	iy = hy&0x7fffffff;		/* |y| */
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth 	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
37*37da2899SCharles.Forsyth 	   ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
38*37da2899SCharles.Forsyth 	   return x+y;
39*37da2899SCharles.Forsyth 	if(x==y) return x;		/* x=y, return x */
40*37da2899SCharles.Forsyth 	if((ix|lx)==0) {			/* x == 0 */
41*37da2899SCharles.Forsyth 	    __HI(x) = hy&0x80000000;	/* return +-minsubnormal */
42*37da2899SCharles.Forsyth 	    __LO(x) = 1;
43*37da2899SCharles.Forsyth 	    y = x*x;
44*37da2899SCharles.Forsyth 	    if(y==x) return y; else return x;	/* raise underflow flag */
45*37da2899SCharles.Forsyth 	}
46*37da2899SCharles.Forsyth 	if(hx>=0) {				/* x > 0 */
47*37da2899SCharles.Forsyth 	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
48*37da2899SCharles.Forsyth 		if(lx==0) hx -= 1;
49*37da2899SCharles.Forsyth 		lx -= 1;
50*37da2899SCharles.Forsyth 	    } else {				/* x < y, x += ulp */
51*37da2899SCharles.Forsyth 		lx += 1;
52*37da2899SCharles.Forsyth 		if(lx==0) hx += 1;
53*37da2899SCharles.Forsyth 	    }
54*37da2899SCharles.Forsyth 	} else {				/* x < 0 */
55*37da2899SCharles.Forsyth 	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
56*37da2899SCharles.Forsyth 		if(lx==0) hx -= 1;
57*37da2899SCharles.Forsyth 		lx -= 1;
58*37da2899SCharles.Forsyth 	    } else {				/* x > y, x += ulp */
59*37da2899SCharles.Forsyth 		lx += 1;
60*37da2899SCharles.Forsyth 		if(lx==0) hx += 1;
61*37da2899SCharles.Forsyth 	    }
62*37da2899SCharles.Forsyth 	}
63*37da2899SCharles.Forsyth 	hy = hx&0x7ff00000;
64*37da2899SCharles.Forsyth 	if(hy>=0x7ff00000) return x+x;	/* overflow  */
65*37da2899SCharles.Forsyth 	if(hy<0x00100000) {		/* underflow */
66*37da2899SCharles.Forsyth 	    y = x*x;
67*37da2899SCharles.Forsyth 	    if(y!=x) {		/* raise underflow flag */
68*37da2899SCharles.Forsyth 		__HI(y) = hx; __LO(y) = lx;
69*37da2899SCharles.Forsyth 		return y;
70*37da2899SCharles.Forsyth 	    }
71*37da2899SCharles.Forsyth 	}
72*37da2899SCharles.Forsyth 	__HI(x) = hx; __LO(x) = lx;
73*37da2899SCharles.Forsyth 	return x;
74*37da2899SCharles.Forsyth }
75