From c814fb2991fc9d44c7466da5bbf20e58c0f4238f Mon Sep 17 00:00:00 2001 From: Vladimir Kisil Date: Tue, 14 Apr 2015 23:14:09 +0200 Subject: [PATCH] Make power::expand() (x*p)^c -> x^c * p^c, if p>0. This expansion seems to be helpful in many cases. --- check/exam_powerlaws.cpp | 32 ++++++++++++++++++++++++++++ ginac/power.cpp | 45 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/check/exam_powerlaws.cpp b/check/exam_powerlaws.cpp index 0903c4e1..b8176035 100644 --- a/check/exam_powerlaws.cpp +++ b/check/exam_powerlaws.cpp @@ -288,6 +288,37 @@ static unsigned exam_powerlaws5() return 0; } +static unsigned exam_powerlaws6() +{ + // check expansion rules for positive symbols + + symbol a("a"); + symbol b("b"); + symbol c("c"); + realsymbol x("x"); + realsymbol y("y"); + possymbol p("p"); + possymbol q("q"); + numeric half=numeric(1,2); + + ex e1 = pow(5*pow(3*a*b*x*y*p*q,2),7*half*c).expand(); + ex e2 = pow(p,7*c)*pow(q,7*c)*pow(pow(a*b*x*y,2),numeric(7,2)*c)*pow(45,numeric(7,2)*c); + if (!e1.is_equal(e2)) { + clog << "Could not expand exponents with positive bases in " << e1 << endl; + return 1; + } + + ex e3 = pow(-pow(-a*x*p,3)*pow(b*y*p,3),half*c).expand().normal(); + ex e4 = pow(p,3*c)*pow(pow(a*b*x*y,3),half*c); + + if (!e3.is_equal(e4)) { + clog << "Could not expand exponents with positive bases in " << e3 << endl; + return 1; + } + + return 0; +} + unsigned exam_powerlaws() { unsigned result = 0; @@ -299,6 +330,7 @@ unsigned exam_powerlaws() result += exam_powerlaws3(); cout << '.' << flush; result += exam_powerlaws4(); cout << '.' << flush; result += exam_powerlaws5(); cout << '.' << flush; + result += exam_powerlaws6(); cout << '.' << flush; return result; } diff --git a/ginac/power.cpp b/ginac/power.cpp index 6d6f81da..82200d7a 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -799,6 +799,51 @@ ex power::expand(unsigned options) const return *this; } + // (x*p)^c -> x^c * p^c, if p>0 + // makes sense before expanding the basis + if (is_exactly_a(basis) && !basis.info(info_flags::indefinite)) { + const mul &m = ex_to(basis); + exvector prodseq; + epvector powseq; + prodseq.reserve(m.seq.size() + 1); + powseq.reserve(m.seq.size() + 1); + epvector::const_iterator last = m.seq.end(); + epvector::const_iterator cit = m.seq.begin(); + bool possign = true; + + // search for positive/negative factors + while (cit!=last) { + ex e=m.recombine_pair_to_ex(*cit); + if (e.info(info_flags::positive)) + prodseq.push_back(pow(e, exponent).expand(options)); + else if (e.info(info_flags::negative)) { + prodseq.push_back(pow(-e, exponent).expand(options)); + possign = !possign; + } else + powseq.push_back(*cit); + ++cit; + } + + // take care on the numeric coefficient + ex coeff=(possign? _ex1 : _ex_1); + if (m.overall_coeff.info(info_flags::positive) && m.overall_coeff != _ex1) + prodseq.push_back(power(m.overall_coeff, exponent)); + else if (m.overall_coeff.info(info_flags::negative) && m.overall_coeff != _ex_1) + prodseq.push_back(power(-m.overall_coeff, exponent)); + else + coeff *= m.overall_coeff; + + // If positive/negative factors are found, then extract them. + // 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_to(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); + } else + ex_to(basis).setflag(status_flags::purely_indefinite); + } + const ex expanded_basis = basis.expand(options); const ex expanded_exponent = exponent.expand(options); -- 2.44.0