fcnvfx.c revision 1.1 1 /* $NetBSD: fcnvfx.c,v 1.1 2002/06/05 01:04:25 fredette Exp $ */
2
3 /* $OpenBSD: fcnvfx.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 "../spmath/float.h"
45 #include "../spmath/sgl_float.h"
46 #include "../spmath/dbl_float.h"
47 #include "../spmath/cnv_float.h"
48
49 /*
50 * Single Floating-point to Single Fixed-point
51 */
52 /*ARGSUSED*/
53 int
54 sgl_to_sgl_fcnvfx(srcptr,dstptr,status)
55
56 sgl_floating_point *srcptr;
57 int *dstptr;
58 unsigned int *status;
59 {
60 register unsigned int src, temp;
61 register int src_exponent, result;
62 register int inexact = FALSE;
63
64 src = *srcptr;
65 src_exponent = Sgl_exponent(src) - SGL_BIAS;
66
67 /*
68 * Test for overflow
69 */
70 if (src_exponent > SGL_FX_MAX_EXP) {
71 /* check for MININT */
72 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
73 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
74 /*
75 * Since source is a number which cannot be
76 * represented in fixed-point format, return
77 * largest (or smallest) fixed-point number.
78 */
79 Sgl_return_overflow(src,dstptr);
80 }
81 }
82 /*
83 * Generate result
84 */
85 if (src_exponent >= 0) {
86 temp = src;
87 Sgl_clear_signexponent_set_hidden(temp);
88 Int_from_sgl_mantissa(temp,src_exponent);
89 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
90 else result = Sgl_all(temp);
91
92 /* check for inexact */
93 if (Sgl_isinexact_to_fix(src,src_exponent)) {
94 inexact = TRUE;
95 /* round result */
96 switch (Rounding_mode()) {
97 case ROUNDPLUS:
98 if (Sgl_iszero_sign(src)) result++;
99 break;
100 case ROUNDMINUS:
101 if (Sgl_isone_sign(src)) result--;
102 break;
103 case ROUNDNEAREST:
104 if (Sgl_isone_roundbit(src,src_exponent)) {
105 if (Sgl_isone_stickybit(src,src_exponent)
106 || (Sgl_isone_lowmantissa(temp))) {
107 if (Sgl_iszero_sign(src)) result++;
108 else result--;
109 }
110 }
111 }
112 }
113 }
114 else {
115 result = 0;
116
117 /* check for inexact */
118 if (Sgl_isnotzero_exponentmantissa(src)) {
119 inexact = TRUE;
120 /* round result */
121 switch (Rounding_mode()) {
122 case ROUNDPLUS:
123 if (Sgl_iszero_sign(src)) result++;
124 break;
125 case ROUNDMINUS:
126 if (Sgl_isone_sign(src)) result--;
127 break;
128 case ROUNDNEAREST:
129 if (src_exponent == -1)
130 if (Sgl_isnotzero_mantissa(src)) {
131 if (Sgl_iszero_sign(src)) result++;
132 else result--;
133 }
134 }
135 }
136 }
137 *dstptr = result;
138 if (inexact) {
139 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
140 else Set_inexactflag();
141 }
142 return(NOEXCEPTION);
143 }
144
145 /*
146 * Single Floating-point to Double Fixed-point
147 */
148 /*ARGSUSED*/
149 int
150 sgl_to_dbl_fcnvfx(srcptr,dstptr,status)
151
152 sgl_floating_point *srcptr;
153 dbl_integer *dstptr;
154 unsigned int *status;
155 {
156 register int src_exponent, resultp1;
157 register unsigned int src, temp, resultp2;
158 register int inexact = FALSE;
159
160 src = *srcptr;
161 src_exponent = Sgl_exponent(src) - SGL_BIAS;
162
163 /*
164 * Test for overflow
165 */
166 if (src_exponent > DBL_FX_MAX_EXP) {
167 /* check for MININT */
168 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
169 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
170 /*
171 * Since source is a number which cannot be
172 * represented in fixed-point format, return
173 * largest (or smallest) fixed-point number.
174 */
175 Sgl_return_overflow_dbl(src,dstptr);
176 }
177 Dint_set_minint(resultp1,resultp2);
178 Dint_copytoptr(resultp1,resultp2,dstptr);
179 return(NOEXCEPTION);
180 }
181 /*
182 * Generate result
183 */
184 if (src_exponent >= 0) {
185 temp = src;
186 Sgl_clear_signexponent_set_hidden(temp);
187 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
188 if (Sgl_isone_sign(src)) {
189 Dint_setone_sign(resultp1,resultp2);
190 }
191
192 /* check for inexact */
193 if (Sgl_isinexact_to_fix(src,src_exponent)) {
194 inexact = TRUE;
195 /* round result */
196 switch (Rounding_mode()) {
197 case ROUNDPLUS:
198 if (Sgl_iszero_sign(src)) {
199 Dint_increment(resultp1,resultp2);
200 }
201 break;
202 case ROUNDMINUS:
203 if (Sgl_isone_sign(src)) {
204 Dint_decrement(resultp1,resultp2);
205 }
206 break;
207 case ROUNDNEAREST:
208 if (Sgl_isone_roundbit(src,src_exponent))
209 if (Sgl_isone_stickybit(src,src_exponent) ||
210 (Dint_isone_lowp2(resultp2))) {
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
213 }
214 else {
215 Dint_decrement(resultp1,resultp2);
216 }
217 }
218 }
219 }
220 }
221 else {
222 Dint_setzero(resultp1,resultp2);
223
224 /* check for inexact */
225 if (Sgl_isnotzero_exponentmantissa(src)) {
226 inexact = TRUE;
227 /* round result */
228 switch (Rounding_mode()) {
229 case ROUNDPLUS:
230 if (Sgl_iszero_sign(src)) {
231 Dint_increment(resultp1,resultp2);
232 }
233 break;
234 case ROUNDMINUS:
235 if (Sgl_isone_sign(src)) {
236 Dint_decrement(resultp1,resultp2);
237 }
238 break;
239 case ROUNDNEAREST:
240 if (src_exponent == -1)
241 if (Sgl_isnotzero_mantissa(src)) {
242 if (Sgl_iszero_sign(src)) {
243 Dint_increment(resultp1,resultp2);
244 }
245 else {
246 Dint_decrement(resultp1,resultp2);
247 }
248 }
249 }
250 }
251 }
252 Dint_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 /*
261 * Double Floating-point to Single Fixed-point
262 */
263 /*ARGSUSED*/
264 int
265 dbl_to_sgl_fcnvfx(srcptr,dstptr,status)
266
267 dbl_floating_point *srcptr;
268 int *dstptr;
269 unsigned int *status;
270 {
271 register unsigned int srcp1,srcp2, tempp1,tempp2;
272 register int src_exponent, result;
273 register int inexact = FALSE;
274
275 Dbl_copyfromptr(srcptr,srcp1,srcp2);
276 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
277
278 /*
279 * Test for overflow
280 */
281 if (src_exponent > SGL_FX_MAX_EXP) {
282 /* check for MININT */
283 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
284 /*
285 * Since source is a number which cannot be
286 * represented in fixed-point format, return
287 * largest (or smallest) fixed-point number.
288 */
289 Dbl_return_overflow(srcp1,srcp2,dstptr);
290 }
291 }
292 /*
293 * Generate result
294 */
295 if (src_exponent >= 0) {
296 tempp1 = srcp1;
297 tempp2 = srcp2;
298 Dbl_clear_signexponent_set_hidden(tempp1);
299 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
300 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
301 result = -Dbl_allp1(tempp1);
302 else result = Dbl_allp1(tempp1);
303
304 /* check for inexact */
305 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
306 inexact = TRUE;
307 /* round result */
308 switch (Rounding_mode()) {
309 case ROUNDPLUS:
310 if (Dbl_iszero_sign(srcp1)) result++;
311 break;
312 case ROUNDMINUS:
313 if (Dbl_isone_sign(srcp1)) result--;
314 break;
315 case ROUNDNEAREST:
316 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
317 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
318 (Dbl_isone_lowmantissap1(tempp1))) {
319 if (Dbl_iszero_sign(srcp1)) result++;
320 else result--;
321 }
322 }
323 /* check for overflow */
324 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
325 (Dbl_isone_sign(srcp1) && result > 0)) {
326 Dbl_return_overflow(srcp1,srcp2,dstptr);
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 /*ARGSUSED*/
365 int
366 dbl_to_dbl_fcnvfx(srcptr,dstptr,status)
367
368 dbl_floating_point *srcptr;
369 dbl_integer *dstptr;
370 unsigned int *status;
371 {
372 register int src_exponent, resultp1;
373 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
374 register int inexact = FALSE;
375
376 Dbl_copyfromptr(srcptr,srcp1,srcp2);
377 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
378
379 /*
380 * Test for overflow
381 */
382 if (src_exponent > DBL_FX_MAX_EXP) {
383 /* check for MININT */
384 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
385 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
386 /*
387 * Since source is a number which cannot be
388 * represented in fixed-point format, return
389 * largest (or smallest) fixed-point number.
390 */
391 Dbl_return_overflow_dbl(srcp1,srcp2,dstptr);
392 }
393 }
394
395 /*
396 * Generate result
397 */
398 if (src_exponent >= 0) {
399 tempp1 = srcp1;
400 tempp2 = srcp2;
401 Dbl_clear_signexponent_set_hidden(tempp1);
402 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
403 resultp1, resultp2);
404 if (Dbl_isone_sign(srcp1)) {
405 Dint_setone_sign(resultp1,resultp2);
406 }
407
408 /* check for inexact */
409 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
410 inexact = TRUE;
411 /* round result */
412 switch (Rounding_mode()) {
413 case ROUNDPLUS:
414 if (Dbl_iszero_sign(srcp1)) {
415 Dint_increment(resultp1,resultp2);
416 }
417 break;
418 case ROUNDMINUS:
419 if (Dbl_isone_sign(srcp1)) {
420 Dint_decrement(resultp1,resultp2);
421 }
422 break;
423 case ROUNDNEAREST:
424 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
425 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
426 (Dint_isone_lowp2(resultp2))) {
427 if (Dbl_iszero_sign(srcp1)) {
428 Dint_increment(resultp1,resultp2);
429 }
430 else {
431 Dint_decrement(resultp1,resultp2);
432 }
433 }
434 }
435 }
436 }
437 else {
438 Dint_setzero(resultp1,resultp2);
439
440 /* check for inexact */
441 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
442 inexact = TRUE;
443 /* round result */
444 switch (Rounding_mode()) {
445 case ROUNDPLUS:
446 if (Dbl_iszero_sign(srcp1)) {
447 Dint_increment(resultp1,resultp2);
448 }
449 break;
450 case ROUNDMINUS:
451 if (Dbl_isone_sign(srcp1)) {
452 Dint_decrement(resultp1,resultp2);
453 }
454 break;
455 case ROUNDNEAREST:
456 if (src_exponent == -1)
457 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
458 if (Dbl_iszero_sign(srcp1)) {
459 Dint_increment(resultp1,resultp2);
460 }
461 else {
462 Dint_decrement(resultp1,resultp2);
463 }
464 }
465 }
466 }
467 }
468 Dint_copytoptr(resultp1,resultp2,dstptr);
469 if (inexact) {
470 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
471 else Set_inexactflag();
472 }
473 return(NOEXCEPTION);
474 }
475