s_nextafterf.c revision 140685
1238106Sdes/* s_nextafterf.c -- float version of s_nextafter.c.
2238106Sdes * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3238106Sdes */
4238106Sdes
5238106Sdes/*
6238106Sdes * ====================================================
7238106Sdes * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8238106Sdes *
9238106Sdes * Developed at SunPro, a Sun Microsystems, Inc. business.
10238106Sdes * Permission to use, copy, modify, and distribute this
11238106Sdes * software is freely granted, provided that this notice
12238106Sdes * is preserved.
13238106Sdes * ====================================================
14238106Sdes */
15238106Sdes
16238106Sdes#ifndef lint
17238106Sdesstatic char rcsid[] = "$FreeBSD: head/lib/msun/src/s_nextafterf.c 140685 2005-01-23 22:56:08Z das $";
18238106Sdes#endif
19238106Sdes
20238106Sdes#include "math.h"
21238106Sdes#include "math_private.h"
22238106Sdes
23238106Sdesfloat
24269257Sdesnextafterf(float x, float y)
25269257Sdes{
26269257Sdes	int32_t hx,hy,ix,iy;
27269257Sdes
28269257Sdes	GET_FLOAT_WORD(hx,x);
29269257Sdes	GET_FLOAT_WORD(hy,y);
30269257Sdes	ix = hx&0x7fffffff;		/* |x| */
31269257Sdes	iy = hy&0x7fffffff;		/* |y| */
32269257Sdes
33269257Sdes	if((ix>0x7f800000) ||   /* x is nan */
34238106Sdes	   (iy>0x7f800000))     /* y is nan */
35238106Sdes	   return x+y;
36238106Sdes	if(x==y) return y;		/* x=y, return y */
37238106Sdes	if(ix==0) {				/* x == 0 */
38238106Sdes	    SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
39238106Sdes	    y = x*x;
40238106Sdes	    if(y==x) return y; else return x;	/* raise underflow flag */
41238106Sdes	}
42238106Sdes	if(hx>=0) {				/* x > 0 */
43238106Sdes	    if(hx>hy) {				/* x > y, x -= ulp */
44238106Sdes		hx -= 1;
45238106Sdes	    } else {				/* x < y, x += ulp */
46238106Sdes		hx += 1;
47238106Sdes	    }
48238106Sdes	} else {				/* x < 0 */
49238106Sdes	    if(hy>=0||hx>hy){			/* x < y, x -= ulp */
50238106Sdes		hx -= 1;
51238106Sdes	    } else {				/* x > y, x += ulp */
52238106Sdes		hx += 1;
53238106Sdes	    }
54238106Sdes	}
55238106Sdes	hy = hx&0x7f800000;
56238106Sdes	if(hy>=0x7f800000) return x+x;	/* overflow  */
57238106Sdes	if(hy<0x00800000) {		/* underflow */
58238106Sdes	    y = x*x;
59238106Sdes	    if(y!=x) {		/* raise underflow flag */
60238106Sdes	        SET_FLOAT_WORD(y,hx);
61238106Sdes		return y;
62238106Sdes	    }
63238106Sdes	}
64238106Sdes	SET_FLOAT_WORD(x,hx);
65238106Sdes	return x;
66238106Sdes}
67238106Sdes