. service tells you which device it couldn't stat
[minix3.git] / lib / float / compact.c
bloba5a1074d147ba4476c3dedac79531fb202e97746
1 /*
2 (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 See the copyright notice in the ACK home directory, in the file "Copyright".
4 */
6 /* $Header$ */
8 /*
9 COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
12 # include "FP_bias.h"
13 # include "FP_shift.h"
14 # include "FP_trap.h"
15 # include "FP_types.h"
16 # include "get_put.h"
18 void
19 compact(f,to,size)
20 EXTEND *f;
21 unsigned long *to;
22 int size;
24 int error = 0;
26 if (size == sizeof(DOUBLE)) {
28 * COMPACT EXTENDED INTO DOUBLE
30 DOUBLE *DBL = (DOUBLE *) (void *) to;
32 if ((f->m1|(f->m2 & DBL_ZERO)) == 0L) {
33 zrf8(DBL);
34 return;
36 f->exp += DBL_BIAS; /* restore proper bias */
37 if (f->exp > DBL_MAX) {
38 dbl_over: trap(EFOVFL);
39 f->exp = DBL_MAX+1;
40 f->m1 = 0;
41 f->m2 = 0;
42 if (error++)
43 return;
45 else if (f->exp < DBL_MIN) {
46 b64_rsft(&(f->mantissa));
47 if (f->exp < 0) {
48 b64_sft(&(f->mantissa), -f->exp);
49 f->exp = 0;
51 /* underflow ??? */
54 /* local CAST conversion */
56 /* because of special format shift only 10 bits */
57 /* bit shift mantissa 10 bits */
59 /* first align within words, then do store operation */
61 DBL->d[0] = f->m1 >> DBL_RUNPACK; /* plus 22 == 32 */
62 DBL->d[1] = f->m2 >> DBL_RUNPACK; /* plus 22 == 32 */
63 DBL->d[1] |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
65 /* if not exact then round to nearest */
66 /* on a tie, round to even */
68 #ifdef EXCEPTION_INEXACT
69 if ((f->m2 & DBL_EXACT) != 0) {
70 INEXACT();
71 #endif
72 if (((f->m2 & DBL_EXACT) > DBL_ROUNDUP)
73 || ((f->m2 & DBL_EXACT) == DBL_ROUNDUP
74 && (f->m2 & (DBL_ROUNDUP << 1)))) {
75 DBL->d[1]++; /* rounding up */
76 if (DBL->d[1] == 0L) { /* carry out */
77 DBL->d[0]++;
79 if (f->exp == 0 && (DBL->d[0] & ~DBL_MASK)) {
80 f->exp++;
82 if (DBL->d[0] & DBL_CARRYOUT) { /* carry out */
83 if (DBL->d[0] & 01)
84 DBL->d[1] = CARRYBIT;
85 DBL->d[0] >>= 1;
86 f->exp++;
89 /* check for overflow */
90 if (f->exp > DBL_MAX)
91 goto dbl_over;
93 #ifdef EXCEPTION_INEXACT
95 #endif
98 * STORE EXPONENT AND SIGN:
100 * 1) clear leading bits (B4-B15)
101 * 2) shift and store exponent
104 DBL->d[0] &= DBL_MASK;
105 DBL->d[0] |=
106 ((long) (f->exp << DBL_EXPSHIFT) << EXP_STORE);
107 if (f->sign)
108 DBL->d[0] |= CARRYBIT;
111 * STORE MANTISSA
114 #if FL_MSL_AT_LOW_ADDRESS
115 put4(DBL->d[0], (char *) &DBL->d[0]);
116 put4(DBL->d[1], (char *) &DBL->d[1]);
117 #else
118 { unsigned long l;
119 put4(DBL->d[1], (char *) &l);
120 put4(DBL->d[0], (char *) &DBL->d[1]);
121 DBL->d[0] = l;
123 #endif
125 else {
127 * COMPACT EXTENDED INTO FLOAT
129 SINGLE *SGL;
131 /* local CAST conversion */
132 SGL = (SINGLE *) (void *) to;
133 if ((f->m1 & SGL_ZERO) == 0L) {
134 *SGL = 0L;
135 return;
137 f->exp += SGL_BIAS; /* restore bias */
138 if (f->exp > SGL_MAX) {
139 sgl_over: trap(EFOVFL);
140 f->exp = SGL_MAX+1;
141 f->m1 = 0L;
142 f->m2 = 0L;
143 if (error++)
144 return;
146 else if (f->exp < SGL_MIN) {
147 b64_rsft(&(f->mantissa));
148 if (f->exp < 0) {
149 b64_sft(&(f->mantissa), -f->exp);
150 f->exp = 0;
152 /* underflow ??? */
155 /* shift mantissa and store */
156 *SGL = (f->m1 >> SGL_RUNPACK);
158 /* check for rounding to nearest */
159 /* on a tie, round to even */
160 #ifdef EXCEPTION_INEXACT
161 if (f->m2 != 0 ||
162 (f->m1 & SGL_EXACT) != 0L) {
163 INEXACT();
164 #endif
165 if (((f->m1 & SGL_EXACT) > SGL_ROUNDUP)
166 || ((f->m1 & SGL_EXACT) == SGL_ROUNDUP
167 && (f->m1 & (SGL_ROUNDUP << 1)))) {
168 (*SGL)++;
169 if (f->exp == 0 && (*SGL & ~SGL_MASK)) {
170 f->exp++;
172 /* check normal */
173 if (*SGL & SGL_CARRYOUT) {
174 *SGL >>= 1;
175 f->exp++;
177 if (f->exp > SGL_MAX)
178 goto sgl_over;
180 #ifdef EXCEPTION_INEXACT
182 #endif
185 * STORE EXPONENT AND SIGN:
187 * 1) clear leading bit of fraction
188 * 2) shift and store exponent
191 *SGL &= SGL_MASK; /* B23-B31 are 0 */
192 *SGL |= ((long) (f->exp << SGL_EXPSHIFT) << EXP_STORE);
193 if (f->sign)
194 *SGL |= CARRYBIT;
197 * STORE MANTISSA
200 put4(*SGL, (char *) &SGL);