]> www.ginac.de Git - ginac.git/blobdiff - ginac/mul.cpp
Remove info_flags::algebraic.
[ginac.git] / ginac / mul.cpp
index 48d64787e164f0078212af441b72599ff1492e47..eef287cac8d3f090f13d7c82f8d830aa4b6a07b7 100644 (file)
@@ -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))
@@ -464,22 +464,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<mul>(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<mul>(std::move(evaled), overall_coeff);
+       }
+
        size_t seq_size = seq.size();
        if (overall_coeff.is_zero()) {
                // *(...,x;0) -> 0
@@ -501,7 +500,7 @@ ex mul::eval(int level) const
                        distrseq.push_back(addref.combine_pair_with_coeff_to_pair(it, overall_coeff));
                }
                return dynallocate<add>(std::move(distrseq),
-                                        ex_to<numeric>(addref.overall_coeff).mul_dyn(ex_to<numeric>(overall_coeff)))
+                                       ex_to<numeric>(addref.overall_coeff).mul_dyn(ex_to<numeric>(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 +554,9 @@ ex mul::eval(int level) const
                        add & primitive = dynallocate<add>(addref);
                        primitive.clearflag(status_flags::hash_calculated);
                        primitive.overall_coeff = ex_to<numeric>(primitive.overall_coeff).div_dyn(c);
-                       for (epvector::iterator ai = primitive.seq.begin(); ai != primitive.seq.end(); ++ai)
-                               ai->coeff = ex_to<numeric>(ai->coeff).div_dyn(c);
-                       
+                       for (auto & ai : primitive.seq)
+                               ai.coeff = ex_to<numeric>(ai.coeff).div_dyn(c);
+
                        s.push_back(expair(primitive, _ex1));
 
                        ++i;
@@ -578,7 +577,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 +587,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<mul>(std::move(s), overall_coeff.evalf(level));
 }
 
 void mul::find_real_imag(ex & rp, ex & ip) const
@@ -799,10 +797,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 +812,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 +879,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<mul>(mulseq, overall_coeff * i->coeff));
@@ -966,6 +964,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<numeric>(c));
+
+       // First, try a common shortcut:
+       if (is_exactly_a<symbol>(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 +977,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<numeric>(p.coeff));
+       GINAC_ASSERT(is_exactly_a<numeric>(c));
+
        // to avoid duplication of power simplification rules,
        // we create a temporary power object
        // otherwise it would be hard to correctly evaluate
@@ -986,7 +993,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 +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<symbol>(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<symbol>(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);