1 /****************************************************************
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 #define _DEFAULT_SOURCE
33 #include <string.h>
34 #include <locale.h>
35 #include "mprec.h"
36 #include "gdtoa.h"
37
38 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG)
39 const unsigned char __hexdig[256]=
40 {
41 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
42 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
43 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
44 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,
45 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,
46 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
47 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,
48 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
49 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
50 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
51 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
52 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
53 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
54 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
57 };
58 #else /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG) */
59 unsigned char
__hexdig_fun(unsigned char c)60 __hexdig_fun (unsigned char c)
61 {
62 if(c>='0' && c<='9') return c-'0'+0x10;
63 else if(c>='a' && c<='f') return c-'a'+0x10+10;
64 else if(c>='A' && c<='F') return c-'A'+0x10+10;
65 else return 0;
66 }
67 #endif /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG) */
68
69 static void
rshift(_Bigint * b,int k)70 rshift (_Bigint *b,
71 int k)
72 {
73 __ULong *x, *x1, *xe, y;
74 int n;
75
76 x = x1 = b->_x;
77 n = k >> kshift;
78 if (n < b->_wds) {
79 xe = x + b->_wds;
80 x += n;
81 if (k &= kmask) {
82 n = ULbits - k;
83 y = *x++ >> k;
84 while(x < xe) {
85 *x1++ = (y | (*x << n)) & ALL_ON;
86 y = *x++ >> k;
87 }
88 if ((*x1 = y) !=0)
89 x1++;
90 }
91 else
92 while(x < xe)
93 *x1++ = *x++;
94 }
95 if ((b->_wds = x1 - b->_x) == 0)
96 b->_x[0] = 0;
97 }
98
99 static _Bigint *
increment(_Bigint * b)100 increment (
101 _Bigint *b)
102 {
103 __ULong *x, *xe;
104 _Bigint *b1;
105 #ifdef Pack_16
106 __ULong carry = 1, y;
107 #endif
108
109 if (!b)
110 return NULL;
111
112 x = b->_x;
113 xe = x + b->_wds;
114 #ifdef Pack_32
115 do {
116 if (*x < (__ULong)0xffffffffL) {
117 ++*x;
118 return b;
119 }
120 *x++ = 0;
121 } while(x < xe);
122 #else
123 do {
124 y = *x + carry;
125 carry = y >> 16;
126 *x++ = y & 0xffff;
127 if (!carry)
128 return b;
129 } while(x < xe);
130 if (carry)
131 #endif
132 {
133 if (b->_wds >= b->_maxwds) {
134 b1 = Balloc(b->_k+1);
135 if (!b1) {
136 Bfree(b);
137 return NULL;
138 }
139 Bcopy(b1, b);
140 Bfree(b);
141 b = b1;
142 }
143 b->_x[b->_wds++] = 1;
144 }
145 return b;
146 }
147
148
149 int
gethex(const char ** sp,const FPI * fpi,Long * exp,_Bigint ** bp,int sign,locale_t loc)150 gethex (const char **sp, const FPI *fpi,
151 Long *exp, _Bigint **bp, int sign, locale_t loc)
152 {
153 _Bigint *b;
154 const unsigned char *decpt, *s0, *s, *s1;
155 int esign, havedig, irv, k, n, nbits, up, zret;
156 __ULong L, lostbits, *x;
157 Long e, e1;
158 #ifdef __HAVE_LOCALE_INFO__
159 const unsigned char *decimalpoint = (const unsigned char *)
160 __get_numeric_locale(loc)->decimal_point;
161 const size_t decp_len = strlen ((const char *) decimalpoint);
162 const unsigned char decp_end = decimalpoint[decp_len - 1];
163 #else
164 const unsigned char *decimalpoint = (const unsigned char *) ".";
165 const size_t decp_len = 1;
166 const unsigned char decp_end = (unsigned char) '.';
167 (void) loc;
168 #endif
169
170 havedig = 0;
171 s0 = *(const unsigned char **)sp + 2;
172 while(s0[havedig] == '0')
173 havedig++;
174 s0 += havedig;
175 s = s0;
176 decpt = 0;
177 zret = 0;
178 e = 0;
179 if (!__get_hexdig(*s)) {
180 zret = 1;
181 if (strncmp ((const char *) s, (const char *) decimalpoint,
182 decp_len) != 0)
183 goto pcheck;
184 decpt = (s += decp_len);
185 if (!__get_hexdig(*s))
186 goto pcheck;
187 while(*s == '0')
188 s++;
189 if (__get_hexdig(*s))
190 zret = 0;
191 havedig = 1;
192 s0 = s;
193 }
194 while(__get_hexdig(*s))
195 s++;
196 if (strncmp ((const char *) s, (const char *) decimalpoint,
197 decp_len) == 0
198 && !decpt) {
199 decpt = (s += decp_len);
200 while(__get_hexdig(*s))
201 s++;
202 }
203 if (decpt)
204 e = -(((Long)(s-decpt)) << 2);
205 pcheck:
206 s1 = s;
207 switch(*s) {
208 case 'p':
209 case 'P':
210 esign = 0;
211 switch(*++s) {
212 case '-':
213 esign = 1;
214 __PICOLIBC_FALLTHROUGH;
215 case '+':
216 s++;
217 }
218 if ((n = __get_hexdig(*s)) == 0 || n > 0x19) {
219 s = s1;
220 break;
221 }
222 e1 = n - 0x10;
223 while((n = __get_hexdig(*++s)) !=0 && n <= 0x19)
224 e1 = 10*e1 + n - 0x10;
225 if (esign)
226 e1 = -e1;
227 e += e1;
228 }
229 *sp = (char*)s;
230 if (zret)
231 return havedig ? STRTOG_Zero : STRTOG_NoNumber;
232 n = s1 - s0 - 1;
233 for(k = 0; n > 7; n >>= 1)
234 k++;
235 b = Balloc(k);
236 if (!b)
237 return STRTOG_NoNumber;
238 x = b->_x;
239 n = 0;
240 L = 0;
241 while(s1 > s0) {
242 if (*--s1 == decp_end && s1 - decp_len + 1 >= s0
243 && strncmp ((const char *) s1 - decp_len + 1,
244 (const char *) decimalpoint, decp_len) == 0) {
245 s1 -= decp_len - 1; /* Note the --s1 above! */
246 continue;
247 }
248 if (n == 32) {
249 *x++ = L;
250 L = 0;
251 n = 0;
252 }
253 L |= (__ULong) (__get_hexdig(*s1) & 0x0f) << n;
254 n += 4;
255 }
256 *x++ = L;
257 b->_wds = n = x - b->_x;
258 n = 32*n - hi0bits(L);
259 nbits = fpi->nbits;
260 lostbits = 0;
261 x = b->_x;
262 if (n > nbits) {
263 n -= nbits;
264 if (any_on(b,n)) {
265 lostbits = 1;
266 k = n - 1;
267 if (x[k>>kshift] & (__ULong) 1 << (k & kmask)) {
268 lostbits = 2;
269 if (k > 1 && any_on(b,k-1))
270 lostbits = 3;
271 }
272 }
273 rshift(b, n);
274 e += n;
275 }
276 else if (n < nbits) {
277 n = nbits - n;
278 b = lshift(b, n);
279 e -= n;
280 x = b->_x;
281 }
282 if (e > fpi->emax) {
283 ovfl:
284 Bfree(b);
285 *bp = 0;
286 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
287 }
288 irv = STRTOG_Normal;
289 if (e < fpi->emin) {
290 irv = STRTOG_Denormal;
291 n = fpi->emin - e;
292 if (n >= nbits) {
293 switch (fpi->rounding) {
294 case FPI_Round_near:
295 if (n == nbits && (n < 2 || any_on(b,n-1)))
296 goto one_bit;
297 break;
298 case FPI_Round_up:
299 if (!sign)
300 goto one_bit;
301 break;
302 case FPI_Round_down:
303 if (sign) {
304 one_bit:
305 *exp = fpi->emin;
306 x[0] = b->_wds = 1;
307 *bp = b;
308 return STRTOG_Denormal | STRTOG_Inexhi
309 | STRTOG_Underflow;
310 }
311 }
312 Bfree(b);
313 *bp = 0;
314 return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
315 }
316 k = n - 1;
317 if (lostbits)
318 lostbits = 1;
319 else if (k > 0)
320 lostbits = any_on(b,k);
321 if (x[k>>kshift] & (__ULong) 1 << (k & kmask))
322 lostbits |= 2;
323 nbits -= n;
324 rshift(b,n);
325 e = fpi->emin;
326 }
327 if (lostbits) {
328 up = 0;
329 switch(fpi->rounding) {
330 case FPI_Round_zero:
331 break;
332 case FPI_Round_near:
333 if ((lostbits & 2)
334 && ((lostbits & 1) | (x[0] & 1)))
335 up = 1;
336 break;
337 case FPI_Round_up:
338 up = 1 - sign;
339 break;
340 case FPI_Round_down:
341 up = sign;
342 }
343 if (up) {
344 k = b->_wds;
345 b = increment(b);
346 if (!b)
347 return STRTOG_NoNumber;
348 x = b->_x;
349 if (irv == STRTOG_Denormal) {
350 if (nbits == fpi->nbits - 1
351 && x[nbits >> kshift] & (__ULong) 1 << (nbits & kmask))
352 irv = STRTOG_Normal;
353 }
354 else if ((b->_wds > k)
355 || ((n = nbits & kmask) !=0
356 && (hi0bits(x[k-1]) < 32-n))) {
357 rshift(b,1);
358 if (++e > fpi->emax)
359 goto ovfl;
360 }
361 irv |= STRTOG_Inexhi;
362 }
363 else
364 irv |= STRTOG_Inexlo;
365 }
366 *bp = b;
367 *exp = e;
368 return irv;
369 }
370
371