1/* Copyright (C) 2007, 2009 Free Software Foundation, Inc. 2 3This file is part of GCC. 4 5GCC is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License as published by the Free 7Software Foundation; either version 3, or (at your option) any later 8version. 9 10GCC is distributed in the hope that it will be useful, but WITHOUT ANY 11WARRANTY; without even the implied warranty of MERCHANTABILITY or 12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13for more details. 14 15Under Section 7 of GPL version 3, you are granted additional 16permissions described in the GCC Runtime Library Exception, version 173.1, as published by the Free Software Foundation. 18 19You should have received a copy of the GNU General Public License and 20a copy of the GCC Runtime Library Exception along with this program; 21see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22<http://www.gnu.org/licenses/>. */ 23 24#include <ctype.h> 25#include "bid_internal.h" 26#include "bid128_2_str.h" 27#include "bid128_2_str_macros.h" 28 29#define MAX_FORMAT_DIGITS 16 30#define DECIMAL_EXPONENT_BIAS 398 31#define MAX_DECIMAL_EXPONENT 767 32 33#if DECIMAL_CALL_BY_REFERENCE 34 35void 36bid64_to_string (char *ps, UINT64 * px 37 _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { 38 UINT64 x; 39#else 40 41void 42bid64_to_string (char *ps, UINT64 x 43 _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { 44#endif 45// the destination string (pointed to by ps) must be pre-allocated 46 UINT64 sign_x, coefficient_x, D, ER10; 47 int istart, exponent_x, j, digits_x, bin_expon_cx; 48 int_float tempx; 49 UINT32 MiDi[12], *ptr; 50 UINT64 HI_18Dig, LO_18Dig, Tmp; 51 char *c_ptr_start, *c_ptr; 52 int midi_ind, k_lcv, len; 53 unsigned int save_fpsf; 54 55#if DECIMAL_CALL_BY_REFERENCE 56 x = *px; 57#endif 58 59 save_fpsf = *pfpsf; // place holder only 60 // unpack arguments, check for NaN or Infinity 61 if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) { 62 // x is Inf. or NaN or 0 63 64 // Inf or NaN? 65 if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) { 66 if ((x & 0x7c00000000000000ull) == 0x7c00000000000000ull) { 67 ps[0] = (sign_x) ? '-' : '+'; 68 ps[1] = ((x & MASK_SNAN) == MASK_SNAN)? 'S':'Q'; 69 ps[2] = 'N'; 70 ps[3] = 'a'; 71 ps[4] = 'N'; 72 ps[5] = 0; 73 return; 74 } 75 // x is Inf 76 ps[0] = (sign_x) ? '-' : '+'; 77 ps[1] = 'I'; 78 ps[2] = 'n'; 79 ps[3] = 'f'; 80 ps[4] = 0; 81 return; 82 } 83 // 0 84 istart = 0; 85 if (sign_x) { 86 ps[istart++] = '-'; 87 } 88 89 ps[istart++] = '0'; 90 ps[istart++] = 'E'; 91 92 exponent_x -= 398; 93 if (exponent_x < 0) { 94 ps[istart++] = '-'; 95 exponent_x = -exponent_x; 96 } else 97 ps[istart++] = '+'; 98 99 if (exponent_x) { 100 // get decimal digits in coefficient_x 101 tempx.d = (float) exponent_x; 102 bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f; 103 digits_x = estimate_decimal_digits[bin_expon_cx]; 104 if ((UINT64)exponent_x >= power10_table_128[digits_x].w[0]) 105 digits_x++; 106 107 j = istart + digits_x - 1; 108 istart = j + 1; 109 110 // 2^32/10 111 ER10 = 0x1999999a; 112 113 while (exponent_x > 9) { 114 D = (UINT64) exponent_x *ER10; 115 D >>= 32; 116 exponent_x = exponent_x - (D << 1) - (D << 3); 117 118 ps[j--] = '0' + (char) exponent_x; 119 exponent_x = D; 120 } 121 ps[j] = '0' + (char) exponent_x; 122 } else { 123 ps[istart++] = '0'; 124 } 125 126 ps[istart] = 0; 127 128 return; 129 } 130 // convert expon, coeff to ASCII 131 exponent_x -= DECIMAL_EXPONENT_BIAS; 132 133 ER10 = 0x1999999a; 134 135 istart = 0; 136 if (sign_x) { 137 ps[0] = '-'; 138 istart = 1; 139 } 140 // if zero or non-canonical, set coefficient to '0' 141 if ((coefficient_x > 9999999999999999ull) || // non-canonical 142 ((coefficient_x == 0)) // significand is zero 143 ) { 144 ps[istart++] = '0'; 145 } else { 146 /* **************************************************** 147 This takes a bid coefficient in C1.w[1],C1.w[0] 148 and put the converted character sequence at location 149 starting at &(str[k]). The function returns the number 150 of MiDi returned. Note that the character sequence 151 does not have leading zeros EXCEPT when the input is of 152 zero value. It will then output 1 character '0' 153 The algorithm essentailly tries first to get a sequence of 154 Millenial Digits "MiDi" and then uses table lookup to get the 155 character strings of these MiDis. 156 **************************************************** */ 157 /* Algorithm first decompose possibly 34 digits in hi and lo 158 18 digits. (The high can have at most 16 digits). It then 159 uses macro that handle 18 digit portions. 160 The first step is to get hi and lo such that 161 2^(64) C1.w[1] + C1.w[0] = hi * 10^18 + lo, 0 <= lo < 10^18. 162 We use a table lookup method to obtain the hi and lo 18 digits. 163 [C1.w[1],C1.w[0]] = c_8 2^(107) + c_7 2^(101) + ... + c_0 2^(59) + d 164 where 0 <= d < 2^59 and each c_j has 6 bits. Because d fits in 165 18 digits, we set hi = 0, and lo = d to begin with. 166 We then retrieve from a table, for j = 0, 1, ..., 8 167 that gives us A and B where c_j 2^(59+6j) = A * 10^18 + B. 168 hi += A ; lo += B; After each accumulation into lo, we normalize 169 immediately. So at the end, we have the decomposition as we need. */ 170 171 Tmp = coefficient_x >> 59; 172 LO_18Dig = (coefficient_x << 5) >> 5; 173 HI_18Dig = 0; 174 k_lcv = 0; 175 176 while (Tmp) { 177 midi_ind = (int) (Tmp & 0x000000000000003FLL); 178 midi_ind <<= 1; 179 Tmp >>= 6; 180 HI_18Dig += mod10_18_tbl[k_lcv][midi_ind++]; 181 LO_18Dig += mod10_18_tbl[k_lcv++][midi_ind]; 182 __L0_Normalize_10to18 (HI_18Dig, LO_18Dig); 183 } 184 185 ptr = MiDi; 186 __L1_Split_MiDi_6_Lead (LO_18Dig, ptr); 187 len = ptr - MiDi; 188 c_ptr_start = &(ps[istart]); 189 c_ptr = c_ptr_start; 190 191 /* now convert the MiDi into character strings */ 192 __L0_MiDi2Str_Lead (MiDi[0], c_ptr); 193 for (k_lcv = 1; k_lcv < len; k_lcv++) { 194 __L0_MiDi2Str (MiDi[k_lcv], c_ptr); 195 } 196 istart = istart + (c_ptr - c_ptr_start); 197 } 198 199 ps[istart++] = 'E'; 200 201 if (exponent_x < 0) { 202 ps[istart++] = '-'; 203 exponent_x = -exponent_x; 204 } else 205 ps[istart++] = '+'; 206 207 if (exponent_x) { 208 // get decimal digits in coefficient_x 209 tempx.d = (float) exponent_x; 210 bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f; 211 digits_x = estimate_decimal_digits[bin_expon_cx]; 212 if ((UINT64)exponent_x >= power10_table_128[digits_x].w[0]) 213 digits_x++; 214 215 j = istart + digits_x - 1; 216 istart = j + 1; 217 218 // 2^32/10 219 ER10 = 0x1999999a; 220 221 while (exponent_x > 9) { 222 D = (UINT64) exponent_x *ER10; 223 D >>= 32; 224 exponent_x = exponent_x - (D << 1) - (D << 3); 225 226 ps[j--] = '0' + (char) exponent_x; 227 exponent_x = D; 228 } 229 ps[j] = '0' + (char) exponent_x; 230 } else { 231 ps[istart++] = '0'; 232 } 233 234 ps[istart] = 0; 235 236 return; 237 238} 239 240 241#if DECIMAL_CALL_BY_REFERENCE 242void 243bid64_from_string (UINT64 * pres, char *ps 244 _RND_MODE_PARAM _EXC_FLAGS_PARAM 245 _EXC_MASKS_PARAM _EXC_INFO_PARAM) { 246#else 247UINT64 248bid64_from_string (char *ps 249 _RND_MODE_PARAM _EXC_FLAGS_PARAM 250 _EXC_MASKS_PARAM _EXC_INFO_PARAM) { 251#endif 252 UINT64 sign_x, coefficient_x = 0, rounded = 0, res; 253 int expon_x = 0, sgn_expon, ndigits, add_expon = 0, midpoint = 254 0, rounded_up = 0; 255 int dec_expon_scale = 0, right_radix_leading_zeros = 0, rdx_pt_enc = 256 0; 257 unsigned fpsc; 258 char c; 259 unsigned int save_fpsf; 260 261#if DECIMAL_CALL_BY_REFERENCE 262#if !DECIMAL_GLOBAL_ROUNDING 263 _IDEC_round rnd_mode = *prnd_mode; 264#endif 265#endif 266 267 save_fpsf = *pfpsf; // place holder only 268 // eliminate leading whitespace 269 while (((*ps == ' ') || (*ps == '\t')) && (*ps)) 270 ps++; 271 272 // get first non-whitespace character 273 c = *ps; 274 275 // detect special cases (INF or NaN) 276 if (!c || (c != '.' && c != '-' && c != '+' && (c < '0' || c > '9'))) { 277 // Infinity? 278 if ((tolower_macro (ps[0]) == 'i' && tolower_macro (ps[1]) == 'n' && 279 tolower_macro (ps[2]) == 'f') && (!ps[3] || 280 (tolower_macro (ps[3]) == 'i' && 281 tolower_macro (ps[4]) == 'n' && tolower_macro (ps[5]) == 'i' && 282 tolower_macro (ps[6]) == 't' && tolower_macro (ps[7]) == 'y' && 283 !ps[8]))) { 284 res = 0x7800000000000000ull; 285 BID_RETURN (res); 286 } 287 // return sNaN 288 if (tolower_macro (ps[0]) == 's' && tolower_macro (ps[1]) == 'n' && 289 tolower_macro (ps[2]) == 'a' && tolower_macro (ps[3]) == 'n') { 290 // case insensitive check for snan 291 res = 0x7e00000000000000ull; 292 BID_RETURN (res); 293 } else { 294 // return qNaN 295 res = 0x7c00000000000000ull; 296 BID_RETURN (res); 297 } 298 } 299 // detect +INF or -INF 300 if ((tolower_macro (ps[1]) == 'i' && tolower_macro (ps[2]) == 'n' && 301 tolower_macro (ps[3]) == 'f') && (!ps[4] || 302 (tolower_macro (ps[4]) == 'i' && tolower_macro (ps[5]) == 'n' && 303 tolower_macro (ps[6]) == 'i' && tolower_macro (ps[7]) == 't' && 304 tolower_macro (ps[8]) == 'y' && !ps[9]))) { 305 if (c == '+') 306 res = 0x7800000000000000ull; 307 else if (c == '-') 308 res = 0xf800000000000000ull; 309 else 310 res = 0x7c00000000000000ull; 311 BID_RETURN (res); 312 } 313 // if +sNaN, +SNaN, -sNaN, or -SNaN 314 if (tolower_macro (ps[1]) == 's' && tolower_macro (ps[2]) == 'n' 315 && tolower_macro (ps[3]) == 'a' && tolower_macro (ps[4]) == 'n') { 316 if (c == '-') 317 res = 0xfe00000000000000ull; 318 else 319 res = 0x7e00000000000000ull; 320 BID_RETURN (res); 321 } 322 // determine sign 323 if (c == '-') 324 sign_x = 0x8000000000000000ull; 325 else 326 sign_x = 0; 327 328 // get next character if leading +/- sign 329 if (c == '-' || c == '+') { 330 ps++; 331 c = *ps; 332 } 333 // if c isn't a decimal point or a decimal digit, return NaN 334 if (c != '.' && (c < '0' || c > '9')) { 335 // return NaN 336 res = 0x7c00000000000000ull | sign_x; 337 BID_RETURN (res); 338 } 339 340 rdx_pt_enc = 0; 341 342 // detect zero (and eliminate/ignore leading zeros) 343 if (*(ps) == '0' || *(ps) == '.') { 344 345 if (*(ps) == '.') { 346 rdx_pt_enc = 1; 347 ps++; 348 } 349 // if all numbers are zeros (with possibly 1 radix point, the number is zero 350 // should catch cases such as: 000.0 351 while (*ps == '0') { 352 ps++; 353 // for numbers such as 0.0000000000000000000000000000000000001001, 354 // we want to count the leading zeros 355 if (rdx_pt_enc) { 356 right_radix_leading_zeros++; 357 } 358 // if this character is a radix point, make sure we haven't already 359 // encountered one 360 if (*(ps) == '.') { 361 if (rdx_pt_enc == 0) { 362 rdx_pt_enc = 1; 363 // if this is the first radix point, and the next character is NULL, 364 // we have a zero 365 if (!*(ps + 1)) { 366 res = 367 ((UINT64) (398 - right_radix_leading_zeros) << 53) | 368 sign_x; 369 BID_RETURN (res); 370 } 371 ps = ps + 1; 372 } else { 373 // if 2 radix points, return NaN 374 res = 0x7c00000000000000ull | sign_x; 375 BID_RETURN (res); 376 } 377 } else if (!*(ps)) { 378 //pres->w[1] = 0x3040000000000000ull | sign_x; 379 res = 380 ((UINT64) (398 - right_radix_leading_zeros) << 53) | sign_x; 381 BID_RETURN (res); 382 } 383 } 384 } 385 386 c = *ps; 387 388 ndigits = 0; 389 while ((c >= '0' && c <= '9') || c == '.') { 390 if (c == '.') { 391 if (rdx_pt_enc) { 392 // return NaN 393 res = 0x7c00000000000000ull | sign_x; 394 BID_RETURN (res); 395 } 396 rdx_pt_enc = 1; 397 ps++; 398 c = *ps; 399 continue; 400 } 401 dec_expon_scale += rdx_pt_enc; 402 403 ndigits++; 404 if (ndigits <= 16) { 405 coefficient_x = (coefficient_x << 1) + (coefficient_x << 3); 406 coefficient_x += (UINT64) (c - '0'); 407 } else if (ndigits == 17) { 408 // coefficient rounding 409 switch(rnd_mode){ 410 case ROUNDING_TO_NEAREST: 411 midpoint = (c == '5' && !(coefficient_x & 1)) ? 1 : 0; 412 // if coefficient is even and c is 5, prepare to round up if 413 // subsequent digit is nonzero 414 // if str[MAXDIG+1] > 5, we MUST round up 415 // if str[MAXDIG+1] == 5 and coefficient is ODD, ROUND UP! 416 if (c > '5' || (c == '5' && (coefficient_x & 1))) { 417 coefficient_x++; 418 rounded_up = 1; 419 break; 420 421 case ROUNDING_DOWN: 422 if(sign_x) { coefficient_x++; rounded_up=1; } 423 break; 424 case ROUNDING_UP: 425 if(!sign_x) { coefficient_x++; rounded_up=1; } 426 break; 427 case ROUNDING_TIES_AWAY: 428 if(c>='5') { coefficient_x++; rounded_up=1; } 429 break; 430 } 431 if (coefficient_x == 10000000000000000ull) { 432 coefficient_x = 1000000000000000ull; 433 add_expon = 1; 434 } 435 } 436 if (c > '0') 437 rounded = 1; 438 add_expon += 1; 439 } else { // ndigits > 17 440 add_expon++; 441 if (midpoint && c > '0') { 442 coefficient_x++; 443 midpoint = 0; 444 rounded_up = 1; 445 } 446 if (c > '0') 447 rounded = 1; 448 } 449 ps++; 450 c = *ps; 451 } 452 453 add_expon -= (dec_expon_scale + right_radix_leading_zeros); 454 455 if (!c) { 456 res = 457 fast_get_BID64_check_OF (sign_x, 458 add_expon + DECIMAL_EXPONENT_BIAS, 459 coefficient_x, 0, &fpsc); 460 BID_RETURN (res); 461 } 462 463 if (c != 'E' && c != 'e') { 464 // return NaN 465 res = 0x7c00000000000000ull | sign_x; 466 BID_RETURN (res); 467 } 468 ps++; 469 c = *ps; 470 sgn_expon = (c == '-') ? 1 : 0; 471 if (c == '-' || c == '+') { 472 ps++; 473 c = *ps; 474 } 475 if (!c || c < '0' || c > '9') { 476 // return NaN 477 res = 0x7c00000000000000ull | sign_x; 478 BID_RETURN (res); 479 } 480 481 while (c >= '0' && c <= '9') { 482 expon_x = (expon_x << 1) + (expon_x << 3); 483 expon_x += (int) (c - '0'); 484 485 ps++; 486 c = *ps; 487 } 488 489 if (c) { 490 // return NaN 491 res = 0x7c00000000000000ull | sign_x; 492 BID_RETURN (res); 493 } 494 495 if (sgn_expon) 496 expon_x = -expon_x; 497 498 expon_x += add_expon + DECIMAL_EXPONENT_BIAS; 499 500 if (expon_x < 0) { 501 if (rounded_up) 502 coefficient_x--; 503 rnd_mode = 0; 504 res = 505 get_BID64_UF (sign_x, expon_x, coefficient_x, rounded, rnd_mode, 506 &fpsc); 507 BID_RETURN (res); 508 } 509 res = get_BID64 (sign_x, expon_x, coefficient_x, rnd_mode, &fpsc); 510 BID_RETURN (res); 511} 512