Esempio n. 1
0
//
// floating point input
// required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*]
//
void
mpatoflt(Mpflt *a, char *as)
{
	Mpflt b;
	int dp, c, f, ef, ex, eb, base;
	char *s, *start;

	while(*as == ' ' || *as == '\t')
		as++;

	/* determine base */
	s = as;
	base = -1;
	while(base == -1) {
		switch(*s++) {
		case '-':
		case '+':
			break;

		case '0':
			if(*s == 'x')
				base = 16;
			else
				base = 10;
			break;

		default:
			base = 10;
		}
	}

	s = as;
	dp = 0;		/* digits after decimal point */
	f = 0;		/* sign */
	ex = 0;		/* exponent */
	eb = 0;		/* binary point */

	mpmovecflt(a, 0.0);
	if(base == 16) {
		start = nil;
		for(;;) {
			c = *s;
			if(c == '-') {
				f = 1;
				s++;
			}
			else if(c == '+') {
				s++;
			}
			else if(c == '0' && s[1] == 'x') {
				s += 2;
				start = s;
			}
			else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
				s++;
			}
			else {
				break;
			}
		}
		if(start == nil)
			goto bad;

		mphextofix(&a->val, start, s-start);
		if(a->val.ovf)
			goto bad;
		a->exp = 0;
		mpnorm(a);
	}
	for(;;) {
		switch(c = *s++) {
		default:
			goto bad;

		case '-':
			f = 1;

		case ' ':
		case '\t':
		case '+':
			continue;

		case '.':
			if(base == 16)
				goto bad;
			dp = 1;
			continue;

		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '0':
			mpmulcflt(a, 10);
			mpaddcflt(a, c-'0');
			if(dp)
				dp++;
			continue;

		case 'P':
		case 'p':
			eb = 1;

		case 'E':
		case 'e':
			ex = 0;
			ef = 0;
			for(;;) {
				c = *s++;
				if(c == '+' || c == ' ' || c == '\t')
					continue;
				if(c == '-') {
					ef = 1;
					continue;
				}
				if(c >= '0' && c <= '9') {
					ex = ex*10 + (c-'0');
					if(ex > 1e8) {
						yyerror("constant exponent out of range: %s", as);
						errorexit();
					}
					continue;
				}
				break;
			}
			if(ef)
				ex = -ex;

		case 0:
			break;
		}
		break;
	}

	if(eb) {
		if(dp)
			goto bad;
		mpsetexp(a, a->exp+ex);
		goto out;
	}

	if(dp)
		dp--;
	if(mpcmpfltc(a, 0.0) != 0) {
		if(ex >= dp) {
			mppow10flt(&b, ex-dp);
			mpmulfltflt(a, &b);
		} else {
			// 4 approximates least_upper_bound(log2(10)).
			if(dp-ex >= (1<<(8*sizeof(dp)-3)) || (short)(4*(dp-ex)) != 4*(dp-ex)) {
				mpmovecflt(a, 0.0);
			}
			else {
				mppow10flt(&b, dp-ex);
				mpdivfltflt(a, &b);
			}
		}
	}

out:
	if(f)
		mpnegflt(a);
	return;

bad:
	yyerror("constant too large: %s", as);
	mpmovecflt(a, 0.0);
}
Esempio n. 2
0
//
// floating point input
// required syntax is [+-]d*[.]d*[e[+-]d*]
//
void
mpatoflt(Mpflt *a, char *as)
{
	Mpflt b;
	int dp, c, f, ef, ex, eb, zer;
	char *s;

	s = as;
	dp = 0;		/* digits after decimal point */
	f = 0;		/* sign */
	ex = 0;		/* exponent */
	eb = 0;		/* binary point */
	zer = 1;	/* zero */

	mpmovecflt(a, 0.0);
	for(;;) {
		switch(c = *s++) {
		default:
			goto bad;

		case '-':
			f = 1;

		case ' ':
		case  '\t':
		case  '+':
			continue;

		case '.':
			dp = 1;
			continue;

		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			zer = 0;

		case '0':
			mpmulcflt(a, 10);
			mpaddcflt(a, c-'0');
			if(dp)
				dp++;
			continue;

		case 'P':
		case 'p':
			eb = 1;

		case 'E':
		case 'e':
			ex = 0;
			ef = 0;
			for(;;) {
				c = *s++;
				if(c == '+' || c == ' ' || c == '\t')
					continue;
				if(c == '-') {
					ef = 1;
					continue;
				}
				if(c >= '0' && c <= '9') {
					ex = ex*10 + (c-'0');
					continue;
				}
				break;
			}
			if(ef)
				ex = -ex;

		case 0:
			break;
		}
		break;
	}

	if(eb) {
		if(dp)
			goto bad;
		a->exp += ex;
		goto out;
	}

	if(dp)
		dp--;
	if(mpcmpfltc(a, 0.0) != 0) {
		if(ex >= dp) {
			mppow10flt(&b, ex-dp);
			mpmulfltflt(a, &b);
		} else {
			mppow10flt(&b, dp-ex);
			mpdivfltflt(a, &b);
		}
	}

out:
	if(f)
		mpnegflt(a);
	return;

bad:
	yyerror("set ovf in mpatof");
	mpmovecflt(a, 0.0);
}