1 /* $OpenBSD: frnd.c,v 1.9 2023/03/08 04:43:07 guenther Exp $ */
2 /*
3 (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4 To anyone who acknowledges that this file is provided "AS IS"
5 without any express or implied warranty:
6 permission to use, copy, modify, and distribute this file
7 for any purpose is hereby granted without fee, provided that
8 the above copyright notice and this notice appears in all
9 copies, and that the name of Hewlett-Packard Company not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific, written prior permission.
12 Hewlett-Packard Company makes no representations about the
13 suitability of this software for any purpose.
14 */
15 /* @(#)frnd.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:24 */
16
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "quad_float.h"
21 #include "cnv_float.h"
22
23 /*
24 * Single Floating-point Round to Integer
25 */
26
27 int
sgl_frnd(srcptr,null,dstptr,status)28 sgl_frnd(srcptr, null, dstptr, status)
29 sgl_floating_point *srcptr, *null, *dstptr;
30 unsigned int *status;
31 {
32 register unsigned int src, result;
33 register int src_exponent;
34 register int inexact = FALSE;
35
36 src = *srcptr;
37 /*
38 * check source operand for NaN or infinity
39 */
40 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
41 /*
42 * is signaling NaN?
43 */
44 if (Sgl_isone_signaling(src)) {
45 /* trap if INVALIDTRAP enabled */
46 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
47 /* make NaN quiet */
48 Set_invalidflag();
49 Sgl_set_quiet(src);
50 }
51 /*
52 * return quiet NaN or infinity
53 */
54 *dstptr = src;
55 return(NOEXCEPTION);
56 }
57 /*
58 * Need to round?
59 */
60 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
61 *dstptr = src;
62 return(NOEXCEPTION);
63 }
64 /*
65 * Generate result
66 */
67 if (src_exponent >= 0) {
68 Sgl_clear_exponent_set_hidden(src);
69 result = src;
70 Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
71 /* check for inexact */
72 if (Sgl_isinexact_to_fix(src,src_exponent)) {
73 inexact = TRUE;
74 /* round result */
75 switch (Rounding_mode()) {
76 case ROUNDPLUS:
77 if (Sgl_iszero_sign(src)) Sgl_increment(result);
78 break;
79 case ROUNDMINUS:
80 if (Sgl_isone_sign(src)) Sgl_increment(result);
81 break;
82 case ROUNDNEAREST:
83 if (Sgl_isone_roundbit(src,src_exponent))
84 if (Sgl_isone_stickybit(src,src_exponent)
85 || (Sgl_isone_lowmantissa(result)))
86 Sgl_increment(result);
87 }
88 }
89 Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
90 if (Sgl_isone_hiddenoverflow(result))
91 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
92 else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
93 }
94 else {
95 result = src; /* set sign */
96 Sgl_setzero_exponentmantissa(result);
97 /* check for inexact */
98 if (Sgl_isnotzero_exponentmantissa(src)) {
99 inexact = TRUE;
100 /* round result */
101 switch (Rounding_mode()) {
102 case ROUNDPLUS:
103 if (Sgl_iszero_sign(src))
104 Sgl_set_exponent(result,SGL_BIAS);
105 break;
106 case ROUNDMINUS:
107 if (Sgl_isone_sign(src))
108 Sgl_set_exponent(result,SGL_BIAS);
109 break;
110 case ROUNDNEAREST:
111 if (src_exponent == -1)
112 if (Sgl_isnotzero_mantissa(src))
113 Sgl_set_exponent(result,SGL_BIAS);
114 }
115 }
116 }
117 *dstptr = result;
118 if (inexact) {
119 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
120 else Set_inexactflag();
121 }
122 return(NOEXCEPTION);
123 }
124
125 /*
126 * Double Floating-point Round to Integer
127 */
128
129 int
dbl_frnd(srcptr,null,dstptr,status)130 dbl_frnd(srcptr, null, dstptr, status)
131 dbl_floating_point *srcptr, *null, *dstptr;
132 unsigned int *status;
133 {
134 register unsigned int srcp1, srcp2, resultp1, resultp2;
135 register int src_exponent;
136 register int inexact = FALSE;
137
138 Dbl_copyfromptr(srcptr,srcp1,srcp2);
139 /*
140 * check source operand for NaN or infinity
141 */
142 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
143 /*
144 * is signaling NaN?
145 */
146 if (Dbl_isone_signaling(srcp1)) {
147 /* trap if INVALIDTRAP enabled */
148 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
149 /* make NaN quiet */
150 Set_invalidflag();
151 Dbl_set_quiet(srcp1);
152 }
153 /*
154 * return quiet NaN or infinity
155 */
156 Dbl_copytoptr(srcp1,srcp2,dstptr);
157 return(NOEXCEPTION);
158 }
159 /*
160 * Need to round?
161 */
162 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
163 Dbl_copytoptr(srcp1,srcp2,dstptr);
164 return(NOEXCEPTION);
165 }
166 /*
167 * Generate result
168 */
169 if (src_exponent >= 0) {
170 Dbl_clear_exponent_set_hidden(srcp1);
171 resultp1 = srcp1;
172 resultp2 = srcp2;
173 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
174 /* check for inexact */
175 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
176 inexact = TRUE;
177 /* round result */
178 switch (Rounding_mode()) {
179 case ROUNDPLUS:
180 if (Dbl_iszero_sign(srcp1))
181 Dbl_increment(resultp1,resultp2);
182 break;
183 case ROUNDMINUS:
184 if (Dbl_isone_sign(srcp1))
185 Dbl_increment(resultp1,resultp2);
186 break;
187 case ROUNDNEAREST:
188 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
189 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
190 || (Dbl_isone_lowmantissap2(resultp2)))
191 Dbl_increment(resultp1,resultp2);
192 }
193 }
194 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
195 if (Dbl_isone_hiddenoverflow(resultp1))
196 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
197 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
198 }
199 else {
200 resultp1 = srcp1; /* set sign */
201 Dbl_setzero_exponentmantissa(resultp1,resultp2);
202 /* check for inexact */
203 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
204 inexact = TRUE;
205 /* round result */
206 switch (Rounding_mode()) {
207 case ROUNDPLUS:
208 if (Dbl_iszero_sign(srcp1))
209 Dbl_set_exponent(resultp1,DBL_BIAS);
210 break;
211 case ROUNDMINUS:
212 if (Dbl_isone_sign(srcp1))
213 Dbl_set_exponent(resultp1,DBL_BIAS);
214 break;
215 case ROUNDNEAREST:
216 if (src_exponent == -1)
217 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
218 Dbl_set_exponent(resultp1,DBL_BIAS);
219 }
220 }
221 }
222 Dbl_copytoptr(resultp1,resultp2,dstptr);
223 if (inexact) {
224 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
225 else Set_inexactflag();
226 }
227 return(NOEXCEPTION);
228 }
229
230 int
quad_frnd(srcptr,null,dstptr,status)231 quad_frnd(srcptr, null, dstptr, status)
232 quad_floating_point *srcptr, *null, *dstptr;
233 unsigned int *status;
234 {
235 return(UNIMPLEMENTEDEXCEPTION);
236 }
237