Optimization Tokenizer::simplifyMathFunctions. Make an a priori check whether the token combination can be a function call at all.

This commit is contained in:
Frank Zingsheim 2014-03-09 13:22:58 +01:00 committed by Daniel Marjamäki
parent b13e3ac549
commit 6e9e20d5b1
1 changed files with 235 additions and 232 deletions

View File

@ -8241,249 +8241,252 @@ bool Tokenizer::simplifyMathFunctions()
{
bool simplifcationMade = false;
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "atol ( %str% )")) { //@todo Add support for atoll()
if (tok->previous() &&
Token::simpleMatch(tok->tokAt(-2), "std ::")) {
tok = tok->tokAt(-2);// set token index two steps back
tok->deleteNext(2); // delete "std ::"
}
const std::string strNumber = tok->tokAt(2)->strValue(); // get number
const bool isNotAnInteger = (!MathLib::isInt(strNumber));// check: is not an integer
if (!strNumber.empty() && isNotAnInteger) {
// Ignore strings which we can't convert
continue;
}
// remove atol ( %num%
tok->deleteNext(3);
// Convert string into a number and insert into token list
tok->str(MathLib::toString(MathLib::toLongNumber(strNumber)));
simplifcationMade = true;
} else if (Token::Match(tok, "abs|fabs|labs|llabs ( %num% )")) {
if (tok->previous() &&
Token::simpleMatch(tok->tokAt(-2), "std ::")) {
tok = tok->tokAt(-2);// set token index two steps back
tok->deleteNext(2); // delete "std ::"
}
// get number string
std::string strNumber(tok->tokAt(2)->str());
// is the string negative?
if (!strNumber.empty() && strNumber[0] == '-') {
strNumber = strNumber.substr(1); // remove '-' sign
}
tok->deleteNext(3); // delete e.g. abs ( 1 )
tok->str(strNumber); // insert result into token list
simplifcationMade = true;
} else if (Token::Match(tok, "fma|fmaf|fmal ( %any% , %any% , %any% )")) {
// Simplify: fma(a,b,c) == > ( a ) * ( b ) + ( c )
// get parameters
const std::string a(tok->tokAt(2)->str());
const std::string b(tok->tokAt(4)->str());
const std::string c(tok->tokAt(6)->str());
if (!a.empty() && !b.empty() && !c.empty()) {
tok->deleteNext(7); // delete fma call
tok->str("( " + a + " ) * ( " + b + " ) + ( " + c + " )"); // insert result into token list
const Token * tokNext = tok->next();
if (tokNext && tokNext->str() == "(") { // precondition for function
if (Token::Match(tok, "atol ( %str% )")) { //@todo Add support for atoll()
if (tok->previous() &&
Token::simpleMatch(tok->tokAt(-2), "std ::")) {
tok = tok->tokAt(-2);// set token index two steps back
tok->deleteNext(2); // delete "std ::"
}
const std::string strNumber = tok->tokAt(2)->strValue(); // get number
const bool isNotAnInteger = (!MathLib::isInt(strNumber));// check: is not an integer
if (!strNumber.empty() && isNotAnInteger) {
// Ignore strings which we can't convert
continue;
}
// remove atol ( %num%
tok->deleteNext(3);
// Convert string into a number and insert into token list
tok->str(MathLib::toString(MathLib::toLongNumber(strNumber)));
simplifcationMade = true;
}
} else if (Token::Match(tok, "sqrt|sqrtf|sqrtl|cbrt|cbrtf|cbrtl ( %num% )")) {
// Simplify: sqrt(0) = 0 and cbrt(0) == 0
// sqrt(1) = 1 and cbrt(1) == 1
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
} else if (Token::Match(tok, "abs|fabs|labs|llabs ( %num% )")) {
if (tok->previous() &&
Token::simpleMatch(tok->tokAt(-2), "std ::")) {
tok = tok->tokAt(-2);// set token index two steps back
tok->deleteNext(2); // delete "std ::"
}
// get number string
std::string strNumber(tok->tokAt(2)->str());
// is the string negative?
if (!strNumber.empty() && strNumber[0] == '-') {
strNumber = strNumber.substr(1); // remove '-' sign
}
tok->deleteNext(3); // delete e.g. abs ( 1 )
tok->str(strNumber); // insert result into token list
simplifcationMade = true;
} else if (isOneNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("1"); // insert result into token list
simplifcationMade = true;
}
} else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l|cos|cosf|cosl|cosh|coshf|coshl|erfc|erfcf|erfcl ( %num% )")) {
// Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1
// cosh[f|l](0) = 1 and cos[f|l](0) = 1
// erfc[f|l](0) = 1
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("1"); // insert result into token list
simplifcationMade = true;
}
} else if (Token::Match(tok, "log1p|log1pf|log1pl|sin|sinf|sinl|sinh|sinhf|sinhl|erf|erff|erfl|asin|asinf|asinl|asinh|asinhf|asinhl|tan|tanf|tanl|tanh|tanhf|tanhl|atan|atanf|atanl|atanh|atanhf|atanhl|expm1|expm1f|expm1l ( %num% )")) {
// Simplify: log1p[f|l](0) = 0 and sin[f|l](0) = 0
// sinh[f|l](0) = 0 and erf[f|l](0) = 0
// asin[f|l](0) = 0 and sinh[f|l](0) = 0
// tan[f|l](0) = 0 and tanh[f|l](0) = 0
// atan[f|l](0) = 0 and atanh[f|l](0)= 0
// expm1[f|l](0) = 0
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
simplifcationMade = true;
}
} else if (Token::Match(tok, "log2|log2f|log2l|log|logf|logl|log10|log10f|log10l|logb|logbf|logbl|acosh|acoshf|acoshl|acos|acosf|acosl|ilogb|ilogbf|ilogbl ( %num% )")) {
// Simplify: log2[f|l](1) = 0 , log10[f|l](1) = 0
// log[f|l](1) = 0 , logb10[f|l](1) = 0
// acosh[f|l](1) = 0 , acos[f|l](1) = 0
// ilogb[f|l](1) = 0
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 1 ?
if (isOneNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
simplifcationMade = true;
}
} 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));
// e.g. printf ("fmin (-1.0, NaN) = %f\n", fmin(-1.0,NaN));
const std::string strLeftNumber(tok->tokAt(2)->str());
const std::string strRightNumber(tok->tokAt(4)->str());
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber);
// case: left <= right ==> insert left
if (!strLeftNumber.empty() && !strRightNumber.empty() && isLessEqual) {
tok->deleteNext(5); // delete e.g. fmin ( -1.0, 1.0 )
tok->str(strLeftNumber); // insert e.g. -1.0
simplifcationMade = true;
} else { // case left > right ==> insert right
tok->deleteNext(5); // delete e.g. fmin ( 1.0, 0.0 )
tok->str(strRightNumber); // insert e.g. 0.0
simplifcationMade = true;
}
} else if (Token::Match(tok, "fmax|fmaxl|fmaxf ( %num% , %num% )")) {
// @todo if one of the parameters is NaN the other is returned
// e.g. printf ("fmax (NaN, -1.0) = %f\n", fmax(NaN,-1.0));
// e.g. printf ("fmax (-1.0, NaN) = %f\n", fmax(-1.0,NaN));
const std::string strLeftNumber(tok->tokAt(2)->str());
const std::string strRightNumber(tok->tokAt(4)->str());
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber);
// case: left <= right ==> insert right
if (!strLeftNumber.empty() && !strRightNumber.empty() && isLessEqual) {
tok->deleteNext(5); // delete e.g. fmax ( -1.0, 1.0 )
tok->str(strRightNumber);// insert e.g. 1.0
simplifcationMade = true;
} else { // case left > right ==> insert left
tok->deleteNext(5); // delete e.g. fmax ( 1.0, 0.0 )
tok->str(strLeftNumber); // insert e.g. 1.0
simplifcationMade = true;
}
} else if (Token::Match(tok, "isgreater ( %num% , %num% )")) {
// The isgreater(x,y) function is the same as calculating (x)>(y).
// It returns true (1) if x is greater than y and false (0) otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isGreater = MathLib::isGreater(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isGreater == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "isgreaterequal ( %num% , %num% )")) {
// The isgreaterequal(x,y) function is the same as calculating (x)>=(y).
// It returns true (1) if x is greater than or equal to y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isGreaterEqual = MathLib::isGreaterEqual(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isGreaterEqual == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "isless ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<(y).
// It returns true (1) if x is less than y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLess = MathLib::isLess(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLess == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "islessequal ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<=(y).
// It returns true (1) if x is less or equal to y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLessEqual == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "islessgreater ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<(y) || (x)>(y).
// It returns true (1) if x is less than y or x is greater than y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLessOrGreater(MathLib::isLess(strLeftNumber, strRightNumber) ||
MathLib::isGreater(strLeftNumber, strRightNumber)); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLessOrGreater == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "div|ldiv|lldiv ( %any% , %num% )")) {
// Calling the function 'div(x,y)' is the same as calculating (x)/(y). In case y has the value 1
// (the identity element), the call can be simplified to (x).
const std::string leftParameter(tok->tokAt(2)->str()); // get the left parameter
const std::string rightNumber(tok->tokAt(4)->str()); // get right number
if (!rightNumber.empty() && !leftParameter.empty()) {
if (isOneNumber(rightNumber)) {
tok->deleteNext(5); // delete tokens
tok->str(leftParameter); // insert simplified result
} else if (Token::Match(tok, "fma|fmaf|fmal ( %any% , %any% , %any% )")) {
// Simplify: fma(a,b,c) == > ( a ) * ( b ) + ( c )
// get parameters
const std::string a(tok->tokAt(2)->str());
const std::string b(tok->tokAt(4)->str());
const std::string c(tok->tokAt(6)->str());
if (!a.empty() && !b.empty() && !c.empty()) {
tok->deleteNext(7); // delete fma call
tok->str("( " + a + " ) * ( " + b + " ) + ( " + c + " )"); // insert result into token list
simplifcationMade = true;
}
}
} else if (Token::Match(tok, "pow|powf|powl (")) {
if (tok && Token::Match(tok->tokAt(2), "%num% , %num% )")) {
// In case of pow ( 0 , anyNumber > 0): It can be simplified to 0
// In case of pow ( 0 , 0 ): It simplified to 1
// In case of pow ( 1 , anyNumber ): It simplified to 1
const std::string leftNumber(tok->tokAt(2)->str()); // get the left parameter
const std::string rightNumber(tok->tokAt(4)->str()); // get the right parameter
if (!leftNumber.empty() && !rightNumber.empty()) {
const bool isLeftNumberZero = isZeroNumber(leftNumber);
const bool isLeftNumberOne = isOneNumber(leftNumber);
const bool isRightNumberZero = isZeroNumber(rightNumber);
if (isLeftNumberZero && !isRightNumberZero && MathLib::isPositive(rightNumber)) { // case: 0^(y) = 0 and y > 0
tok->deleteNext(5); // delete tokens
tok->str("0"); // insert simplified result
simplifcationMade = true;
} else if (isLeftNumberZero && isRightNumberZero) { // case: 0^0 = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
} else if (isLeftNumberOne) { // case 1^(y) = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
}
} else if (Token::Match(tok, "sqrt|sqrtf|sqrtl|cbrt|cbrtf|cbrtl ( %num% )")) {
// Simplify: sqrt(0) = 0 and cbrt(0) == 0
// sqrt(1) = 1 and cbrt(1) == 1
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
simplifcationMade = true;
} else if (isOneNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("1"); // insert result into token list
simplifcationMade = true;
}
}
if (tok && Token::Match(tok->tokAt(2), "%any% , %num% )")) {
// In case of pow( x , 1 ): It can be simplified to x.
} else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l|cos|cosf|cosl|cosh|coshf|coshl|erfc|erfcf|erfcl ( %num% )")) {
// Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1
// cosh[f|l](0) = 1 and cos[f|l](0) = 1
// erfc[f|l](0) = 1
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("1"); // insert result into token list
simplifcationMade = true;
}
} else if (Token::Match(tok, "log1p|log1pf|log1pl|sin|sinf|sinl|sinh|sinhf|sinhl|erf|erff|erfl|asin|asinf|asinl|asinh|asinhf|asinhl|tan|tanf|tanl|tanh|tanhf|tanhl|atan|atanf|atanl|atanh|atanhf|atanhl|expm1|expm1f|expm1l ( %num% )")) {
// Simplify: log1p[f|l](0) = 0 and sin[f|l](0) = 0
// sinh[f|l](0) = 0 and erf[f|l](0) = 0
// asin[f|l](0) = 0 and sinh[f|l](0) = 0
// tan[f|l](0) = 0 and tanh[f|l](0) = 0
// atan[f|l](0) = 0 and atanh[f|l](0)= 0
// expm1[f|l](0) = 0
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 0 ?
if (isZeroNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
simplifcationMade = true;
}
} else if (Token::Match(tok, "log2|log2f|log2l|log|logf|logl|log10|log10f|log10l|logb|logbf|logbl|acosh|acoshf|acoshl|acos|acosf|acosl|ilogb|ilogbf|ilogbl ( %num% )")) {
// Simplify: log2[f|l](1) = 0 , log10[f|l](1) = 0
// log[f|l](1) = 0 , logb10[f|l](1) = 0
// acosh[f|l](1) = 0 , acos[f|l](1) = 0
// ilogb[f|l](1) = 0
// get number string
const std::string parameter(tok->tokAt(2)->str());
// is parameter 1 ?
if (isOneNumber(parameter)) {
tok->deleteNext(3); // delete tokens
tok->str("0"); // insert result into token list
simplifcationMade = true;
}
} 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));
// e.g. printf ("fmin (-1.0, NaN) = %f\n", fmin(-1.0,NaN));
const std::string strLeftNumber(tok->tokAt(2)->str());
const std::string strRightNumber(tok->tokAt(4)->str());
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber);
// case: left <= right ==> insert left
if (!strLeftNumber.empty() && !strRightNumber.empty() && isLessEqual) {
tok->deleteNext(5); // delete e.g. fmin ( -1.0, 1.0 )
tok->str(strLeftNumber); // insert e.g. -1.0
simplifcationMade = true;
} else { // case left > right ==> insert right
tok->deleteNext(5); // delete e.g. fmin ( 1.0, 0.0 )
tok->str(strRightNumber); // insert e.g. 0.0
simplifcationMade = true;
}
} else if (Token::Match(tok, "fmax|fmaxl|fmaxf ( %num% , %num% )")) {
// @todo if one of the parameters is NaN the other is returned
// e.g. printf ("fmax (NaN, -1.0) = %f\n", fmax(NaN,-1.0));
// e.g. printf ("fmax (-1.0, NaN) = %f\n", fmax(-1.0,NaN));
const std::string strLeftNumber(tok->tokAt(2)->str());
const std::string strRightNumber(tok->tokAt(4)->str());
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber);
// case: left <= right ==> insert right
if (!strLeftNumber.empty() && !strRightNumber.empty() && isLessEqual) {
tok->deleteNext(5); // delete e.g. fmax ( -1.0, 1.0 )
tok->str(strRightNumber);// insert e.g. 1.0
simplifcationMade = true;
} else { // case left > right ==> insert left
tok->deleteNext(5); // delete e.g. fmax ( 1.0, 0.0 )
tok->str(strLeftNumber); // insert e.g. 1.0
simplifcationMade = true;
}
} else if (Token::Match(tok, "isgreater ( %num% , %num% )")) {
// The isgreater(x,y) function is the same as calculating (x)>(y).
// It returns true (1) if x is greater than y and false (0) otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isGreater = MathLib::isGreater(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isGreater == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "isgreaterequal ( %num% , %num% )")) {
// The isgreaterequal(x,y) function is the same as calculating (x)>=(y).
// It returns true (1) if x is greater than or equal to y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isGreaterEqual = MathLib::isGreaterEqual(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isGreaterEqual == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "isless ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<(y).
// It returns true (1) if x is less than y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLess = MathLib::isLess(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLess == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "islessequal ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<=(y).
// It returns true (1) if x is less or equal to y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLessEqual == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "islessgreater ( %num% , %num% )")) {
// Calling this function is the same as calculating (x)<(y) || (x)>(y).
// It returns true (1) if x is less than y or x is greater than y.
// False (0) is returned otherwise.
const std::string strLeftNumber(tok->tokAt(2)->str()); // get left number
const std::string strRightNumber(tok->tokAt(4)->str()); // get right number
if (!strRightNumber.empty() && !strLeftNumber.empty()) {
const bool isLessOrGreater(MathLib::isLess(strLeftNumber, strRightNumber) ||
MathLib::isGreater(strLeftNumber, strRightNumber)); // compare numbers
tok->deleteNext(5); // delete tokens
tok->str((isLessOrGreater == true) ? "true": "false"); // insert results
simplifcationMade = true;
}
} else if (Token::Match(tok, "div|ldiv|lldiv ( %any% , %num% )")) {
// Calling the function 'div(x,y)' is the same as calculating (x)/(y). In case y has the value 1
// (the identity element), the call can be simplified to (x).
const std::string leftParameter(tok->tokAt(2)->str()); // get the left parameter
const std::string rightNumber(tok->tokAt(4)->str()); // get right number
if (!rightNumber.empty() && !leftParameter.empty()) {
if (isOneNumber(rightNumber)) { // case: x^(1) = x
if (isOneNumber(rightNumber)) {
tok->deleteNext(5); // delete tokens
tok->str(leftParameter); // insert simplified result
simplifcationMade = true;
} else if (isZeroNumber(rightNumber)) { // case: x^(0) = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
}
}
} else if (Token::Match(tok, "pow|powf|powl (")) {
if (tok && Token::Match(tok->tokAt(2), "%num% , %num% )")) {
// In case of pow ( 0 , anyNumber > 0): It can be simplified to 0
// In case of pow ( 0 , 0 ): It simplified to 1
// In case of pow ( 1 , anyNumber ): It simplified to 1
const std::string leftNumber(tok->tokAt(2)->str()); // get the left parameter
const std::string rightNumber(tok->tokAt(4)->str()); // get the right parameter
if (!leftNumber.empty() && !rightNumber.empty()) {
const bool isLeftNumberZero = isZeroNumber(leftNumber);
const bool isLeftNumberOne = isOneNumber(leftNumber);
const bool isRightNumberZero = isZeroNumber(rightNumber);
if (isLeftNumberZero && !isRightNumberZero && MathLib::isPositive(rightNumber)) { // case: 0^(y) = 0 and y > 0
tok->deleteNext(5); // delete tokens
tok->str("0"); // insert simplified result
simplifcationMade = true;
} else if (isLeftNumberZero && isRightNumberZero) { // case: 0^0 = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
} else if (isLeftNumberOne) { // case 1^(y) = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
}
}
}
if (tok && Token::Match(tok->tokAt(2), "%any% , %num% )")) {
// In case of pow( x , 1 ): It can be simplified to x.
const std::string leftParameter(tok->tokAt(2)->str()); // get the left parameter
const std::string rightNumber(tok->tokAt(4)->str()); // get right number
if (!rightNumber.empty() && !leftParameter.empty()) {
if (isOneNumber(rightNumber)) { // case: x^(1) = x
tok->deleteNext(5); // delete tokens
tok->str(leftParameter); // insert simplified result
simplifcationMade = true;
} else if (isZeroNumber(rightNumber)) { // case: x^(0) = 1
tok->deleteNext(5); // delete tokens
tok->str("1"); // insert simplified result
simplifcationMade = true;
}
}
}
}