xref: /titanic_50/usr/src/lib/libbc/libc/gen/common/_sprintf_sup.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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