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