X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=ginac%2Fmul.cpp;h=0fdd9549f3863df3df355cf4369327f588b00a56;hb=71fdb941e62f5e4bf131bc40468cfa7a4a5c986a;hp=0a6fca40b7a06cb25749f80cae700c9bf5fb1b63;hpb=6c946d4c762f5a0d6a3b742f03556dd018d63886;p=ginac.git diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 0a6fca40..0fdd9549 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's products of expressions. */ /* - * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -89,6 +89,13 @@ mul::mul(const epvector & v, const ex & oc, bool do_index_renaming) GINAC_ASSERT(is_canonical()); } +mul::mul(epvector && vp) +{ + overall_coeff = _ex1; + construct_from_epvector(std::move(vp)); + GINAC_ASSERT(is_canonical()); +} + mul::mul(epvector && vp, const ex & oc, bool do_index_renaming) { overall_coeff = oc; @@ -285,13 +292,6 @@ bool mul::info(unsigned inf) const return true; return overall_coeff.info(inf); } - case info_flags::algebraic: { - for (auto & it : seq) { - if (recombine_pair_to_ex(it).info(inf)) - return true; - } - return false; - } case info_flags::positive: case info_flags::negative: { if ((inf==info_flags::positive) && (flags & status_flags::is_positive)) @@ -500,7 +500,7 @@ ex mul::eval() const distrseq.push_back(addref.combine_pair_with_coeff_to_pair(it, overall_coeff)); } return dynallocate(std::move(distrseq), - ex_to(addref.overall_coeff).mul_dyn(ex_to(overall_coeff))) + ex_to(addref.overall_coeff).mul_dyn(ex_to(overall_coeff))) .setflag(status_flags::evaluated); } else if ((seq_size >= 2) && (! (flags & status_flags::expanded))) { // Strip the content and the unit part from each term. Thus @@ -554,9 +554,9 @@ ex mul::eval() const add & primitive = dynallocate(addref); primitive.clearflag(status_flags::hash_calculated); primitive.overall_coeff = ex_to(primitive.overall_coeff).div_dyn(c); - for (epvector::iterator ai = primitive.seq.begin(); ai != primitive.seq.end(); ++ai) - ai->coeff = ex_to(ai->coeff).div_dyn(c); - + for (auto & ai : primitive.seq) + ai.coeff = ex_to(ai.coeff).div_dyn(c); + s.push_back(expair(primitive, _ex1)); ++i; @@ -574,22 +574,14 @@ ex mul::eval() const return this->hold(); } -ex mul::evalf(int level) const +ex mul::evalf() const { - if (level==1) - return mul(seq,overall_coeff); - - if (level==-max_recursion_level) - throw(std::runtime_error("max recursion level reached")); - epvector s; s.reserve(seq.size()); - --level; - for (auto & it : seq) { - s.push_back(expair(it.rest.evalf(level), it.coeff)); - } - return dynallocate(std::move(s), overall_coeff.evalf(level)); + for (auto & it : seq) + s.push_back(expair(it.rest.evalf(), it.coeff)); + return dynallocate(std::move(s), overall_coeff.evalf()); } void mul::find_real_imag(ex & rp, ex & ip) const @@ -797,10 +789,10 @@ retry1: subsed[j] = true; ex subsed_pattern = it.first.subs(repls, subs_options::no_pattern); - divide_by *= power(subsed_pattern, nummatches); + divide_by *= pow(subsed_pattern, nummatches); ex subsed_result = it.second.subs(repls, subs_options::no_pattern); - multiply_by *= power(subsed_result, nummatches); + multiply_by *= pow(subsed_result, nummatches); goto retry1; } else { @@ -812,10 +804,10 @@ retry1: subsed[j] = true; ex subsed_pattern = it.first.subs(repls, subs_options::no_pattern); - divide_by *= power(subsed_pattern, nummatches); + divide_by *= pow(subsed_pattern, nummatches); ex subsed_result = it.second.subs(repls, subs_options::no_pattern); - multiply_by *= power(subsed_result, nummatches); + multiply_by *= pow(subsed_result, nummatches); } } } @@ -879,7 +871,7 @@ ex mul::derivative(const symbol & s) const auto i = seq.begin(), end = seq.end(); auto i2 = mulseq.begin(); while (i != end) { - expair ep = split_ex_to_pair(power(i->rest, i->coeff - _ex1) * + expair ep = split_ex_to_pair(pow(i->rest, i->coeff - _ex1) * i->rest.diff(s)); ep.swap(*i2); addseq.push_back(dynallocate(mulseq, overall_coeff * i->coeff)); @@ -970,14 +962,15 @@ expair mul::combine_ex_with_coeff_to_pair(const ex & e, if (is_exactly_a(e)) return expair(e, c); + // trivial case: exponent 1 + if (c.is_equal(_ex1)) + return split_ex_to_pair(e); + // to avoid duplication of power simplification rules, // we create a temporary power object // otherwise it would be hard to correctly evaluate // expression like (4^(1/3))^(3/2) - if (c.is_equal(_ex1)) - return split_ex_to_pair(e); - - return split_ex_to_pair(power(e,c)); + return split_ex_to_pair(pow(e,c)); } expair mul::combine_pair_with_coeff_to_pair(const expair & p, @@ -986,19 +979,26 @@ expair mul::combine_pair_with_coeff_to_pair(const expair & p, GINAC_ASSERT(is_exactly_a(p.coeff)); GINAC_ASSERT(is_exactly_a(c)); + // First, try a common shortcut: + if (is_exactly_a(p.rest)) + return expair(p.rest, p.coeff * c); + + // trivial case: exponent 1 + if (c.is_equal(_ex1)) + return p; + if (p.coeff.is_equal(_ex1)) + return expair(p.rest, c); + // to avoid duplication of power simplification rules, // we create a temporary power object // otherwise it would be hard to correctly evaluate // expression like (4^(1/3))^(3/2) - if (c.is_equal(_ex1)) - return p; - - return split_ex_to_pair(power(recombine_pair_to_ex(p),c)); + return split_ex_to_pair(pow(recombine_pair_to_ex(p),c)); } ex mul::recombine_pair_to_ex(const expair & p) const { - if (ex_to(p.coeff).is_equal(*_num1_p)) + if (p.coeff.is_equal(_ex1)) return p.rest; else return dynallocate(p.rest, p.coeff); @@ -1071,20 +1071,22 @@ bool mul::can_be_further_expanded(const ex & e) ex mul::expand(unsigned options) const { - { - // trivial case: expanding the monomial (~ 30% of all calls) - epvector::const_iterator i = seq.begin(), seq_end = seq.end(); - while ((i != seq.end()) && is_a(i->rest) && i->coeff.info(info_flags::integer)) - ++i; - if (i == seq_end) { - setflag(status_flags::expanded); - return *this; + // Check for trivial case: expanding the monomial (~ 30% of all calls) + bool monomial_case = true; + for (const auto & i : seq) { + if (!is_a(i.rest) || !i.coeff.info(info_flags::integer)) { + monomial_case = false; + break; } } + if (monomial_case) { + setflag(status_flags::expanded); + return *this; + } // do not rename indices if the object has no indices at all if ((!(options & expand_options::expand_rename_idx)) && - this->info(info_flags::has_indices)) + this->info(info_flags::has_indices)) options |= expand_options::expand_rename_idx; const bool skip_idx_rename = !(options & expand_options::expand_rename_idx);