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