12116Sjkh/* @(#)s_nextafter.c 5.1 93/09/24 */
22116Sjkh/*
32116Sjkh * ====================================================
42116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
52116Sjkh *
62116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business.
72116Sjkh * Permission to use, copy, modify, and distribute this
88870Srgrimes * software is freely granted, provided that this notice
92116Sjkh * is preserved.
102116Sjkh * ====================================================
112116Sjkh */
122116Sjkh
13176451Sdas#include <sys/cdefs.h>
14176451Sdas__FBSDID("$FreeBSD$");
152116Sjkh
162116Sjkh/* IEEE functions
172116Sjkh *	nextafter(x,y)
182116Sjkh *	return the next machine floating-point number of x in the
192116Sjkh *	direction toward y.
202116Sjkh *   Special cases:
212116Sjkh */
222116Sjkh
23143216Sdas#include <float.h>
24143216Sdas
252116Sjkh#include "math.h"
262116Sjkh#include "math_private.h"
272116Sjkh
2897413Salfreddouble
2997413Salfrednextafter(double x, double y)
302116Sjkh{
31143216Sdas	volatile double t;
322116Sjkh	int32_t hx,hy,ix,iy;
332116Sjkh	u_int32_t lx,ly;
342116Sjkh
352116Sjkh	EXTRACT_WORDS(hx,lx,x);
362116Sjkh	EXTRACT_WORDS(hy,ly,y);
372116Sjkh	ix = hx&0x7fffffff;		/* |x| */
382116Sjkh	iy = hy&0x7fffffff;		/* |y| */
392116Sjkh
408870Srgrimes	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
418870Srgrimes	   ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
428870Srgrimes	   return x+y;
43140685Sdas	if(x==y) return y;		/* x=y, return y */
442116Sjkh	if((ix|lx)==0) {			/* x == 0 */
452116Sjkh	    INSERT_WORDS(x,hy&0x80000000,1);	/* return +-minsubnormal */
46143216Sdas	    t = x*x;
47143216Sdas	    if(t==x) return t; else return x;	/* raise underflow flag */
488870Srgrimes	}
492116Sjkh	if(hx>=0) {				/* x > 0 */
502116Sjkh	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
512116Sjkh		if(lx==0) hx -= 1;
522116Sjkh		lx -= 1;
532116Sjkh	    } else {				/* x < y, x += ulp */
542116Sjkh		lx += 1;
552116Sjkh		if(lx==0) hx += 1;
562116Sjkh	    }
572116Sjkh	} else {				/* x < 0 */
582116Sjkh	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
592116Sjkh		if(lx==0) hx -= 1;
602116Sjkh		lx -= 1;
612116Sjkh	    } else {				/* x > y, x += ulp */
622116Sjkh		lx += 1;
632116Sjkh		if(lx==0) hx += 1;
642116Sjkh	    }
652116Sjkh	}
662116Sjkh	hy = hx&0x7ff00000;
672116Sjkh	if(hy>=0x7ff00000) return x+x;	/* overflow  */
682116Sjkh	if(hy<0x00100000) {		/* underflow */
69143216Sdas	    t = x*x;
70143216Sdas	    if(t!=x) {		/* raise underflow flag */
712116Sjkh	        INSERT_WORDS(y,hx,lx);
722116Sjkh		return y;
732116Sjkh	    }
742116Sjkh	}
752116Sjkh	INSERT_WORDS(x,hx,lx);
762116Sjkh	return x;
772116Sjkh}
78143216Sdas
79143216Sdas#if (LDBL_MANT_DIG == 53)
80143264Sdas__weak_reference(nextafter, nexttoward);
81143264Sdas__weak_reference(nextafter, nexttowardl);
82143264Sdas__weak_reference(nextafter, nextafterl);
83143216Sdas#endif
84