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