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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [stdlib/] [gdtoa-gethex.c] - Blame information for rev 158

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/****************************************************************
2
 
3
The author of this software is David M. Gay.
4
 
5
Copyright (C) 1998 by Lucent Technologies
6
All Rights Reserved
7
 
8
Permission to use, copy, modify, and distribute this software and
9
its documentation for any purpose and without fee is hereby
10
granted, provided that the above copyright notice appear in all
11
copies and that both that the copyright notice and this
12
permission notice and warranty disclaimer appear in supporting
13
documentation, and that the name of Lucent or any of its entities
14
not be used in advertising or publicity pertaining to
15
distribution of the software without specific, written prior
16
permission.
17
 
18
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25
THIS SOFTWARE.
26
 
27
****************************************************************/
28
 
29
/* Please send bug reports to David M. Gay (dmg at acm dot org,
30
 * with " at " changed at "@" and " dot " changed to ".").      */
31
 
32
#include <_ansi.h>
33
#include <reent.h>
34
#include <string.h>
35
#include "mprec.h"
36
#include "gdtoa.h"
37
#include "gd_qnan.h"
38
 
39
#ifdef USE_LOCALE
40
#include "locale.h"
41
#endif
42
 
43
unsigned char hexdig[256];
44
 
45
static void
46
_DEFUN (htinit, (h, s, inc),
47
        unsigned char *h _AND
48
        unsigned char *s _AND
49
        int inc)
50
{
51
        int i, j;
52
        for(i = 0; (j = s[i]) !=0; i++)
53
                h[j] = i + inc;
54
}
55
 
56
void
57
_DEFUN_VOID (hexdig_init)
58
{
59
#define USC (unsigned char *)
60
        htinit(hexdig, USC "0123456789", 0x10);
61
        htinit(hexdig, USC "abcdef", 0x10 + 10);
62
        htinit(hexdig, USC "ABCDEF", 0x10 + 10);
63
}
64
 
65
static void
66
_DEFUN(rshift, (b, k),
67
        _Bigint *b _AND
68
        int k)
69
{
70
        __ULong *x, *x1, *xe, y;
71
        int n;
72
 
73
        x = x1 = b->_x;
74
        n = k >> kshift;
75
        if (n < b->_wds) {
76
                xe = x + b->_wds;
77
                x += n;
78
                if (k &= kmask) {
79
                        n = ULbits - k;
80
                        y = *x++ >> k;
81
                        while(x < xe) {
82
                                *x1++ = (y | (*x << n)) & ALL_ON;
83
                                y = *x++ >> k;
84
                                }
85
                        if ((*x1 = y) !=0)
86
                                x1++;
87
                        }
88
                else
89
                        while(x < xe)
90
                                *x1++ = *x++;
91
                }
92
        if ((b->_wds = x1 - b->_x) == 0)
93
                b->_x[0] = 0;
94
}
95
 
96
static _Bigint *
97
_DEFUN (increment, (ptr, b),
98
        struct _reent *ptr _AND
99
        _Bigint *b)
100
{
101
        __ULong *x, *xe;
102
        _Bigint *b1;
103
#ifdef Pack_16
104
        __ULong carry = 1, y;
105
#endif
106
 
107
        x = b->_x;
108
        xe = x + b->_wds;
109
#ifdef Pack_32
110
        do {
111
                if (*x < (__ULong)0xffffffffL) {
112
                        ++*x;
113
                        return b;
114
                        }
115
                *x++ = 0;
116
                } while(x < xe);
117
#else
118
        do {
119
                y = *x + carry;
120
                carry = y >> 16;
121
                *x++ = y & 0xffff;
122
                if (!carry)
123
                        return b;
124
                } while(x < xe);
125
        if (carry)
126
#endif
127
        {
128
                if (b->_wds >= b->_maxwds) {
129
                        b1 = Balloc(ptr, b->_k+1);
130
                        Bcopy(b1, b);
131
                        Bfree(ptr, b);
132
                        b = b1;
133
                        }
134
                b->_x[b->_wds++] = 1;
135
                }
136
        return b;
137
}
138
 
139
 
140
int
141
_DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
142
        struct _reent *ptr _AND
143
        _CONST char **sp _AND
144
        FPI *fpi _AND
145
        Long *exp _AND
146
        _Bigint **bp _AND
147
        int sign)
148
{
149
        _Bigint *b;
150
        _CONST unsigned char *decpt, *s0, *s, *s1;
151
        int esign, havedig, irv, k, n, nbits, up, zret;
152
        __ULong L, lostbits, *x;
153
        Long e, e1;
154
#ifdef USE_LOCALE
155
        unsigned char decimalpoint = *localeconv()->decimal_point;
156
#else
157
#define decimalpoint '.'
158
#endif
159
 
160
        if (!hexdig['0'])
161
                hexdig_init();
162
        havedig = 0;
163
        s0 = *(_CONST unsigned char **)sp + 2;
164
        while(s0[havedig] == '0')
165
                havedig++;
166
        s0 += havedig;
167
        s = s0;
168
        decpt = 0;
169
        zret = 0;
170
        e = 0;
171
        if (!hexdig[*s]) {
172
                zret = 1;
173
                if (*s != decimalpoint)
174
                        goto pcheck;
175
                decpt = ++s;
176
                if (!hexdig[*s])
177
                        goto pcheck;
178
                while(*s == '0')
179
                        s++;
180
                if (hexdig[*s])
181
                        zret = 0;
182
                havedig = 1;
183
                s0 = s;
184
                }
185
        while(hexdig[*s])
186
                s++;
187
        if (*s == decimalpoint && !decpt) {
188
                decpt = ++s;
189
                while(hexdig[*s])
190
                        s++;
191
                }
192
        if (decpt)
193
                e = -(((Long)(s-decpt)) << 2);
194
 pcheck:
195
        s1 = s;
196
        switch(*s) {
197
          case 'p':
198
          case 'P':
199
                esign = 0;
200
                switch(*++s) {
201
                  case '-':
202
                        esign = 1;
203
                        /* no break */
204
                  case '+':
205
                        s++;
206
                  }
207
                if ((n = hexdig[*s]) == 0 || n > 0x19) {
208
                        s = s1;
209
                        break;
210
                        }
211
                e1 = n - 0x10;
212
                while((n = hexdig[*++s]) !=0 && n <= 0x19)
213
                        e1 = 10*e1 + n - 0x10;
214
                if (esign)
215
                        e1 = -e1;
216
                e += e1;
217
          }
218
        *sp = (char*)s;
219
        if (zret)
220
                return havedig ? STRTOG_Zero : STRTOG_NoNumber;
221
        n = s1 - s0 - 1;
222
        for(k = 0; n > 7; n >>= 1)
223
                k++;
224
        b = Balloc(ptr, k);
225
        x = b->_x;
226
        n = 0;
227
        L = 0;
228
        while(s1 > s0) {
229
                if (*--s1 == decimalpoint)
230
                        continue;
231
                if (n == 32) {
232
                        *x++ = L;
233
                        L = 0;
234
                        n = 0;
235
                        }
236
                L |= (hexdig[*s1] & 0x0f) << n;
237
                n += 4;
238
                }
239
        *x++ = L;
240
        b->_wds = n = x - b->_x;
241
        n = 32*n - hi0bits(L);
242
        nbits = fpi->nbits;
243
        lostbits = 0;
244
        x = b->_x;
245
        if (n > nbits) {
246
                n -= nbits;
247
                if (any_on(b,n)) {
248
                        lostbits = 1;
249
                        k = n - 1;
250
                        if (x[k>>kshift] & 1 << (k & kmask)) {
251
                                lostbits = 2;
252
                                if (k > 1 && any_on(b,k-1))
253
                                        lostbits = 3;
254
                                }
255
                        }
256
                rshift(b, n);
257
                e += n;
258
                }
259
        else if (n < nbits) {
260
                n = nbits - n;
261
                b = lshift(ptr, b, n);
262
                e -= n;
263
                x = b->_x;
264
                }
265
        if (e > fpi->emax) {
266
 ovfl:
267
                Bfree(ptr, b);
268
                *bp = 0;
269
                return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
270
                }
271
        irv = STRTOG_Normal;
272
        if (e < fpi->emin) {
273
                irv = STRTOG_Denormal;
274
                n = fpi->emin - e;
275
                if (n >= nbits) {
276
                        switch (fpi->rounding) {
277
                          case FPI_Round_near:
278
                                if (n == nbits && (n < 2 || any_on(b,n-1)))
279
                                        goto one_bit;
280
                                break;
281
                          case FPI_Round_up:
282
                                if (!sign)
283
                                        goto one_bit;
284
                                break;
285
                          case FPI_Round_down:
286
                                if (sign) {
287
 one_bit:
288
                                        *exp = fpi->emin;
289
                                        x[0] = b->_wds = 1;
290
                                        *bp = b;
291
                                        return STRTOG_Denormal | STRTOG_Inexhi
292
                                                | STRTOG_Underflow;
293
                                        }
294
                          }
295
                        Bfree(ptr, b);
296
                        *bp = 0;
297
                        return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
298
                        }
299
                k = n - 1;
300
                if (lostbits)
301
                        lostbits = 1;
302
                else if (k > 0)
303
                        lostbits = any_on(b,k);
304
                if (x[k>>kshift] & 1 << (k & kmask))
305
                        lostbits |= 2;
306
                nbits -= n;
307
                rshift(b,n);
308
                e = fpi->emin;
309
                }
310
        if (lostbits) {
311
                up = 0;
312
                switch(fpi->rounding) {
313
                  case FPI_Round_zero:
314
                        break;
315
                  case FPI_Round_near:
316
                    if ((lostbits & 2)
317
                            && ((lostbits & 1) | (x[0] & 1)))
318
                                up = 1;
319
                        break;
320
                  case FPI_Round_up:
321
                        up = 1 - sign;
322
                        break;
323
                  case FPI_Round_down:
324
                        up = sign;
325
                  }
326
                if (up) {
327
                        k = b->_wds;
328
                        b = increment(ptr, b);
329
                        x = b->_x;
330
                        if (irv == STRTOG_Denormal) {
331
                                if (nbits == fpi->nbits - 1
332
                                 && x[nbits >> kshift] & 1 << (nbits & kmask))
333
                                        irv =  STRTOG_Normal;
334
                                }
335
                        else if ((b->_wds > k)
336
                         || ((n = nbits & kmask) !=0
337
                             && (hi0bits(x[k-1]) < 32-n))) {
338
                                rshift(b,1);
339
                                if (++e > fpi->emax)
340
                                        goto ovfl;
341
                                }
342
                        irv |= STRTOG_Inexhi;
343
                        }
344
                else
345
                        irv |= STRTOG_Inexlo;
346
                }
347
        *bp = b;
348
        *exp = e;
349
        return irv;
350
}
351
 

powered by: WebSVN 2.1.0

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