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