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.");
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// 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
|
||||
// @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 isFloat = MathLib::isFloat(s);
|
||||
const bool isZeroValue = ((isPositive && isInteger && (MathLib::toLongNumber(s) == 0L)) // case: integer number
|
||||
|| (isPositive && isFloat && MathLib::toString(MathLib::toDoubleNumber(s)) == "0.0")); // case: float number
|
||||
const bool isZeroValue = ((isInteger && (MathLib::toLongNumber(s) == 0L)) // case: integer number
|
||||
|| (isFloat && MathLib::toString(MathLib::toDoubleNumber(s)) == "0.0")); // case: float number
|
||||
|
||||
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
|
||||
// @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 isInteger = MathLib::isInt(s);
|
||||
|
@ -8310,7 +8309,8 @@ static bool isOneNumber(const std::string &s)
|
|||
// fmaxf(), isgreater(), isgreaterequal(), isless()
|
||||
// islessgreater(), islessequal(), pow(), powf(), powl(),
|
||||
// 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.
|
||||
//
|
||||
// Reference:
|
||||
|
@ -8362,8 +8362,8 @@ void Tokenizer::simplifyMathFunctions()
|
|||
tok->deleteNext(3); // delete tokens
|
||||
tok->str("1"); // insert result into token list
|
||||
}
|
||||
} else if (Token::Match(tok, "exp|expf|expl ( %num% )")) {
|
||||
// Simplify: exp(0) = 1
|
||||
} else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l ( %num% )")) {
|
||||
// Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1
|
||||
// get number string
|
||||
const std::string parameter(tok->tokAt(2)->str());
|
||||
// is parameter 0 ?
|
||||
|
@ -8371,6 +8371,15 @@ void Tokenizer::simplifyMathFunctions()
|
|||
tok->deleteNext(3); // delete tokens
|
||||
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% )")) {
|
||||
// @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));
|
||||
|
|
|
@ -748,6 +748,20 @@ public:
|
|||
*/
|
||||
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:
|
||||
/** Disable copy constructor, no implementation */
|
||||
Tokenizer(const Tokenizer &);
|
||||
|
|
|
@ -309,6 +309,9 @@ private:
|
|||
|
||||
TEST_CASE(doublesharp);
|
||||
|
||||
TEST_CASE(isZeroNumber);
|
||||
TEST_CASE(isOneNumber);
|
||||
|
||||
TEST_CASE(macrodoublesharp);
|
||||
|
||||
TEST_CASE(simplifyFunctionParameters);
|
||||
|
@ -8278,13 +8281,121 @@ private:
|
|||
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
|
||||
|
||||
// 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
|
||||
const char code_exp[] ="void f(int x) {\n"
|
||||
" std::cout << exp(x);\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
|
||||
"}";
|
||||
const char expected_exp[] = "void f ( int x ) {\n"
|
||||
|
@ -8298,7 +8409,7 @@ private:
|
|||
const char code_expf[] ="void f(float x) {\n"
|
||||
" std::cout << expf(x);\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
|
||||
"}";
|
||||
const char expected_expf[] = "void f ( float x ) {\n"
|
||||
|
@ -8312,7 +8423,7 @@ private:
|
|||
const char code_expl[] ="void f(long double x) {\n"
|
||||
" std::cout << expl(x);\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
|
||||
"}";
|
||||
const char expected_expl[] = "void f ( long double x ) {\n"
|
||||
|
|
Loading…
Reference in New Issue