8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / gen / common / pack_float.c
blob4a75254292bfc5246f95c2da51ae5f852e0d7b9c
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1988-1995, by Sun Microsystems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "base_conversion.h"
30 void
31 _fp_rightshift(pu, n)
32 unpacked *pu;
33 int n;
35 /* Right shift significand sticky by n bits. */
38 int i;
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;
44 return;
45 } else {
46 for (i = 0; i < (UNPACKED_SIZE - 1); i++)
47 pu->significand[i] = 0;
48 pu->significand[UNPACKED_SIZE - 1] = 1;
49 return;
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;
58 n -= 32;
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;
66 shiftout = low;
68 if (shiftout != 0)
69 pu->significand[UNPACKED_SIZE - 1] |= 1;
73 PRIVATE int
74 overflow_to_infinity(sign)
75 int sign;
77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
80 int inf;
82 switch (_fp_current_direction) {
83 case fp_nearest:
84 inf = 1;
85 break;
86 case fp_tozero:
87 inf = 0;
88 break;
89 case fp_positive:
90 inf = !sign;
91 break;
92 case fp_negative:
93 inf = sign;
94 break;
96 return (inf);
99 PRIVATE void
100 round(pu, roundword)
101 unpacked *pu;
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 */
110 int is;
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
115 * sticky bottom of
116 * roundword. */
117 pu->significand[roundword] |= 1;
118 break;
120 if (pu->significand[roundword] == 0)
121 return;
122 _fp_set_exception(fp_inexact);
123 switch (_fp_current_direction) {
124 case fp_nearest:
125 increment = pu->significand[roundword] >= 0x80000000;
126 break;
127 case fp_tozero:
128 increment = 0;
129 break;
130 case fp_positive:
131 increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
132 break;
133 case fp_negative:
134 increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
135 break;
137 if (increment) {
138 msw=pu->significand[0]; /* save msw before round */
139 is = roundword;
140 do {
141 is--;
142 pu->significand[is]++;
144 while ((pu->significand[is] == 0) && (is > 0));
145 if (pu->significand[0] < msw) { /* rounding carried out */
146 pu->exponent++;
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 */
155 void
156 _pack_single(pu, px)
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) {
164 case fp_zero:
165 kluge.f.msw.exponent = 0;
166 kluge.f.msw.significand = 0;
167 break;
168 case fp_infinity:
169 infinity:
170 kluge.f.msw.exponent = 0xff;
171 kluge.f.msw.significand = 0;
172 break;
173 case fp_quiet:
174 kluge.f.msw.exponent = 0xff;
175 kluge.f.msw.significand = 0x400000 | (0x3fffff & (pu->significand[0] >> 8));
176 break;
177 case fp_normal:
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);
183 round(pu, 1);
184 if (pu->significand[0] == 0x800000) { /* rounded back up to
185 * normal */
186 kluge.f.msw.exponent = 1;
187 kluge.f.msw.significand = 0;
188 _fp_set_exception(fp_underflow);
189 goto ret;
191 if (_fp_current_exceptions & (1 << fp_inexact))
192 _fp_set_exception(fp_underflow);
193 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
194 goto ret;
196 round(pu, 1);
197 if (pu->significand[0] == 0x1000000) { /* rounding overflow */
198 pu->significand[0] = 0x800000;
199 pu->exponent += 1;
201 if (pu->exponent >= 0xff) {
202 _fp_set_exception(fp_overflow);
203 _fp_set_exception(fp_inexact);
204 if (overflow_to_infinity(pu->sign))
205 goto infinity;
206 kluge.f.msw.exponent = 0xfe;
207 kluge.f.msw.significand = 0x7fffff;
208 goto ret;
210 kluge.f.msw.exponent = pu->exponent;
211 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
213 ret:
214 *px = kluge.x;
217 void
218 _pack_double(pu, px)
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) {
226 case fp_zero:
227 kluge.f.msw.exponent = 0;
228 kluge.f.msw.significand = 0;
229 kluge.f.significand2 = 0;
230 break;
231 case fp_infinity:
232 infinity:
233 kluge.f.msw.exponent = 0x7ff;
234 kluge.f.msw.significand = 0;
235 kluge.f.significand2 = 0;
236 break;
237 case fp_quiet:
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];
242 break;
243 case fp_normal:
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);
249 round(pu, 2);
250 if (pu->significand[0] == 0x100000) { /* rounded back up to
251 * normal */
252 kluge.f.msw.exponent = 1;
253 kluge.f.msw.significand = 0;
254 kluge.f.significand2 = 0;
255 _fp_set_exception(fp_underflow);
256 goto ret;
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];
263 goto ret;
265 round(pu, 2);
266 if (pu->significand[0] == 0x200000) { /* rounding overflow */
267 pu->significand[0] = 0x100000;
268 pu->exponent += 1;
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))
274 goto infinity;
275 kluge.f.msw.exponent = 0x7fe;
276 kluge.f.msw.significand = 0xfffff;
277 kluge.f.significand2 = 0xffffffff;
278 goto ret;
280 kluge.f.msw.exponent = pu->exponent;
281 kluge.f.msw.significand = 0xfffff & pu->significand[0];
282 kluge.f.significand2 = pu->significand[1];
283 break;
285 ret:
286 *px = kluge.x;
289 void
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) {
298 case fp_zero:
299 kluge.f.msw.exponent = 0;
300 kluge.f.significand = 0;
301 kluge.f.significand2 = 0;
302 break;
303 case fp_infinity:
304 infinity:
305 kluge.f.msw.exponent = 0x7fff;
306 kluge.f.significand = 0;
307 kluge.f.significand2 = 0;
308 break;
309 case fp_quiet:
310 kluge.f.msw.exponent = 0x7fff;
311 kluge.f.significand = 0x40000000 | (0x7fffffff & pu->significand[0]);
312 kluge.f.significand2 = pu->significand[1];
313 break;
314 case fp_normal:
315 switch (_fp_current_precision) {
316 case fp_single:
318 single s;
319 _pack_single(pu, &s);
320 _unpack_single(pu, &s);
321 break;
323 case fp_double:
325 double s;
326 _pack_double(pu, &s);
327 _unpack_double(pu, &s);
328 break;
331 pu->exponent += EXTENDED_BIAS;
332 if (pu->exponent <= 0) { /* underflow */
333 kluge.f.msw.exponent = 0;
334 _fp_rightshift(pu, -pu->exponent);
335 round(pu, 2);
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];
341 goto ret;
343 round(pu, 2);
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))
348 goto infinity;
349 kluge.f.msw.exponent = 0x7ffe;
350 kluge.f.significand = 0xffffffff;
351 kluge.f.significand2 = 0xffffffff;
352 goto ret;
354 kluge.f.msw.exponent = pu->exponent;
355 kluge.f.significand = pu->significand[0];
356 kluge.f.significand2 = pu->significand[1];
357 break;
359 ret:
360 (*px)[0] = kluge.x[0];
361 (*px)[1] = kluge.x[1];
362 (*px)[2] = kluge.x[2];
365 void
366 _pack_quadruple(pu, px)
367 unpacked *pu; /* unpacked result */
368 quadruple *px; /* packed quadruple */
370 quadruple_equivalence kluge;
371 int i;
373 kluge.f.msw.sign = pu->sign;
374 switch (pu->fpclass) {
375 case fp_zero:
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;
381 break;
382 case fp_infinity:
383 infinity:
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;
389 break;
390 case fp_quiet:
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];
397 break;
398 case fp_normal:
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);
404 round(pu, 4);
405 if (pu->significand[0] == 0x10000) { /* rounded back up to
406 * normal */
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);
413 goto ret;
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];
422 goto ret;
424 round(pu, 4);
425 if (pu->significand[0] == 0x20000) { /* rounding overflow */
426 pu->significand[0] = 0x10000;
427 pu->exponent += 1;
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))
433 goto infinity;
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;
439 goto ret;
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];
446 break;
448 ret:
449 #ifdef __STDC__
450 *px = kluge.x;
451 #else
452 for (i = 0; i < 4; i++)
453 px->u[i] = kluge.x.u[i];
454 #endif