s_nexttowardf.c revision 143218
13229Spst/*
23229Spst * ====================================================
318471Swosch * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
418471Swosch *
53229Spst * Developed at SunPro, a Sun Microsystems, Inc. business.
63229Spst * Permission to use, copy, modify, and distribute this
73229Spst * software is freely granted, provided that this notice
83229Spst * is preserved.
93229Spst * ====================================================
103229Spst */
113229Spst
123229Spst#ifndef lint
133229Spststatic char rcsid[] = "$FreeBSD: head/lib/msun/src/s_nexttowardf.c 143218 2005-03-07 04:57:38Z das $";
143229Spst#endif
153229Spst
163229Spst#include <float.h>
173229Spst
183229Spst#include "fpmath.h"
193229Spst#include "math.h"
203229Spst#include "math_private.h"
213229Spst
223229Spst#define	LDBL_INFNAN_EXP	(LDBL_MAX_EXP * 2 - 1)
233229Spst
243229Spstfloat
253229Spstnexttowardf(float x, long double y)
263229Spst{
273229Spst	union IEEEl2bits uy;
283229Spst	volatile float t;
293229Spst	int32_t hx,ix;
303229Spst
313229Spst	GET_FLOAT_WORD(hx,x);
323229Spst	ix = hx&0x7fffffff;		/* |x| */
333229Spst	uy.e = y;
343229Spst
353229Spst	if((ix>0x7f800000) ||
363229Spst	   (uy.bits.exp == LDBL_INFNAN_EXP &&
373229Spst	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
383229Spst	   return x+y;	/* x or y is nan */
393229Spst	if(x==y) return (float)y;		/* x=y, return y */
403229Spst	if(ix==0) {				/* x == 0 */
413229Spst	    SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
423229Spst	    t = x*x;
433229Spst	    if(t==x) return t; else return x;	/* raise underflow flag */
443229Spst	}
453229Spst	if(hx>=0 ^ x < y)			/* x -= ulp */
463229Spst	    hx -= 1;
473229Spst	else					/* x += ulp */
483229Spst	    hx += 1;
493229Spst	ix = hx&0x7f800000;
503229Spst	if(ix>=0x7f800000) return x+x;	/* overflow  */
513229Spst	if(ix<0x00800000) {		/* underflow */
523229Spst	    t = x*x;
533229Spst	    if(t!=x) {		/* raise underflow flag */
543229Spst	        SET_FLOAT_WORD(y,hx);
553229Spst		return y;
563229Spst	    }
573229Spst	}
583229Spst	SET_FLOAT_WORD(x,hx);
593229Spst	return x;
603229Spst}
613229Spst