OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [libbid/] [bid64_string.c] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.