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