1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include "base_conversion.h"
30
31 #ifdef DEBUG
32
33 void
_display_big_float(_big_float * pbf,unsigned base)34 _display_big_float(_big_float *pbf, unsigned base)
35 {
36 int i;
37
38 for (i = 0; i < pbf->blength; i++) {
39 switch (base) {
40 case 2:
41 printf(" + %d * 2** %d", pbf->bsignificand[i], (16 * i + pbf->bexponent));
42 break;
43 case 10:
44 printf(" + %d * 10** %d", pbf->bsignificand[i], (4 * i + pbf->bexponent));
45 break;
46 }
47 if ((i % 4) == 3)
48 printf("\n");
49 }
50 printf("\n");
51 }
52
53 #endif
54
55 void
_integerstring_to_big_decimal(char ds[],unsigned ndigs,unsigned nzin,unsigned * pnzout,_big_float * pd)56 _integerstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin,
57 unsigned *pnzout, _big_float *pd)
58 {
59 /*
60 * Convert ndigs decimal digits from ds, and up to 3 trailing zeros,
61 * into a decimal big_float in *pd. nzin tells how many implicit
62 * trailing zeros may be used, while *pnzout tells how many were
63 * actually absorbed. Up to 3 are used if available so that
64 * (ndigs+*pnzout) % 4 = 0.
65 */
66
67 int extras, taken, id, ids;
68
69 #ifdef DEBUG
70 printf(" _integerstring_to_big_decimal: ndigs %d nzin %d ds %s \n", ndigs, nzin, ds);
71 #endif
72
73 /* Compute how many trailing zeros we're going to put in *pd. */
74
75 extras = ndigs % 4;
76 if ((extras > 0) && (nzin != 0)) {
77 taken = 4 - extras;
78 if (taken > nzin)
79 taken = nzin;
80 } else
81 taken = 0;
82
83 *pnzout = nzin - taken;
84
85 #define IDIGIT(i) ((i < 0) ? 0 : ((i < ndigs) ? (ds[i] - '0') : 0))
86
87 pd->bexponent = 0;
88 pd->blength = (ndigs + taken + 3) / 4;
89
90 ids = (ndigs + taken) - 4 * pd->blength;
91 id = pd->blength - 1;
92
93 #ifdef DEBUG
94 printf(" _integerstring_to_big_decimal exponent %d ids %d id %d \n", pd->bexponent, ids, id);
95 #endif
96
97 pd->bsignificand[id] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3);
98 ids += 4;
99
100 for (; ids < (int) (ndigs + taken - 4); ids += 4) { /* Additional digits to
101 * be found. Main loop. */
102 id--;
103 pd->bsignificand[id] = 1000 * ds[ids] + 100 * ds[ids + 1] + 10 * ds[ids + 2] + ds[ids + 3] - 1111 * '0';
104 }
105
106 #ifdef DEBUG
107 assert((id == 1) || (id == 0));
108 #endif
109 if (id != 0)
110 pd->bsignificand[0] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3);
111
112 #ifdef DEBUG
113 printf(" _integerstring_to_big_decimal: ");
114 _display_big_float(pd, 10);
115 #endif
116 }
117
118 void
_fractionstring_to_big_decimal(char ds[],unsigned ndigs,unsigned nzin,_big_float * pbf)119 _fractionstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin,
120 _big_float *pbf)
121 {
122 /*
123 * Converts a decimal string containing an implicit point, nzin
124 * leading implicit zeros, and ndigs explicit digits, into a big
125 * float.
126 */
127
128 int ids, ibf;
129
130 #ifdef DEBUG
131 printf(" _fractionstring_to_big_decimal ndigs %d nzin %d s %s \n", ndigs, nzin, ds);
132 #endif
133
134 pbf->bexponent = -(int) (nzin + ndigs);
135 pbf->blength = (ndigs + 3) / 4;
136
137 ids = nzin + ndigs - 4 * pbf->blength;
138 ibf = pbf->blength - 1;
139
140 #ifdef DEBUG
141 printf(" _fractionstring_to_big_decimal exponent %d ids %d ibf %d \n", pbf->bexponent, ids, ibf);
142 #endif
143
144 #define FDIGIT(i) ((i < nzin) ? 0 : ((i < (nzin+ndigs)) ? (ds[i-nzin] - '0') : 0))
145
146 pbf->bsignificand[ibf] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3);
147 ids += 4;
148
149 for (; ids < (int) (nzin + ndigs - 4); ids += 4) { /* Additional digits to
150 * be found. Main loop. */
151 ibf--;
152 pbf->bsignificand[ibf] = 1000 * ds[ids - nzin] + 100 * ds[ids + 1 - nzin] + 10 * ds[ids + 2 - nzin] + ds[ids + 3 - nzin] - 1111 * '0';
153 }
154
155 if (ibf > 0) {
156 #ifdef DEBUG
157 assert(ibf == 1);
158 #endif
159 pbf->bsignificand[0] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3);
160 } else {
161 #ifdef DEBUG
162 assert(ibf == 0);
163 #endif
164 }
165
166 #ifdef DEBUG
167 printf(" _fractionstring_to_big_decimal: ");
168 _display_big_float(pbf, 10);
169 #endif
170 }
171
172 void
_mul_10000short(_big_float * pbf,long unsigned carry)173 _mul_10000short(_big_float *pbf, long unsigned carry)
174 {
175 int j;
176 long unsigned p;
177
178 for (j = 0; j < pbf->blength; j++) {
179 p = _prod_10000_b65536(pbf->bsignificand[j], carry);
180 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
181 carry = p >> 16;
182 }
183 while (carry != 0) {
184 p = _carry_out_b10000(carry);
185 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
186 carry = p >> 16;
187 }
188 pbf->blength = j;
189 }
190
191 void
_big_decimal_to_big_binary(_big_float * pd,_big_float * pb)192 _big_decimal_to_big_binary(_big_float *pd, _big_float *pb)
193 {
194 /* Convert _big_float from decimal form to binary form. */
195
196 int id, idbound;
197 _BIG_FLOAT_DIGIT sticky, carry;
198 _BIG_FLOAT_DIGIT multiplier;
199
200 #ifdef DEBUG
201 assert(pd->bexponent >= -3);
202 assert(pd->bexponent <= 3);
203 #endif
204 pb->bexponent = 0;
205 pb->blength = 1;
206 id = pd->blength - 1;
207 if ((id == 0) && (pd->bexponent < 0)) {
208 pb->bsignificand[0] = 0;
209 } else {
210 pb->bsignificand[0] = pd->bsignificand[id--];
211 idbound = (pd->bexponent < 0) ? 1 : 0; /* How far to carry next
212 * for loop depends on
213 * whether last digit
214 * requires special
215 * treatment. */
216 for (; id >= idbound; id--) {
217 _mul_10000short(pb, (long unsigned) pd->bsignificand[id]);
218 }
219 }
220 if (pd->bexponent < 0) {/* Have to save some integer bits, discard
221 * and stick some fraction bits at the end. */
222 #ifdef DEBUG
223 assert(id == 0);
224 #endif
225 sticky = 0;
226 carry = pd->bsignificand[0];
227 multiplier = 10000;
228 switch (pd->bexponent) {
229 case -1:
230 sticky = carry % 10;
231 carry /= 10;
232 multiplier = 1000;
233 break;
234 case -2:
235 sticky = carry % 100;
236 carry /= 100;
237 multiplier = 100;
238 break;
239 case -3:
240 sticky = carry % 1000;
241 carry /= 1000;
242 multiplier = 10;
243 break;
244 }
245 _multiply_base_two(pb, multiplier, (long unsigned) carry);
246 if (sticky != 0)
247 pb->bsignificand[0] |= 1; /* Save lost bits. */
248 } else if (pd->bexponent > 0) { /* Have to append some zeros. */
249 switch (pd->bexponent) {
250 case 1:
251 multiplier = 10;
252 break;
253 case 2:
254 multiplier = 100;
255 break;
256 case 3:
257 multiplier = 1000;
258 break;
259 }
260 carry = 0;
261 _multiply_base_two(pb, multiplier, (long unsigned) carry);
262 }
263 #ifdef DEBUG
264 printf(" _big_decimal_to_big_binary ");
265 _display_big_float(pb, 2);
266 #endif
267 }
268
269 void
_big_binary_to_unpacked(_big_float * pb,unpacked * pu)270 _big_binary_to_unpacked(_big_float *pb, unpacked *pu)
271 {
272 /* Convert a binary big_float to a binary_unpacked. */
273
274 int ib, iu;
275
276 #ifdef DEBUG
277 assert(pb->bsignificand[pb->blength - 1] != 0); /* Assert pb is
278 * normalized. */
279 #endif
280
281 iu = 0;
282 for (ib = pb->blength - 1; ((ib - 1) >= 0) && (iu < UNPACKED_SIZE); ib -= 2) {
283 pu->significand[iu++] = pb->bsignificand[ib] << 16 | pb->bsignificand[ib - 1];
284 }
285 if (iu < UNPACKED_SIZE) { /* The big float fits in the unpacked
286 * with no rounding. */
287 if (ib == 0)
288 pu->significand[iu++] = pb->bsignificand[ib] << 16;
289 for (; iu < UNPACKED_SIZE; iu++)
290 pu->significand[iu] = 0;
291 } else { /* The big float is too big; chop, stick, and
292 * normalize. */
293 while (pb->bsignificand[ib] == 0)
294 ib--;
295 if (ib >= 0)
296 pu->significand[UNPACKED_SIZE - 1] |= 1; /* Stick lsb if nonzero
297 * found. */
298 }
299
300 pu->exponent = 16 * pb->blength + pb->bexponent - 1;
301 _fp_normalize(pu);
302
303 #ifdef DEBUG
304 printf(" _big_binary_to_unpacked \n");
305 _display_unpacked(pu);
306 #endif
307 }
308