1 /* $OpenBSD: fcnvfx.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 /* @(#)fcnvfx.c: Revision: 2.8.88.2 Date: 93/12/08 13:27:29 */
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 Single Fixed-point
24 */
25 int
sgl_to_sgl_fcnvfx(srcptr,null,dstptr,status)26 sgl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
27 sgl_floating_point *srcptr, *null;
28 int *dstptr;
29 unsigned int *status;
30 {
31 register unsigned int src, temp;
32 register int src_exponent, result;
33 register int inexact = FALSE;
34
35 src = *srcptr;
36 src_exponent = Sgl_exponent(src) - SGL_BIAS;
37
38 /*
39 * Test for overflow
40 */
41 if (src_exponent > SGL_FX_MAX_EXP) {
42 /* check for MININT */
43 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
44 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
45 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
46 else result = 0x80000000;
47
48 if (Is_invalidtrap_enabled()) {
49 return(INVALIDEXCEPTION);
50 }
51 Set_invalidflag();
52 *dstptr = result;
53 return(NOEXCEPTION);
54 }
55 }
56 /*
57 * Generate result
58 */
59 if (src_exponent >= 0) {
60 temp = src;
61 Sgl_clear_signexponent_set_hidden(temp);
62 Int_from_sgl_mantissa(temp,src_exponent);
63 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
64 else result = Sgl_all(temp);
65
66 /* check for inexact */
67 if (Sgl_isinexact_to_fix(src,src_exponent)) {
68 inexact = TRUE;
69 /* round result */
70 switch (Rounding_mode()) {
71 case ROUNDPLUS:
72 if (Sgl_iszero_sign(src)) result++;
73 break;
74 case ROUNDMINUS:
75 if (Sgl_isone_sign(src)) result--;
76 break;
77 case ROUNDNEAREST:
78 if (Sgl_isone_roundbit(src,src_exponent)) {
79 if (Sgl_isone_stickybit(src,src_exponent)
80 || (Sgl_isone_lowmantissa(temp))) {
81 if (Sgl_iszero_sign(src)) result++;
82 else result--;
83 }
84 }
85 }
86 }
87 }
88 else {
89 result = 0;
90
91 /* check for inexact */
92 if (Sgl_isnotzero_exponentmantissa(src)) {
93 inexact = TRUE;
94 /* round result */
95 switch (Rounding_mode()) {
96 case ROUNDPLUS:
97 if (Sgl_iszero_sign(src)) result++;
98 break;
99 case ROUNDMINUS:
100 if (Sgl_isone_sign(src)) result--;
101 break;
102 case ROUNDNEAREST:
103 if (src_exponent == -1)
104 if (Sgl_isnotzero_mantissa(src)) {
105 if (Sgl_iszero_sign(src)) result++;
106 else result--;
107 }
108 }
109 }
110 }
111 *dstptr = result;
112 if (inexact) {
113 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
114 else Set_inexactflag();
115 }
116 return(NOEXCEPTION);
117 }
118
119 /*
120 * Single Floating-point to Double Fixed-point
121 */
122 int
sgl_to_dbl_fcnvfx(srcptr,null,dstptr,status)123 sgl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
124 sgl_floating_point *srcptr, *null;
125 dbl_integer *dstptr;
126 unsigned int *status;
127 {
128 register int src_exponent, resultp1;
129 register unsigned int src, temp, resultp2;
130 register int inexact = FALSE;
131
132 src = *srcptr;
133 src_exponent = Sgl_exponent(src) - SGL_BIAS;
134
135 /*
136 * Test for overflow
137 */
138 if (src_exponent > DBL_FX_MAX_EXP) {
139 /* check for MININT */
140 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
141 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
142 if (Sgl_iszero_sign(src)) {
143 resultp1 = 0x7fffffff;
144 resultp2 = 0xffffffff;
145 }
146 else {
147 resultp1 = 0x80000000;
148 resultp2 = 0;
149 }
150
151 if (Is_invalidtrap_enabled()) {
152 return(INVALIDEXCEPTION);
153 }
154 Set_invalidflag();
155 Dint_copytoptr(resultp1,resultp2,dstptr);
156 return(NOEXCEPTION);
157 }
158 Dint_set_minint(resultp1,resultp2);
159 Dint_copytoptr(resultp1,resultp2,dstptr);
160 return(NOEXCEPTION);
161 }
162 /*
163 * Generate result
164 */
165 if (src_exponent >= 0) {
166 temp = src;
167 Sgl_clear_signexponent_set_hidden(temp);
168 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
169 if (Sgl_isone_sign(src)) {
170 Dint_setone_sign(resultp1,resultp2);
171 }
172
173 /* check for inexact */
174 if (Sgl_isinexact_to_fix(src,src_exponent)) {
175 inexact = TRUE;
176 /* round result */
177 switch (Rounding_mode()) {
178 case ROUNDPLUS:
179 if (Sgl_iszero_sign(src)) {
180 Dint_increment(resultp1,resultp2);
181 }
182 break;
183 case ROUNDMINUS:
184 if (Sgl_isone_sign(src)) {
185 Dint_decrement(resultp1,resultp2);
186 }
187 break;
188 case ROUNDNEAREST:
189 if (Sgl_isone_roundbit(src,src_exponent))
190 if (Sgl_isone_stickybit(src,src_exponent) ||
191 (Dint_isone_lowp2(resultp2))) {
192 if (Sgl_iszero_sign(src)) {
193 Dint_increment(resultp1,resultp2);
194 }
195 else {
196 Dint_decrement(resultp1,resultp2);
197 }
198 }
199 }
200 }
201 }
202 else {
203 Dint_setzero(resultp1,resultp2);
204
205 /* check for inexact */
206 if (Sgl_isnotzero_exponentmantissa(src)) {
207 inexact = TRUE;
208 /* round result */
209 switch (Rounding_mode()) {
210 case ROUNDPLUS:
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
213 }
214 break;
215 case ROUNDMINUS:
216 if (Sgl_isone_sign(src)) {
217 Dint_decrement(resultp1,resultp2);
218 }
219 break;
220 case ROUNDNEAREST:
221 if (src_exponent == -1)
222 if (Sgl_isnotzero_mantissa(src)) {
223 if (Sgl_iszero_sign(src)) {
224 Dint_increment(resultp1,resultp2);
225 }
226 else {
227 Dint_decrement(resultp1,resultp2);
228 }
229 }
230 }
231 }
232 }
233 Dint_copytoptr(resultp1,resultp2,dstptr);
234 if (inexact) {
235 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
236 else Set_inexactflag();
237 }
238 return(NOEXCEPTION);
239 }
240
241 /*
242 * Double Floating-point to Single Fixed-point
243 */
244 int
dbl_to_sgl_fcnvfx(srcptr,null,dstptr,status)245 dbl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
246 dbl_floating_point *srcptr, *null;
247 int *dstptr;
248 unsigned int *status;
249 {
250 register unsigned int srcp1,srcp2, tempp1,tempp2;
251 register int src_exponent, result;
252 register int inexact = FALSE;
253
254 Dbl_copyfromptr(srcptr,srcp1,srcp2);
255 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
256
257 /*
258 * Test for overflow
259 */
260 if (src_exponent > SGL_FX_MAX_EXP) {
261 /* check for MININT */
262 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
263 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
264 else result = 0x80000000;
265
266 if (Is_invalidtrap_enabled()) {
267 return(INVALIDEXCEPTION);
268 }
269 Set_invalidflag();
270 *dstptr = result;
271 return(NOEXCEPTION);
272 }
273 }
274 /*
275 * Generate result
276 */
277 if (src_exponent >= 0) {
278 tempp1 = srcp1;
279 tempp2 = srcp2;
280 Dbl_clear_signexponent_set_hidden(tempp1);
281 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
282 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
283 result = -Dbl_allp1(tempp1);
284 else result = Dbl_allp1(tempp1);
285
286 /* check for inexact */
287 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
288 inexact = TRUE;
289 /* round result */
290 switch (Rounding_mode()) {
291 case ROUNDPLUS:
292 if (Dbl_iszero_sign(srcp1))
293 result++;
294 break;
295 case ROUNDMINUS:
296 if (Dbl_isone_sign(srcp1)) result--;
297 break;
298 case ROUNDNEAREST:
299 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
300 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
301 (Dbl_isone_lowmantissap1(tempp1))) {
302 if (Dbl_iszero_sign(srcp1)) result++;
303 else result--;
304 }
305 }
306 /* check for overflow */
307 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
308 (Dbl_isone_sign(srcp1) && result > 0)) {
309
310 if (Dbl_iszero_sign(srcp1))
311 result = 0x7fffffff;
312 else
313 result = 0x80000000;
314
315 if (Is_overflowtrap_enabled()) {
316 if (Is_inexacttrap_enabled())
317 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
318 else Set_inexactflag();
319 return(OVERFLOWEXCEPTION);
320 }
321 Set_overflowflag();
322 *dstptr = result;
323 if (Is_inexacttrap_enabled() )
324 return(INEXACTEXCEPTION);
325 else Set_inexactflag();
326 return(NOEXCEPTION);
327 }
328 }
329 }
330 else {
331 result = 0;
332
333 /* check for inexact */
334 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
335 inexact = TRUE;
336 /* round result */
337 switch (Rounding_mode()) {
338 case ROUNDPLUS:
339 if (Dbl_iszero_sign(srcp1)) result++;
340 break;
341 case ROUNDMINUS:
342 if (Dbl_isone_sign(srcp1)) result--;
343 break;
344 case ROUNDNEAREST:
345 if (src_exponent == -1)
346 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
347 if (Dbl_iszero_sign(srcp1)) result++;
348 else result--;
349 }
350 }
351 }
352 }
353 *dstptr = result;
354 if (inexact) {
355 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
356 else Set_inexactflag();
357 }
358 return(NOEXCEPTION);
359 }
360
361 /*
362 * Double Floating-point to Double Fixed-point
363 */
364 int
dbl_to_dbl_fcnvfx(srcptr,null,dstptr,status)365 dbl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
366 dbl_floating_point *srcptr, *null;
367 dbl_integer *dstptr;
368 unsigned int *status;
369 {
370 register int src_exponent, resultp1;
371 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
372 register int inexact = FALSE;
373
374 Dbl_copyfromptr(srcptr,srcp1,srcp2);
375 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
376
377 /*
378 * Test for overflow
379 */
380 if (src_exponent > DBL_FX_MAX_EXP) {
381 /* check for MININT */
382 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
383 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
384 if (Dbl_iszero_sign(srcp1)) {
385 resultp1 = 0x7fffffff;
386 resultp2 = 0xffffffff;
387 }
388 else {
389 resultp1 = 0x80000000;
390 resultp2 = 0;
391 }
392
393 if (Is_invalidtrap_enabled()) {
394 return(INVALIDEXCEPTION);
395 }
396 Set_invalidflag();
397 Dint_copytoptr(resultp1,resultp2,dstptr);
398 return(NOEXCEPTION);
399 }
400 }
401
402 /*
403 * Generate result
404 */
405 if (src_exponent >= 0) {
406 tempp1 = srcp1;
407 tempp2 = srcp2;
408 Dbl_clear_signexponent_set_hidden(tempp1);
409 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
410 resultp1, resultp2);
411 if (Dbl_isone_sign(srcp1)) {
412 Dint_setone_sign(resultp1,resultp2);
413 }
414
415 /* check for inexact */
416 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
417 inexact = TRUE;
418 /* round result */
419 switch (Rounding_mode()) {
420 case ROUNDPLUS:
421 if (Dbl_iszero_sign(srcp1)) {
422 Dint_increment(resultp1,resultp2);
423 }
424 break;
425 case ROUNDMINUS:
426 if (Dbl_isone_sign(srcp1)) {
427 Dint_decrement(resultp1,resultp2);
428 }
429 break;
430 case ROUNDNEAREST:
431 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
432 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
433 (Dint_isone_lowp2(resultp2))) {
434 if (Dbl_iszero_sign(srcp1)) {
435 Dint_increment(resultp1,resultp2);
436 }
437 else {
438 Dint_decrement(resultp1,resultp2);
439 }
440 }
441 }
442 }
443 }
444 else {
445 Dint_setzero(resultp1,resultp2);
446
447 /* check for inexact */
448 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
449 inexact = TRUE;
450 /* round result */
451 switch (Rounding_mode()) {
452 case ROUNDPLUS:
453 if (Dbl_iszero_sign(srcp1)) {
454 Dint_increment(resultp1,resultp2);
455 }
456 break;
457 case ROUNDMINUS:
458 if (Dbl_isone_sign(srcp1)) {
459 Dint_decrement(resultp1,resultp2);
460 }
461 break;
462 case ROUNDNEAREST:
463 if (src_exponent == -1)
464 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
465 if (Dbl_iszero_sign(srcp1)) {
466 Dint_increment(resultp1,resultp2);
467 }
468 else {
469 Dint_decrement(resultp1,resultp2);
470 }
471 }
472 }
473 }
474 }
475 Dint_copytoptr(resultp1,resultp2,dstptr);
476 if (inexact) {
477 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
478 else Set_inexactflag();
479 }
480 return(NOEXCEPTION);
481 }
482