Mercurial > hg > CbC > CbC_gcc
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 } |