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 			__PICOLIBC_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 |= (__ULong) (__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] & (__ULong) 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] & (__ULong) 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] & (__ULong) 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