11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)s_nextafter.c 5.1 93/09/24 */
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business.
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h>
14a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$");
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* IEEE functions
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	nextafter(x,y)
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	return the next machine floating-point number of x in the
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	direction toward y.
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   Special cases:
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <float.h>
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fpmath.h"
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h"
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h"
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if LDBL_MAX_EXP != 0x4000
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#error "Unsupported long double format"
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlong double
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnextafterl(long double x, long double y)
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	volatile long double t;
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	union IEEEl2bits ux, uy;
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ux.e = x;
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uy.e = y;
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((ux.bits.exp == 0x7fff &&
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    (uy.bits.exp == 0x7fff &&
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   return x+y;	/* x or y is nan */
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(x==y) return y;		/* x=y, return y */
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(x==0.0) {
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ux.bits.manh = 0;			/* return +-minsubnormal */
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ux.bits.manl = 1;
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ux.bits.sign = uy.bits.sign;
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = ux.e*ux.e;
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(x>0.0 ^ x<y) {			/* x -= ulp */
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(ux.bits.manl==0) {
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((ux.bits.manh&~LDBL_NBIT)==0)
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ux.bits.exp -= 1;
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ux.bits.manl -= 1;
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {				/* x += ulp */
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ux.bits.manl += 1;
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(ux.bits.manl==0) {
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((ux.bits.manh&~LDBL_NBIT)==0)
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ux.bits.exp += 1;
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ux.bits.exp==0x7fff) return x+x;	/* overflow  */
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ux.bits.exp==0) {			/* underflow */
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    mask_nbit_l(ux);
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = ux.e * ux.e;
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(t!=ux.e)			/* raise underflow flag */
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return ux.e;
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return ux.e;
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__strong_reference(nextafterl, nexttowardl);
81