diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal/floatscan.c | 20 | 
1 files changed, 16 insertions, 4 deletions
| diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index dbe07987..aa962f41 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -24,6 +24,8 @@  #define MASK (KMAX-1) +#define CONCAT2(x,y) x ## y +#define CONCAT(x,y) CONCAT2(x,y)  static long long scanexp(FILE *f, int pok)  { @@ -63,6 +65,8 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po  	int gotdig = 0, gotrad = 0;  	int rp;  	int e2; +	int emax = -emin-bits+3; +	int denormal = 0;  	long double y;  	long double frac=0;  	long double bias=0; @@ -250,6 +254,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po  	if (bits > LDBL_MANT_DIG+e2-emin) {  		bits = LDBL_MANT_DIG+e2-emin;  		if (bits<0) bits=0; +		denormal = 1;  	}  	/* Calculate bias term to force rounding, move out lower bits */ @@ -280,11 +285,18 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po  	y += frac;  	y -= bias; -	y = scalbnl(y, e2); - -	if (!y) errno = ERANGE; +	if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { +		if (fabs(y) >= CONCAT(0x1p, LDBL_MANT_DIG)) { +			if (denormal && bits==LDBL_MANT_DIG+e2-emin) +				denormal = 0; +			y *= 0.5; +			e2++; +		} +		if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) +			errno = ERANGE; +	} -	return y; +	return scalbnl(y, e2);  }  static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) | 
