xref: /minix3/lib/libm/src/s_nexttowardf.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: s_nexttowardf.c,v 1.3 2013/02/09 23:14:44 christos Exp $	*/
2*84d9c625SLionel Sambuc 
3*84d9c625SLionel Sambuc /*
4*84d9c625SLionel Sambuc  * ====================================================
5*84d9c625SLionel Sambuc  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6*84d9c625SLionel Sambuc  *
7*84d9c625SLionel Sambuc  * Developed at SunPro, a Sun Microsystems, Inc. business.
8*84d9c625SLionel Sambuc  * Permission to use, copy, modify, and distribute this
9*84d9c625SLionel Sambuc  * software is freely granted, provided that this notice
10*84d9c625SLionel Sambuc  * is preserved.
11*84d9c625SLionel Sambuc  * ====================================================
12*84d9c625SLionel Sambuc  */
13*84d9c625SLionel Sambuc 
14*84d9c625SLionel Sambuc #include <sys/cdefs.h>
15*84d9c625SLionel Sambuc #if 0
16*84d9c625SLionel Sambuc __FBSDID("$FreeBSD: src/lib/msun/src/s_nexttowardf.c,v 1.3 2011/02/10 07:38:38 das Exp $");
17*84d9c625SLionel Sambuc #else
18*84d9c625SLionel Sambuc __RCSID("$NetBSD: s_nexttowardf.c,v 1.3 2013/02/09 23:14:44 christos Exp $");
19*84d9c625SLionel Sambuc #endif
20*84d9c625SLionel Sambuc 
21*84d9c625SLionel Sambuc #include <string.h>
22*84d9c625SLionel Sambuc #include <float.h>
23*84d9c625SLionel Sambuc #include <machine/ieee.h>
24*84d9c625SLionel Sambuc 
25*84d9c625SLionel Sambuc #include "math.h"
26*84d9c625SLionel Sambuc #include "math_private.h"
27*84d9c625SLionel Sambuc 
28*84d9c625SLionel Sambuc #ifdef EXT_EXP_INFNAN
29*84d9c625SLionel Sambuc float
nexttowardf(float x,long double y)30*84d9c625SLionel Sambuc nexttowardf(float x, long double y)
31*84d9c625SLionel Sambuc {
32*84d9c625SLionel Sambuc 	volatile float t;
33*84d9c625SLionel Sambuc 	int32_t hx,ix;
34*84d9c625SLionel Sambuc 	union ieee_ext_u uy;
35*84d9c625SLionel Sambuc 
36*84d9c625SLionel Sambuc 	GET_FLOAT_WORD(hx,x);
37*84d9c625SLionel Sambuc 	ix = hx&0x7fffffff;		/* |x| */
38*84d9c625SLionel Sambuc 
39*84d9c625SLionel Sambuc 	memset(&uy, 0, sizeof(uy));
40*84d9c625SLionel Sambuc 	uy.extu_ld = y;
41*84d9c625SLionel Sambuc 	uy.extu_ext.ext_frach &= ~0x80000000;
42*84d9c625SLionel Sambuc 
43*84d9c625SLionel Sambuc 	if((ix>0x7f800000) ||
44*84d9c625SLionel Sambuc 	   (uy.extu_ext.ext_exp == EXT_EXP_INFNAN &&
45*84d9c625SLionel Sambuc 	    (uy.extu_ext.ext_frach | uy.extu_ext.ext_fracl) != 0))
46*84d9c625SLionel Sambuc 	   return x+y;	/* x or y is nan */
47*84d9c625SLionel Sambuc 	if(x==y) return (float)y;		/* x=y, return y */
48*84d9c625SLionel Sambuc 	if(ix==0) {				/* x == 0 */
49*84d9c625SLionel Sambuc 	    SET_FLOAT_WORD(x,(uy.extu_ext.ext_sign<<31)|1);/* return +-minsubnormal */
50*84d9c625SLionel Sambuc 	    t = x*x;
51*84d9c625SLionel Sambuc 	    if(t==x) return t; else return x;	/* raise underflow flag */
52*84d9c625SLionel Sambuc 	}
53*84d9c625SLionel Sambuc 	if((hx >= 0) ^ (x < y))			/* x -= ulp */
54*84d9c625SLionel Sambuc 	    hx -= 1;
55*84d9c625SLionel Sambuc 	else					/* x += ulp */
56*84d9c625SLionel Sambuc 	    hx += 1;
57*84d9c625SLionel Sambuc 	ix = hx&0x7f800000;
58*84d9c625SLionel Sambuc 	if(ix>=0x7f800000) return x+x;	/* overflow  */
59*84d9c625SLionel Sambuc 	if(ix<0x00800000) {		/* underflow */
60*84d9c625SLionel Sambuc 	    t = x*x;
61*84d9c625SLionel Sambuc 	    if(t!=x) {		/* raise underflow flag */
62*84d9c625SLionel Sambuc 	        SET_FLOAT_WORD(x,hx);
63*84d9c625SLionel Sambuc 		return x;
64*84d9c625SLionel Sambuc 	    }
65*84d9c625SLionel Sambuc 	}
66*84d9c625SLionel Sambuc 	SET_FLOAT_WORD(x,hx);
67*84d9c625SLionel Sambuc 	return x;
68*84d9c625SLionel Sambuc }
69*84d9c625SLionel Sambuc #endif
70