X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmul.cpp;h=3f2d5cdbfc06f8cade28ce9dc8b4ade995a68caa;hp=48d64787e164f0078212af441b72599ff1492e47;hb=6eb7dee7ea9e83d3e0599aec9ab7c6084a47b71c;hpb=65f2693a0948d1db0bc68d7656c64e1fed91c158 diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 48d64787..3f2d5cdb 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -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; @@ -464,22 +471,21 @@ ex mul::coeff(const ex & s, int n) const * - *(+(x1,x2,...);c) -> *(+(*(x1,c),*(x2,c),...)) * - *(x;1) -> x * - *(;c) -> c - * - * @param level cut-off in recursive evaluation */ -ex mul::eval(int level) const + */ +ex mul::eval() const { - epvector evaled = evalchildren(level); - if (unlikely(!evaled.empty())) { - // do more evaluation later - return dynallocate(std::move(evaled), overall_coeff); - } - if (flags & status_flags::evaluated) { GINAC_ASSERT(seq.size()>0); GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1)); return *this; } - + + const epvector evaled = evalchildren(); + if (unlikely(!evaled.empty())) { + // start over evaluating a new object + return dynallocate(std::move(evaled), overall_coeff); + } + size_t seq_size = seq.size(); if (overall_coeff.is_zero()) { // *(...,x;0) -> 0 @@ -501,7 +507,7 @@ ex mul::eval(int level) 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 @@ -555,9 +561,9 @@ ex mul::eval(int level) 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; @@ -578,7 +584,7 @@ ex mul::eval(int level) const ex mul::evalf(int level) const { if (level==1) - return mul(seq,overall_coeff); + return mul(seq, overall_coeff); if (level==-max_recursion_level) throw(std::runtime_error("max recursion level reached")); @@ -588,10 +594,9 @@ ex mul::evalf(int level) const --level; for (auto & it : seq) { - s.push_back(combine_ex_with_coeff_to_pair(it.rest.evalf(level), - it.coeff)); + s.push_back(expair(it.rest.evalf(level), it.coeff)); } - return mul(std::move(s), overall_coeff.evalf(level)); + return dynallocate(std::move(s), overall_coeff.evalf(level)); } void mul::find_real_imag(ex & rp, ex & ip) const @@ -799,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); goto retry1; } else { @@ -814,10 +819,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); } } } @@ -881,7 +886,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)); @@ -966,6 +971,12 @@ expair mul::split_ex_to_pair(const ex & e) const expair mul::combine_ex_with_coeff_to_pair(const ex & e, const ex & c) const { + GINAC_ASSERT(is_exactly_a(c)); + + // First, try a common shortcut: + if (is_exactly_a(e)) + return expair(e, c); + // to avoid duplication of power simplification rules, // we create a temporary power object // otherwise it would be hard to correctly evaluate @@ -973,12 +984,15 @@ expair mul::combine_ex_with_coeff_to_pair(const ex & e, 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, const ex & c) const { + GINAC_ASSERT(is_exactly_a(p.coeff)); + GINAC_ASSERT(is_exactly_a(c)); + // to avoid duplication of power simplification rules, // we create a temporary power object // otherwise it would be hard to correctly evaluate @@ -986,7 +1000,7 @@ expair mul::combine_pair_with_coeff_to_pair(const expair & p, 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 @@ -1064,20 +1078,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);