1 /* Copyright (C) 2007 Free Software Foundation, Inc.
3 This file is part of GCC.
5 GCC is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2, or (at your option) any later
10 In addition to the permissions in the GNU General Public License, the
11 Free Software Foundation gives you unlimited permission to link the
12 compiled version of this file into combinations with other programs,
13 and to distribute those combinations without any restriction coming
14 from the use of this file. (The General Public License restrictions
15 do apply in other respects; for example, they cover modification of
16 the file, and distribution when not linked into a combine
19 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING. If not, write to the Free
26 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "bid_internal.h"
31 #include "bid128_2_str.h"
32 #include "bid128_2_str_macros.h"
34 #define MAX_FORMAT_DIGITS 16
35 #define DECIMAL_EXPONENT_BIAS 398
36 #define MAX_DECIMAL_EXPONENT 767
38 #if DECIMAL_CALL_BY_REFERENCE
41 __bid64_to_string (char *ps, UINT64 * px
42 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
48 __bid64_to_string (char *ps, UINT64 x
49 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
52 // the destination string (pointed to by ps) must be pre-allocated
53 UINT64 sign_x, coefficient_x, D, ER10;
54 int istart, exponent_x, j, digits_x, bin_expon_cx;
56 UINT32 MiDi[12], *ptr;
57 UINT64 HI_18Dig, LO_18Dig, Tmp;
58 char *c_ptr_start, *c_ptr;
59 int midi_ind, k_lcv, len;
61 #if DECIMAL_CALL_BY_REFERENCE
62 #if !DECIMAL_GLOBAL_ROUNDING
63 _IDEC_round rnd_mode = *prnd_mode;
68 // unpack arguments, check for NaN or Infinity
69 if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) {
70 // x is Inf. or NaN or 0
73 if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
74 if ((x & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
82 ps[0] = (sign_x) ? '-' : '+';
101 exponent_x = -exponent_x;
106 // get decimal digits in coefficient_x
107 tempx.d = (float) exponent_x;
108 bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
109 digits_x = __bid_estimate_decimal_digits[bin_expon_cx];
110 if ((UINT64)exponent_x >= __bid_power10_table_128[digits_x].w[0])
113 j = istart + digits_x - 1;
119 while (exponent_x > 9) {
120 D = (UINT64) exponent_x *ER10;
122 exponent_x = exponent_x - (D << 1) - (D << 3);
124 ps[j--] = '0' + (char) exponent_x;
127 ps[j] = '0' + (char) exponent_x;
136 // convert expon, coeff to ASCII
137 exponent_x -= DECIMAL_EXPONENT_BIAS;
146 // if zero or non-canonical, set coefficient to '0'
147 if ((coefficient_x > 9999999999999999ull) || // non-canonical
148 ((coefficient_x == 0)) // significand is zero
152 /* ****************************************************
153 This takes a bid coefficient in C1.w[1],C1.w[0]
154 and put the converted character sequence at location
155 starting at &(str[k]). The function returns the number
156 of MiDi returned. Note that the character sequence
157 does not have leading zeros EXCEPT when the input is of
158 zero value. It will then output 1 character '0'
159 The algorithm essentailly tries first to get a sequence of
160 Millenial Digits "MiDi" and then uses table lookup to get the
161 character strings of these MiDis.
162 **************************************************** */
163 /* Algorithm first decompose possibly 34 digits in hi and lo
164 18 digits. (The high can have at most 16 digits). It then
165 uses macro that handle 18 digit portions.
166 The first step is to get hi and lo such that
167 2^(64) C1.w[1] + C1.w[0] = hi * 10^18 + lo, 0 <= lo < 10^18.
168 We use a table lookup method to obtain the hi and lo 18 digits.
169 [C1.w[1],C1.w[0]] = c_8 2^(107) + c_7 2^(101) + ... + c_0 2^(59) + d
170 where 0 <= d < 2^59 and each c_j has 6 bits. Because d fits in
171 18 digits, we set hi = 0, and lo = d to begin with.
172 We then retrieve from a table, for j = 0, 1, ..., 8
173 that gives us A and B where c_j 2^(59+6j) = A * 10^18 + B.
174 hi += A ; lo += B; After each accumulation into lo, we normalize
175 immediately. So at the end, we have the decomposition as we need. */
177 Tmp = coefficient_x >> 59;
178 LO_18Dig = (coefficient_x << 5) >> 5;
183 midi_ind = (int) (Tmp & 0x000000000000003FLL);
186 HI_18Dig += __bid_mod10_18_tbl[k_lcv][midi_ind++];
187 LO_18Dig += __bid_mod10_18_tbl[k_lcv++][midi_ind];
188 __L0_Normalize_10to18 (HI_18Dig, LO_18Dig);
192 __L1_Split_MiDi_6_Lead (LO_18Dig, ptr);
194 c_ptr_start = &(ps[istart]);
197 /* now convert the MiDi into character strings */
198 __L0_MiDi2Str_Lead (MiDi[0], c_ptr);
199 for (k_lcv = 1; k_lcv < len; k_lcv++) {
200 __L0_MiDi2Str (MiDi[k_lcv], c_ptr);
202 istart = istart + (c_ptr - c_ptr_start);
207 if (exponent_x < 0) {
209 exponent_x = -exponent_x;
214 // get decimal digits in coefficient_x
215 tempx.d = (float) exponent_x;
216 bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
217 digits_x = __bid_estimate_decimal_digits[bin_expon_cx];
218 if ((UINT64)exponent_x >= __bid_power10_table_128[digits_x].w[0])
221 j = istart + digits_x - 1;
227 while (exponent_x > 9) {
228 D = (UINT64) exponent_x *ER10;
230 exponent_x = exponent_x - (D << 1) - (D << 3);
232 ps[j--] = '0' + (char) exponent_x;
235 ps[j] = '0' + (char) exponent_x;
248 #if DECIMAL_CALL_BY_REFERENCE
251 __bid64_from_string (UINT64 * pres, char *ps
252 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
257 __bid64_from_string (char *ps
258 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
261 UINT64 sign_x, coefficient_x = 0, rounded = 0, res;
262 int expon_x = 0, sgn_expon, ndigits, add_expon = 0, midpoint =
264 int dec_expon_scale = 0, right_radix_leading_zeros = 0, rdx_pt_enc =
269 #if DECIMAL_CALL_BY_REFERENCE
270 #if !DECIMAL_GLOBAL_ROUNDING
271 _IDEC_round rnd_mode = *prnd_mode;
275 // eliminate leading whitespace
276 while (((*ps == ' ') || (*ps == '\t')) && (*ps))
279 // get first non-whitespace character
282 // detect special cases (INF or NaN)
283 if (!c || (c != '.' && c != '-' && c != '+' && (c < '0' || c > '9'))) {
285 if ((tolower_macro (ps[0]) == 'i' && tolower_macro (ps[1]) == 'n' &&
286 tolower_macro (ps[2]) == 'f') && (!ps[3] ||
287 (tolower_macro (ps[3]) == 'i' &&
288 tolower_macro (ps[4]) == 'n' && tolower_macro (ps[5]) == 'i' &&
289 tolower_macro (ps[6]) == 't' && tolower_macro (ps[7]) == 'y' &&
291 res = 0x7800000000000000ull;
295 if (tolower_macro (ps[0]) == 's' && tolower_macro (ps[1]) == 'n' &&
296 tolower_macro (ps[2]) == 'a' && tolower_macro (ps[3]) == 'n') {
297 // case insensitive check for snan
298 res = 0x7e00000000000000ull;
302 res = 0x7c00000000000000ull;
306 // detect +INF or -INF
307 if ((tolower_macro (ps[1]) == 'i' && tolower_macro (ps[2]) == 'n' &&
308 tolower_macro (ps[3]) == 'f') && (!ps[4] ||
309 (tolower_macro (ps[4]) == 'i' && tolower_macro (ps[5]) == 'n' &&
310 tolower_macro (ps[6]) == 'i' && tolower_macro (ps[7]) == 't' &&
311 tolower_macro (ps[8]) == 'y' && !ps[9]))) {
313 res = 0x7800000000000000ull;
315 res = 0xf800000000000000ull;
317 res = 0x7c00000000000000ull;
320 // if +sNaN, +SNaN, -sNaN, or -SNaN
321 if (tolower_macro (ps[1]) == 's' && tolower_macro (ps[2]) == 'n'
322 && tolower_macro (ps[3]) == 'a' && tolower_macro (ps[4]) == 'n') {
324 res = 0xfe00000000000000ull;
326 res = 0x7e00000000000000ull;
331 sign_x = 0x8000000000000000ull;
335 // get next character if leading +/- sign
336 if (c == '-' || c == '+') {
340 // if c isn't a decimal point or a decimal digit, return NaN
341 if (c != '.' && (c < '0' || c > '9')) {
343 res = 0x7c00000000000000ull | sign_x;
349 // detect zero (and eliminate/ignore leading zeros)
350 if (*(ps) == '0' || *(ps) == '.') {
356 // if all numbers are zeros (with possibly 1 radix point, the number is zero
357 // should catch cases such as: 000.0
360 // for numbers such as 0.0000000000000000000000000000000000001001,
361 // we want to count the leading zeros
363 right_radix_leading_zeros++;
365 // if this character is a radix point, make sure we haven't already
368 if (rdx_pt_enc == 0) {
370 // if this is the first radix point, and the next character is NULL,
374 ((UINT64) (398 - right_radix_leading_zeros) << 53) |
380 // if 2 radix points, return NaN
381 res = 0x7c00000000000000ull | sign_x;
385 //pres->w[1] = 0x3040000000000000ull | sign_x;
387 ((UINT64) (398 - right_radix_leading_zeros) << 53) | sign_x;
396 while ((c >= '0' && c <= '9') || c == '.') {
400 res = 0x7c00000000000000ull | sign_x;
408 dec_expon_scale += rdx_pt_enc;
412 coefficient_x = (coefficient_x << 1) + (coefficient_x << 3);
413 coefficient_x += (UINT64) (c - '0');
414 } else if (ndigits == 17) {
415 // coefficient rounding
416 midpoint = (c == '5' && !(coefficient_x & 1)) ? 1 : 0;
417 // if coefficient is even and c is 5, prepare to round up if
418 // subsequent digit is nonzero
419 // if str[MAXDIG+1] > 5, we MUST round up
420 // if str[MAXDIG+1] == 5 and coefficient is ODD, ROUND UP!
421 if (c > '5' || (c == '5' && (coefficient_x & 1))) {
424 if (coefficient_x == 10000000000000000ull) {
425 coefficient_x = 1000000000000000ull;
432 } else { // ndigits > 17
434 if (midpoint && c > '0') {
446 add_expon -= (dec_expon_scale + right_radix_leading_zeros);
450 fast_get_BID64_check_OF (sign_x,
451 add_expon + DECIMAL_EXPONENT_BIAS,
452 coefficient_x, 0, &fpsc);
456 if (c != 'E' && c != 'e') {
458 res = 0x7c00000000000000ull | sign_x;
463 sgn_expon = (c == '-') ? 1 : 0;
464 if (c == '-' || c == '+') {
468 if (!c || c < '0' || c > '9') {
470 res = 0x7c00000000000000ull | sign_x;
474 while (c >= '0' && c <= '9') {
475 expon_x = (expon_x << 1) + (expon_x << 3);
476 expon_x += (int) (c - '0');
484 res = 0x7c00000000000000ull | sign_x;
491 expon_x += add_expon + DECIMAL_EXPONENT_BIAS;
498 get_BID64_UF (sign_x, expon_x, coefficient_x, rounded, rnd_mode,
502 res = get_BID64 (sign_x, expon_x, coefficient_x, rnd_mode, &fpsc);