* gcc-interface/decl.c (gnat_to_gnu_field): Do not set the alignment
[official-gcc.git] / libgcc / config / libbid / bid64_string.c
blobf3dccffa8f7669829ef13330b2cf2959d8406047
1 /* Copyright (C) 2007-2017 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 #include <ctype.h>
25 #include "bid_internal.h"
26 #include "bid128_2_str.h"
27 #include "bid128_2_str_macros.h"
29 #define MAX_FORMAT_DIGITS 16
30 #define DECIMAL_EXPONENT_BIAS 398
31 #define MAX_DECIMAL_EXPONENT 767
33 #if DECIMAL_CALL_BY_REFERENCE
35 void
36 bid64_to_string (char *ps, UINT64 * px
37 _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
38 UINT64 x;
39 #else
41 void
42 bid64_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;
55 #if DECIMAL_CALL_BY_REFERENCE
56 x = *px;
57 #endif
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
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;
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;
83 // 0
84 istart = 0;
85 if (sign_x) {
86 ps[istart++] = '-';
89 ps[istart++] = '0';
90 ps[istart++] = 'E';
92 exponent_x -= 398;
93 if (exponent_x < 0) {
94 ps[istart++] = '-';
95 exponent_x = -exponent_x;
96 } else
97 ps[istart++] = '+';
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++;
107 j = istart + digits_x - 1;
108 istart = j + 1;
110 // 2^32/10
111 ER10 = 0x1999999a;
113 while (exponent_x > 9) {
114 D = (UINT64) exponent_x *ER10;
115 D >>= 32;
116 exponent_x = exponent_x - (D << 1) - (D << 3);
118 ps[j--] = '0' + (char) exponent_x;
119 exponent_x = D;
121 ps[j] = '0' + (char) exponent_x;
122 } else {
123 ps[istart++] = '0';
126 ps[istart] = 0;
128 return;
130 // convert expon, coeff to ASCII
131 exponent_x -= DECIMAL_EXPONENT_BIAS;
133 ER10 = 0x1999999a;
135 istart = 0;
136 if (sign_x) {
137 ps[0] = '-';
138 istart = 1;
140 // if zero or non-canonical, set coefficient to '0'
141 if ((coefficient_x > 9999999999999999ull) || // non-canonical
142 ((coefficient_x == 0)) // significand is zero
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. */
171 Tmp = coefficient_x >> 59;
172 LO_18Dig = (coefficient_x << 5) >> 5;
173 HI_18Dig = 0;
174 k_lcv = 0;
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);
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;
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);
196 istart = istart + (c_ptr - c_ptr_start);
199 ps[istart++] = 'E';
201 if (exponent_x < 0) {
202 ps[istart++] = '-';
203 exponent_x = -exponent_x;
204 } else
205 ps[istart++] = '+';
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++;
215 j = istart + digits_x - 1;
216 istart = j + 1;
218 // 2^32/10
219 ER10 = 0x1999999a;
221 while (exponent_x > 9) {
222 D = (UINT64) exponent_x *ER10;
223 D >>= 32;
224 exponent_x = exponent_x - (D << 1) - (D << 3);
226 ps[j--] = '0' + (char) exponent_x;
227 exponent_x = D;
229 ps[j] = '0' + (char) exponent_x;
230 } else {
231 ps[istart++] = '0';
234 ps[istart] = 0;
236 return;
241 #if DECIMAL_CALL_BY_REFERENCE
242 void
243 bid64_from_string (UINT64 * pres, char *ps
244 _RND_MODE_PARAM _EXC_FLAGS_PARAM
245 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
246 #else
247 UINT64
248 bid64_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 =
257 unsigned fpsc;
258 char c;
259 unsigned int save_fpsf;
261 #if DECIMAL_CALL_BY_REFERENCE
262 #if !DECIMAL_GLOBAL_ROUNDING
263 _IDEC_round rnd_mode = *prnd_mode;
264 #endif
265 #endif
267 save_fpsf = *pfpsf; // place holder only
268 // eliminate leading whitespace
269 while (((*ps == ' ') || (*ps == '\t')) && (*ps))
270 ps++;
272 // get first non-whitespace character
273 c = *ps;
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);
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);
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);
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);
322 // determine sign
323 if (c == '-')
324 sign_x = 0x8000000000000000ull;
325 else
326 sign_x = 0;
328 // get next character if leading +/- sign
329 if (c == '-' || c == '+') {
330 ps++;
331 c = *ps;
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);
340 rdx_pt_enc = 0;
342 // detect zero (and eliminate/ignore leading zeros)
343 if (*(ps) == '0' || *(ps) == '.') {
345 if (*(ps) == '.') {
346 rdx_pt_enc = 1;
347 ps++;
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++;
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);
371 ps = ps + 1;
372 } else {
373 // if 2 radix points, return NaN
374 res = 0x7c00000000000000ull | sign_x;
375 BID_RETURN (res);
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);
386 c = *ps;
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);
396 rdx_pt_enc = 1;
397 ps++;
398 c = *ps;
399 continue;
401 dec_expon_scale += rdx_pt_enc;
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;
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;
431 if (coefficient_x == 10000000000000000ull) {
432 coefficient_x = 1000000000000000ull;
433 add_expon = 1;
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;
446 if (c > '0')
447 rounded = 1;
449 ps++;
450 c = *ps;
453 add_expon -= (dec_expon_scale + right_radix_leading_zeros);
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);
463 if (c != 'E' && c != 'e') {
464 // return NaN
465 res = 0x7c00000000000000ull | sign_x;
466 BID_RETURN (res);
468 ps++;
469 c = *ps;
470 sgn_expon = (c == '-') ? 1 : 0;
471 if (c == '-' || c == '+') {
472 ps++;
473 c = *ps;
475 if (!c || c < '0' || c > '9') {
476 // return NaN
477 res = 0x7c00000000000000ull | sign_x;
478 BID_RETURN (res);
481 while (c >= '0' && c <= '9') {
482 expon_x = (expon_x << 1) + (expon_x << 3);
483 expon_x += (int) (c - '0');
485 ps++;
486 c = *ps;
489 if (c) {
490 // return NaN
491 res = 0x7c00000000000000ull | sign_x;
492 BID_RETURN (res);
495 if (sgn_expon)
496 expon_x = -expon_x;
498 expon_x += add_expon + DECIMAL_EXPONENT_BIAS;
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);
509 res = get_BID64 (sign_x, expon_x, coefficient_x, rnd_mode, &fpsc);
510 BID_RETURN (res);