bid64_string.c 14 KB

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