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 /*
32 * Fundamental utilities of base conversion required for sprintf - but too
33 * complex or too seldom used to be worth assembly language coding.
34 */
35
36 /* p = x * y + c ; return (p/10000 << 16 | p%10000) */
37 unsigned long
_prodc_b10000(_BIG_FLOAT_DIGIT x,_BIG_FLOAT_DIGIT y,unsigned long c)38 _prodc_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y, unsigned long c)
39 {
40 unsigned long p = x * (unsigned long) y + c;
41
42 return ((p / 10000) << 16) | (p % 10000);
43 }
44
45 /* p = x * y ; return p */
46 unsigned long
_prod_b65536(_BIG_FLOAT_DIGIT x,_BIG_FLOAT_DIGIT y)47 _prod_b65536(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)
48 {
49 return (x * (unsigned long)y);
50 }
51
52 /* p = x * y ; return (p/10000 << 16 | p%10000) */
53 unsigned long
_prod_b10000(_BIG_FLOAT_DIGIT x,_BIG_FLOAT_DIGIT y)54 _prod_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)
55 {
56 unsigned long p = x * (unsigned long) y;
57
58 return ((p / 10000) << 16) | (p % 10000);
59 }
60
61 /* p = x << n + c ; return (p/10000 << 16 | p%10000) */
62 unsigned long
_lshift_b10000(_BIG_FLOAT_DIGIT x,short unsigned n,long unsigned c)63 _lshift_b10000(_BIG_FLOAT_DIGIT x, short unsigned n, long unsigned c)
64 {
65 unsigned long p = (((unsigned long) x) << n) + c;
66
67 return ((p / 10000) << 16) | (p % 10000);
68 }
69
70 /* p = x * 10000 + c ; return p */
71 unsigned long
_prod_10000_b65536(_BIG_FLOAT_DIGIT x,long unsigned c)72 _prod_10000_b65536(_BIG_FLOAT_DIGIT x, long unsigned c)
73 {
74 return (x * (unsigned long) 10000 + c);
75 }
76
77 /* p = x << 16 + c ; return (p/10000 << 16 | p%10000) */
78 unsigned long
_prod_65536_b10000(_BIG_FLOAT_DIGIT x,long unsigned c)79 _prod_65536_b10000(_BIG_FLOAT_DIGIT x, long unsigned c)
80 {
81 unsigned long p = (((unsigned long) x) << 16) + c;
82
83 return ((p / 10000) << 16) | (p % 10000);
84 }
85
86 /* p = c ; return (p/10000 << 16 | p%10000) */
87 unsigned long
_carry_out_b10000(unsigned long c)88 _carry_out_b10000(unsigned long c)
89 {
90 return ((c / 10000) << 16) | (c % 10000);
91 }
92
93 void
_left_shift_base_ten(_big_float * pbf,short unsigned multiplier)94 _left_shift_base_ten(_big_float *pbf, short unsigned multiplier)
95 {
96 /*
97 * Multiply a base-10**4 significand by 2<<multiplier. Extend length
98 * as necessary to accommodate carries.
99 */
100
101 short unsigned length = pbf->blength;
102 int j;
103 unsigned long carry;
104 long p;
105
106 carry = 0;
107 for (j = 0; j < length; j++) {
108 p = _lshift_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, carry);
109 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
110 carry = p >> 16;
111 }
112 while (carry != 0) {
113 p = _carry_out_b10000(carry);
114 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
115 carry = p >> 16;
116 }
117 pbf->blength = j;
118 }
119
120 void
_left_shift_base_two(_big_float * pbf,short unsigned multiplier)121 _left_shift_base_two(_big_float *pbf, short unsigned multiplier)
122 {
123 /*
124 * Multiply a base-2**16 significand by 2<<multiplier. Extend length
125 * as necessary to accommodate carries.
126 */
127
128 short unsigned length = pbf->blength;
129 long unsigned p;
130 int j;
131 unsigned long carry;
132
133 carry = 0;
134 for (j = 0; j < length; j++) {
135 p = _lshift_b65536(pbf->bsignificand[j], multiplier, carry);
136 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
137 carry = p >> 16;
138 }
139 if (carry != 0) {
140 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
141 }
142 pbf->blength = j;
143 }
144
145 void
_right_shift_base_two(_big_float * pbf,short unsigned multiplier,_BIG_FLOAT_DIGIT * sticky)146 _right_shift_base_two(_big_float *pbf, short unsigned multiplier,
147 _BIG_FLOAT_DIGIT *sticky)
148 {
149 /* *pb = *pb / 2**multiplier to normalize. 15 <= multiplier <= 1 */
150 /* Any bits shifted out got to *sticky. */
151
152 long unsigned p;
153 int j;
154 unsigned long carry;
155
156 carry = 0;
157 for (j = pbf->blength - 1; j >= 0; j--) {
158 p = _rshift_b65536(pbf->bsignificand[j], multiplier, carry);
159 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p >> 16);
160 carry = p & 0xffff;
161 }
162 *sticky = (_BIG_FLOAT_DIGIT) carry;
163 }
164
165 void
_multiply_base_ten(_big_float * pbf,_BIG_FLOAT_DIGIT multiplier)166 _multiply_base_ten(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier)
167 {
168 /*
169 * Multiply a base-10**4 significand by multiplier. Extend length as
170 * necessary to accommodate carries.
171 */
172
173 int j;
174 unsigned long carry;
175 long p;
176
177 carry = 0;
178 for (j = 0; j < pbf->blength; j++) {
179 p = _prodc_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, 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
_multiply_base_two(_big_float * pbf,_BIG_FLOAT_DIGIT multiplier,long unsigned carry)192 _multiply_base_two(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier,
193 long unsigned carry)
194 {
195 /*
196 * Multiply a base-2**16 significand by multiplier. Extend length as
197 * necessary to accommodate carries.
198 */
199
200 short unsigned length = pbf->blength;
201 long unsigned p;
202 int j;
203
204 for (j = 0; j < length; j++) {
205 p = _prodc_b65536(pbf->bsignificand[j], multiplier, carry);
206 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
207 carry = p >> 16;
208 }
209 if (carry != 0) {
210 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
211 }
212 pbf->blength = j;
213 }
214
215 void
_multiply_base_ten_by_two(_big_float * pbf,short unsigned multiplier)216 _multiply_base_ten_by_two(_big_float *pbf, short unsigned multiplier)
217 {
218 /*
219 * Multiply a base-10**4 significand by 2**multiplier. Extend length
220 * as necessary to accommodate carries.
221 */
222
223 short unsigned length = pbf->blength;
224 int j;
225 long unsigned carry, p;
226
227 carry = 0;
228 for (j = 0; j < length; j++) {
229 p = _lshift_b10000(pbf->bsignificand[j], multiplier, carry);
230 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
231 carry = p >> 16;
232 }
233 while (carry != 0) {
234 p = _carry_out_b10000(carry);
235 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
236 carry = p >> 16;
237 }
238 pbf->blength = j;
239 }
240
241 void
_unpacked_to_big_float(unpacked * pu,_big_float * pb,int * pe)242 _unpacked_to_big_float(unpacked *pu, _big_float *pb, int *pe)
243 {
244 /*
245 * Converts pu into a bigfloat *pb of minimal length; exponent *pe
246 * such that pu = *pb * 2 ** *pe
247 */
248
249 int iz, it;
250
251 for (iz = (UNPACKED_SIZE - 2); pu->significand[iz] == 0; iz--); /* Find lsw. */
252
253 for (it = 0; it <= iz; it++) {
254 pb->bsignificand[2 * (iz - it)] = pu->significand[it] & 0xffff;
255 pb->bsignificand[2 * (iz - it) + 1] = pu->significand[it] >> 16;
256 }
257
258 pb->blength = 2 * iz + 2;
259 if (pb->bsignificand[0] == 0) {
260 for (it = 1; it < pb->blength; it++)
261 pb->bsignificand[it - 1] = pb->bsignificand[it];
262 pb->blength--;
263 }
264 *pe = pu->exponent + 1 - 16 * pb->blength;
265 pb->bexponent = 0;
266
267 #ifdef DEBUG
268 printf(" unpacked to big float 2**%d * ", *pe);
269 _display_big_float(pb, 2);
270 #endif
271 }
272
273 void
_mul_65536short(_big_float * pbf,unsigned long carry)274 _mul_65536short(_big_float *pbf, unsigned long carry)
275 {
276 /* *pbf *= 65536 ; += carry ; */
277
278 long unsigned p;
279 int j;
280
281 for (j = 0; j < pbf->blength; j++) {
282 p = _prod_65536_b10000(pbf->bsignificand[j], carry);
283 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
284 carry = p >> 16;
285 }
286 while (carry != 0) {
287 p = _carry_out_b10000(carry);
288 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
289 carry = p >> 16;
290 }
291 pbf->blength = j;
292 }
293
294 void
_big_binary_to_big_decimal(_big_float * pb,_big_float * pd)295 _big_binary_to_big_decimal(_big_float *pb, _big_float *pd)
296 {
297 /* Convert _big_float from binary form to decimal form. */
298
299 int i;
300
301 pd->bsignificand[0] = pb->bsignificand[pb->blength - 1] % 10000;
302 if (pd->bsignificand[0] == pb->bsignificand[pb->blength - 1]) {
303 pd->blength = 1;
304 } else {
305 pd->blength = 2;
306 pd->bsignificand[1] = pb->bsignificand[pb->blength - 1] / 10000;
307 }
308 for (i = pb->blength - 2; i >= 0; i--) { /* Multiply by 2**16 and
309 * add next significand. */
310 _mul_65536short(pd, (unsigned long) pb->bsignificand[i]);
311 }
312 for (i = 0; i <= (pb->bexponent - 16); i += 16) { /* Multiply by 2**16 for
313 * each trailing zero. */
314 _mul_65536short(pd, (unsigned long) 0);
315 }
316 if (pb->bexponent > i)
317 _left_shift_base_ten(pd, (short unsigned) (pb->bexponent - i));
318 pd->bexponent = 0;
319
320 #ifdef DEBUG
321 printf(" _big_binary_to_big_decimal ");
322 _display_big_float(pd, 10);
323 #endif
324 }
325