1 /* $NetBSD: frnd.c,v 1.5 2012/02/04 17:03:10 skrll Exp $ */
2
3 /* $OpenBSD: frnd.c,v 1.5 2001/03/29 03:58:18 mickey Exp $ */
4
5 /*
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
7 * All Rights Reserved
8 *
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appears in all copies and
12 * that both the copyright notice and this permission notice appear in
13 * supporting documentation.
14 *
15 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 *
25 */
26 /*
27 * pmk1.1
28 */
29 /*
30 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
31 *
32 * To anyone who acknowledges that this file is provided "AS IS"
33 * without any express or implied warranty:
34 * permission to use, copy, modify, and distribute this file
35 * for any purpose is hereby granted without fee, provided that
36 * the above copyright notice and this notice appears in all
37 * copies, and that the name of Hewlett-Packard Company not be
38 * used in advertising or publicity pertaining to distribution
39 * of the software without specific, written prior permission.
40 * Hewlett-Packard Company makes no representations about the
41 * suitability of this software for any purpose.
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: frnd.c,v 1.5 2012/02/04 17:03:10 skrll Exp $");
46
47 #include "../spmath/float.h"
48 #include "../spmath/sgl_float.h"
49 #include "../spmath/dbl_float.h"
50 #include "../spmath/quad_float.h"
51 #include "../spmath/cnv_float.h"
52
53 /*
54 * Single Floating-point Round to Integer
55 */
56
57 /*ARGSUSED*/
58 int
sgl_frnd(sgl_floating_point * srcptr,sgl_floating_point * dstptr,unsigned int * status)59 sgl_frnd(sgl_floating_point *srcptr, sgl_floating_point *dstptr,
60 unsigned int *status)
61 {
62 register unsigned int src, result;
63 register int src_exponent;
64 register int inexact = false;
65
66 src = *srcptr;
67 /*
68 * check source operand for NaN or infinity
69 */
70 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
71 /*
72 * is signaling NaN?
73 */
74 if (Sgl_isone_signaling(src)) {
75 /* trap if INVALIDTRAP enabled */
76 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
77 /* make NaN quiet */
78 Set_invalidflag();
79 Sgl_set_quiet(src);
80 }
81 /*
82 * return quiet NaN or infinity
83 */
84 *dstptr = src;
85 return(NOEXCEPTION);
86 }
87 /*
88 * Need to round?
89 */
90 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
91 *dstptr = src;
92 return(NOEXCEPTION);
93 }
94 /*
95 * Generate result
96 */
97 if (src_exponent >= 0) {
98 Sgl_clear_exponent_set_hidden(src);
99 result = src;
100 Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
101 /* check for inexact */
102 if (Sgl_isinexact_to_fix(src,src_exponent)) {
103 inexact = true;
104 /* round result */
105 switch (Rounding_mode()) {
106 case ROUNDPLUS:
107 if (Sgl_iszero_sign(src)) Sgl_increment(result);
108 break;
109 case ROUNDMINUS:
110 if (Sgl_isone_sign(src)) Sgl_increment(result);
111 break;
112 case ROUNDNEAREST:
113 if (Sgl_isone_roundbit(src,src_exponent))
114 if (Sgl_isone_stickybit(src,src_exponent)
115 || (Sgl_isone_lowmantissa(result)))
116 Sgl_increment(result);
117 }
118 }
119 Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
120 if (Sgl_isone_hiddenoverflow(result))
121 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
122 else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
123 }
124 else {
125 result = src; /* set sign */
126 Sgl_setzero_exponentmantissa(result);
127 /* check for inexact */
128 if (Sgl_isnotzero_exponentmantissa(src)) {
129 inexact = true;
130 /* round result */
131 switch (Rounding_mode()) {
132 case ROUNDPLUS:
133 if (Sgl_iszero_sign(src))
134 Sgl_set_exponent(result,SGL_BIAS);
135 break;
136 case ROUNDMINUS:
137 if (Sgl_isone_sign(src))
138 Sgl_set_exponent(result,SGL_BIAS);
139 break;
140 case ROUNDNEAREST:
141 if (src_exponent == -1)
142 if (Sgl_isnotzero_mantissa(src))
143 Sgl_set_exponent(result,SGL_BIAS);
144 }
145 }
146 }
147 *dstptr = result;
148 if (inexact) {
149 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
150 else Set_inexactflag();
151 }
152 return(NOEXCEPTION);
153 }
154
155 /*
156 * Double Floating-point Round to Integer
157 */
158
159 /*ARGSUSED*/
160 int
dbl_frnd(dbl_floating_point * srcptr,dbl_floating_point * dstptr,unsigned int * status)161 dbl_frnd(dbl_floating_point *srcptr, dbl_floating_point *dstptr,
162 unsigned int *status)
163 {
164 register unsigned int srcp1, srcp2, resultp1, resultp2;
165 register int src_exponent;
166 register int inexact = false;
167
168 Dbl_copyfromptr(srcptr,srcp1,srcp2);
169 /*
170 * check source operand for NaN or infinity
171 */
172 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
173 /*
174 * is signaling NaN?
175 */
176 if (Dbl_isone_signaling(srcp1)) {
177 /* trap if INVALIDTRAP enabled */
178 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
179 /* make NaN quiet */
180 Set_invalidflag();
181 Dbl_set_quiet(srcp1);
182 }
183 /*
184 * return quiet NaN or infinity
185 */
186 Dbl_copytoptr(srcp1,srcp2,dstptr);
187 return(NOEXCEPTION);
188 }
189 /*
190 * Need to round?
191 */
192 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
193 Dbl_copytoptr(srcp1,srcp2,dstptr);
194 return(NOEXCEPTION);
195 }
196 /*
197 * Generate result
198 */
199 if (src_exponent >= 0) {
200 Dbl_clear_exponent_set_hidden(srcp1);
201 resultp1 = srcp1;
202 resultp2 = srcp2;
203 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
204 /* check for inexact */
205 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
206 inexact = true;
207 /* round result */
208 switch (Rounding_mode()) {
209 case ROUNDPLUS:
210 if (Dbl_iszero_sign(srcp1))
211 Dbl_increment(resultp1,resultp2);
212 break;
213 case ROUNDMINUS:
214 if (Dbl_isone_sign(srcp1))
215 Dbl_increment(resultp1,resultp2);
216 break;
217 case ROUNDNEAREST:
218 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
219 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
220 || (Dbl_isone_lowmantissap2(resultp2)))
221 Dbl_increment(resultp1,resultp2);
222 }
223 }
224 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
225 if (Dbl_isone_hiddenoverflow(resultp1))
226 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
227 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
228 }
229 else {
230 resultp1 = srcp1; /* set sign */
231 Dbl_setzero_exponentmantissa(resultp1,resultp2);
232 /* check for inexact */
233 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
234 inexact = true;
235 /* round result */
236 switch (Rounding_mode()) {
237 case ROUNDPLUS:
238 if (Dbl_iszero_sign(srcp1))
239 Dbl_set_exponent(resultp1,DBL_BIAS);
240 break;
241 case ROUNDMINUS:
242 if (Dbl_isone_sign(srcp1))
243 Dbl_set_exponent(resultp1,DBL_BIAS);
244 break;
245 case ROUNDNEAREST:
246 if (src_exponent == -1)
247 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
248 Dbl_set_exponent(resultp1,DBL_BIAS);
249 }
250 }
251 }
252 Dbl_copytoptr(resultp1,resultp2,dstptr);
253 if (inexact) {
254 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
255 else Set_inexactflag();
256 }
257 return(NOEXCEPTION);
258 }
259
260 /*ARGSUSED*/
261 int
quad_frnd(quad_floating_point * srcptr,quad_floating_point * dstptr,unsigned int * status)262 quad_frnd(quad_floating_point *srcptr, quad_floating_point *dstptr,
263 unsigned int *status)
264 {
265 return(UNIMPLEMENTEDEXCEPTION);
266 }
267
268