4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1988-1995, by Sun Microsystems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "base_conversion.h"
35 /* Right shift significand sticky by n bits. */
40 if (n
>= (32 * UNPACKED_SIZE
)) { /* drastic */
41 for (i
= 0; (pu
->significand
[i
] == 0) && (i
< UNPACKED_SIZE
); i
++);
42 if (i
>= UNPACKED_SIZE
) {
43 pu
->fpclass
= fp_zero
;
46 for (i
= 0; i
< (UNPACKED_SIZE
- 1); i
++)
47 pu
->significand
[i
] = 0;
48 pu
->significand
[UNPACKED_SIZE
- 1] = 1;
52 while (n
>= 32) { /* big shift */
53 if (pu
->significand
[UNPACKED_SIZE
- 1] != 0)
54 pu
->significand
[UNPACKED_SIZE
- 2] |= 1;
55 for (i
= UNPACKED_SIZE
- 2; i
>= 0; i
--)
56 pu
->significand
[i
+ 1] = pu
->significand
[i
];
57 pu
->significand
[0] = 0;
60 if (n
>= 1) { /* small shift */
61 unsigned long high
, low
, shiftout
= 0;
62 for (i
= 0; i
< UNPACKED_SIZE
; i
++) {
63 high
= pu
->significand
[i
] >> n
;
64 low
= pu
->significand
[i
] << (32 - n
);
65 pu
->significand
[i
] = shiftout
| high
;
69 pu
->significand
[UNPACKED_SIZE
- 1] |= 1;
74 overflow_to_infinity(sign
)
77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
82 switch (_fp_current_direction
) {
104 * Round according to current rounding mode. pu must be shifted to so that
105 * the roundbit is pu->significand[roundword] & 0x80000000
109 int increment
; /* boolean to indicate round up */
111 unsigned msw
; /* msw before increment */
113 for (is
= (roundword
+ 1); is
< UNPACKED_SIZE
; is
++)
114 if (pu
->significand
[is
] != 0) { /* Condense extra bits into
117 pu
->significand
[roundword
] |= 1;
120 if (pu
->significand
[roundword
] == 0)
122 _fp_set_exception(fp_inexact
);
123 switch (_fp_current_direction
) {
125 increment
= pu
->significand
[roundword
] >= 0x80000000;
131 increment
= (pu
->sign
== 0) & (pu
->significand
[roundword
] != 0);
134 increment
= (pu
->sign
!= 0) & (pu
->significand
[roundword
] != 0);
138 msw
=pu
->significand
[0]; /* save msw before round */
142 pu
->significand
[is
]++;
144 while ((pu
->significand
[is
] == 0) && (is
> 0));
145 if (pu
->significand
[0] < msw
) { /* rounding carried out */
147 pu
->significand
[0] = 0x80000000;
150 if ((_fp_current_direction
== fp_nearest
) && (pu
->significand
[roundword
] == 0x80000000)) { /* ambiguous case */
151 pu
->significand
[roundword
- 1] &= ~1; /* force round to even */
157 unpacked
*pu
; /* unpacked result */
158 single
*px
; /* packed single */
160 single_equivalence kluge
;
162 kluge
.f
.msw
.sign
= pu
->sign
;
163 switch (pu
->fpclass
) {
165 kluge
.f
.msw
.exponent
= 0;
166 kluge
.f
.msw
.significand
= 0;
170 kluge
.f
.msw
.exponent
= 0xff;
171 kluge
.f
.msw
.significand
= 0;
174 kluge
.f
.msw
.exponent
= 0xff;
175 kluge
.f
.msw
.significand
= 0x400000 | (0x3fffff & (pu
->significand
[0] >> 8));
178 _fp_rightshift(pu
, 8);
179 pu
->exponent
+= SINGLE_BIAS
;
180 if (pu
->exponent
<= 0) {
181 kluge
.f
.msw
.exponent
= 0;
182 _fp_rightshift(pu
, 1 - pu
->exponent
);
184 if (pu
->significand
[0] == 0x800000) { /* rounded back up to
186 kluge
.f
.msw
.exponent
= 1;
187 kluge
.f
.msw
.significand
= 0;
188 _fp_set_exception(fp_underflow
);
191 if (_fp_current_exceptions
& (1 << fp_inexact
))
192 _fp_set_exception(fp_underflow
);
193 kluge
.f
.msw
.significand
= 0x7fffff & pu
->significand
[0];
197 if (pu
->significand
[0] == 0x1000000) { /* rounding overflow */
198 pu
->significand
[0] = 0x800000;
201 if (pu
->exponent
>= 0xff) {
202 _fp_set_exception(fp_overflow
);
203 _fp_set_exception(fp_inexact
);
204 if (overflow_to_infinity(pu
->sign
))
206 kluge
.f
.msw
.exponent
= 0xfe;
207 kluge
.f
.msw
.significand
= 0x7fffff;
210 kluge
.f
.msw
.exponent
= pu
->exponent
;
211 kluge
.f
.msw
.significand
= 0x7fffff & pu
->significand
[0];
219 unpacked
*pu
; /* unpacked result */
220 double *px
; /* packed double */
222 double_equivalence kluge
;
224 kluge
.f
.msw
.sign
= pu
->sign
;
225 switch (pu
->fpclass
) {
227 kluge
.f
.msw
.exponent
= 0;
228 kluge
.f
.msw
.significand
= 0;
229 kluge
.f
.significand2
= 0;
233 kluge
.f
.msw
.exponent
= 0x7ff;
234 kluge
.f
.msw
.significand
= 0;
235 kluge
.f
.significand2
= 0;
238 kluge
.f
.msw
.exponent
= 0x7ff;
239 _fp_rightshift(pu
, 11);
240 kluge
.f
.msw
.significand
= 0x80000 | (0x7ffff & pu
->significand
[0]);
241 kluge
.f
.significand2
= pu
->significand
[1];
244 _fp_rightshift(pu
, 11);
245 pu
->exponent
+= DOUBLE_BIAS
;
246 if (pu
->exponent
<= 0) { /* underflow */
247 kluge
.f
.msw
.exponent
= 0;
248 _fp_rightshift(pu
, 1 - pu
->exponent
);
250 if (pu
->significand
[0] == 0x100000) { /* rounded back up to
252 kluge
.f
.msw
.exponent
= 1;
253 kluge
.f
.msw
.significand
= 0;
254 kluge
.f
.significand2
= 0;
255 _fp_set_exception(fp_underflow
);
258 if (_fp_current_exceptions
& (1 << fp_inexact
))
259 _fp_set_exception(fp_underflow
);
260 kluge
.f
.msw
.exponent
= 0;
261 kluge
.f
.msw
.significand
= 0xfffff & pu
->significand
[0];
262 kluge
.f
.significand2
= pu
->significand
[1];
266 if (pu
->significand
[0] == 0x200000) { /* rounding overflow */
267 pu
->significand
[0] = 0x100000;
270 if (pu
->exponent
>= 0x7ff) { /* overflow */
271 _fp_set_exception(fp_overflow
);
272 _fp_set_exception(fp_inexact
);
273 if (overflow_to_infinity(pu
->sign
))
275 kluge
.f
.msw
.exponent
= 0x7fe;
276 kluge
.f
.msw
.significand
= 0xfffff;
277 kluge
.f
.significand2
= 0xffffffff;
280 kluge
.f
.msw
.exponent
= pu
->exponent
;
281 kluge
.f
.msw
.significand
= 0xfffff & pu
->significand
[0];
282 kluge
.f
.significand2
= pu
->significand
[1];
290 _pack_extended(pu
, px
)
291 unpacked
*pu
; /* unpacked result */
292 extended
*px
; /* packed extended */
294 extended_equivalence kluge
;
296 kluge
.f
.msw
.sign
= pu
->sign
;
297 switch (pu
->fpclass
) {
299 kluge
.f
.msw
.exponent
= 0;
300 kluge
.f
.significand
= 0;
301 kluge
.f
.significand2
= 0;
305 kluge
.f
.msw
.exponent
= 0x7fff;
306 kluge
.f
.significand
= 0;
307 kluge
.f
.significand2
= 0;
310 kluge
.f
.msw
.exponent
= 0x7fff;
311 kluge
.f
.significand
= 0x40000000 | (0x7fffffff & pu
->significand
[0]);
312 kluge
.f
.significand2
= pu
->significand
[1];
315 switch (_fp_current_precision
) {
319 _pack_single(pu
, &s
);
320 _unpack_single(pu
, &s
);
326 _pack_double(pu
, &s
);
327 _unpack_double(pu
, &s
);
331 pu
->exponent
+= EXTENDED_BIAS
;
332 if (pu
->exponent
<= 0) { /* underflow */
333 kluge
.f
.msw
.exponent
= 0;
334 _fp_rightshift(pu
, -pu
->exponent
);
336 if (_fp_current_exceptions
& (1 << fp_inexact
))
337 _fp_set_exception(fp_underflow
);
338 kluge
.f
.msw
.exponent
= 0;
339 kluge
.f
.significand
= pu
->significand
[0];
340 kluge
.f
.significand2
= pu
->significand
[1];
344 if (pu
->exponent
>= 0x7fff) { /* overflow */
345 _fp_set_exception(fp_overflow
);
346 _fp_set_exception(fp_inexact
);
347 if (overflow_to_infinity(pu
->sign
))
349 kluge
.f
.msw
.exponent
= 0x7ffe;
350 kluge
.f
.significand
= 0xffffffff;
351 kluge
.f
.significand2
= 0xffffffff;
354 kluge
.f
.msw
.exponent
= pu
->exponent
;
355 kluge
.f
.significand
= pu
->significand
[0];
356 kluge
.f
.significand2
= pu
->significand
[1];
360 (*px
)[0] = kluge
.x
[0];
361 (*px
)[1] = kluge
.x
[1];
362 (*px
)[2] = kluge
.x
[2];
366 _pack_quadruple(pu
, px
)
367 unpacked
*pu
; /* unpacked result */
368 quadruple
*px
; /* packed quadruple */
370 quadruple_equivalence kluge
;
373 kluge
.f
.msw
.sign
= pu
->sign
;
374 switch (pu
->fpclass
) {
376 kluge
.f
.msw
.exponent
= 0;
377 kluge
.f
.msw
.significand
= 0;
378 kluge
.f
.significand2
= 0;
379 kluge
.f
.significand3
= 0;
380 kluge
.f
.significand4
= 0;
384 kluge
.f
.msw
.exponent
= 0x7fff;
385 kluge
.f
.msw
.significand
= 0;
386 kluge
.f
.significand2
= 0;
387 kluge
.f
.significand3
= 0;
388 kluge
.f
.significand4
= 0;
391 kluge
.f
.msw
.exponent
= 0x7fff;
392 _fp_rightshift(pu
, 15);
393 kluge
.f
.msw
.significand
= 0x8000 | (0xffff & pu
->significand
[0]);
394 kluge
.f
.significand2
= pu
->significand
[1];
395 kluge
.f
.significand3
= pu
->significand
[2];
396 kluge
.f
.significand4
= pu
->significand
[3];
399 _fp_rightshift(pu
, 15);
400 pu
->exponent
+= QUAD_BIAS
;
401 if (pu
->exponent
<= 0) { /* underflow */
402 kluge
.f
.msw
.exponent
= 0;
403 _fp_rightshift(pu
, 1 - pu
->exponent
);
405 if (pu
->significand
[0] == 0x10000) { /* rounded back up to
407 kluge
.f
.msw
.exponent
= 1;
408 kluge
.f
.msw
.significand
= 0;
409 kluge
.f
.significand2
= 0;
410 kluge
.f
.significand3
= 0;
411 kluge
.f
.significand4
= 0;
412 _fp_set_exception(fp_underflow
);
415 if (_fp_current_exceptions
& (1 << fp_inexact
))
416 _fp_set_exception(fp_underflow
);
417 kluge
.f
.msw
.exponent
= 0;
418 kluge
.f
.msw
.significand
= 0xffff & pu
->significand
[0];
419 kluge
.f
.significand2
= pu
->significand
[1];
420 kluge
.f
.significand3
= pu
->significand
[2];
421 kluge
.f
.significand4
= pu
->significand
[3];
425 if (pu
->significand
[0] == 0x20000) { /* rounding overflow */
426 pu
->significand
[0] = 0x10000;
429 if (pu
->exponent
>= 0x7fff) { /* overflow */
430 _fp_set_exception(fp_overflow
);
431 _fp_set_exception(fp_inexact
);
432 if (overflow_to_infinity(pu
->sign
))
434 kluge
.f
.msw
.exponent
= 0x7ffe;
435 kluge
.f
.msw
.significand
= 0xffff;
436 kluge
.f
.significand2
= 0xffffffff;
437 kluge
.f
.significand3
= 0xffffffff;
438 kluge
.f
.significand4
= 0xffffffff;
441 kluge
.f
.msw
.exponent
= pu
->exponent
;
442 kluge
.f
.msw
.significand
= pu
->significand
[0] & 0xffff;
443 kluge
.f
.significand2
= pu
->significand
[1];
444 kluge
.f
.significand3
= pu
->significand
[2];
445 kluge
.f
.significand4
= pu
->significand
[3];
452 for (i
= 0; i
< 4; i
++)
453 px
->u
[i
] = kluge
.x
.u
[i
];