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 1988 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "base_conversion.h"
34 _display_big_float(_big_float
*pbf
, unsigned base
)
38 for (i
= 0; i
< pbf
->blength
; i
++) {
41 printf(" + %d * 2** %d", pbf
->bsignificand
[i
], (16 * i
+ pbf
->bexponent
));
44 printf(" + %d * 10** %d", pbf
->bsignificand
[i
], (4 * i
+ pbf
->bexponent
));
56 _integerstring_to_big_decimal(char ds
[], unsigned ndigs
, unsigned nzin
,
57 unsigned *pnzout
, _big_float
*pd
)
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.
67 int extras
, taken
, id
, ids
;
70 printf(" _integerstring_to_big_decimal: ndigs %d nzin %d ds %s \n", ndigs
, nzin
, ds
);
73 /* Compute how many trailing zeros we're going to put in *pd. */
76 if ((extras
> 0) && (nzin
!= 0)) {
83 *pnzout
= nzin
- taken
;
85 #define IDIGIT(i) ((i < 0) ? 0 : ((i < ndigs) ? (ds[i] - '0') : 0))
88 pd
->blength
= (ndigs
+ taken
+ 3) / 4;
90 ids
= (ndigs
+ taken
) - 4 * pd
->blength
;
94 printf(" _integerstring_to_big_decimal exponent %d ids %d id %d \n", pd
->bexponent
, ids
, id
);
97 pd
->bsignificand
[id
] = 1000 * IDIGIT(ids
) + 100 * IDIGIT(ids
+ 1) + 10 * IDIGIT(ids
+ 2) + IDIGIT(ids
+ 3);
100 for (; ids
< (int) (ndigs
+ taken
- 4); ids
+= 4) { /* Additional digits to
101 * be found. Main loop. */
103 pd
->bsignificand
[id
] = 1000 * ds
[ids
] + 100 * ds
[ids
+ 1] + 10 * ds
[ids
+ 2] + ds
[ids
+ 3] - 1111 * '0';
107 assert((id
== 1) || (id
== 0));
110 pd
->bsignificand
[0] = 1000 * IDIGIT(ids
) + 100 * IDIGIT(ids
+ 1) + 10 * IDIGIT(ids
+ 2) + IDIGIT(ids
+ 3);
113 printf(" _integerstring_to_big_decimal: ");
114 _display_big_float(pd
, 10);
119 _fractionstring_to_big_decimal(char ds
[], unsigned ndigs
, unsigned nzin
,
123 * Converts a decimal string containing an implicit point, nzin
124 * leading implicit zeros, and ndigs explicit digits, into a big
131 printf(" _fractionstring_to_big_decimal ndigs %d nzin %d s %s \n", ndigs
, nzin
, ds
);
134 pbf
->bexponent
= -(int) (nzin
+ ndigs
);
135 pbf
->blength
= (ndigs
+ 3) / 4;
137 ids
= nzin
+ ndigs
- 4 * pbf
->blength
;
138 ibf
= pbf
->blength
- 1;
141 printf(" _fractionstring_to_big_decimal exponent %d ids %d ibf %d \n", pbf
->bexponent
, ids
, ibf
);
144 #define FDIGIT(i) ((i < nzin) ? 0 : ((i < (nzin+ndigs)) ? (ds[i-nzin] - '0') : 0))
146 pbf
->bsignificand
[ibf
] = 1000 * FDIGIT(ids
) + 100 * FDIGIT(ids
+ 1) + 10 * FDIGIT(ids
+ 2) + FDIGIT(ids
+ 3);
149 for (; ids
< (int) (nzin
+ ndigs
- 4); ids
+= 4) { /* Additional digits to
150 * be found. Main loop. */
152 pbf
->bsignificand
[ibf
] = 1000 * ds
[ids
- nzin
] + 100 * ds
[ids
+ 1 - nzin
] + 10 * ds
[ids
+ 2 - nzin
] + ds
[ids
+ 3 - nzin
] - 1111 * '0';
159 pbf
->bsignificand
[0] = 1000 * FDIGIT(ids
) + 100 * FDIGIT(ids
+ 1) + 10 * FDIGIT(ids
+ 2) + FDIGIT(ids
+ 3);
167 printf(" _fractionstring_to_big_decimal: ");
168 _display_big_float(pbf
, 10);
173 _mul_10000short(_big_float
*pbf
, long unsigned carry
)
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);
184 p
= _carry_out_b10000(carry
);
185 pbf
->bsignificand
[j
++] = (_BIG_FLOAT_DIGIT
) (p
& 0xffff);
192 _big_decimal_to_big_binary(_big_float
*pd
, _big_float
*pb
)
194 /* Convert _big_float from decimal form to binary form. */
197 _BIG_FLOAT_DIGIT sticky
, carry
;
198 _BIG_FLOAT_DIGIT multiplier
;
201 assert(pd
->bexponent
>= -3);
202 assert(pd
->bexponent
<= 3);
206 id
= pd
->blength
- 1;
207 if ((id
== 0) && (pd
->bexponent
< 0)) {
208 pb
->bsignificand
[0] = 0;
210 pb
->bsignificand
[0] = pd
->bsignificand
[id
--];
211 idbound
= (pd
->bexponent
< 0) ? 1 : 0; /* How far to carry next
212 * for loop depends on
216 for (; id
>= idbound
; id
--) {
217 _mul_10000short(pb
, (long unsigned) pd
->bsignificand
[id
]);
220 if (pd
->bexponent
< 0) {/* Have to save some integer bits, discard
221 * and stick some fraction bits at the end. */
226 carry
= pd
->bsignificand
[0];
228 switch (pd
->bexponent
) {
235 sticky
= carry
% 100;
240 sticky
= carry
% 1000;
245 _multiply_base_two(pb
, multiplier
, (long unsigned) carry
);
247 pb
->bsignificand
[0] |= 1; /* Save lost bits. */
248 } else if (pd
->bexponent
> 0) { /* Have to append some zeros. */
249 switch (pd
->bexponent
) {
261 _multiply_base_two(pb
, multiplier
, (long unsigned) carry
);
264 printf(" _big_decimal_to_big_binary ");
265 _display_big_float(pb
, 2);
270 _big_binary_to_unpacked(_big_float
*pb
, unpacked
*pu
)
272 /* Convert a binary big_float to a binary_unpacked. */
277 assert(pb
->bsignificand
[pb
->blength
- 1] != 0); /* Assert pb is
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];
285 if (iu
< UNPACKED_SIZE
) { /* The big float fits in the unpacked
286 * with no rounding. */
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
293 while (pb
->bsignificand
[ib
] == 0)
296 pu
->significand
[UNPACKED_SIZE
- 1] |= 1; /* Stick lsb if nonzero
300 pu
->exponent
= 16 * pb
->blength
+ pb
->bexponent
- 1;
304 printf(" _big_binary_to_unpacked \n");
305 _display_unpacked(pu
);