From 6e9e20d5b14c71a561af136df97eb91c05c99410 Mon Sep 17 00:00:00 2001 From: Frank Zingsheim Date: Sun, 9 Mar 2014 13:22:58 +0100 Subject: [PATCH] Optimization Tokenizer::simplifyMathFunctions. Make an a priori check whether the token combination can be a function call at all. --- lib/tokenize.cpp | 467 ++++++++++++++++++++++++----------------------- 1 file changed, 235 insertions(+), 232 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index fce9988a9..fb3591e54 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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; + } } } }