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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Short cut for conversion from double precision to decimal
29 * floating point
30 */
31
32 #include "lint.h"
33 #include <sys/types.h>
34 #include <sys/isa_defs.h>
35 #include "base_conversion.h"
36
37 /*
38 * Powers of ten rounded up. If i is the largest index such that
39 * tbl_decade[i] <= x, then:
40 *
41 * if i == 0 then x < 10^-49
42 * else if i == TBL_DECADE_MAX then x >= 10^67
43 * else 10^(i-TBL_DECADE_OFFSET) <= x < 10^(i-TBL_DECADE_OFFSET+1)
44 */
45
46 #define TBL_DECADE_OFFSET 50
47 #define TBL_DECADE_MAX 117
48
49 static const double tbl_decade[TBL_DECADE_MAX + 1] = {
50 0.0,
51 1.00000000000000012631e-49, 1.00000000000000012631e-48,
52 1.00000000000000009593e-47, 1.00000000000000002300e-46,
53 1.00000000000000013968e-45, 1.00000000000000007745e-44,
54 1.00000000000000007745e-43, 1.00000000000000003762e-42,
55 1.00000000000000000576e-41, 1.00000000000000013321e-40,
56 1.00000000000000009243e-39, 1.00000000000000009243e-38,
57 1.00000000000000006632e-37, 1.00000000000000010809e-36,
58 1.00000000000000000786e-35, 1.00000000000000014150e-34,
59 1.00000000000000005597e-33, 1.00000000000000005597e-32,
60 1.00000000000000008334e-31, 1.00000000000000008334e-30,
61 1.00000000000000008334e-29, 1.00000000000000008334e-28,
62 1.00000000000000003849e-27, 1.00000000000000003849e-26,
63 1.00000000000000003849e-25, 1.00000000000000010737e-24,
64 1.00000000000000010737e-23, 1.00000000000000004860e-22,
65 1.00000000000000009562e-21, 1.00000000000000009562e-20,
66 1.00000000000000009562e-19, 1.00000000000000007154e-18,
67 1.00000000000000007154e-17, 1.00000000000000010236e-16,
68 1.00000000000000007771e-15, 1.00000000000000015659e-14,
69 1.00000000000000003037e-13, 1.00000000000000018184e-12,
70 1.00000000000000010106e-11, 1.00000000000000003643e-10,
71 1.00000000000000006228e-09, 1.00000000000000002092e-08,
72 1.00000000000000008710e-07, 1.00000000000000016651e-06,
73 1.00000000000000008180e-05, 1.00000000000000004792e-04,
74 1.00000000000000002082e-03, 1.00000000000000002082e-02,
75 1.00000000000000005551e-01, 1.00000000000000000000e+00,
76 1.00000000000000000000e+01, 1.00000000000000000000e+02,
77 1.00000000000000000000e+03, 1.00000000000000000000e+04,
78 1.00000000000000000000e+05, 1.00000000000000000000e+06,
79 1.00000000000000000000e+07, 1.00000000000000000000e+08,
80 1.00000000000000000000e+09, 1.00000000000000000000e+10,
81 1.00000000000000000000e+11, 1.00000000000000000000e+12,
82 1.00000000000000000000e+13, 1.00000000000000000000e+14,
83 1.00000000000000000000e+15, 1.00000000000000000000e+16,
84 1.00000000000000000000e+17, 1.00000000000000000000e+18,
85 1.00000000000000000000e+19, 1.00000000000000000000e+20,
86 1.00000000000000000000e+21, 1.00000000000000000000e+22,
87 1.00000000000000008389e+23, 1.00000000000000011744e+24,
88 1.00000000000000009060e+25, 1.00000000000000004765e+26,
89 1.00000000000000001329e+27, 1.00000000000000017821e+28,
90 1.00000000000000009025e+29, 1.00000000000000001988e+30,
91 1.00000000000000007618e+31, 1.00000000000000005366e+32,
92 1.00000000000000008969e+33, 1.00000000000000006087e+34,
93 1.00000000000000015310e+35, 1.00000000000000004242e+36,
94 1.00000000000000007194e+37, 1.00000000000000016638e+38,
95 1.00000000000000009082e+39, 1.00000000000000003038e+40,
96 1.00000000000000000620e+41, 1.00000000000000004489e+42,
97 1.00000000000000001394e+43, 1.00000000000000008821e+44,
98 1.00000000000000008821e+45, 1.00000000000000011990e+46,
99 1.00000000000000004385e+47, 1.00000000000000004385e+48,
100 1.00000000000000007630e+49, 1.00000000000000007630e+50,
101 1.00000000000000015937e+51, 1.00000000000000012614e+52,
102 1.00000000000000020590e+53, 1.00000000000000007829e+54,
103 1.00000000000000001024e+55, 1.00000000000000009190e+56,
104 1.00000000000000004835e+57, 1.00000000000000008319e+58,
105 1.00000000000000008319e+59, 1.00000000000000012779e+60,
106 1.00000000000000009211e+61, 1.00000000000000003502e+62,
107 1.00000000000000005786e+63, 1.00000000000000002132e+64,
108 1.00000000000000010901e+65, 1.00000000000000013239e+66,
109 1.00000000000000013239e+67
110 };
111
112 /*
113 * Convert a positive double precision integer x <= 2147483647999999744
114 * (the largest double less than 2^31 * 10^9; this implementation works
115 * up to the largest double less than 2^25 * 10^12) to a string of ASCII
116 * decimal digits, adding leading zeroes so that the result has at least
117 * n digits. The string is terminated by a null byte, and its length
118 * is returned.
119 *
120 * This routine assumes round-to-nearest mode is in effect and any
121 * exceptions raised will be ignored.
122 */
123
124 #define tenm4 tbl_decade[TBL_DECADE_OFFSET - 4]
125 #define ten4 tbl_decade[TBL_DECADE_OFFSET + 4]
126 #define tenm12 tbl_decade[TBL_DECADE_OFFSET - 12]
127 #define ten12 tbl_decade[TBL_DECADE_OFFSET + 12]
128 #define one tbl_decade[TBL_DECADE_OFFSET]
129
130 static int
__double_to_digits(double x,char * s,int n)131 __double_to_digits(double x, char *s, int n)
132 {
133 double y;
134 int d[5], i, j;
135 char *ss, tmp[4];
136
137 /* decompose x into four-digit chunks */
138 y = (int)(x * tenm12);
139 x -= y * ten12;
140 if (x < 0.0) {
141 y -= one;
142 x += ten12;
143 }
144 d[0] = (int)(y * tenm4);
145 d[1] = (int)(y - d[0] * ten4);
146 y = (int)(x * tenm4);
147 d[4] = (int)(x - y * ten4);
148 d[2] = (int)(y * tenm4);
149 d[3] = (int)(y - d[2] * ten4);
150
151 /*
152 * Find the first nonzero chunk or the point at which to start
153 * converting so we have n digits, whichever comes first.
154 */
155 ss = s;
156 if (n > 20) {
157 for (j = 0; j < n - 20; j++)
158 *ss++ = '0';
159 i = 0;
160 } else {
161 for (i = 0; d[i] == 0 && n <= ((4 - i) << 2); i++)
162 ;
163 __four_digits_quick(d[i], tmp);
164 for (j = 0; tmp[j] == '0' && n <= ((4 - i) << 2) + 3 - j; j++)
165 ;
166 while (j < 4)
167 *ss++ = tmp[j++];
168 i++;
169 }
170
171 /* continue converting four-digit chunks */
172 while (i < 5) {
173 __four_digits_quick(d[i], ss);
174 ss += 4;
175 i++;
176 }
177
178 *ss = '\0';
179 return (ss - s);
180 }
181
182 /*
183 * Round a positive double precision number *x to the nearest integer,
184 * returning the result and passing back an indication of accuracy in
185 * *pe. On entry, nrx is the number of rounding errors already com-
186 * mitted in forming *x. On exit, *pe is 0 if *x was already integral
187 * and exact, 1 if the result is the correctly rounded integer value
188 * but not exact, and 2 if error in *x precludes determining the cor-
189 * rectly rounded integer value (i.e., the error might be larger than
190 * 1/2 - |*x - rx|, where rx is the nearest integer to *x).
191 */
192
193 static union {
194 unsigned int i[2];
195 double d;
196 } C[] = {
197 #ifdef _LITTLE_ENDIAN
198 { 0x00000000, 0x43300000 },
199 { 0x00000000, 0x3ca00000 },
200 { 0x00000000, 0x3fe00000 },
201 { 0xffffffff, 0x3fdfffff },
202 #else
203 { 0x43300000, 0x00000000 },
204 { 0x3ca00000, 0x00000000 },
205 { 0x3fe00000, 0x00000000 },
206 { 0x3fdfffff, 0xffffffff }, /* nextafter(1/2, 0) */
207 #endif
208 };
209
210 #define two52 C[0].d
211 #define twom53 C[1].d
212 #define half C[2].d
213 #define halfdec C[3].d
214
215 static double
__arint_set_n(double * x,int nrx,int * pe)216 __arint_set_n(double *x, int nrx, int *pe)
217 {
218 int hx;
219 double rx, rmx;
220
221 #ifdef _LITTLE_ENDIAN
222 hx = *(1+(int *)x);
223 #else
224 hx = *(int *)x;
225 #endif
226 if (hx >= 0x43300000) {
227 /* x >= 2^52, so it's already integral */
228 if (nrx == 0)
229 *pe = 0;
230 else if (nrx == 1 && hx < 0x43400000)
231 *pe = 1;
232 else
233 *pe = 2;
234 return (*x);
235 } else if (hx < 0x3fe00000) {
236 /* x < 1/2 */
237 if (nrx > 1 && hx == 0x3fdfffff)
238 *pe = (*x == halfdec)? 2 : 1;
239 else
240 *pe = 1;
241 return (0.0);
242 }
243
244 rx = (*x + two52) - two52;
245 if (nrx == 0) {
246 *pe = (rx == *x)? 0 : 1;
247 } else {
248 rmx = rx - *x;
249 if (rmx < 0.0)
250 rmx = -rmx;
251 *pe = (nrx * twom53 * *x < half - rmx)? 1 : 2;
252 }
253 return (rx);
254 }
255
256 /*
257 * Attempt to convert dd to a decimal record *pd according to the
258 * modes in *pm using double precision floating point. Return zero
259 * and sets *ps to reflect any exceptions incurred if successful.
260 * Return a nonzero value if unsuccessful.
261 */
262 int
__fast_double_to_decimal(double * dd,decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps)263 __fast_double_to_decimal(double *dd, decimal_mode *pm, decimal_record *pd,
264 fp_exception_field_type *ps)
265 {
266 int i, is, esum, eround, hd;
267 double dds;
268 __ieee_flags_type fb;
269
270 if (pm->rd != fp_nearest)
271 return (1);
272
273 if (pm->df == fixed_form) {
274 /* F format */
275 if (pm->ndigits < 0 || pm->ndigits > __TBL_TENS_MAX)
276 return (1);
277 __get_ieee_flags(&fb);
278 dds = __dabs(dd);
279 esum = 0;
280 if (pm->ndigits) {
281 /* scale by a positive power of ten */
282 if (pm->ndigits > __TBL_TENS_EXACT) {
283 dds *= __tbl_tens[pm->ndigits];
284 esum = 2;
285 } else {
286 dds = __mul_set(dds, __tbl_tens[pm->ndigits],
287 &eround);
288 esum = eround;
289 }
290 }
291 if (dds > 2147483647999999744.0) {
292 __set_ieee_flags(&fb);
293 return (1);
294 }
295 dds = __arint_set_n(&dds, esum, &eround);
296 if (eround == 2) {
297 /* error is too large to round reliably; punt */
298 __set_ieee_flags(&fb);
299 return (1);
300 }
301 if (dds == 0.0) {
302 is = (pm->ndigits > 0)? pm->ndigits : 1;
303 for (i = 0; i < is; i++)
304 pd->ds[i] = '0';
305 pd->ds[is] = '\0';
306 eround++;
307 } else {
308 is = __double_to_digits(dds, pd->ds, pm->ndigits);
309 }
310 pd->ndigits = is;
311 pd->exponent = -pm->ndigits;
312 } else {
313 /* E format */
314 if (pm->ndigits < 1 || pm->ndigits > 18)
315 return (1);
316 __get_ieee_flags(&fb);
317 dds = __dabs(dd);
318 /* find the decade containing dds */
319 #ifdef _LITTLE_ENDIAN
320 hd = *(1+(int *)dd);
321 #else
322 hd = *(int *)dd;
323 #endif
324 hd = (hd >> 20) & 0x7ff;
325 if (hd >= 0x400) {
326 if (hd > 0x4e0)
327 i = TBL_DECADE_MAX;
328 else
329 i = TBL_DECADE_MAX - ((0x4e0 - hd) >> 2);
330 } else {
331 if (hd < 0x358)
332 i = 0;
333 else
334 i = TBL_DECADE_OFFSET - ((0x3ff - hd) >> 2);
335 }
336 while (dds < tbl_decade[i])
337 i--;
338 /* determine the power of ten by which to scale */
339 i = pm->ndigits - 1 - (i - TBL_DECADE_OFFSET);
340 esum = 0;
341 if (i > 0) {
342 /* scale by a positive power of ten */
343 if (i > __TBL_TENS_EXACT) {
344 if (i > __TBL_TENS_MAX) {
345 __set_ieee_flags(&fb);
346 return (1);
347 }
348 dds *= __tbl_tens[i];
349 esum = 2;
350 } else {
351 dds = __mul_set(dds, __tbl_tens[i], &eround);
352 esum = eround;
353 }
354 } else if (i < 0) {
355 /* scale by a negative power of ten */
356 if (-i > __TBL_TENS_EXACT) {
357 if (-i > __TBL_TENS_MAX) {
358 __set_ieee_flags(&fb);
359 return (1);
360 }
361 dds /= __tbl_tens[-i];
362 esum = 2;
363 } else {
364 dds = __div_set(dds, __tbl_tens[-i], &eround);
365 esum = eround;
366 }
367 }
368 dds = __arint_set_n(&dds, esum, &eround);
369 if (eround == 2) {
370 /* error is too large to round reliably; punt */
371 __set_ieee_flags(&fb);
372 return (1);
373 }
374 is = __double_to_digits(dds, pd->ds, 1);
375 if (is > pm->ndigits) {
376 /*
377 * The result rounded up to the next larger power
378 * of ten; just discard the last zero and adjust
379 * the exponent.
380 */
381 pd->ds[--is] = '\0';
382 i--;
383 }
384 pd->ndigits = is;
385 pd->exponent = -i;
386 }
387 *ps = (eround == 0)? 0 : (1 << fp_inexact);
388 __set_ieee_flags(&fb);
389 return (0);
390 }
391