提交 0be993c0 编写于 作者: A Andrew Scheidecker 提交者: Matt Witherspoon

Use David Gay's strtod for hex floats as well to fix incorrect rounding in my code.

上级 6bce2f7c
......@@ -14,10 +14,9 @@
#include <stdlib.h>
#define IEEE_8087
#define NO_HEX_FP
#define NO_INFNAN_CHECK
#define strtod parseDecimalF64
#define dtoa printDecimalF64
#define strtod parseNonSpecialF64
#define dtoa printNonSpecialF64
#ifdef _MSC_VER
#pragma warning(push)
......@@ -43,7 +42,6 @@
#endif
#undef IEEE_8087
#undef NO_HEX_FP
#undef NO_STRTOD_BIGCOMP
#undef NO_INFNAN_CHECK
#undef strtod
......@@ -158,11 +156,11 @@ Float parseInfinity(const char* nextChar)
// Parses a decimal floating point literal, advancing nextChar past the parsed characters.
// Assumes it will only be called for input that's already been accepted by the lexer as a decimal float literal.
template<typename Float>
Float parseDecimalFloat(const char*& nextChar,ParseState& state)
Float parseFloat(const char*& nextChar,ParseState& state)
{
// Use David Gay's strtod to parse a floating point number.
const char* firstChar = nextChar;
F64 f64 = parseDecimalF64(nextChar,const_cast<char**>(&nextChar));
F64 f64 = parseNonSpecialF64(nextChar,const_cast<char**>(&nextChar));
if(nextChar == firstChar)
{
++nextChar;
......@@ -176,105 +174,6 @@ Float parseDecimalFloat(const char*& nextChar,ParseState& state)
return (Float)f64;
}
// Parses a hexadecimal floating point literal, advancing nextChar past the parsed characters.
// Assumes it will only be called for input that's already been accepted by the lexer as a hexadecimal float literal.
template<typename Float>
Float parseHexFloat(const char*& nextChar,ParseState& state)
{
typedef typename Floats::FloatComponents<Float> FloatComponents;
typedef typename FloatComponents::Bits FloatBits;
FloatComponents resultComponents;
resultComponents.bits.sign = parseSign(nextChar) ? 1 : 0;
assert(nextChar[0] == '0' && (nextChar[1] == 'x' || nextChar[1] == 'X'));
nextChar += 2;
// Parse hexits into a 64-bit fixed point number, keeping track of where the point is in exponent.
U64 fixedPoint64 = 0;
bool hasSeenPoint = false;
I64 exponent = 0;
while(true)
{
U8 hexit = 0;
if(tryParseHexit(nextChar,hexit))
{
// Once there are too many hexits to accumulate in the 64-bit fixed point number, ignore
// the hexits, but continue to update exponent so we get an accurate but imprecise number.
if(fixedPoint64 <= (UINT64_MAX - 15) / 16)
{
assert(fixedPoint64 * 16 + hexit >= fixedPoint64);
fixedPoint64 = fixedPoint64 * 16 + hexit;
exponent -= hasSeenPoint ? 4 : 0;
}
else
{
exponent += hasSeenPoint ? 0 : 4;
}
}
else if(*nextChar == '.')
{
assert(!hasSeenPoint);
hasSeenPoint = true;
++nextChar;
}
else { break; }
}
// Parse an optional exponent.
if(*nextChar == 'p' || *nextChar == 'P')
{
++nextChar;
const bool isExponentNegative = parseSign(nextChar);
const U64 userExponent = parseDecimalUnsignedInt(nextChar,state,U64(-INT32_MIN),"float literal exponent");
exponent = isExponentNegative ? exponent - userExponent : exponent + userExponent;
}
if(!fixedPoint64)
{
// If both the integer and fractional part are zero, just return zero.
resultComponents.bits.exponent = 0;
resultComponents.bits.significand = 0;
}
else
{
// Shift the fixed point number's most significant set bit into the MSB.
const Uptr leadingZeroes = Platform::countLeadingZeroes(fixedPoint64);
fixedPoint64 <<= leadingZeroes;
exponent += 64;
exponent -= leadingZeroes;
const I64 exponentWithImplicitLeadingOne = exponent - 1;
if(exponentWithImplicitLeadingOne > FloatComponents::maxNormalExponent)
{
// If the number is out of range, produce an error and return infinity.
resultComponents.bits.exponent = FloatComponents::maxExponentBits;
resultComponents.bits.significand = FloatComponents::maxSignificand;
parseErrorf(state,state.nextToken,"hexadecimal float literal is out of range");
}
else if(exponentWithImplicitLeadingOne < FloatComponents::minNormalExponent)
{
// Denormals are encoded as if their exponent is minNormalExponent, but
// with the significand shifted down to include the leading 1 that is implicit for
// normal numbers, and with the encoded exponent = 0.
const Uptr denormalShift = FloatComponents::minNormalExponent - exponent;
fixedPoint64 = denormalShift >= 64 ? 0 : (fixedPoint64 >> denormalShift);
resultComponents.bits.exponent = 0;
resultComponents.bits.significand = FloatBits(fixedPoint64 >> (64 - FloatComponents::numSignificandBits));
}
else
{
// Encode a normal floating point value.
assert(exponentWithImplicitLeadingOne >= FloatComponents::minNormalExponent);
assert(exponentWithImplicitLeadingOne <= FloatComponents::maxNormalExponent);
resultComponents.bits.exponent = FloatBits(exponentWithImplicitLeadingOne + FloatComponents::exponentBias);
resultComponents.bits.significand = FloatBits(fixedPoint64 >> (63 - FloatComponents::numSignificandBits));
}
}
return resultComponents.value;
}
// Tries to parse an numeric literal token as an integer, advancing state.nextToken.
// Returns true if it matched a token.
template<typename UnsignedInt>
......@@ -315,9 +214,9 @@ bool tryParseFloat(ParseState& state,Float& outFloat)
switch(state.nextToken->type)
{
case t_decimalInt:
case t_decimalFloat: outFloat = parseDecimalFloat<Float>(nextChar,state); break;
case t_decimalFloat: outFloat = parseFloat<Float>(nextChar,state); break;
case t_hexInt:
case t_hexFloat: outFloat = parseHexFloat<Float>(nextChar,state); break;
case t_hexFloat: outFloat = parseFloat<Float>(nextChar,state); break;
case t_floatNaN: outFloat = parseNaN<Float>(nextChar,state); break;
case t_floatInf: outFloat = parseInfinity<Float>(nextChar); break;
default:
......
......@@ -45,3 +45,93 @@
(module quote "(func (i64.const -9223372036854775809) drop)")
"constant out of range"
)
(module (func (f32.const 0x1p127) drop))
(module (func (f32.const -0x1p127) drop))
(module (func (f32.const 0x1.fffffep127) drop))
(module (func (f32.const -0x1.fffffep127) drop))
(module (func (f32.const 0x1.fffffe7p127) drop))
(module (func (f32.const -0x1.fffffe7p127) drop))
(assert_malformed
(module quote "(func (f32.const 0x1p128) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f32.const -0x1p128) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f32.const 0x1.ffffffp127) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f32.const -0x1.ffffffp127) drop)")
"constant out of range"
)
(module (func (f32.const 1e38) drop))
(module (func (f32.const -1e38) drop))
(assert_malformed
(module quote "(func (f32.const 1e39) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f32.const -1e39) drop)")
"constant out of range"
)
(module (func (f32.const 340282356779733623858607532500980858880) drop))
(module (func (f32.const -340282356779733623858607532500980858880) drop))
(assert_malformed
(module quote "(func (f32.const 340282356779733661637539395458142568448) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f32.const -340282356779733661637539395458142568448) drop)")
"constant out of range"
)
(module (func (f64.const 0x1p1023) drop))
(module (func (f64.const -0x1p1023) drop))
(module (func (f64.const 0x1.fffffffffffffp1023) drop))
(module (func (f64.const -0x1.fffffffffffffp1023) drop))
(module (func (f64.const 0x1.fffffffffffff7p1023) drop))
(module (func (f64.const -0x1.fffffffffffff7p1023) drop))
(assert_malformed
(module quote "(func (f64.const 0x1p1024) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f64.const -0x1p1024) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f64.const 0x1.fffffffffffff8p1023) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f64.const -0x1.fffffffffffff8p1023) drop)")
"constant out of range"
)
(module (func (f64.const 1e308) drop))
(module (func (f64.const -1e308) drop))
(assert_malformed
(module quote "(func (f64.const 1e309) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f64.const -1e309) drop)")
"constant out of range"
)
(module (func (f64.const 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368) drop))
(module (func (f64.const -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368) drop))
(assert_malformed
(module quote "(func (f64.const 269653970229347356221791135597556535197105851288767494898376215204735891170042808140884337949150317257310688430271573696351481990334196274152701320055306275479074865864826923114368235135583993416113802762682700913456874855354834422248712838998185022412196739306217084753107265771378949821875606039276187287552) drop)")
"constant out of range"
)
(assert_malformed
(module quote "(func (f64.const -269653970229347356221791135597556535197105851288767494898376215204735891170042808140884337949150317257310688430271573696351481990334196274152701320055306275479074865864826923114368235135583993416113802762682700913456874855354834422248712838998185022412196739306217084753107265771378949821875606039276187287552) drop)")
"constant out of range"
)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册