Subversion Repositories Kolibri OS

Rev

Rev 4874 | Details | Compare with Previous | Last modification | View Log | RSS feed

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