11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved.
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nexttowardf.c,v 1.1 2005/03/07 04:57:38 das Exp $";
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <float.h>
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fpmath.h"
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h"
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h"
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	LDBL_INFNAN_EXP	(LDBL_MAX_EXP * 2 - 1)
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfloat
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnexttowardf(float x, long double y)
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	union IEEEl2bits uy;
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	volatile float t;
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int32_t hx,ix;
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	GET_FLOAT_WORD(hx,x);
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ix = hx&0x7fffffff;		/* |x| */
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uy.e = y;
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if((ix>0x7f800000) ||
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   (uy.bits.exp == LDBL_INFNAN_EXP &&
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   return x+y;	/* x or y is nan */
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(x==y) return (float)y;		/* x=y, return y */
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix==0) {				/* x == 0 */
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = x*x;
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(t==x) return t; else return x;	/* raise underflow flag */
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(hx>=0 ^ x < y)			/* x -= ulp */
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    hx -= 1;
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else					/* x += ulp */
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    hx += 1;
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ix = hx&0x7f800000;
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix>=0x7f800000) return x+x;	/* overflow  */
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix<0x00800000) {		/* underflow */
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = x*x;
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(t!=x) {		/* raise underflow flag */
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        SET_FLOAT_WORD(y,hx);
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return y;
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	SET_FLOAT_WORD(x,hx);
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return x;
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
61