Daily bump.
[official-gcc.git] / libgcc / config / libbid / bid128_string.c
bloba6270fb0c8e55ef41375388100b28a7b081ab9f1
1 /* Copyright (C) 2007-2015 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 3, or (at your option) any later
8 version.
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
15 Under Section 7 of GPL version 3, you are granted additional
16 permissions described in the GCC Runtime Library Exception, version
17 3.1, as published by the Free Software Foundation.
19 You should have received a copy of the GNU General Public License and
20 a copy of the GCC Runtime Library Exception along with this program;
21 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
22 <http://www.gnu.org/licenses/>. */
24 /*****************************************************************************
25 * BID128_to_string
26 ****************************************************************************/
28 #define BID_128RES
29 #include <stdio.h>
30 #include "bid_internal.h"
31 #include "bid128_2_str.h"
32 #include "bid128_2_str_macros.h"
34 extern int bid128_coeff_2_string (UINT64 X_hi, UINT64 X_lo,
35 char *char_ptr);
37 #if DECIMAL_CALL_BY_REFERENCE
39 void
40 bid128_to_string (char *str,
41 UINT128 *
42 px _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
43 _EXC_INFO_PARAM) {
44 UINT128 x;
45 #else
47 void
48 bid128_to_string (char *str, UINT128 x
49 _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
50 #endif
51 UINT64 x_sign;
52 UINT64 x_exp;
53 int exp; // unbiased exponent
54 // Note: C1.w[1], C1.w[0] represent x_signif_hi, x_signif_lo (all are UINT64)
55 int ind;
56 UINT128 C1;
57 unsigned int k = 0; // pointer in the string
58 unsigned int d0, d123;
59 UINT64 HI_18Dig, LO_18Dig, Tmp;
60 UINT32 MiDi[12], *ptr;
61 char *c_ptr_start, *c_ptr;
62 int midi_ind, k_lcv, len;
64 #if DECIMAL_CALL_BY_REFERENCE
65 x = *px;
66 #endif
68 BID_SWAP128(x);
69 // check for NaN or Infinity
70 if ((x.w[1] & MASK_SPECIAL) == MASK_SPECIAL) {
71 // x is special
72 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
73 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNAN
74 // set invalid flag
75 str[0] = ((SINT64)x.w[1]<0)? '-':'+';
76 str[1] = 'S';
77 str[2] = 'N';
78 str[3] = 'a';
79 str[4] = 'N';
80 str[5] = '\0';
81 } else { // x is QNaN
82 str[0] = ((SINT64)x.w[1]<0)? '-':'+';
83 str[1] = 'Q';
84 str[2] = 'N';
85 str[3] = 'a';
86 str[4] = 'N';
87 str[5] = '\0';
89 } else { // x is not a NaN, so it must be infinity
90 if ((x.w[1] & MASK_SIGN) == 0x0ull) { // x is +inf
91 str[0] = '+';
92 str[1] = 'I';
93 str[2] = 'n';
94 str[3] = 'f';
95 str[4] = '\0';
96 } else { // x is -inf
97 str[0] = '-';
98 str[1] = 'I';
99 str[2] = 'n';
100 str[3] = 'f';
101 str[4] = '\0';
104 return;
105 } else if (((x.w[1] & MASK_COEFF) == 0x0ull) && (x.w[0] == 0x0ull)) {
106 // x is 0
107 len = 0;
109 //determine if +/-
110 if (x.w[1] & MASK_SIGN)
111 str[len++] = '-';
112 else
113 str[len++] = '+';
114 str[len++] = '0';
115 str[len++] = 'E';
117 // extract the exponent and print
118 exp = (int) (((x.w[1] & MASK_EXP) >> 49) - 6176);
119 if(exp > (((0x5ffe)>>1) - (6176))) {
120 exp = (int) ((((x.w[1]<<2) & MASK_EXP) >> 49) - 6176);
122 if (exp >= 0) {
123 str[len++] = '+';
124 len += sprintf (str + len, "%u", exp);// should not use sprintf (should
125 // use sophisticated algorithm, since we know range of exp is limited)
126 str[len++] = '\0';
127 } else {
128 len += sprintf (str + len, "%d", exp);// should not use sprintf (should
129 // use sophisticated algorithm, since we know range of exp is limited)
130 str[len++] = '\0';
132 return;
133 } else { // x is not special and is not zero
134 // unpack x
135 x_sign = x.w[1] & MASK_SIGN;// 0 for positive, MASK_SIGN for negative
136 x_exp = x.w[1] & MASK_EXP;// biased and shifted left 49 bit positions
137 if ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull)
138 x_exp = (x.w[1]<<2) & MASK_EXP;// biased and shifted left 49 bit positions
139 C1.w[1] = x.w[1] & MASK_COEFF;
140 C1.w[0] = x.w[0];
141 exp = (x_exp >> 49) - 6176;
143 // determine sign's representation as a char
144 if (x_sign)
145 str[k++] = '-';// negative number
146 else
147 str[k++] = '+';// positive number
149 // determine coefficient's representation as a decimal string
151 // if zero or non-canonical, set coefficient to '0'
152 if ((C1.w[1] > 0x0001ed09bead87c0ull) ||
153 (C1.w[1] == 0x0001ed09bead87c0ull &&
154 (C1.w[0] > 0x378d8e63ffffffffull)) ||
155 ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) ||
156 ((C1.w[1] == 0) && (C1.w[0] == 0))) {
157 str[k++] = '0';
158 } else {
159 /* ****************************************************
160 This takes a bid coefficient in C1.w[1],C1.w[0]
161 and put the converted character sequence at location
162 starting at &(str[k]). The function returns the number
163 of MiDi returned. Note that the character sequence
164 does not have leading zeros EXCEPT when the input is of
165 zero value. It will then output 1 character '0'
166 The algorithm essentailly tries first to get a sequence of
167 Millenial Digits "MiDi" and then uses table lookup to get the
168 character strings of these MiDis.
169 **************************************************** */
170 /* Algorithm first decompose possibly 34 digits in hi and lo
171 18 digits. (The high can have at most 16 digits). It then
172 uses macro that handle 18 digit portions.
173 The first step is to get hi and lo such that
174 2^(64) C1.w[1] + C1.w[0] = hi * 10^18 + lo, 0 <= lo < 10^18.
175 We use a table lookup method to obtain the hi and lo 18 digits.
176 [C1.w[1],C1.w[0]] = c_8 2^(107) + c_7 2^(101) + ... + c_0 2^(59) + d
177 where 0 <= d < 2^59 and each c_j has 6 bits. Because d fits in
178 18 digits, we set hi = 0, and lo = d to begin with.
179 We then retrieve from a table, for j = 0, 1, ..., 8
180 that gives us A and B where c_j 2^(59+6j) = A * 10^18 + B.
181 hi += A ; lo += B; After each accumulation into lo, we normalize
182 immediately. So at the end, we have the decomposition as we need. */
184 Tmp = C1.w[0] >> 59;
185 LO_18Dig = (C1.w[0] << 5) >> 5;
186 Tmp += (C1.w[1] << 5);
187 HI_18Dig = 0;
188 k_lcv = 0;
189 // Tmp = {C1.w[1]{49:0}, C1.w[0]{63:59}}
190 // Lo_18Dig = {C1.w[0]{58:0}}
192 while (Tmp) {
193 midi_ind = (int) (Tmp & 0x000000000000003FLL);
194 midi_ind <<= 1;
195 Tmp >>= 6;
196 HI_18Dig += mod10_18_tbl[k_lcv][midi_ind++];
197 LO_18Dig += mod10_18_tbl[k_lcv++][midi_ind];
198 __L0_Normalize_10to18 (HI_18Dig, LO_18Dig);
200 ptr = MiDi;
201 if (HI_18Dig == 0LL) {
202 __L1_Split_MiDi_6_Lead (LO_18Dig, ptr);
203 } else {
204 __L1_Split_MiDi_6_Lead (HI_18Dig, ptr);
205 __L1_Split_MiDi_6 (LO_18Dig, ptr);
207 len = ptr - MiDi;
208 c_ptr_start = &(str[k]);
209 c_ptr = c_ptr_start;
211 /* now convert the MiDi into character strings */
212 __L0_MiDi2Str_Lead (MiDi[0], c_ptr);
213 for (k_lcv = 1; k_lcv < len; k_lcv++) {
214 __L0_MiDi2Str (MiDi[k_lcv], c_ptr);
216 k = k + (c_ptr - c_ptr_start);
219 // print E and sign of exponent
220 str[k++] = 'E';
221 if (exp < 0) {
222 exp = -exp;
223 str[k++] = '-';
224 } else {
225 str[k++] = '+';
228 // determine exponent's representation as a decimal string
229 // d0 = exp / 1000;
230 // Use Property 1
231 d0 = (exp * 0x418a) >> 24;// 0x418a * 2^-24 = (10^(-3))RP,15
232 d123 = exp - 1000 * d0;
234 if (d0) { // 1000 <= exp <= 6144 => 4 digits to return
235 str[k++] = d0 + 0x30;// ASCII for decimal digit d0
236 ind = 3 * d123;
237 str[k++] = char_table3[ind];
238 str[k++] = char_table3[ind + 1];
239 str[k++] = char_table3[ind + 2];
240 } else { // 0 <= exp <= 999 => d0 = 0
241 if (d123 < 10) { // 0 <= exp <= 9 => 1 digit to return
242 str[k++] = d123 + 0x30;// ASCII
243 } else if (d123 < 100) { // 10 <= exp <= 99 => 2 digits to return
244 ind = 2 * (d123 - 10);
245 str[k++] = char_table2[ind];
246 str[k++] = char_table2[ind + 1];
247 } else { // 100 <= exp <= 999 => 3 digits to return
248 ind = 3 * d123;
249 str[k++] = char_table3[ind];
250 str[k++] = char_table3[ind + 1];
251 str[k++] = char_table3[ind + 2];
254 str[k] = '\0';
257 return;
262 #define MAX_FORMAT_DIGITS_128 34
263 #define MAX_STRING_DIGITS_128 100
264 #define MAX_SEARCH MAX_STRING_DIGITS_128-MAX_FORMAT_DIGITS_128-1
267 #if DECIMAL_CALL_BY_REFERENCE
269 void
270 bid128_from_string (UINT128 * pres,
271 char *ps _RND_MODE_PARAM _EXC_FLAGS_PARAM
272 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
273 #else
275 UINT128
276 bid128_from_string (char *ps _RND_MODE_PARAM _EXC_FLAGS_PARAM
277 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
278 #endif
279 UINT128 CX, res;
280 UINT64 sign_x, coeff_high, coeff_low, coeff2, coeff_l2, carry = 0x0ull,
281 scale_high, right_radix_leading_zeros;
282 int ndigits_before, ndigits_after, ndigits_total, dec_expon, sgn_exp,
283 i, d2, rdx_pt_enc;
284 char c, buffer[MAX_STRING_DIGITS_128];
285 int save_rnd_mode;
286 int save_fpsf;
288 #if DECIMAL_CALL_BY_REFERENCE
289 #if !DECIMAL_GLOBAL_ROUNDING
290 _IDEC_round rnd_mode = *prnd_mode;
291 #endif
292 #endif
294 save_rnd_mode = rnd_mode; // dummy
295 save_fpsf = *pfpsf; // dummy
297 right_radix_leading_zeros = rdx_pt_enc = 0;
299 // if null string, return NaN
300 if (!ps) {
301 res.w[1] = 0x7c00000000000000ull;
302 res.w[0] = 0;
303 BID_RETURN (res);
305 // eliminate leading white space
306 while ((*ps == ' ') || (*ps == '\t'))
307 ps++;
309 // c gets first character
310 c = *ps;
313 // if c is null or not equal to a (radix point, negative sign,
314 // positive sign, or number) it might be SNaN, sNaN, Infinity
315 if (!c
316 || (c != '.' && c != '-' && c != '+'
317 && ((unsigned) (c - '0') > 9))) {
318 res.w[0] = 0;
319 // Infinity?
320 if ((tolower_macro (ps[0]) == 'i' && tolower_macro (ps[1]) == 'n'
321 && tolower_macro (ps[2]) == 'f')
322 && (!ps[3]
323 || (tolower_macro (ps[3]) == 'i'
324 && tolower_macro (ps[4]) == 'n'
325 && tolower_macro (ps[5]) == 'i'
326 && tolower_macro (ps[6]) == 't'
327 && tolower_macro (ps[7]) == 'y' && !ps[8])
328 )) {
329 res.w[1] = 0x7800000000000000ull;
330 BID_RETURN (res);
332 // return sNaN
333 if (tolower_macro (ps[0]) == 's' && tolower_macro (ps[1]) == 'n' &&
334 tolower_macro (ps[2]) == 'a' && tolower_macro (ps[3]) == 'n') {
335 // case insensitive check for snan
336 res.w[1] = 0x7e00000000000000ull;
337 BID_RETURN (res);
338 } else {
339 // return qNaN
340 res.w[1] = 0x7c00000000000000ull;
341 BID_RETURN (res);
344 // if +Inf, -Inf, +Infinity, or -Infinity (case insensitive check for inf)
345 if ((tolower_macro (ps[1]) == 'i' && tolower_macro (ps[2]) == 'n' &&
346 tolower_macro (ps[3]) == 'f') && (!ps[4] ||
347 (tolower_macro (ps[4]) == 'i' && tolower_macro (ps[5]) == 'n' &&
348 tolower_macro (ps[6]) == 'i' && tolower_macro (ps[7]) == 't' &&
349 tolower_macro (ps[8]) == 'y' && !ps[9]))) { // ci check for infinity
350 res.w[0] = 0;
352 if (c == '+')
353 res.w[1] = 0x7800000000000000ull;
354 else if (c == '-')
355 res.w[1] = 0xf800000000000000ull;
356 else
357 res.w[1] = 0x7c00000000000000ull;
359 BID_RETURN (res);
361 // if +sNaN, +SNaN, -sNaN, or -SNaN
362 if (tolower_macro (ps[1]) == 's' && tolower_macro (ps[2]) == 'n'
363 && tolower_macro (ps[3]) == 'a' && tolower_macro (ps[4]) == 'n') {
364 res.w[0] = 0;
365 if (c == '-')
366 res.w[1] = 0xfe00000000000000ull;
367 else
368 res.w[1] = 0x7e00000000000000ull;
369 BID_RETURN (res);
371 // set up sign_x to be OR'ed with the upper word later
372 if (c == '-')
373 sign_x = 0x8000000000000000ull;
374 else
375 sign_x = 0;
377 // go to next character if leading sign
378 if (c == '-' || c == '+')
379 ps++;
381 c = *ps;
383 // if c isn't a decimal point or a decimal digit, return NaN
384 if (c != '.' && ((unsigned) (c - '0') > 9)) {
385 res.w[1] = 0x7c00000000000000ull | sign_x;
386 res.w[0] = 0;
387 BID_RETURN (res);
389 // detect zero (and eliminate/ignore leading zeros)
390 if (*(ps) == '0') {
392 // if all numbers are zeros (with possibly 1 radix point, the number is zero
393 // should catch cases such as: 000.0
394 while (*ps == '0') {
396 ps++;
398 // for numbers such as 0.0000000000000000000000000000000000001001,
399 // we want to count the leading zeros
400 if (rdx_pt_enc) {
401 right_radix_leading_zeros++;
403 // if this character is a radix point, make sure we haven't already
404 // encountered one
405 if (*(ps) == '.') {
406 if (rdx_pt_enc == 0) {
407 rdx_pt_enc = 1;
408 // if this is the first radix point, and the next character is NULL,
409 // we have a zero
410 if (!*(ps + 1)) {
411 res.w[1] =
412 (0x3040000000000000ull -
413 (right_radix_leading_zeros << 49)) | sign_x;
414 res.w[0] = 0;
415 BID_RETURN (res);
417 ps = ps + 1;
418 } else {
419 // if 2 radix points, return NaN
420 res.w[1] = 0x7c00000000000000ull | sign_x;
421 res.w[0] = 0;
422 BID_RETURN (res);
424 } else if (!*(ps)) {
425 //res.w[1] = 0x3040000000000000ull | sign_x;
426 res.w[1] =
427 (0x3040000000000000ull -
428 (right_radix_leading_zeros << 49)) | sign_x;
429 res.w[0] = 0;
430 BID_RETURN (res);
435 c = *ps;
437 // initialize local variables
438 ndigits_before = ndigits_after = ndigits_total = 0;
439 sgn_exp = 0;
440 // pstart_coefficient = ps;
442 if (!rdx_pt_enc) {
443 // investigate string (before radix point)
444 while ((unsigned) (c - '0') <= 9
445 && ndigits_before < MAX_STRING_DIGITS_128) {
446 buffer[ndigits_before] = c;
447 ps++;
448 c = *ps;
449 ndigits_before++;
452 ndigits_total = ndigits_before;
453 if (c == '.') {
454 ps++;
455 if ((c = *ps)) {
457 // investigate string (after radix point)
458 while ((unsigned) (c - '0') <= 9
459 && ndigits_total < MAX_STRING_DIGITS_128) {
460 buffer[ndigits_total] = c;
461 ps++;
462 c = *ps;
463 ndigits_total++;
465 ndigits_after = ndigits_total - ndigits_before;
468 } else {
469 // we encountered a radix point while detecting zeros
470 //if (c = *ps){
472 c = *ps;
473 ndigits_total = 0;
474 // investigate string (after radix point)
475 while ((unsigned) (c - '0') <= 9
476 && ndigits_total < MAX_STRING_DIGITS_128) {
477 buffer[ndigits_total] = c;
478 ps++;
479 c = *ps;
480 ndigits_total++;
482 ndigits_after = ndigits_total - ndigits_before;
485 // get exponent
486 dec_expon = 0;
487 if (ndigits_total < MAX_STRING_DIGITS_128) {
488 if (c) {
489 if (c != 'e' && c != 'E') {
490 // return NaN
491 res.w[1] = 0x7c00000000000000ull;
492 res.w[0] = 0;
493 BID_RETURN (res);
495 ps++;
496 c = *ps;
498 if (((unsigned) (c - '0') > 9)
499 && ((c != '+' && c != '-') || (unsigned) (ps[1] - '0') > 9)) {
500 // return NaN
501 res.w[1] = 0x7c00000000000000ull;
502 res.w[0] = 0;
503 BID_RETURN (res);
506 if (c == '-') {
507 sgn_exp = -1;
508 ps++;
509 c = *ps;
510 } else if (c == '+') {
511 ps++;
512 c = *ps;
515 dec_expon = c - '0';
516 i = 1;
517 ps++;
518 c = *ps - '0';
519 while (((unsigned) c) <= 9 && i < 7) {
520 d2 = dec_expon + dec_expon;
521 dec_expon = (d2 << 2) + d2 + c;
522 ps++;
523 c = *ps - '0';
524 i++;
528 dec_expon = (dec_expon + sgn_exp) ^ sgn_exp;
532 if (ndigits_total <= MAX_FORMAT_DIGITS_128) {
533 dec_expon +=
534 DECIMAL_EXPONENT_BIAS_128 - ndigits_after -
535 right_radix_leading_zeros;
536 if (dec_expon < 0) {
537 res.w[1] = 0 | sign_x;
538 res.w[0] = 0;
540 if (ndigits_total == 0) {
541 CX.w[0] = 0;
542 CX.w[1] = 0;
543 } else if (ndigits_total <= 19) {
544 coeff_high = buffer[0] - '0';
545 for (i = 1; i < ndigits_total; i++) {
546 coeff2 = coeff_high + coeff_high;
547 coeff_high = (coeff2 << 2) + coeff2 + buffer[i] - '0';
549 CX.w[0] = coeff_high;
550 CX.w[1] = 0;
551 } else {
552 coeff_high = buffer[0] - '0';
553 for (i = 1; i < ndigits_total - 17; i++) {
554 coeff2 = coeff_high + coeff_high;
555 coeff_high = (coeff2 << 2) + coeff2 + buffer[i] - '0';
557 coeff_low = buffer[i] - '0';
558 i++;
559 for (; i < ndigits_total; i++) {
560 coeff_l2 = coeff_low + coeff_low;
561 coeff_low = (coeff_l2 << 2) + coeff_l2 + buffer[i] - '0';
563 // now form the coefficient as coeff_high*10^19+coeff_low+carry
564 scale_high = 100000000000000000ull;
565 __mul_64x64_to_128_fast (CX, coeff_high, scale_high);
567 CX.w[0] += coeff_low;
568 if (CX.w[0] < coeff_low)
569 CX.w[1]++;
571 get_BID128 (&res, sign_x, dec_expon, CX,&rnd_mode,pfpsf);
572 BID_RETURN (res);
573 } else {
574 // simply round using the digits that were read
576 dec_expon +=
577 ndigits_before + DECIMAL_EXPONENT_BIAS_128 -
578 MAX_FORMAT_DIGITS_128 - right_radix_leading_zeros;
580 if (dec_expon < 0) {
581 res.w[1] = 0 | sign_x;
582 res.w[0] = 0;
585 coeff_high = buffer[0] - '0';
586 for (i = 1; i < MAX_FORMAT_DIGITS_128 - 17; i++) {
587 coeff2 = coeff_high + coeff_high;
588 coeff_high = (coeff2 << 2) + coeff2 + buffer[i] - '0';
590 coeff_low = buffer[i] - '0';
591 i++;
592 for (; i < MAX_FORMAT_DIGITS_128; i++) {
593 coeff_l2 = coeff_low + coeff_low;
594 coeff_low = (coeff_l2 << 2) + coeff_l2 + buffer[i] - '0';
596 switch(rnd_mode) {
597 case ROUNDING_TO_NEAREST:
598 carry = ((unsigned) ('4' - buffer[i])) >> 31;
599 if ((buffer[i] == '5' && !(coeff_low & 1)) || dec_expon < 0) {
600 if (dec_expon >= 0) {
601 carry = 0;
602 i++;
604 for (; i < ndigits_total; i++) {
605 if (buffer[i] > '0') {
606 carry = 1;
607 break;
611 break;
613 case ROUNDING_DOWN:
614 if(sign_x)
615 for (; i < ndigits_total; i++) {
616 if (buffer[i] > '0') {
617 carry = 1;
618 break;
621 break;
622 case ROUNDING_UP:
623 if(!sign_x)
624 for (; i < ndigits_total; i++) {
625 if (buffer[i] > '0') {
626 carry = 1;
627 break;
630 break;
631 case ROUNDING_TO_ZERO:
632 carry=0;
633 break;
634 case ROUNDING_TIES_AWAY:
635 carry = ((unsigned) ('4' - buffer[i])) >> 31;
636 if (dec_expon < 0) {
637 for (; i < ndigits_total; i++) {
638 if (buffer[i] > '0') {
639 carry = 1;
640 break;
644 break;
648 // now form the coefficient as coeff_high*10^17+coeff_low+carry
649 scale_high = 100000000000000000ull;
650 if (dec_expon < 0) {
651 if (dec_expon > -MAX_FORMAT_DIGITS_128) {
652 scale_high = 1000000000000000000ull;
653 coeff_low = (coeff_low << 3) + (coeff_low << 1);
654 dec_expon--;
656 if (dec_expon == -MAX_FORMAT_DIGITS_128
657 && coeff_high > 50000000000000000ull)
658 carry = 0;
661 __mul_64x64_to_128_fast (CX, coeff_high, scale_high);
663 coeff_low += carry;
664 CX.w[0] += coeff_low;
665 if (CX.w[0] < coeff_low)
666 CX.w[1]++;
669 get_BID128(&res, sign_x, dec_expon, CX, &rnd_mode, pfpsf);
670 BID_RETURN (res);