gethex.c revision 112158
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
30	David M. Gay
31	Bell Laboratories, Room 2C-463
32	600 Mountain Avenue
33	Murray Hill, NJ 07974-0636
34	U.S.A.
35	dmg@bell-labs.com
36 */
37
38#include "gdtoaimp.h"
39
40 int
41#ifdef KR_headers
42gethex(sp, fpi, exp, bp, sign)
43	CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
44#else
45gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
46#endif
47{
48	Bigint *b;
49	CONST unsigned char *decpt, *s0, *s, *s1;
50	int esign, havedig, irv, k, n, nbits, up;
51	ULong L, lostbits, *x;
52	Long e, e1;
53
54	if (!hexdig['0'])
55		hexdig_init_D2A();
56	havedig = 0;
57	s0 = *(CONST unsigned char **)sp + 2;
58	while(s0[havedig] == '0')
59		havedig++;
60	s0 += havedig;
61	s = s0;
62	decpt = 0;
63	if (!hexdig[*s]) {
64		if (*s == '.') {
65			decpt = ++s;
66			if (!hexdig[*s])
67				goto ret0;
68			}
69		else {
70 ret0:
71			*sp = (char*)s;
72			return havedig ? STRTOG_Zero : STRTOG_NoNumber;
73			}
74		while(*s == '0')
75			s++;
76		havedig = 1;
77		if (!hexdig[*s])
78			goto ret0;
79		s0 = s;
80		}
81	while(hexdig[*s])
82		s++;
83	if (*s == '.' && !decpt) {
84		decpt = ++s;
85		while(hexdig[*s])
86			s++;
87		}
88	e = 0;
89	if (decpt)
90		e = -(((Long)(s-decpt)) << 2);
91	s1 = s;
92	switch(*s) {
93	  case 'p':
94	  case 'P':
95		esign = 0;
96		switch(*++s) {
97		  case '-':
98			esign = 1;
99			/* no break */
100		  case '+':
101			s++;
102		  }
103		if ((n = hexdig[*s]) == 0 || n > 0x19) {
104			s = s1;
105			break;
106			}
107		e1 = n - 0x10;
108		while((n = hexdig[*++s]) !=0 && n <= 0x19)
109			e1 = 10*e1 + n - 0x10;
110		if (esign)
111			e1 = -e1;
112		e += e1;
113	  }
114	*sp = (char*)s;
115	n = s1 - s0 - 1;
116	for(k = 0; n > 7; n >>= 1)
117		k++;
118	b = Balloc(k);
119	x = b->x;
120	n = 0;
121	L = 0;
122	while(s1 > s0) {
123		if (*--s1 == '.')
124			continue;
125		if (n == 32) {
126			*x++ = L;
127			L = 0;
128			n = 0;
129			}
130		L |= (hexdig[*s1] & 0x0f) << n;
131		n += 4;
132		}
133	*x++ = L;
134	b->wds = n = x - b->x;
135	n = 32*n - hi0bits(L);
136	nbits = fpi->nbits;
137	lostbits = 0;
138	x = b->x;
139	if (n > nbits) {
140		n -= nbits;
141		if (any_on(b,n)) {
142			lostbits = 1;
143			k = n - 1;
144			if (x[k>>kshift] & 1 << (k & kmask)) {
145				lostbits = 2;
146				if (k > 1 && any_on(b,k-1))
147					lostbits = 3;
148				}
149			}
150		rshift(b, n);
151		e += n;
152		}
153	else if (n < nbits) {
154		n = nbits - n;
155		b = lshift(b, n);
156		e -= n;
157		x = b->x;
158		}
159	if (e > fpi->emax) {
160 ovfl:
161		Bfree(b);
162		return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
163		}
164	irv = STRTOG_Normal;
165	if (e < fpi->emin) {
166		irv = STRTOG_Denormal;
167		n = fpi->emin - e;
168		if (n >= nbits) {
169			switch (fpi->rounding) {
170			  case FPI_Round_near:
171				if (n == nbits && n < 2 || any_on(b,n-1))
172					goto one_bit;
173				break;
174			  case FPI_Round_up:
175				if (!sign)
176					goto one_bit;
177				break;
178			  case FPI_Round_down:
179				if (sign) {
180 one_bit:
181					*exp = fpi->emin;
182					x[0] = b->wds = 1;
183					*bp = b;
184					return STRTOG_Denormal | STRTOG_Inexhi
185						| STRTOG_Underflow;
186					}
187			  }
188			Bfree(b);
189			return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
190			}
191		k = n - 1;
192		if (lostbits)
193			lostbits = 1;
194		else if (k > 0)
195			lostbits = any_on(b,k);
196		if (x[k>>kshift] & 1 << (k & kmask))
197			lostbits |= 2;
198		nbits -= n;
199		rshift(b,n);
200		e = fpi->emin;
201		}
202	if (lostbits) {
203		up = 0;
204		switch(fpi->rounding) {
205		  case FPI_Round_zero:
206			break;
207		  case FPI_Round_near:
208			if (lostbits & 2
209			 && (lostbits & 1) | x[0] & 1)
210				up = 1;
211			break;
212		  case FPI_Round_up:
213			up = 1 - sign;
214			break;
215		  case FPI_Round_down:
216			up = sign;
217		  }
218		if (up) {
219			k = b->wds;
220			b = increment(b);
221			x = b->x;
222			if (b->wds > k
223			 || (n = nbits & kmask) !=0
224			     && hi0bits(x[k-1]) < 32-n) {
225				rshift(b,1);
226				if (++e > fpi->emax)
227					goto ovfl;
228				}
229			else if (irv == STRTOG_Denormal) {
230				k = nbits - 1;
231				if (x[k >> kshift] & 1 << (k & kmask))
232					irv = STRTOG_Normal;
233				}
234			irv |= STRTOG_Inexhi;
235			}
236		else
237			irv |= STRTOG_Inexlo;
238		}
239	*bp = b;
240	*exp = e;
241	return irv;
242	}
243