// treat powers specially, because it's better to unroll them and // avoid a function call if we have an exact integral power std::string cpp_cse::print_power(const GiNaC::ex& expr, bool use_count) { std::ostringstream out; size_t n = expr.nops(); if(n != 2) { error_context err_ctx = this->data_payload.make_error_context(); err_ctx.error(ERROR_CSE_POWER_ARGUMENTS); out << "std::pow(" << this->print_operands(expr, ",", use_count) << ")"; return std::string{}; } // set up aliases for base and exponent expressions const auto& base_expr = expr.op(0); const auto& exponent_expr = expr.op(1); // perform use-counting on exponent, which is necessary since its values may have been // used elsewhere in the CSE tree, even if it is an integer that we will unroll and not use explicitly std::string exponent; if(use_count) exponent = this->get_symbol_with_use_count(exponent_expr); else exponent = this->get_symbol_without_use_count(exponent_expr); if(GiNaC::is_a<GiNaC::numeric>(exponent_expr)) { const auto& exp_numeric = GiNaC::ex_to<GiNaC::numeric>(exponent_expr); std::string base; if(use_count) base = this->get_symbol_with_use_count(expr.op(0)); else base = this->get_symbol_without_use_count(expr.op(0)); if(GiNaC::is_integer(exp_numeric)) { if(GiNaC::is_nonneg_integer(exp_numeric)) { if(exp_numeric.to_int() == 0) out << "1.0"; else if(exp_numeric.to_int() == 1) out << unwrap_power(base, base_expr, 1); else if(exp_numeric.to_int() == 2) out << "(" << unwrap_power(base, base_expr, 2) << ")"; else if(exp_numeric.to_int() == 3) out << "(" << unwrap_power(base, base_expr, 3) << ")"; else if(exp_numeric.to_int() == 4) out << "(" << unwrap_power(base, base_expr, 4) << ")"; else out << "std::pow(" << base << "," << exp_numeric.to_int() << ")"; } else // negative integer { if(exp_numeric.to_int() == -0) out << "1.0"; else if(exp_numeric.to_int() == -1) out << "1.0/" << unwrap_power(base, base_expr, 1); else if(exp_numeric.to_int() == -2) out << "1.0/" << "(" << unwrap_power(base, base_expr, 2) << ")"; else if(exp_numeric.to_int() == -3) out << "1.0/" << "(" << unwrap_power(base, base_expr, 3) << ")"; else if(exp_numeric.to_int() == -4) out << "1.0/" << "(" << unwrap_power(base, base_expr, 4) << ")"; else out << "std::pow(" << base << "," << exp_numeric.to_int() << ")"; } } else // not an integer { out << "std::pow(" << base << "," << exponent << ")"; } } return(out.str()); }
int Expr::getMaxDegree() const { int Max = 0; for (auto It = Expr_.preorder_begin(), E = Expr_.preorder_end(); It != E; ++It) { GiNaC::ex Ex = *It; if (GiNaC::is_a<GiNaC::power>(Ex)) Max = std::max(Max, GiNaC::ex_to<GiNaC::numeric>(Ex.op(1)).to_int()); else if (GiNaC::is_a<GiNaC::symbol>(Ex)) Max = std::max(Max, 1); } return Max; }