Tokenizer: simplifyMathFunctions: added more simplifications for exp(), exp2() and log2() functions.
This commit is contained in:
parent
b6d7e797a2
commit
fa5ee8fd13
|
@ -8272,27 +8272,26 @@ void Tokenizer::cppcheckError(const Token *tok) const
|
||||||
"Analysis failed. If the code is valid then please report this failure.");
|
"Analysis failed. If the code is valid then please report this failure.");
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Helper function to check wether number is zero (0,0.0 or 0E+0) or not?
|
// Helper function to check wether number is zero (0 or 0.0 or 0E+0) or not?
|
||||||
// @param s --> a string to check
|
// @param s --> a string to check
|
||||||
// @return true in case s is zero and false otherwise.
|
// @return true in case s is zero and false otherwise.
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static bool isZeroNumber(const std::string &s)
|
bool Tokenizer::isZeroNumber(const std::string &s)
|
||||||
{
|
{
|
||||||
const bool isPositive = MathLib::isPositive(s);
|
|
||||||
const bool isInteger = MathLib::isInt(s);
|
const bool isInteger = MathLib::isInt(s);
|
||||||
const bool isFloat = MathLib::isFloat(s);
|
const bool isFloat = MathLib::isFloat(s);
|
||||||
const bool isZeroValue = ((isPositive && isInteger && (MathLib::toLongNumber(s) == 0L)) // case: integer number
|
const bool isZeroValue = ((isInteger && (MathLib::toLongNumber(s) == 0L)) // case: integer number
|
||||||
|| (isPositive && isFloat && MathLib::toString(MathLib::toDoubleNumber(s)) == "0.0")); // case: float number
|
|| (isFloat && MathLib::toString(MathLib::toDoubleNumber(s)) == "0.0")); // case: float number
|
||||||
|
|
||||||
return isZeroValue;
|
return isZeroValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Helper function to check wether number is one (1,0.1 or 1E+0) or not?
|
// Helper function to check wether number is one (1 or 0.1E+1 or 1E+0) or not?
|
||||||
// @param s --> a string to check
|
// @param s --> a string to check
|
||||||
// @return true in case s is zero and false otherwise.
|
// @return true in case s is zero and false otherwise.
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static bool isOneNumber(const std::string &s)
|
bool Tokenizer::isOneNumber(const std::string &s)
|
||||||
{
|
{
|
||||||
const bool isPositive = MathLib::isPositive(s);
|
const bool isPositive = MathLib::isPositive(s);
|
||||||
const bool isInteger = MathLib::isInt(s);
|
const bool isInteger = MathLib::isInt(s);
|
||||||
|
@ -8310,7 +8309,8 @@ static bool isOneNumber(const std::string &s)
|
||||||
// fmaxf(), isgreater(), isgreaterequal(), isless()
|
// fmaxf(), isgreater(), isgreaterequal(), isless()
|
||||||
// islessgreater(), islessequal(), pow(), powf(), powl(),
|
// islessgreater(), islessequal(), pow(), powf(), powl(),
|
||||||
// div(),ldiv(),lldiv(), cbrt(), cbrtl(), cbtrf(), sqrt(),
|
// div(),ldiv(),lldiv(), cbrt(), cbrtl(), cbtrf(), sqrt(),
|
||||||
// sqrtf(), sqrtl(), exp(), expf(), expl()
|
// sqrtf(), sqrtl(), exp(), expf(), expl(), exp2(),
|
||||||
|
// exp2f(), exp2l(), log2(), log2f(), log2l()
|
||||||
// in the tokenlist.
|
// in the tokenlist.
|
||||||
//
|
//
|
||||||
// Reference:
|
// Reference:
|
||||||
|
@ -8362,8 +8362,8 @@ void Tokenizer::simplifyMathFunctions()
|
||||||
tok->deleteNext(3); // delete tokens
|
tok->deleteNext(3); // delete tokens
|
||||||
tok->str("1"); // insert result into token list
|
tok->str("1"); // insert result into token list
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, "exp|expf|expl ( %num% )")) {
|
} else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l ( %num% )")) {
|
||||||
// Simplify: exp(0) = 1
|
// Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1
|
||||||
// get number string
|
// get number string
|
||||||
const std::string parameter(tok->tokAt(2)->str());
|
const std::string parameter(tok->tokAt(2)->str());
|
||||||
// is parameter 0 ?
|
// is parameter 0 ?
|
||||||
|
@ -8371,6 +8371,15 @@ void Tokenizer::simplifyMathFunctions()
|
||||||
tok->deleteNext(3); // delete tokens
|
tok->deleteNext(3); // delete tokens
|
||||||
tok->str("1"); // insert result into token list
|
tok->str("1"); // insert result into token list
|
||||||
}
|
}
|
||||||
|
} else if (Token::Match(tok, "log2|log2f|log2l ( %num% )")) {
|
||||||
|
// Simplify: log2[f|l](1) = 0
|
||||||
|
// get number string
|
||||||
|
const std::string parameter(tok->tokAt(2)->str());
|
||||||
|
// is parameter 0 ?
|
||||||
|
if (isOneNumber(parameter)) {
|
||||||
|
tok->deleteNext(3); // delete tokens
|
||||||
|
tok->str("0"); // insert result into token list
|
||||||
|
}
|
||||||
} else if (Token::Match(tok, "fmin|fminl|fminf ( %num% , %num% )")) {
|
} else if (Token::Match(tok, "fmin|fminl|fminf ( %num% , %num% )")) {
|
||||||
// @todo if one of the parameters is NaN the other is returned
|
// @todo if one of the parameters is NaN the other is returned
|
||||||
// e.g. printf ("fmin (NaN, -1.0) = %f\n", fmin(NaN,-1.0));
|
// e.g. printf ("fmin (NaN, -1.0) = %f\n", fmin(NaN,-1.0));
|
||||||
|
|
|
@ -748,6 +748,20 @@ public:
|
||||||
*/
|
*/
|
||||||
static Token *copyTokens(Token *dest, const Token *first, const Token *last, bool one_line = true);
|
static Token *copyTokens(Token *dest, const Token *first, const Token *last, bool one_line = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to check wether number is zero (0 or 0.0 or 0E+0) or not?
|
||||||
|
* @param s --> a string to check
|
||||||
|
* @return true in case s is zero and false otherwise.
|
||||||
|
*/
|
||||||
|
static bool isZeroNumber(const std::string &s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to check wether number is one (1 or 0.1E+1 or 1E+0) or not?
|
||||||
|
* @param s --> a string to check
|
||||||
|
* @return true in case s is zero and false otherwise.
|
||||||
|
*/
|
||||||
|
static bool isOneNumber(const std::string &s);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Disable copy constructor, no implementation */
|
/** Disable copy constructor, no implementation */
|
||||||
Tokenizer(const Tokenizer &);
|
Tokenizer(const Tokenizer &);
|
||||||
|
|
|
@ -309,6 +309,9 @@ private:
|
||||||
|
|
||||||
TEST_CASE(doublesharp);
|
TEST_CASE(doublesharp);
|
||||||
|
|
||||||
|
TEST_CASE(isZeroNumber);
|
||||||
|
TEST_CASE(isOneNumber);
|
||||||
|
|
||||||
TEST_CASE(macrodoublesharp);
|
TEST_CASE(macrodoublesharp);
|
||||||
|
|
||||||
TEST_CASE(simplifyFunctionParameters);
|
TEST_CASE(simplifyFunctionParameters);
|
||||||
|
@ -8278,13 +8281,121 @@ private:
|
||||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Win32W));
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Win32W));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void isZeroNumber() const {
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("0.0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0.0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0.0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0L"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0E+0"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isZeroNumber("1.0"));
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isZeroNumber("+1.0"));
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isZeroNumber("-1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void isOneNumber() const {
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("1.0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1.0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("1.0e+0"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1L"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("1"));
|
||||||
|
ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1E+0"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isOneNumber("0.0"));
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isOneNumber("+0.0"));
|
||||||
|
ASSERT_EQUALS(false, Tokenizer::isOneNumber("-0"));
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyMathFunctions() { //#5031
|
void simplifyMathFunctions() { //#5031
|
||||||
|
|
||||||
|
// verify log2(), log2f(), log2l() - simplifcation
|
||||||
|
const char code_log2[] ="void f(int x) {\n"
|
||||||
|
" std::cout << log2(x);\n" // do not simplify
|
||||||
|
" std::cout << log2(10);\n" // do not simplify
|
||||||
|
" std::cout << log2(1L);\n" // simplify to 0
|
||||||
|
"}";
|
||||||
|
const char expected_log2[] = "void f ( int x ) {\n"
|
||||||
|
"std :: cout << log2 ( x ) ;\n"
|
||||||
|
"std :: cout << log2 ( 10 ) ;\n"
|
||||||
|
"std :: cout << 0 ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_log2, tokenizeAndStringify(code_log2));
|
||||||
|
|
||||||
|
const char code_log2f[] ="void f(float x) {\n"
|
||||||
|
" std::cout << log2f(x);\n" // do not simplify
|
||||||
|
" std::cout << log2f(10);\n" // do not simplify
|
||||||
|
" std::cout << log2f(1.0f);\n" // simplify to 0
|
||||||
|
"}";
|
||||||
|
const char expected_log2f[] = "void f ( float x ) {\n"
|
||||||
|
"std :: cout << log2f ( x ) ;\n"
|
||||||
|
"std :: cout << log2f ( 10 ) ;\n"
|
||||||
|
"std :: cout << 0 ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_log2f, tokenizeAndStringify(code_log2f));
|
||||||
|
|
||||||
|
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
|
||||||
|
"}";
|
||||||
|
const char expected_log2l[] = "void f ( long double x ) {\n"
|
||||||
|
"std :: cout << log2l ( x ) ;\n"
|
||||||
|
"std :: cout << log2l ( 10.0d ) ;\n"
|
||||||
|
"std :: cout << 0 ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_log2l, tokenizeAndStringify(code_log2l));
|
||||||
|
|
||||||
|
// verify exp2(), exp2f(), exp2l() - simplifcation
|
||||||
|
const char code_exp2[] ="void f(int x) {\n"
|
||||||
|
" std::cout << exp2(x);\n" // do not simplify
|
||||||
|
" std::cout << exp2(-1);\n" // do not simplify
|
||||||
|
" std::cout << exp2(0L);\n" // simplify to 0
|
||||||
|
" std::cout << exp2(1L);\n" // do not simplify
|
||||||
|
"}";
|
||||||
|
const char expected_exp2[] = "void f ( int x ) {\n"
|
||||||
|
"std :: cout << exp2 ( x ) ;\n"
|
||||||
|
"std :: cout << exp2 ( -1 ) ;\n"
|
||||||
|
"std :: cout << 1 ;\n"
|
||||||
|
"std :: cout << exp2 ( 1L ) ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_exp2, tokenizeAndStringify(code_exp2));
|
||||||
|
|
||||||
|
const char code_exp2f[] ="void f(float x) {\n"
|
||||||
|
" std::cout << exp2f(x);\n" // do not simplify
|
||||||
|
" std::cout << exp2f(-1.0);\n" // do not simplify
|
||||||
|
" std::cout << exp2f(0.0);\n" // simplify to 1
|
||||||
|
" std::cout << exp2f(1.0);\n" // do not simplify
|
||||||
|
"}";
|
||||||
|
const char expected_exp2f[] = "void f ( float x ) {\n"
|
||||||
|
"std :: cout << exp2f ( x ) ;\n"
|
||||||
|
"std :: cout << exp2f ( -1.0 ) ;\n"
|
||||||
|
"std :: cout << 1 ;\n"
|
||||||
|
"std :: cout << exp2f ( 1.0 ) ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_exp2f, tokenizeAndStringify(code_exp2f));
|
||||||
|
|
||||||
|
const char code_exp2l[] ="void f(long double x) {\n"
|
||||||
|
" std::cout << exp2l(x);\n" // do not simplify
|
||||||
|
" std::cout << exp2l(-1.0);\n" // do not simplify
|
||||||
|
" std::cout << exp2l(0.0);\n" // simplify to 1
|
||||||
|
" std::cout << exp2l(1.0);\n" // do not simplify
|
||||||
|
"}";
|
||||||
|
const char expected_exp2l[] = "void f ( long double x ) {\n"
|
||||||
|
"std :: cout << exp2l ( x ) ;\n"
|
||||||
|
"std :: cout << exp2l ( -1.0 ) ;\n"
|
||||||
|
"std :: cout << 1 ;\n"
|
||||||
|
"std :: cout << exp2l ( 1.0 ) ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected_exp2l, tokenizeAndStringify(code_exp2l));
|
||||||
|
|
||||||
// verify exp(), expf(), expl() - simplifcation
|
// verify exp(), expf(), expl() - simplifcation
|
||||||
const char code_exp[] ="void f(int x) {\n"
|
const char code_exp[] ="void f(int x) {\n"
|
||||||
" std::cout << exp(x);\n" // do not simplify
|
" std::cout << exp(x);\n" // do not simplify
|
||||||
" std::cout << exp(-1);\n" // do not simplify
|
" std::cout << exp(-1);\n" // do not simplify
|
||||||
" std::cout << exp(0L);\n" // simplify to 0
|
" std::cout << exp(0L);\n" // simplify to 1
|
||||||
" std::cout << exp(1L);\n" // do not simplify
|
" std::cout << exp(1L);\n" // do not simplify
|
||||||
"}";
|
"}";
|
||||||
const char expected_exp[] = "void f ( int x ) {\n"
|
const char expected_exp[] = "void f ( int x ) {\n"
|
||||||
|
@ -8298,7 +8409,7 @@ private:
|
||||||
const char code_expf[] ="void f(float x) {\n"
|
const char code_expf[] ="void f(float x) {\n"
|
||||||
" std::cout << expf(x);\n" // do not simplify
|
" std::cout << expf(x);\n" // do not simplify
|
||||||
" std::cout << expf(-1.0);\n" // do not simplify
|
" std::cout << expf(-1.0);\n" // do not simplify
|
||||||
" std::cout << expf(0.0);\n" // simplify to 0
|
" std::cout << expf(0.0);\n" // simplify to 1
|
||||||
" std::cout << expf(1.0);\n" // do not simplify
|
" std::cout << expf(1.0);\n" // do not simplify
|
||||||
"}";
|
"}";
|
||||||
const char expected_expf[] = "void f ( float x ) {\n"
|
const char expected_expf[] = "void f ( float x ) {\n"
|
||||||
|
@ -8312,7 +8423,7 @@ private:
|
||||||
const char code_expl[] ="void f(long double x) {\n"
|
const char code_expl[] ="void f(long double x) {\n"
|
||||||
" std::cout << expl(x);\n" // do not simplify
|
" std::cout << expl(x);\n" // do not simplify
|
||||||
" std::cout << expl(-1.0);\n" // do not simplify
|
" std::cout << expl(-1.0);\n" // do not simplify
|
||||||
" std::cout << expl(0.0);\n" // simplify to 0
|
" std::cout << expl(0.0);\n" // simplify to 1
|
||||||
" std::cout << expl(1.0);\n" // do not simplify
|
" std::cout << expl(1.0);\n" // do not simplify
|
||||||
"}";
|
"}";
|
||||||
const char expected_expl[] = "void f ( long double x ) {\n"
|
const char expected_expl[] = "void f ( long double x ) {\n"
|
||||||
|
|
Loading…
Reference in New Issue