Fixed #5304 (Wrong simplification of numbers like 001E+07 to 1.0)

This commit is contained in:
Alexander Mai 2014-02-24 18:52:31 +01:00 committed by Daniel Marjamäki
parent acf5723bdd
commit 0747b55485
3 changed files with 147 additions and 106 deletions

View File

@ -103,46 +103,84 @@ template<> std::string MathLib::toString(double value)
bool MathLib::isFloat(const std::string &s)
{
// every number that contains a . is a float
if (s.find("." , 0) != std::string::npos)
return true;
// scientific notation (without dot!)
std::string::const_iterator it=s.begin();
if (*it=='+' || *it=='-') { // mantissa sign char
++it;
if (it == s.end())
return false;
}
if (!std::isdigit(*it))
if (s.empty())
return false;
++it;
while (std::isdigit(*it)) { // number
++it;
if (it == s.end())
enum {START, BASE_PLUSMINUS, BASE_DIGITS1, LEADING_DECIMAL, TRAILING_DECIMAL, BASE_DIGITS2, E, MANTISSA_PLUSMINUS, MANTISSA_DIGITS, F} state = START;
for (std::string::const_iterator it = s.begin(); it != s.end(); it++) {
switch (state) {
case START:
if (*it=='+' || *it=='-')
state=BASE_PLUSMINUS;
else if (*it=='.')
state=LEADING_DECIMAL;
else if (std::isdigit(*it))
state=BASE_DIGITS1;
else
return false;
break;
case BASE_PLUSMINUS:
if (*it=='.')
state=LEADING_DECIMAL;
else if (std::isdigit(*it))
state=BASE_DIGITS1;
else if (*it=='e' || *it=='E')
state=E;
else
return false;
break;
case LEADING_DECIMAL:
if (std::isdigit(*it))
state=BASE_DIGITS2;
break;
case BASE_DIGITS1:
if (*it=='e' || *it=='E')
state=E;
else if (*it=='.')
state=TRAILING_DECIMAL;
else if (!std::isdigit(*it))
return false;
break;
case TRAILING_DECIMAL:
if (*it=='e' || *it=='E')
state=E;
else if (std::isdigit(*it))
state=BASE_DIGITS2;
else
return false;
break;
case BASE_DIGITS2:
if (*it=='e' || *it=='E')
state=E;
else if (*it=='f' || *it=='F')
state=F;
else if (!std::isdigit(*it))
return false;
break;
case E:
if (*it=='+' || *it=='-')
state=MANTISSA_PLUSMINUS;
else if (std::isdigit(*it))
state=MANTISSA_DIGITS;
else
return false;
break;
case MANTISSA_PLUSMINUS:
if (!std::isdigit(*it))
return false;
else
state=MANTISSA_DIGITS;
break;
case MANTISSA_DIGITS:
if (*it=='f' || *it=='F')
state=F;
else if (!std::isdigit(*it))
return false;
break;
case F:
return false;
}
}
if (*it!='e' && *it!='E')
return false;
else
++it;
if (it == s.end())
return false; // incomplete exponent number
if (*it=='+' || *it=='-') { // exponent sign char
++it;
if (it == s.end())
return false; // incomplete exponent number
}
while (std::isdigit(*it)) { // number
++it;
if (it == s.end())
return true;
}
if (it==s.end())
return true;
if ((*it=='f' || *it=='F') && (it+1)==s.end()) // trailing 'f'/'F' to indicate a float literal (as opposed to a double literal)
return true;
return false;
return (state==BASE_DIGITS2 || state == MANTISSA_DIGITS || state == TRAILING_DECIMAL || state == F);
}
bool MathLib::isNegative(const std::string &s)

View File

@ -345,19 +345,18 @@ private:
}
void isfloat() const {
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("..."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("+E."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("+e."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("-E."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("-e."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("-."));
TODO_ASSERT_EQUALS(false, true, MathLib::isFloat("-."));
ASSERT_EQUALS(false, MathLib::isFloat(""));
ASSERT_EQUALS(false, MathLib::isFloat("."));
ASSERT_EQUALS(false, MathLib::isFloat("..."));
ASSERT_EQUALS(false, MathLib::isFloat("+E."));
ASSERT_EQUALS(false, MathLib::isFloat("+e."));
ASSERT_EQUALS(false, MathLib::isFloat("-E."));
ASSERT_EQUALS(false, MathLib::isFloat("-e."));
ASSERT_EQUALS(false, MathLib::isFloat("-."));
ASSERT_EQUALS(false, MathLib::isFloat("-."));
ASSERT_EQUALS(false, MathLib::isFloat("-"));
ASSERT_EQUALS(false, MathLib::isFloat("+"));
ASSERT_EQUALS(false, MathLib::isFloat(" "));
ASSERT_EQUALS(false, MathLib::isFloat(""));
ASSERT_EQUALS(false, MathLib::isFloat("0"));
ASSERT_EQUALS(false, MathLib::isFloat("0 "));
@ -365,9 +364,9 @@ private:
ASSERT_EQUALS(false, MathLib::isFloat(" 0"));
ASSERT_EQUALS(true , MathLib::isFloat("0."));
ASSERT_EQUALS(true , MathLib::isFloat("0. "));
ASSERT_EQUALS(true , MathLib::isFloat(" 0. "));
ASSERT_EQUALS(true , MathLib::isFloat(" 0."));
ASSERT_EQUALS(false , MathLib::isFloat("0. "));
ASSERT_EQUALS(false , MathLib::isFloat(" 0. "));
ASSERT_EQUALS(false , MathLib::isFloat(" 0."));
ASSERT_EQUALS(true , MathLib::isFloat("0.0"));
ASSERT_EQUALS(true , MathLib::isFloat("-0."));
@ -393,14 +392,15 @@ private:
ASSERT_EQUALS(true , MathLib::isFloat("+1E+1"));
ASSERT_EQUALS(true , MathLib::isFloat("+1E+100"));
ASSERT_EQUALS(true , MathLib::isFloat("+1E+100f"));
ASSERT_EQUALS(true , MathLib::isFloat("+1E+007")); // to be sure about #5485
ASSERT_EQUALS(true , MathLib::isFloat("+1E+001f"));
ASSERT_EQUALS(false , MathLib::isFloat("+1E+001f2"));
ASSERT_EQUALS(true , MathLib::isFloat("+1E+10000"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E+1"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E+10000"));
ASSERT_EQUALS(true , MathLib::isFloat(".1250E+04"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E-1"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E-10000"));
ASSERT_EQUALS(true , MathLib::isFloat(".1250E+04"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E-1"));
ASSERT_EQUALS(true , MathLib::isFloat("-1E-10000"));
ASSERT_EQUALS(true , MathLib::isFloat("+1.23e+01"));
ASSERT_EQUALS(true , MathLib::isFloat("+1.23E+01"));
@ -409,6 +409,7 @@ private:
ASSERT_EQUALS(true , MathLib::isFloat("0.00004"));
ASSERT_EQUALS(true , MathLib::isFloat("2352.00001f"));
ASSERT_EQUALS(true , MathLib::isFloat(".4"));
ASSERT_EQUALS(true , MathLib::isFloat(".3e2"));
ASSERT_EQUALS(true , MathLib::isFloat("1.0E+1"));
ASSERT_EQUALS(true , MathLib::isFloat("1.0E-1"));
ASSERT_EQUALS(true , MathLib::isFloat("-1.0E+1"));

View File

@ -8589,7 +8589,7 @@ private:
const char code_erfcl[] ="void f(long double x) {\n"
" std::cout << erfcl(x);\n" // do not simplify
" std::cout << erfcl(0.0d);\n" // simplify to 1
" std::cout << erfcl(0.0f);\n" // simplify to 1
"}";
const char expected_erfcl[] = "void f ( long double x ) {\n"
"std :: cout << erfcl ( x ) ;\n"
@ -8622,7 +8622,7 @@ private:
const char code_cosl[] ="void f(long double x) {\n"
" std::cout << cosl(x);\n" // do not simplify
" std::cout << cosl(0.0d);\n" // simplify to 1
" std::cout << cosl(0.0f);\n" // simplify to 1
"}";
const char expected_cosl[] = "void f ( long double x ) {\n"
"std :: cout << cosl ( x ) ;\n"
@ -8655,7 +8655,7 @@ private:
const char code_coshl[] ="void f(long double x) {\n"
" std::cout << coshl(x);\n" // do not simplify
" std::cout << coshl(0.0d);\n" // simplify to 1
" std::cout << coshl(0.0f);\n" // simplify to 1
"}";
const char expected_coshl[] = "void f ( long double x ) {\n"
"std :: cout << coshl ( x ) ;\n"
@ -8688,7 +8688,7 @@ private:
const char code_acosl[] ="void f(long double x) {\n"
" std::cout << acosl(x);\n" // do not simplify
" std::cout << acosl(1.0d);\n" // simplify to 0
" std::cout << acosl(1.0f);\n" // simplify to 0
"}";
const char expected_acosl[] = "void f ( long double x ) {\n"
"std :: cout << acosl ( x ) ;\n"
@ -8721,7 +8721,7 @@ private:
const char code_acoshl[] ="void f(long double x) {\n"
" std::cout << acoshl(x);\n" // do not simplify
" std::cout << acoshl(1.0d);\n" // simplify to 0
" std::cout << acoshl(1.0f);\n" // simplify to 0
"}";
const char expected_acoshl[] = "void f ( long double x ) {\n"
"std :: cout << acoshl ( x ) ;\n"
@ -8938,12 +8938,12 @@ private:
const char code_erfl[] ="void f(long double x) {\n"
" std::cout << erfl(x);\n" // do not simplify
" std::cout << erfl(10.0d);\n" // do not simplify
" std::cout << erfl(0.0d);\n" // simplify to 0
" std::cout << erfl(10.0f);\n" // do not simplify
" std::cout << erfl(0.0f);\n" // simplify to 0
"}";
const char expected_erfl[] = "void f ( long double x ) {\n"
"std :: cout << erfl ( x ) ;\n"
"std :: cout << erfl ( 10.0d ) ;\n"
"std :: cout << erfl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_erfl, tokenizeAndStringify(code_erfl));
@ -8977,12 +8977,14 @@ private:
const char code_atanhl[] ="void f(long double x) {\n"
" std::cout << atanhl(x);\n" // do not simplify
" std::cout << atanhl(10.0d);\n" // do not simplify
" std::cout << atanhl(0.0d);\n" // simplify to 0
" std::cout << atanhl(10.0f);\n" // do not simplify
" std::cout << atanhl(0.0d);\n" // do not simplify - invalid number!
" std::cout << atanhl(0.0f);\n" // simplify to 0
"}";
const char expected_atanhl[] = "void f ( long double x ) {\n"
"std :: cout << atanhl ( x ) ;\n"
"std :: cout << atanhl ( 10.0d ) ;\n"
"std :: cout << atanhl ( 10.0f ) ;\n"
"std :: cout << atanhl ( 0.0d ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_atanhl, tokenizeAndStringify(code_atanhl));
@ -9016,12 +9018,12 @@ private:
const char code_atanl[] ="void f(long double x) {\n"
" std::cout << atanl(x);\n" // do not simplify
" std::cout << atanl(10.0d);\n" // do not simplify
" std::cout << atanl(0.0d);\n" // simplify to 0
" std::cout << atanl(10.0f);\n" // do not simplify
" std::cout << atanl(0.0f);\n" // simplify to 0
"}";
const char expected_atanl[] = "void f ( long double x ) {\n"
"std :: cout << atanl ( x ) ;\n"
"std :: cout << atanl ( 10.0d ) ;\n"
"std :: cout << atanl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_atanl, tokenizeAndStringify(code_atanl));
@ -9089,12 +9091,12 @@ private:
const char code_tanhl[] ="void f(long double x) {\n"
" std::cout << tanhl(x);\n" // do not simplify
" std::cout << tanhl(10.0d);\n" // do not simplify
" std::cout << tanhl(0.0d);\n" // simplify to 0
" std::cout << tanhl(10.0f);\n" // do not simplify
" std::cout << tanhl(0.0f);\n" // simplify to 0
"}";
const char expected_tanhl[] = "void f ( long double x ) {\n"
"std :: cout << tanhl ( x ) ;\n"
"std :: cout << tanhl ( 10.0d ) ;\n"
"std :: cout << tanhl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_tanhl, tokenizeAndStringify(code_tanhl));
@ -9128,12 +9130,12 @@ private:
const char code_tanl[] ="void f(long double x) {\n"
" std::cout << tanl(x);\n" // do not simplify
" std::cout << tanl(10.0d);\n" // do not simplify
" std::cout << tanl(0.0d);\n" // simplify to 0
" std::cout << tanl(10.0f);\n" // do not simplify
" std::cout << tanl(0.0f);\n" // simplify to 0
"}";
const char expected_tanl[] = "void f ( long double x ) {\n"
"std :: cout << tanl ( x ) ;\n"
"std :: cout << tanl ( 10.0d ) ;\n"
"std :: cout << tanl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_tanl, tokenizeAndStringify(code_tanl));
@ -9167,12 +9169,12 @@ private:
const char code_expm1l[] ="void f(long double x) {\n"
" std::cout << expm1l(x);\n" // do not simplify
" std::cout << expm1l(10.0d);\n" // do not simplify
" std::cout << expm1l(0.0d);\n" // simplify to 0
" std::cout << expm1l(10.0f);\n" // do not simplify
" std::cout << expm1l(0.0f);\n" // simplify to 0
"}";
const char expected_expm1l[] = "void f ( long double x ) {\n"
"std :: cout << expm1l ( x ) ;\n"
"std :: cout << expm1l ( 10.0d ) ;\n"
"std :: cout << expm1l ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_expm1l, tokenizeAndStringify(code_expm1l));
@ -9206,12 +9208,12 @@ private:
const char code_asinhl[] ="void f(long double x) {\n"
" std::cout << asinhl(x);\n" // do not simplify
" std::cout << asinhl(10.0d);\n" // do not simplify
" std::cout << asinhl(0.0d);\n" // simplify to 0
" std::cout << asinhl(10.0f);\n" // do not simplify
" std::cout << asinhl(0.0f);\n" // simplify to 0
"}";
const char expected_asinhl[] = "void f ( long double x ) {\n"
"std :: cout << asinhl ( x ) ;\n"
"std :: cout << asinhl ( 10.0d ) ;\n"
"std :: cout << asinhl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_asinhl, tokenizeAndStringify(code_asinhl));
@ -9245,12 +9247,12 @@ private:
const char code_asinl[] ="void f(long double x) {\n"
" std::cout << asinl(x);\n" // do not simplify
" std::cout << asinl(10.0d);\n" // do not simplify
" std::cout << asinl(0.0d);\n" // simplify to 0
" std::cout << asinl(10.0f);\n" // do not simplify
" std::cout << asinl(0.0f);\n" // simplify to 0
"}";
const char expected_asinl[] = "void f ( long double x ) {\n"
"std :: cout << asinl ( x ) ;\n"
"std :: cout << asinl ( 10.0d ) ;\n"
"std :: cout << asinl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_asinl, tokenizeAndStringify(code_asinl));
@ -9284,12 +9286,12 @@ private:
const char code_sinhl[] ="void f(long double x) {\n"
" std::cout << sinhl(x);\n" // do not simplify
" std::cout << sinhl(10.0d);\n" // do not simplify
" std::cout << sinhl(0.0d);\n" // simplify to 0
" std::cout << sinhl(10.0f);\n" // do not simplify
" std::cout << sinhl(0.0f);\n" // simplify to 0
"}";
const char expected_sinhl[] = "void f ( long double x ) {\n"
"std :: cout << sinhl ( x ) ;\n"
"std :: cout << sinhl ( 10.0d ) ;\n"
"std :: cout << sinhl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_sinhl, tokenizeAndStringify(code_sinhl));
@ -9323,12 +9325,12 @@ private:
const char code_sinl[] ="void f(long double x) {\n"
" std::cout << sinl(x);\n" // do not simplify
" std::cout << sinl(10.0d);\n" // do not simplify
" std::cout << sinl(0.0d);\n" // simplify to 0
" std::cout << sinl(10.0f);\n" // do not simplify
" std::cout << sinl(0.0f);\n" // simplify to 0
"}";
const char expected_sinl[] = "void f ( long double x ) {\n"
"std :: cout << sinl ( x ) ;\n"
"std :: cout << sinl ( 10.0d ) ;\n"
"std :: cout << sinl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_sinl, tokenizeAndStringify(code_sinl));
@ -9362,12 +9364,12 @@ private:
const char code_ilogbl[] ="void f(long double x) {\n"
" std::cout << ilogbl(x);\n" // do not simplify
" std::cout << ilogbl(10.0d);\n" // do not simplify
" std::cout << ilogbl(1.0d);\n" // simplify to 0
" std::cout << ilogbl(10.0f);\n" // do not simplify
" std::cout << ilogbl(1.0f);\n" // simplify to 0
"}";
const char expected_ilogbl[] = "void f ( long double x ) {\n"
"std :: cout << ilogbl ( x ) ;\n"
"std :: cout << ilogbl ( 10.0d ) ;\n"
"std :: cout << ilogbl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_ilogbl, tokenizeAndStringify(code_ilogbl));
@ -9401,12 +9403,12 @@ private:
const char code_logbl[] ="void f(long double x) {\n"
" std::cout << logbl(x);\n" // do not simplify
" std::cout << logbl(10.0d);\n" // do not simplify
" std::cout << logbl(1.0d);\n" // simplify to 0
" std::cout << logbl(10.0f);\n" // do not simplify
" std::cout << logbl(1.0f);\n" // simplify to 0
"}";
const char expected_logbl[] = "void f ( long double x ) {\n"
"std :: cout << logbl ( x ) ;\n"
"std :: cout << logbl ( 10.0d ) ;\n"
"std :: cout << logbl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_logbl, tokenizeAndStringify(code_logbl));
@ -9440,12 +9442,12 @@ private:
const char code_log1pl[] ="void f(long double x) {\n"
" std::cout << log1pl(x);\n" // do not simplify
" std::cout << log1pl(10.0d);\n" // do not simplify
" std::cout << log1pl(0.0d);\n" // simplify to 0
" std::cout << log1pl(10.0f);\n" // do not simplify
" std::cout << log1pl(0.0f);\n" // simplify to 0
"}";
const char expected_log1pl[] = "void f ( long double x ) {\n"
"std :: cout << log1pl ( x ) ;\n"
"std :: cout << log1pl ( 10.0d ) ;\n"
"std :: cout << log1pl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_log1pl, tokenizeAndStringify(code_log1pl));
@ -9479,12 +9481,12 @@ private:
const char code_log10l[] ="void f(long double x) {\n"
" std::cout << log10l(x);\n" // do not simplify
" std::cout << log10l(10.0d);\n" // do not simplify
" std::cout << log10l(1.0d);\n" // simplify to 0
" std::cout << log10l(10.0f);\n" // do not simplify
" std::cout << log10l(1.0f);\n" // simplify to 0
"}";
const char expected_log10l[] = "void f ( long double x ) {\n"
"std :: cout << log10l ( x ) ;\n"
"std :: cout << log10l ( 10.0d ) ;\n"
"std :: cout << log10l ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_log10l, tokenizeAndStringify(code_log10l));
@ -9518,12 +9520,12 @@ private:
const char code_logl[] ="void f(long double x) {\n"
" std::cout << logl(x);\n" // do not simplify
" std::cout << logl(10.0d);\n" // do not simplify
" std::cout << logl(1.0d);\n" // simplify to 0
" std::cout << logl(10.0f);\n" // do not simplify
" std::cout << logl(1.0f);\n" // simplify to 0
"}";
const char expected_logl[] = "void f ( long double x ) {\n"
"std :: cout << logl ( x ) ;\n"
"std :: cout << logl ( 10.0d ) ;\n"
"std :: cout << logl ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_logl, tokenizeAndStringify(code_logl));
@ -9557,12 +9559,12 @@ private:
const char code_log2l[] ="void f(long double x) {\n"
" std::cout << log2l(x);\n" // do not simplify
" std::cout << log2l(10.0d);\n" // do not simplify
" std::cout << log2l(1.0d);\n" // simplify to 0
" std::cout << log2l(10.0f);\n" // do not simplify
" std::cout << log2l(1.0f);\n" // simplify to 0
"}";
const char expected_log2l[] = "void f ( long double x ) {\n"
"std :: cout << log2l ( x ) ;\n"
"std :: cout << log2l ( 10.0d ) ;\n"
"std :: cout << log2l ( 10.0f ) ;\n"
"std :: cout << 0 ;\n"
"}";
ASSERT_EQUALS(expected_log2l, tokenizeAndStringify(code_log2l));