Exemple #1
0
    // 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;
}