1 /* $OpenBSD: fcnvff.c,v 1.8 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 /* @(#)fcnvff.c: Revision: 2.8.88.1 Date: 93/12/07 15:06:09 */
16
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "cnv_float.h"
21
22 /*
23 * Single Floating-point to Double Floating-point
24 */
25 int
sgl_to_dbl_fcnvff(srcptr,null,dstptr,status)26 sgl_to_dbl_fcnvff(srcptr, null, dstptr, status)
27 sgl_floating_point *srcptr, *null;
28 dbl_floating_point *dstptr;
29 unsigned int *status;
30 {
31 register unsigned int src, resultp1, resultp2;
32 register int src_exponent;
33
34 src = *srcptr;
35 src_exponent = Sgl_exponent(src);
36 Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
37 /*
38 * Test for NaN or infinity
39 */
40 if (src_exponent == SGL_INFINITY_EXPONENT) {
41 /*
42 * determine if NaN or infinity
43 */
44 if (Sgl_iszero_mantissa(src)) {
45 /*
46 * is infinity; want to return double infinity
47 */
48 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
49 Dbl_copytoptr(resultp1,resultp2,dstptr);
50 return(NOEXCEPTION);
51 }
52 else {
53 /*
54 * is NaN; signaling or quiet?
55 */
56 if (Sgl_isone_signaling(src)) {
57 /* trap if INVALIDTRAP enabled */
58 if (Is_invalidtrap_enabled())
59 return(INVALIDEXCEPTION);
60 /* make NaN quiet */
61 else {
62 Set_invalidflag();
63 Sgl_set_quiet(src);
64 }
65 }
66 /*
67 * NaN is quiet, return as double NaN
68 */
69 Dbl_setinfinity_exponent(resultp1);
70 Sgl_to_dbl_mantissa(src,resultp1,resultp2);
71 Dbl_copytoptr(resultp1,resultp2,dstptr);
72 return(NOEXCEPTION);
73 }
74 }
75 /*
76 * Test for zero or denormalized
77 */
78 if (src_exponent == 0) {
79 /*
80 * determine if zero or denormalized
81 */
82 if (Sgl_isnotzero_mantissa(src)) {
83 /*
84 * is denormalized; want to normalize
85 */
86 Sgl_clear_signexponent(src);
87 Sgl_leftshiftby1(src);
88 Sgl_normalize(src,src_exponent);
89 Sgl_to_dbl_exponent(src_exponent,resultp1);
90 Sgl_to_dbl_mantissa(src,resultp1,resultp2);
91 }
92 else {
93 Dbl_setzero_exponentmantissa(resultp1,resultp2);
94 }
95 Dbl_copytoptr(resultp1,resultp2,dstptr);
96 return(NOEXCEPTION);
97 }
98 /*
99 * No special cases, just complete the conversion
100 */
101 Sgl_to_dbl_exponent(src_exponent, resultp1);
102 Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
103 Dbl_copytoptr(resultp1,resultp2,dstptr);
104 return(NOEXCEPTION);
105 }
106
107 /*
108 * Double Floating-point to Single Floating-point
109 */
110 int
dbl_to_sgl_fcnvff(srcptr,null,dstptr,status)111 dbl_to_sgl_fcnvff(srcptr, null, dstptr, status)
112 dbl_floating_point *srcptr, *null;
113 sgl_floating_point *dstptr;
114 unsigned int *status;
115 {
116 register unsigned int srcp1, srcp2, result;
117 register int src_exponent, dest_exponent, dest_mantissa;
118 register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
119 register int lsb_odd = FALSE;
120 int is_tiny;
121
122 Dbl_copyfromptr(srcptr,srcp1,srcp2);
123 src_exponent = Dbl_exponent(srcp1);
124 Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
125 /*
126 * Test for NaN or infinity
127 */
128 if (src_exponent == DBL_INFINITY_EXPONENT) {
129 /*
130 * determine if NaN or infinity
131 */
132 if (Dbl_iszero_mantissa(srcp1,srcp2)) {
133 /*
134 * is infinity; want to return single infinity
135 */
136 Sgl_setinfinity_exponentmantissa(result);
137 *dstptr = result;
138 return(NOEXCEPTION);
139 }
140 /*
141 * is NaN; signaling or quiet?
142 */
143 if (Dbl_isone_signaling(srcp1)) {
144 /* trap if INVALIDTRAP enabled */
145 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
146 else {
147 Set_invalidflag();
148 /* make NaN quiet */
149 Dbl_set_quiet(srcp1);
150 }
151 }
152 /*
153 * NaN is quiet, return as single NaN
154 */
155 Sgl_setinfinity_exponent(result);
156 Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
157 if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
158 *dstptr = result;
159 return(NOEXCEPTION);
160 }
161 /*
162 * Generate result
163 */
164 Dbl_to_sgl_exponent(src_exponent,dest_exponent);
165 if (dest_exponent > 0) {
166 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
167 stickybit,lsb_odd);
168 }
169 else {
170 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
171 Sgl_setzero_exponentmantissa(result);
172 *dstptr = result;
173 return(NOEXCEPTION);
174 }
175 if (Is_underflowtrap_enabled()) {
176 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
177 guardbit,stickybit,lsb_odd);
178 }
179 else {
180 /* compute result, determine inexact info,
181 * and set Underflowflag if appropriate
182 */
183 Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
184 dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
185 is_tiny);
186 }
187 }
188 /*
189 * Now round result if not exact
190 */
191 if (inexact) {
192 switch (Rounding_mode()) {
193 case ROUNDPLUS:
194 if (Sgl_iszero_sign(result)) dest_mantissa++;
195 break;
196 case ROUNDMINUS:
197 if (Sgl_isone_sign(result)) dest_mantissa++;
198 break;
199 case ROUNDNEAREST:
200 if (guardbit) {
201 if (stickybit || lsb_odd) dest_mantissa++;
202 }
203 }
204 }
205 Sgl_set_exponentmantissa(result,dest_mantissa);
206
207 /*
208 * check for mantissa overflow after rounding
209 */
210 if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
211 Sgl_isone_hidden(result)) dest_exponent++;
212
213 /*
214 * Test for overflow
215 */
216 if (dest_exponent >= SGL_INFINITY_EXPONENT) {
217 /* trap if OVERFLOWTRAP enabled */
218 if (Is_overflowtrap_enabled()) {
219 /*
220 * Check for gross overflow
221 */
222 if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
223 return(UNIMPLEMENTEDEXCEPTION);
224
225 /*
226 * Adjust bias of result
227 */
228 Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
229 *dstptr = result;
230 if (inexact) {
231 if (Is_inexacttrap_enabled())
232 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
233 else
234 Set_inexactflag();
235 }
236 return(OVERFLOWEXCEPTION);
237 }
238 Set_overflowflag();
239 inexact = TRUE;
240 /* set result to infinity or largest number */
241 Sgl_setoverflow(result);
242 }
243 /*
244 * Test for underflow
245 */
246 else if (dest_exponent <= 0) {
247 /* trap if UNDERFLOWTRAP enabled */
248 if (Is_underflowtrap_enabled()) {
249 /*
250 * Check for gross underflow
251 */
252 if (dest_exponent <= -(SGL_WRAP))
253 return(UNIMPLEMENTEDEXCEPTION);
254 /*
255 * Adjust bias of result
256 */
257 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
258 *dstptr = result;
259 if (inexact) {
260 if (Is_inexacttrap_enabled())
261 return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
262 else
263 Set_inexactflag();
264 }
265 return(UNDERFLOWEXCEPTION);
266 }
267 /*
268 * result is denormalized or signed zero
269 */
270 if (inexact && is_tiny) Set_underflowflag();
271
272 }
273 else Sgl_set_exponent(result,dest_exponent);
274 *dstptr = result;
275 /*
276 * Trap if inexact trap is enabled
277 */
278 if (inexact) {
279 if (Is_inexacttrap_enabled())
280 return(INEXACTEXCEPTION);
281 else
282 Set_inexactflag();
283 }
284 return(NOEXCEPTION);
285 }
286