]> www.ginac.de Git - ginac.git/blobdiff - ginac/power.cpp
Make (a+b+c+...)^n work for huuuge terms.
[ginac.git] / ginac / power.cpp
index b2622d60e932410997b625bc8ac79e5be4e6541b..b9090f818e818cdc259a5753a4e1c16030b9b850 100644 (file)
@@ -571,7 +571,7 @@ ex power::eval(int level) const
                if (num_exponent->is_pos_integer() &&
                    ebasis.return_type() != return_types::commutative &&
                    !is_a<matrix>(ebasis)) {
-                       return ncmul(exvector(num_exponent->to_int(), ebasis), true);
+                       return ncmul(exvector(num_exponent->to_int(), ebasis));
                }
        }
        
@@ -775,7 +775,7 @@ ex power::derivative(const symbol & s) const
                newseq.reserve(2);
                newseq.push_back(expair(basis, exponent - _ex1));
                newseq.push_back(expair(basis.diff(s), _ex1));
-               return mul(newseq, exponent);
+               return mul(std::move(newseq), exponent);
        } else {
                // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b)
                return mul(*this,
@@ -849,9 +849,9 @@ ex power::expand(unsigned options) const
                // In either case we set a flag to avoid the second run on a part
                // which does not have positive/negative terms.
                if (prodseq.size() > 0) {
-                       ex newbasis = coeff*mul(powseq);
+                       ex newbasis = coeff*mul(std::move(powseq));
                        ex_to<basic>(newbasis).setflag(status_flags::purely_indefinite);
-                       return ((new mul(prodseq))->setflag(status_flags::dynallocated)*(new power(newbasis, exponent))->setflag(status_flags::dynallocated).expand(options)).expand(options);
+                       return ((new mul(std::move(prodseq)))->setflag(status_flags::dynallocated)*(new power(newbasis, exponent))->setflag(status_flags::dynallocated).expand(options)).expand(options);
                } else
                        ex_to<basic>(basis).setflag(status_flags::purely_indefinite);
        }
@@ -871,7 +871,7 @@ ex power::expand(unsigned options) const
                // Make sure that e.g. (x+y)^(2+a) expands the (x+y)^2 factor
                if (ex_to<numeric>(a.overall_coeff).is_integer()) {
                        const numeric &num_exponent = ex_to<numeric>(a.overall_coeff);
-                       int int_exponent = num_exponent.to_int();
+                       long int_exponent = num_exponent.to_int();
                        if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
                                distrseq.push_back(expand_add(ex_to<add>(expanded_basis), int_exponent, options));
                        else
@@ -895,7 +895,7 @@ ex power::expand(unsigned options) const
        
        // integer numeric exponent
        const numeric & num_exponent = ex_to<numeric>(expanded_exponent);
-       int int_exponent = num_exponent.to_int();
+       long int_exponent = num_exponent.to_long();
        
        // (x+y)^n, n>0
        if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
@@ -1091,7 +1091,7 @@ public:
  *  where n = p1+p2+...+pk, i.e. p is a partition of n.
  */
 const numeric
-multinomial_coefficient(const std::vector<int> p)
+multinomial_coefficient(const std::vector<int> p)
 {
        numeric n = 0, d = 1;
        for (auto & it : p) {
@@ -1105,7 +1105,7 @@ multinomial_coefficient(const std::vector<int> p)
 
 /** expand a^n where a is an add and n is a positive integer.
  *  @see power::expand */
-ex power::expand_add(const add & a, int n, unsigned options) const
+ex power::expand_add(const add & a, long n, unsigned options) const
 {
        // The special case power(+(x,...y;x),2) can be optimized better.
        if (n==2)
@@ -1167,7 +1167,7 @@ ex power::expand_add(const add & a, int n, unsigned options) const
        // i.e. the number of unordered arrangements of m nonnegative integers
        // which sum up to n.  It is frequently written as C_n(m) and directly
        // related with binomial coefficients: binomial(n+m-1,m-1).
-       size_t result_size = binomial(numeric(n+a.nops()-1), numeric(a.nops()-1)).to_int();
+       size_t result_size = binomial(numeric(n+a.nops()-1), numeric(a.nops()-1)).to_long();
        if (!a.overall_coeff.is_zero()) {
                // the result's overall_coeff is one of the terms
                --result_size;
@@ -1207,7 +1207,6 @@ ex power::expand_add(const add & a, int n, unsigned options) const
                                numeric factor = coeff;
                                for (unsigned i = 0; i < exponent.size(); ++i) {
                                        const ex & r = a.seq[i].rest;
-                                       const ex & c = a.seq[i].coeff;
                                        GINAC_ASSERT(!is_exactly_a<add>(r));
                                        GINAC_ASSERT(!is_exactly_a<power>(r) ||
                                                     !is_exactly_a<numeric>(ex_to<power>(r).exponent) ||
@@ -1215,15 +1214,19 @@ ex power::expand_add(const add & a, int n, unsigned options) const
                                                     !is_exactly_a<add>(ex_to<power>(r).basis) ||
                                                     !is_exactly_a<mul>(ex_to<power>(r).basis) ||
                                                     !is_exactly_a<power>(ex_to<power>(r).basis));
+                                       GINAC_ASSERT(is_exactly_a<numeric>(a.seq[i].coeff));
+                                       const numeric & c = ex_to<numeric>(a.seq[i].coeff);
                                        if (exponent[i] == 0) {
                                                // optimize away
                                        } else if (exponent[i] == 1) {
                                                // optimized
                                                term.push_back(r);
-                                               factor = factor.mul(ex_to<numeric>(c));
+                                               if (c != *_num1_p)
+                                                       factor = factor.mul(c);
                                        } else { // general case exponent[i] > 1
                                                term.push_back((new power(r, exponent[i]))->setflag(status_flags::dynallocated));
-                                               factor = factor.mul(ex_to<numeric>(c).power(exponent[i]));
+                                               if (c != *_num1_p)
+                                                       factor = factor.mul(c.power(exponent[i]));
                                        }
                                }
                                result.push_back(a.combine_ex_with_coeff_to_pair(mul(term).expand(options), factor));
@@ -1234,11 +1237,11 @@ ex power::expand_add(const add & a, int n, unsigned options) const
        GINAC_ASSERT(result.size() == result_size);
 
        if (a.overall_coeff.is_zero()) {
-               return (new add(result))->setflag(status_flags::dynallocated |
-                                                 status_flags::expanded);
+               return (new add(std::move(result)))->setflag(status_flags::dynallocated |
+                                                            status_flags::expanded);
        } else {
-               return (new add(result, ex_to<numeric>(a.overall_coeff).power(n)))->setflag(status_flags::dynallocated |
-                                                                                           status_flags::expanded);
+               return (new add(std::move(result), ex_to<numeric>(a.overall_coeff).power(n)))->setflag(status_flags::dynallocated |
+                                                                                                      status_flags::expanded);
        }
 }
 
@@ -1247,9 +1250,14 @@ ex power::expand_add(const add & a, int n, unsigned options) const
  *  @see power::expand_add */
 ex power::expand_add_2(const add & a, unsigned options) const
 {
-       epvector sum;
-       size_t a_nops = a.nops();
-       sum.reserve((a_nops*(a_nops+1))/2);
+       epvector result;
+       size_t result_size = (a.nops() * (a.nops()+1)) / 2;
+       if (!a.overall_coeff.is_zero()) {
+               // the result's overall_coeff is one of the terms
+               --result_size;
+       }
+       result.reserve(result_size);
+
        epvector::const_iterator last = a.seq.end();
 
        // power(+(x,...,z;c),2)=power(+(x,...,z;0),2)+2*c*+(x,...,z;0)+c*c
@@ -1268,45 +1276,45 @@ ex power::expand_add_2(const add & a, unsigned options) const
                
                if (c.is_equal(_ex1)) {
                        if (is_exactly_a<mul>(r)) {
-                               sum.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
-                                                                             _ex1));
+                               result.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
+                                                                                _ex1));
                        } else {
-                               sum.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
-                                                                             _ex1));
+                               result.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
+                                                                                _ex1));
                        }
                } else {
                        if (is_exactly_a<mul>(r)) {
-                               sum.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
-                                                    ex_to<numeric>(c).power_dyn(*_num2_p)));
+                               result.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
+                                                                                ex_to<numeric>(c).power_dyn(*_num2_p)));
                        } else {
-                               sum.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
-                                                    ex_to<numeric>(c).power_dyn(*_num2_p)));
+                               result.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
+                                                                                ex_to<numeric>(c).power_dyn(*_num2_p)));
                        }
                }
 
                for (epvector::const_iterator cit1=cit0+1; cit1!=last; ++cit1) {
                        const ex & r1 = cit1->rest;
                        const ex & c1 = cit1->coeff;
-                       sum.push_back(a.combine_ex_with_coeff_to_pair(mul(r,r1).expand(options),
-                                                                     _num2_p->mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
+                       result.push_back(a.combine_ex_with_coeff_to_pair(mul(r,r1).expand(options),
+                                                                        _num2_p->mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
                }
        }
        
-       GINAC_ASSERT(sum.size()==(a.seq.size()*(a.seq.size()+1))/2);
-       
        // second part: add terms coming from overall_coeff (if != 0)
        if (!a.overall_coeff.is_zero()) {
-               epvector::const_iterator i = a.seq.begin(), end = a.seq.end();
-               while (i != end) {
-                       sum.push_back(a.combine_pair_with_coeff_to_pair(*i, ex_to<numeric>(a.overall_coeff).mul_dyn(*_num2_p)));
-                       ++i;
-               }
-               sum.push_back(expair(ex_to<numeric>(a.overall_coeff).power_dyn(*_num2_p),_ex1));
+               for (auto & i : a.seq)
+                       result.push_back(a.combine_pair_with_coeff_to_pair(i, ex_to<numeric>(a.overall_coeff).mul_dyn(*_num2_p)));
+       }
+
+       GINAC_ASSERT(result.size() == result_size);
+
+       if (a.overall_coeff.is_zero()) {
+               return (new add(std::move(result)))->setflag(status_flags::dynallocated |
+                                                            status_flags::expanded);
+       } else {
+               return (new add(std::move(result), ex_to<numeric>(a.overall_coeff).power(2)))->setflag(status_flags::dynallocated |
+                                                                                                      status_flags::expanded);
        }
-       
-       GINAC_ASSERT(sum.size()==(a_nops*(a_nops+1))/2);
-       
-       return (new add(sum))->setflag(status_flags::dynallocated | status_flags::expanded);
 }
 
 /** Expand factors of m in m^n where m is a mul and n is an integer.