comparison libgcc/config/libbid/bid64_string.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 04ced10e8804
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
2
3 This file is part of GCC.
4
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.
9
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.
14
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.
18
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/>. */
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
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
40
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;
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
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 =
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 }