xref: /minix3/lib/libm/src/s_nextafterl.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /* @(#)s_nextafter.c 5.1 93/09/24 */
42fe8fb19SBen Gras /*
52fe8fb19SBen Gras  * ====================================================
62fe8fb19SBen Gras  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
72fe8fb19SBen Gras  *
82fe8fb19SBen Gras  * Developed at SunPro, a Sun Microsystems, Inc. business.
92fe8fb19SBen Gras  * Permission to use, copy, modify, and distribute this
102fe8fb19SBen Gras  * software is freely granted, provided that this notice
112fe8fb19SBen Gras  * is preserved.
122fe8fb19SBen Gras  * ====================================================
132fe8fb19SBen Gras  */
142fe8fb19SBen Gras 
152fe8fb19SBen Gras #include <sys/cdefs.h>
16*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt Exp $");
172fe8fb19SBen Gras 
182fe8fb19SBen Gras #include <float.h>
192fe8fb19SBen Gras #include <math.h>
202fe8fb19SBen Gras #include <machine/ieee.h>
212fe8fb19SBen Gras 
2284d9c625SLionel Sambuc #ifdef __HAVE_LONG_DOUBLE
2384d9c625SLionel Sambuc 
242fe8fb19SBen Gras #ifdef EXT_EXP_INFNAN
252fe8fb19SBen Gras #if LDBL_MAX_EXP != 0x4000
262fe8fb19SBen Gras #error "Unsupported long double format"
272fe8fb19SBen Gras #endif
282fe8fb19SBen Gras 
2984d9c625SLionel Sambuc #ifdef LDBL_IMPLICIT_NBIT
3084d9c625SLionel Sambuc #define	LDBL_NBIT	0
3184d9c625SLionel Sambuc #endif
3284d9c625SLionel Sambuc 
332fe8fb19SBen Gras /*
342fe8fb19SBen Gras  * IEEE functions
352fe8fb19SBen Gras  *      nextafterl(x,y)
362fe8fb19SBen Gras  *      return the next machine floating-point number of x in the
372fe8fb19SBen Gras  *      direction toward y.
382fe8fb19SBen Gras  *   Special cases:
392fe8fb19SBen Gras  *	If x == y, y shall be returned
402fe8fb19SBen Gras  *	If x or y is NaN, a NaN shall be returned
412fe8fb19SBen Gras  */
422fe8fb19SBen Gras long double
nextafterl(long double x,long double y)432fe8fb19SBen Gras nextafterl(long double x, long double y)
442fe8fb19SBen Gras {
452fe8fb19SBen Gras 	volatile long double t;
462fe8fb19SBen Gras 	union ieee_ext_u ux, uy;
472fe8fb19SBen Gras 
482fe8fb19SBen Gras 	ux.extu_ld = x;
492fe8fb19SBen Gras 	uy.extu_ld = y;
502fe8fb19SBen Gras 
51*0a6a1f1dSLionel Sambuc 	if ((ux.extu_exp == EXT_EXP_INFNAN &&
522fe8fb19SBen Gras 		((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) ||
53*0a6a1f1dSLionel Sambuc 	    (uy.extu_exp == EXT_EXP_INFNAN &&
542fe8fb19SBen Gras 		((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0))
552fe8fb19SBen Gras 		return x+y;			/* x or y is nan */
562fe8fb19SBen Gras 
572fe8fb19SBen Gras 	if (x == y) return y;			/* x=y, return y */
582fe8fb19SBen Gras 
592fe8fb19SBen Gras 	if (x == 0.0) {
602fe8fb19SBen Gras 		ux.extu_frach = 0;		/* return +-minsubnormal */
612fe8fb19SBen Gras 		ux.extu_fracl = 1;
622fe8fb19SBen Gras 		ux.extu_sign = uy.extu_sign;
632fe8fb19SBen Gras 		t = ux.extu_ld * ux.extu_ld;
642fe8fb19SBen Gras 		if (t == ux.extu_ld)
652fe8fb19SBen Gras 			return t;
662fe8fb19SBen Gras 		else
672fe8fb19SBen Gras 			return ux.extu_ld;	/* raise underflow flag */
682fe8fb19SBen Gras 	}
692fe8fb19SBen Gras 
702fe8fb19SBen Gras 	if ((x>0.0) ^ (x<y)) {			/* x -= ulp */
712fe8fb19SBen Gras 		if (ux.extu_fracl == 0) {
722fe8fb19SBen Gras 			if ((ux.extu_frach & ~LDBL_NBIT) == 0)
732fe8fb19SBen Gras 				ux.extu_exp -= 1;
742fe8fb19SBen Gras 			ux.extu_frach = (ux.extu_frach - 1) |
752fe8fb19SBen Gras 					(ux.extu_frach & LDBL_NBIT);
762fe8fb19SBen Gras 		}
772fe8fb19SBen Gras 		ux.extu_fracl -= 1;
782fe8fb19SBen Gras 	} else {				/* x += ulp */
792fe8fb19SBen Gras 		ux.extu_fracl += 1;
802fe8fb19SBen Gras 		if (ux.extu_fracl == 0) {
812fe8fb19SBen Gras 			ux.extu_frach = (ux.extu_frach + 1) |
822fe8fb19SBen Gras 					(ux.extu_frach & LDBL_NBIT);
832fe8fb19SBen Gras 			if ((ux.extu_frach & ~LDBL_NBIT) == 0)
842fe8fb19SBen Gras 				ux.extu_exp += 1;
852fe8fb19SBen Gras 		}
862fe8fb19SBen Gras 	}
872fe8fb19SBen Gras 
88*0a6a1f1dSLionel Sambuc 	if (ux.extu_exp == EXT_EXP_INFNAN)
892fe8fb19SBen Gras 		return x+x;			/* overflow  */
902fe8fb19SBen Gras 
912fe8fb19SBen Gras 	if (ux.extu_exp == 0) {			/* underflow */
9284d9c625SLionel Sambuc #ifndef LDBL_IMPLICIT_NBIT
932fe8fb19SBen Gras 		mask_nbit_l(ux);
9484d9c625SLionel Sambuc #endif
952fe8fb19SBen Gras 		t = ux.extu_ld * ux.extu_ld;
962fe8fb19SBen Gras 		if (t != ux.extu_ld)		/* raise underflow flag */
972fe8fb19SBen Gras 			return ux.extu_ld;
982fe8fb19SBen Gras 	}
992fe8fb19SBen Gras 
1002fe8fb19SBen Gras 	return ux.extu_ld;
1012fe8fb19SBen Gras }
1022fe8fb19SBen Gras #endif
10384d9c625SLionel Sambuc 
10484d9c625SLionel Sambuc #endif /* __HAVE_LONG_DOUBLE */
105