12fe8fb19SBen Gras /* @(#)s_nextafter.c 5.1 93/09/24 */
22fe8fb19SBen Gras /*
32fe8fb19SBen Gras * ====================================================
42fe8fb19SBen Gras * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
52fe8fb19SBen Gras *
62fe8fb19SBen Gras * Developed at SunPro, a Sun Microsystems, Inc. business.
72fe8fb19SBen Gras * Permission to use, copy, modify, and distribute this
82fe8fb19SBen Gras * software is freely granted, provided that this notice
92fe8fb19SBen Gras * is preserved.
102fe8fb19SBen Gras * ====================================================
112fe8fb19SBen Gras */
122fe8fb19SBen Gras
132fe8fb19SBen Gras #include <sys/cdefs.h>
142fe8fb19SBen Gras #if defined(LIBM_SCCS) && !defined(lint)
15*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: s_nextafter.c,v 1.14 2014/03/18 18:20:37 riastradh Exp $");
162fe8fb19SBen Gras #endif
172fe8fb19SBen Gras
182fe8fb19SBen Gras /* IEEE functions
192fe8fb19SBen Gras * nextafter(x,y)
202fe8fb19SBen Gras * return the next machine floating-point number of x in the
212fe8fb19SBen Gras * direction toward y.
222fe8fb19SBen Gras * Special cases:
232fe8fb19SBen Gras */
242fe8fb19SBen Gras
252fe8fb19SBen Gras #include "math.h"
262fe8fb19SBen Gras #include "math_private.h"
272fe8fb19SBen Gras
2884d9c625SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
__strong_alias(nextafterl,nextafter)2984d9c625SLionel Sambuc __strong_alias(nextafterl, nextafter)
3084d9c625SLionel Sambuc #endif
3184d9c625SLionel Sambuc
322fe8fb19SBen Gras double
332fe8fb19SBen Gras nextafter(double x, double y)
342fe8fb19SBen Gras {
352fe8fb19SBen Gras int32_t hx,hy,ix,iy;
362fe8fb19SBen Gras u_int32_t lx,ly;
372fe8fb19SBen Gras
382fe8fb19SBen Gras EXTRACT_WORDS(hx,lx,x);
392fe8fb19SBen Gras EXTRACT_WORDS(hy,ly,y);
402fe8fb19SBen Gras ix = hx&0x7fffffff; /* |x| */
412fe8fb19SBen Gras iy = hy&0x7fffffff; /* |y| */
422fe8fb19SBen Gras
432fe8fb19SBen Gras if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
442fe8fb19SBen Gras ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */
452fe8fb19SBen Gras return x+y;
4684d9c625SLionel Sambuc if(x==y) return y; /* x=y, return y */
472fe8fb19SBen Gras if((ix|lx)==0) { /* x == 0 */
482fe8fb19SBen Gras INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */
492fe8fb19SBen Gras y = x*x;
502fe8fb19SBen Gras if(y==x) return y; else return x; /* raise underflow flag */
512fe8fb19SBen Gras }
522fe8fb19SBen Gras if(hx>=0) { /* x > 0 */
532fe8fb19SBen Gras if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */
542fe8fb19SBen Gras if(lx==0) hx -= 1;
552fe8fb19SBen Gras lx -= 1;
562fe8fb19SBen Gras } else { /* x < y, x += ulp */
572fe8fb19SBen Gras lx += 1;
582fe8fb19SBen Gras if(lx==0) hx += 1;
592fe8fb19SBen Gras }
602fe8fb19SBen Gras } else { /* x < 0 */
612fe8fb19SBen Gras if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
622fe8fb19SBen Gras if(lx==0) hx -= 1;
632fe8fb19SBen Gras lx -= 1;
642fe8fb19SBen Gras } else { /* x > y, x += ulp */
652fe8fb19SBen Gras lx += 1;
662fe8fb19SBen Gras if(lx==0) hx += 1;
672fe8fb19SBen Gras }
682fe8fb19SBen Gras }
692fe8fb19SBen Gras hy = hx&0x7ff00000;
702fe8fb19SBen Gras if(hy>=0x7ff00000) return x+x; /* overflow */
712fe8fb19SBen Gras if(hy<0x00100000) { /* underflow */
722fe8fb19SBen Gras y = x*x;
732fe8fb19SBen Gras if(y!=x) { /* raise underflow flag */
742fe8fb19SBen Gras INSERT_WORDS(y,hx,lx);
752fe8fb19SBen Gras return y;
762fe8fb19SBen Gras }
772fe8fb19SBen Gras }
782fe8fb19SBen Gras INSERT_WORDS(x,hx,lx);
792fe8fb19SBen Gras return x;
802fe8fb19SBen Gras }
81