GiNaC  1.6.2
power.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include "power.h"
00024 #include "expairseq.h"
00025 #include "add.h"
00026 #include "mul.h"
00027 #include "ncmul.h"
00028 #include "numeric.h"
00029 #include "constant.h"
00030 #include "operators.h"
00031 #include "inifcns.h" // for log() in power::derivative()
00032 #include "matrix.h"
00033 #include "indexed.h"
00034 #include "symbol.h"
00035 #include "lst.h"
00036 #include "archive.h"
00037 #include "utils.h"
00038 #include "relational.h"
00039 #include "compiler.h"
00040 
00041 #include <iostream>
00042 #include <limits>
00043 #include <stdexcept>
00044 #include <vector>
00045 
00046 namespace GiNaC {
00047 
00048 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(power, basic,
00049   print_func<print_dflt>(&power::do_print_dflt).
00050   print_func<print_latex>(&power::do_print_latex).
00051   print_func<print_csrc>(&power::do_print_csrc).
00052   print_func<print_python>(&power::do_print_python).
00053   print_func<print_python_repr>(&power::do_print_python_repr).
00054   print_func<print_csrc_cl_N>(&power::do_print_csrc_cl_N))
00055 
00056 typedef std::vector<int> intvector;
00057 
00059 // default constructor
00061 
00062 power::power() { }
00063 
00065 // other constructors
00067 
00068 // all inlined
00069 
00071 // archiving
00073 
00074 void power::read_archive(const archive_node &n, lst &sym_lst)
00075 {
00076     inherited::read_archive(n, sym_lst);
00077     n.find_ex("basis", basis, sym_lst);
00078     n.find_ex("exponent", exponent, sym_lst);
00079 }
00080 
00081 void power::archive(archive_node &n) const
00082 {
00083     inherited::archive(n);
00084     n.add_ex("basis", basis);
00085     n.add_ex("exponent", exponent);
00086 }
00087 
00089 // functions overriding virtual functions from base classes
00091 
00092 // public
00093 
00094 void power::print_power(const print_context & c, const char *powersymbol, const char *openbrace, const char *closebrace, unsigned level) const
00095 {
00096     // Ordinary output of powers using '^' or '**'
00097     if (precedence() <= level)
00098         c.s << openbrace << '(';
00099     basis.print(c, precedence());
00100     c.s << powersymbol;
00101     c.s << openbrace;
00102     exponent.print(c, precedence());
00103     c.s << closebrace;
00104     if (precedence() <= level)
00105         c.s << ')' << closebrace;
00106 }
00107 
00108 void power::do_print_dflt(const print_dflt & c, unsigned level) const
00109 {
00110     if (exponent.is_equal(_ex1_2)) {
00111 
00112         // Square roots are printed in a special way
00113         c.s << "sqrt(";
00114         basis.print(c);
00115         c.s << ')';
00116 
00117     } else
00118         print_power(c, "^", "", "", level);
00119 }
00120 
00121 void power::do_print_latex(const print_latex & c, unsigned level) const
00122 {
00123     if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_negative()) {
00124 
00125         // Powers with negative numeric exponents are printed as fractions
00126         c.s << "\\frac{1}{";
00127         power(basis, -exponent).eval().print(c);
00128         c.s << '}';
00129 
00130     } else if (exponent.is_equal(_ex1_2)) {
00131 
00132         // Square roots are printed in a special way
00133         c.s << "\\sqrt{";
00134         basis.print(c);
00135         c.s << '}';
00136 
00137     } else
00138         print_power(c, "^", "{", "}", level);
00139 }
00140 
00141 static void print_sym_pow(const print_context & c, const symbol &x, int exp)
00142 {
00143     // Optimal output of integer powers of symbols to aid compiler CSE.
00144     // C.f. ISO/IEC 14882:1998, section 1.9 [intro execution], paragraph 15
00145     // to learn why such a parenthesation is really necessary.
00146     if (exp == 1) {
00147         x.print(c);
00148     } else if (exp == 2) {
00149         x.print(c);
00150         c.s << "*";
00151         x.print(c);
00152     } else if (exp & 1) {
00153         x.print(c);
00154         c.s << "*";
00155         print_sym_pow(c, x, exp-1);
00156     } else {
00157         c.s << "(";
00158         print_sym_pow(c, x, exp >> 1);
00159         c.s << ")*(";
00160         print_sym_pow(c, x, exp >> 1);
00161         c.s << ")";
00162     }
00163 }
00164 
00165 void power::do_print_csrc_cl_N(const print_csrc_cl_N& c, unsigned level) const
00166 {
00167     if (exponent.is_equal(_ex_1)) {
00168         c.s << "recip(";
00169         basis.print(c);
00170         c.s << ')';
00171         return;
00172     }
00173     c.s << "expt(";
00174     basis.print(c);
00175     c.s << ", ";
00176     exponent.print(c);
00177     c.s << ')';
00178 }
00179 
00180 void power::do_print_csrc(const print_csrc & c, unsigned level) const
00181 {
00182     // Integer powers of symbols are printed in a special, optimized way
00183     if (exponent.info(info_flags::integer)
00184      && (is_a<symbol>(basis) || is_a<constant>(basis))) {
00185         int exp = ex_to<numeric>(exponent).to_int();
00186         if (exp > 0)
00187             c.s << '(';
00188         else {
00189             exp = -exp;
00190             c.s << "1.0/(";
00191         }
00192         print_sym_pow(c, ex_to<symbol>(basis), exp);
00193         c.s << ')';
00194 
00195     // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
00196     } else if (exponent.is_equal(_ex_1)) {
00197         c.s << "1.0/(";
00198         basis.print(c);
00199         c.s << ')';
00200 
00201     // Otherwise, use the pow() function
00202     } else {
00203         c.s << "pow(";
00204         basis.print(c);
00205         c.s << ',';
00206         exponent.print(c);
00207         c.s << ')';
00208     }
00209 }
00210 
00211 void power::do_print_python(const print_python & c, unsigned level) const
00212 {
00213     print_power(c, "**", "", "", level);
00214 }
00215 
00216 void power::do_print_python_repr(const print_python_repr & c, unsigned level) const
00217 {
00218     c.s << class_name() << '(';
00219     basis.print(c);
00220     c.s << ',';
00221     exponent.print(c);
00222     c.s << ')';
00223 }
00224 
00225 bool power::info(unsigned inf) const
00226 {
00227     switch (inf) {
00228         case info_flags::polynomial:
00229         case info_flags::integer_polynomial:
00230         case info_flags::cinteger_polynomial:
00231         case info_flags::rational_polynomial:
00232         case info_flags::crational_polynomial:
00233             return exponent.info(info_flags::nonnegint) &&
00234                    basis.info(inf);
00235         case info_flags::rational_function:
00236             return exponent.info(info_flags::integer) &&
00237                    basis.info(inf);
00238         case info_flags::algebraic:
00239             return !exponent.info(info_flags::integer) ||
00240                    basis.info(inf);
00241         case info_flags::expanded:
00242             return (flags & status_flags::expanded);
00243         case info_flags::positive:
00244             return basis.info(info_flags::positive) && exponent.info(info_flags::real);
00245         case info_flags::has_indices: {
00246             if (flags & status_flags::has_indices)
00247                 return true;
00248             else if (flags & status_flags::has_no_indices)
00249                 return false;
00250             else if (basis.info(info_flags::has_indices)) {
00251                 setflag(status_flags::has_indices);
00252                 clearflag(status_flags::has_no_indices);
00253                 return true;
00254             } else {
00255                 clearflag(status_flags::has_indices);
00256                 setflag(status_flags::has_no_indices);
00257                 return false;
00258             }
00259         }
00260     }
00261     return inherited::info(inf);
00262 }
00263 
00264 size_t power::nops() const
00265 {
00266     return 2;
00267 }
00268 
00269 ex power::op(size_t i) const
00270 {
00271     GINAC_ASSERT(i<2);
00272 
00273     return i==0 ? basis : exponent;
00274 }
00275 
00276 ex power::map(map_function & f) const
00277 {
00278     const ex &mapped_basis = f(basis);
00279     const ex &mapped_exponent = f(exponent);
00280 
00281     if (!are_ex_trivially_equal(basis, mapped_basis)
00282      || !are_ex_trivially_equal(exponent, mapped_exponent))
00283         return (new power(mapped_basis, mapped_exponent))->setflag(status_flags::dynallocated);
00284     else
00285         return *this;
00286 }
00287 
00288 bool power::is_polynomial(const ex & var) const
00289 {
00290     if (exponent.has(var))
00291         return false;
00292     if (!exponent.info(info_flags::nonnegint))
00293         return false;
00294     return basis.is_polynomial(var);
00295 }
00296 
00297 int power::degree(const ex & s) const
00298 {
00299     if (is_equal(ex_to<basic>(s)))
00300         return 1;
00301     else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
00302         if (basis.is_equal(s))
00303             return ex_to<numeric>(exponent).to_int();
00304         else
00305             return basis.degree(s) * ex_to<numeric>(exponent).to_int();
00306     } else if (basis.has(s))
00307         throw(std::runtime_error("power::degree(): undefined degree because of non-integer exponent"));
00308     else
00309         return 0;
00310 }
00311 
00312 int power::ldegree(const ex & s) const 
00313 {
00314     if (is_equal(ex_to<basic>(s)))
00315         return 1;
00316     else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
00317         if (basis.is_equal(s))
00318             return ex_to<numeric>(exponent).to_int();
00319         else
00320             return basis.ldegree(s) * ex_to<numeric>(exponent).to_int();
00321     } else if (basis.has(s))
00322         throw(std::runtime_error("power::ldegree(): undefined degree because of non-integer exponent"));
00323     else
00324         return 0;
00325 }
00326 
00327 ex power::coeff(const ex & s, int n) const
00328 {
00329     if (is_equal(ex_to<basic>(s)))
00330         return n==1 ? _ex1 : _ex0;
00331     else if (!basis.is_equal(s)) {
00332         // basis not equal to s
00333         if (n == 0)
00334             return *this;
00335         else
00336             return _ex0;
00337     } else {
00338         // basis equal to s
00339         if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
00340             // integer exponent
00341             int int_exp = ex_to<numeric>(exponent).to_int();
00342             if (n == int_exp)
00343                 return _ex1;
00344             else
00345                 return _ex0;
00346         } else {
00347             // non-integer exponents are treated as zero
00348             if (n == 0)
00349                 return *this;
00350             else
00351                 return _ex0;
00352         }
00353     }
00354 }
00355 
00371 ex power::eval(int level) const
00372 {
00373     if ((level==1) && (flags & status_flags::evaluated))
00374         return *this;
00375     else if (level == -max_recursion_level)
00376         throw(std::runtime_error("max recursion level reached"));
00377     
00378     const ex & ebasis    = level==1 ? basis    : basis.eval(level-1);
00379     const ex & eexponent = level==1 ? exponent : exponent.eval(level-1);
00380     
00381     const numeric *num_basis = NULL;
00382     const numeric *num_exponent = NULL;
00383     
00384     if (is_exactly_a<numeric>(ebasis)) {
00385         num_basis = &ex_to<numeric>(ebasis);
00386     }
00387     if (is_exactly_a<numeric>(eexponent)) {
00388         num_exponent = &ex_to<numeric>(eexponent);
00389     }
00390     
00391     // ^(x,0) -> 1  (0^0 also handled here)
00392     if (eexponent.is_zero()) {
00393         if (ebasis.is_zero())
00394             throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
00395         else
00396             return _ex1;
00397     }
00398     
00399     // ^(x,1) -> x
00400     if (eexponent.is_equal(_ex1))
00401         return ebasis;
00402 
00403     // ^(0,c1) -> 0 or exception  (depending on real value of c1)
00404     if ( ebasis.is_zero() && num_exponent ) {
00405         if ((num_exponent->real()).is_zero())
00406             throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
00407         else if ((num_exponent->real()).is_negative())
00408             throw (pole_error("power::eval(): division by zero",1));
00409         else
00410             return _ex0;
00411     }
00412 
00413     // ^(1,x) -> 1
00414     if (ebasis.is_equal(_ex1))
00415         return _ex1;
00416 
00417     // power of a function calculated by separate rules defined for this function
00418     if (is_exactly_a<function>(ebasis))
00419         return ex_to<function>(ebasis).power(eexponent);
00420 
00421     // Turn (x^c)^d into x^(c*d) in the case that x is positive and c is real.
00422     if (is_exactly_a<power>(ebasis) && ebasis.op(0).info(info_flags::positive) && ebasis.op(1).info(info_flags::real))
00423         return power(ebasis.op(0), ebasis.op(1) * eexponent);
00424 
00425     if ( num_exponent ) {
00426 
00427         // ^(c1,c2) -> c1^c2  (c1, c2 numeric(),
00428         // except if c1,c2 are rational, but c1^c2 is not)
00429         if ( num_basis ) {
00430             const bool basis_is_crational = num_basis->is_crational();
00431             const bool exponent_is_crational = num_exponent->is_crational();
00432             if (!basis_is_crational || !exponent_is_crational) {
00433                 // return a plain float
00434                 return (new numeric(num_basis->power(*num_exponent)))->setflag(status_flags::dynallocated |
00435                                                                                status_flags::evaluated |
00436                                                                                status_flags::expanded);
00437             }
00438 
00439             const numeric res = num_basis->power(*num_exponent);
00440             if (res.is_crational()) {
00441                 return res;
00442             }
00443             GINAC_ASSERT(!num_exponent->is_integer());  // has been handled by now
00444 
00445             // ^(c1,n/m) -> *(c1^q,c1^(n/m-q)), 0<(n/m-q)<1, q integer
00446             if (basis_is_crational && exponent_is_crational
00447                 && num_exponent->is_real()
00448                 && !num_exponent->is_integer()) {
00449                 const numeric n = num_exponent->numer();
00450                 const numeric m = num_exponent->denom();
00451                 numeric r;
00452                 numeric q = iquo(n, m, r);
00453                 if (r.is_negative()) {
00454                     r += m;
00455                     --q;
00456                 }
00457                 if (q.is_zero()) {  // the exponent was in the allowed range 0<(n/m)<1
00458                     if (num_basis->is_rational() && !num_basis->is_integer()) {
00459                         // try it for numerator and denominator separately, in order to
00460                         // partially simplify things like (5/8)^(1/3) -> 1/2*5^(1/3)
00461                         const numeric bnum = num_basis->numer();
00462                         const numeric bden = num_basis->denom();
00463                         const numeric res_bnum = bnum.power(*num_exponent);
00464                         const numeric res_bden = bden.power(*num_exponent);
00465                         if (res_bnum.is_integer())
00466                             return (new mul(power(bden,-*num_exponent),res_bnum))->setflag(status_flags::dynallocated | status_flags::evaluated);
00467                         if (res_bden.is_integer())
00468                             return (new mul(power(bnum,*num_exponent),res_bden.inverse()))->setflag(status_flags::dynallocated | status_flags::evaluated);
00469                     }
00470                     return this->hold();
00471                 } else {
00472                     // assemble resulting product, but allowing for a re-evaluation,
00473                     // because otherwise we'll end up with something like
00474                     //    (7/8)^(4/3)  ->  7/8*(1/2*7^(1/3))
00475                     // instead of 7/16*7^(1/3).
00476                     ex prod = power(*num_basis,r.div(m));
00477                     return prod*power(*num_basis,q);
00478                 }
00479             }
00480         }
00481     
00482         // ^(^(x,c1),c2) -> ^(x,c1*c2)
00483         // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1,
00484         // case c1==1 should not happen, see below!)
00485         if (is_exactly_a<power>(ebasis)) {
00486             const power & sub_power = ex_to<power>(ebasis);
00487             const ex & sub_basis = sub_power.basis;
00488             const ex & sub_exponent = sub_power.exponent;
00489             if (is_exactly_a<numeric>(sub_exponent)) {
00490                 const numeric & num_sub_exponent = ex_to<numeric>(sub_exponent);
00491                 GINAC_ASSERT(num_sub_exponent!=numeric(1));
00492                 if (num_exponent->is_integer() || (abs(num_sub_exponent) - (*_num1_p)).is_negative()) {
00493                     return power(sub_basis,num_sub_exponent.mul(*num_exponent));
00494                 }
00495             }
00496         }
00497     
00498         // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
00499         if (num_exponent->is_integer() && is_exactly_a<mul>(ebasis)) {
00500             return expand_mul(ex_to<mul>(ebasis), *num_exponent, 0);
00501         }
00502 
00503         // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4)
00504         if (num_exponent->is_integer() && is_exactly_a<add>(ebasis)) {
00505             numeric icont = ebasis.integer_content();
00506             const numeric lead_coeff = 
00507                 ex_to<numeric>(ex_to<add>(ebasis).seq.begin()->coeff).div(icont);
00508 
00509             const bool canonicalizable = lead_coeff.is_integer();
00510             const bool unit_normal = lead_coeff.is_pos_integer();
00511             if (canonicalizable && (! unit_normal))
00512                 icont = icont.mul(*_num_1_p);
00513             
00514             if (canonicalizable && (icont != *_num1_p)) {
00515                 const add& addref = ex_to<add>(ebasis);
00516                 add* addp = new add(addref);
00517                 addp->setflag(status_flags::dynallocated);
00518                 addp->clearflag(status_flags::hash_calculated);
00519                 addp->overall_coeff = ex_to<numeric>(addp->overall_coeff).div_dyn(icont);
00520                 for (epvector::iterator i = addp->seq.begin(); i != addp->seq.end(); ++i)
00521                     i->coeff = ex_to<numeric>(i->coeff).div_dyn(icont);
00522 
00523                 const numeric c = icont.power(*num_exponent);
00524                 if (likely(c != *_num1_p))
00525                     return (new mul(power(*addp, *num_exponent), c))->setflag(status_flags::dynallocated);
00526                 else
00527                     return power(*addp, *num_exponent);
00528             }
00529         }
00530 
00531         // ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2)  (c1, c2 numeric(), c1>0)
00532         // ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2)  (c1, c2 numeric(), c1<0)
00533         if (is_exactly_a<mul>(ebasis)) {
00534             GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
00535             const mul & mulref = ex_to<mul>(ebasis);
00536             if (!mulref.overall_coeff.is_equal(_ex1)) {
00537                 const numeric & num_coeff = ex_to<numeric>(mulref.overall_coeff);
00538                 if (num_coeff.is_real()) {
00539                     if (num_coeff.is_positive()) {
00540                         mul *mulp = new mul(mulref);
00541                         mulp->overall_coeff = _ex1;
00542                         mulp->setflag(status_flags::dynallocated);
00543                         mulp->clearflag(status_flags::evaluated);
00544                         mulp->clearflag(status_flags::hash_calculated);
00545                         return (new mul(power(*mulp,exponent),
00546                                         power(num_coeff,*num_exponent)))->setflag(status_flags::dynallocated);
00547                     } else {
00548                         GINAC_ASSERT(num_coeff.compare(*_num0_p)<0);
00549                         if (!num_coeff.is_equal(*_num_1_p)) {
00550                             mul *mulp = new mul(mulref);
00551                             mulp->overall_coeff = _ex_1;
00552                             mulp->setflag(status_flags::dynallocated);
00553                             mulp->clearflag(status_flags::evaluated);
00554                             mulp->clearflag(status_flags::hash_calculated);
00555                             return (new mul(power(*mulp,exponent),
00556                                             power(abs(num_coeff),*num_exponent)))->setflag(status_flags::dynallocated);
00557                         }
00558                     }
00559                 }
00560             }
00561         }
00562 
00563         // ^(nc,c1) -> ncmul(nc,nc,...) (c1 positive integer, unless nc is a matrix)
00564         if (num_exponent->is_pos_integer() &&
00565             ebasis.return_type() != return_types::commutative &&
00566             !is_a<matrix>(ebasis)) {
00567             return ncmul(exvector(num_exponent->to_int(), ebasis), true);
00568         }
00569     }
00570     
00571     if (are_ex_trivially_equal(ebasis,basis) &&
00572         are_ex_trivially_equal(eexponent,exponent)) {
00573         return this->hold();
00574     }
00575     return (new power(ebasis, eexponent))->setflag(status_flags::dynallocated |
00576                                                    status_flags::evaluated);
00577 }
00578 
00579 ex power::evalf(int level) const
00580 {
00581     ex ebasis;
00582     ex eexponent;
00583     
00584     if (level==1) {
00585         ebasis = basis;
00586         eexponent = exponent;
00587     } else if (level == -max_recursion_level) {
00588         throw(std::runtime_error("max recursion level reached"));
00589     } else {
00590         ebasis = basis.evalf(level-1);
00591         if (!is_exactly_a<numeric>(exponent))
00592             eexponent = exponent.evalf(level-1);
00593         else
00594             eexponent = exponent;
00595     }
00596 
00597     return power(ebasis,eexponent);
00598 }
00599 
00600 ex power::evalm() const
00601 {
00602     const ex ebasis = basis.evalm();
00603     const ex eexponent = exponent.evalm();
00604     if (is_a<matrix>(ebasis)) {
00605         if (is_exactly_a<numeric>(eexponent)) {
00606             return (new matrix(ex_to<matrix>(ebasis).pow(eexponent)))->setflag(status_flags::dynallocated);
00607         }
00608     }
00609     return (new power(ebasis, eexponent))->setflag(status_flags::dynallocated);
00610 }
00611 
00612 bool power::has(const ex & other, unsigned options) const
00613 {
00614     if (!(options & has_options::algebraic))
00615         return basic::has(other, options);
00616     if (!is_a<power>(other))
00617         return basic::has(other, options);
00618     if (!exponent.info(info_flags::integer)
00619             || !other.op(1).info(info_flags::integer))
00620         return basic::has(other, options);
00621     if (exponent.info(info_flags::posint)
00622             && other.op(1).info(info_flags::posint)
00623             && ex_to<numeric>(exponent).to_int()
00624                     > ex_to<numeric>(other.op(1)).to_int()
00625             && basis.match(other.op(0)))
00626         return true;
00627     if (exponent.info(info_flags::negint)
00628             && other.op(1).info(info_flags::negint)
00629             && ex_to<numeric>(exponent).to_int()
00630                     < ex_to<numeric>(other.op(1)).to_int()
00631             && basis.match(other.op(0)))
00632         return true;
00633     return basic::has(other, options);
00634 }
00635 
00636 // from mul.cpp
00637 extern bool tryfactsubs(const ex &, const ex &, int &, exmap&);
00638 
00639 ex power::subs(const exmap & m, unsigned options) const
00640 {   
00641     const ex &subsed_basis = basis.subs(m, options);
00642     const ex &subsed_exponent = exponent.subs(m, options);
00643 
00644     if (!are_ex_trivially_equal(basis, subsed_basis)
00645      || !are_ex_trivially_equal(exponent, subsed_exponent)) 
00646         return power(subsed_basis, subsed_exponent).subs_one_level(m, options);
00647 
00648     if (!(options & subs_options::algebraic))
00649         return subs_one_level(m, options);
00650 
00651     for (exmap::const_iterator it = m.begin(); it != m.end(); ++it) {
00652         int nummatches = std::numeric_limits<int>::max();
00653         exmap repls;
00654         if (tryfactsubs(*this, it->first, nummatches, repls)) {
00655             ex anum = it->second.subs(repls, subs_options::no_pattern);
00656             ex aden = it->first.subs(repls, subs_options::no_pattern);
00657             ex result = (*this)*power(anum/aden, nummatches);
00658             return (ex_to<basic>(result)).subs_one_level(m, options);
00659         }
00660     }
00661 
00662     return subs_one_level(m, options);
00663 }
00664 
00665 ex power::eval_ncmul(const exvector & v) const
00666 {
00667     return inherited::eval_ncmul(v);
00668 }
00669 
00670 ex power::conjugate() const
00671 {
00672     // conjugate(pow(x,y))==pow(conjugate(x),conjugate(y)) unless on the
00673     // branch cut which runs along the negative real axis.
00674     if (basis.info(info_flags::positive)) {
00675         ex newexponent = exponent.conjugate();
00676         if (are_ex_trivially_equal(exponent, newexponent)) {
00677             return *this;
00678         }
00679         return (new power(basis, newexponent))->setflag(status_flags::dynallocated);
00680     }
00681     if (exponent.info(info_flags::integer)) {
00682         ex newbasis = basis.conjugate();
00683         if (are_ex_trivially_equal(basis, newbasis)) {
00684             return *this;
00685         }
00686         return (new power(newbasis, exponent))->setflag(status_flags::dynallocated);
00687     }
00688     return conjugate_function(*this).hold();
00689 }
00690 
00691 ex power::real_part() const
00692 {
00693     if (exponent.info(info_flags::integer)) {
00694         ex basis_real = basis.real_part();
00695         if (basis_real == basis)
00696             return *this;
00697         realsymbol a("a"),b("b");
00698         ex result;
00699         if (exponent.info(info_flags::posint))
00700             result = power(a+I*b,exponent);
00701         else
00702             result = power(a/(a*a+b*b)-I*b/(a*a+b*b),-exponent);
00703         result = result.expand();
00704         result = result.real_part();
00705         result = result.subs(lst( a==basis_real, b==basis.imag_part() ));
00706         return result;
00707     }
00708     
00709     ex a = basis.real_part();
00710     ex b = basis.imag_part();
00711     ex c = exponent.real_part();
00712     ex d = exponent.imag_part();
00713     return power(abs(basis),c)*exp(-d*atan2(b,a))*cos(c*atan2(b,a)+d*log(abs(basis)));
00714 }
00715 
00716 ex power::imag_part() const
00717 {
00718     if (exponent.info(info_flags::integer)) {
00719         ex basis_real = basis.real_part();
00720         if (basis_real == basis)
00721             return 0;
00722         realsymbol a("a"),b("b");
00723         ex result;
00724         if (exponent.info(info_flags::posint))
00725             result = power(a+I*b,exponent);
00726         else
00727             result = power(a/(a*a+b*b)-I*b/(a*a+b*b),-exponent);
00728         result = result.expand();
00729         result = result.imag_part();
00730         result = result.subs(lst( a==basis_real, b==basis.imag_part() ));
00731         return result;
00732     }
00733     
00734     ex a=basis.real_part();
00735     ex b=basis.imag_part();
00736     ex c=exponent.real_part();
00737     ex d=exponent.imag_part();
00738     return power(abs(basis),c)*exp(-d*atan2(b,a))*sin(c*atan2(b,a)+d*log(abs(basis)));
00739 }
00740 
00741 // protected
00742 
00743 // protected
00744 
00747 ex power::derivative(const symbol & s) const
00748 {
00749     if (is_a<numeric>(exponent)) {
00750         // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below)
00751         epvector newseq;
00752         newseq.reserve(2);
00753         newseq.push_back(expair(basis, exponent - _ex1));
00754         newseq.push_back(expair(basis.diff(s), _ex1));
00755         return mul(newseq, exponent);
00756     } else {
00757         // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b)
00758         return mul(*this,
00759                    add(mul(exponent.diff(s), log(basis)),
00760                    mul(mul(exponent, basis.diff(s)), power(basis, _ex_1))));
00761     }
00762 }
00763 
00764 int power::compare_same_type(const basic & other) const
00765 {
00766     GINAC_ASSERT(is_exactly_a<power>(other));
00767     const power &o = static_cast<const power &>(other);
00768 
00769     int cmpval = basis.compare(o.basis);
00770     if (cmpval)
00771         return cmpval;
00772     else
00773         return exponent.compare(o.exponent);
00774 }
00775 
00776 unsigned power::return_type() const
00777 {
00778     return basis.return_type();
00779 }
00780 
00781 return_type_t power::return_type_tinfo() const
00782 {
00783     return basis.return_type_tinfo();
00784 }
00785 
00786 ex power::expand(unsigned options) const
00787 {
00788     if (is_a<symbol>(basis) && exponent.info(info_flags::integer)) {
00789         // A special case worth optimizing.
00790         setflag(status_flags::expanded);
00791         return *this;
00792     }
00793 
00794     const ex expanded_basis = basis.expand(options);
00795     const ex expanded_exponent = exponent.expand(options);
00796     
00797     // x^(a+b) -> x^a * x^b
00798     if (is_exactly_a<add>(expanded_exponent)) {
00799         const add &a = ex_to<add>(expanded_exponent);
00800         exvector distrseq;
00801         distrseq.reserve(a.seq.size() + 1);
00802         epvector::const_iterator last = a.seq.end();
00803         epvector::const_iterator cit = a.seq.begin();
00804         while (cit!=last) {
00805             distrseq.push_back(power(expanded_basis, a.recombine_pair_to_ex(*cit)));
00806             ++cit;
00807         }
00808         
00809         // Make sure that e.g. (x+y)^(2+a) expands the (x+y)^2 factor
00810         if (ex_to<numeric>(a.overall_coeff).is_integer()) {
00811             const numeric &num_exponent = ex_to<numeric>(a.overall_coeff);
00812             int int_exponent = num_exponent.to_int();
00813             if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
00814                 distrseq.push_back(expand_add(ex_to<add>(expanded_basis), int_exponent, options));
00815             else
00816                 distrseq.push_back(power(expanded_basis, a.overall_coeff));
00817         } else
00818             distrseq.push_back(power(expanded_basis, a.overall_coeff));
00819         
00820         // Make sure that e.g. (x+y)^(1+a) -> x*(x+y)^a + y*(x+y)^a
00821         ex r = (new mul(distrseq))->setflag(status_flags::dynallocated);
00822         return r.expand(options);
00823     }
00824     
00825     if (!is_exactly_a<numeric>(expanded_exponent) ||
00826         !ex_to<numeric>(expanded_exponent).is_integer()) {
00827         if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) {
00828             return this->hold();
00829         } else {
00830             return (new power(expanded_basis,expanded_exponent))->setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
00831         }
00832     }
00833     
00834     // integer numeric exponent
00835     const numeric & num_exponent = ex_to<numeric>(expanded_exponent);
00836     int int_exponent = num_exponent.to_int();
00837     
00838     // (x+y)^n, n>0
00839     if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
00840         return expand_add(ex_to<add>(expanded_basis), int_exponent, options);
00841     
00842     // (x*y)^n -> x^n * y^n
00843     if (is_exactly_a<mul>(expanded_basis))
00844         return expand_mul(ex_to<mul>(expanded_basis), num_exponent, options, true);
00845     
00846     // cannot expand further
00847     if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent))
00848         return this->hold();
00849     else
00850         return (new power(expanded_basis,expanded_exponent))->setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
00851 }
00852 
00854 // new virtual functions which can be overridden by derived classes
00856 
00857 // none
00858 
00860 // non-virtual functions in this class
00862 
00865 ex power::expand_add(const add & a, int n, unsigned options) const
00866 {
00867     if (n==2)
00868         return expand_add_2(a, options);
00869 
00870     const size_t m = a.nops();
00871     exvector result;
00872     // The number of terms will be the number of combinatorial compositions,
00873     // i.e. the number of unordered arrangements of m nonnegative integers
00874     // which sum up to n.  It is frequently written as C_n(m) and directly
00875     // related with binomial coefficients:
00876     result.reserve(binomial(numeric(n+m-1), numeric(m-1)).to_int());
00877     intvector k(m-1);
00878     intvector k_cum(m-1); // k_cum[l]:=sum(i=0,l,k[l]);
00879     intvector upper_limit(m-1);
00880 
00881     for (size_t l=0; l<m-1; ++l) {
00882         k[l] = 0;
00883         k_cum[l] = 0;
00884         upper_limit[l] = n;
00885     }
00886 
00887     while (true) {
00888         exvector term;
00889         term.reserve(m+1);
00890         for (std::size_t l = 0; l < m - 1; ++l) {
00891             const ex & b = a.op(l);
00892             GINAC_ASSERT(!is_exactly_a<add>(b));
00893             GINAC_ASSERT(!is_exactly_a<power>(b) ||
00894                          !is_exactly_a<numeric>(ex_to<power>(b).exponent) ||
00895                          !ex_to<numeric>(ex_to<power>(b).exponent).is_pos_integer() ||
00896                          !is_exactly_a<add>(ex_to<power>(b).basis) ||
00897                          !is_exactly_a<mul>(ex_to<power>(b).basis) ||
00898                          !is_exactly_a<power>(ex_to<power>(b).basis));
00899             if (is_exactly_a<mul>(b))
00900                 term.push_back(expand_mul(ex_to<mul>(b), numeric(k[l]), options, true));
00901             else
00902                 term.push_back(power(b,k[l]));
00903         }
00904 
00905         const ex & b = a.op(m - 1);
00906         GINAC_ASSERT(!is_exactly_a<add>(b));
00907         GINAC_ASSERT(!is_exactly_a<power>(b) ||
00908                      !is_exactly_a<numeric>(ex_to<power>(b).exponent) ||
00909                      !ex_to<numeric>(ex_to<power>(b).exponent).is_pos_integer() ||
00910                      !is_exactly_a<add>(ex_to<power>(b).basis) ||
00911                      !is_exactly_a<mul>(ex_to<power>(b).basis) ||
00912                      !is_exactly_a<power>(ex_to<power>(b).basis));
00913         if (is_exactly_a<mul>(b))
00914             term.push_back(expand_mul(ex_to<mul>(b), numeric(n-k_cum[m-2]), options, true));
00915         else
00916             term.push_back(power(b,n-k_cum[m-2]));
00917 
00918         numeric f = binomial(numeric(n),numeric(k[0]));
00919         for (std::size_t l = 1; l < m - 1; ++l)
00920             f *= binomial(numeric(n-k_cum[l-1]),numeric(k[l]));
00921 
00922         term.push_back(f);
00923 
00924         result.push_back(ex((new mul(term))->setflag(status_flags::dynallocated)).expand(options));
00925 
00926         // increment k[]
00927         bool done = false;
00928         std::size_t l = m - 2;
00929         while ((++k[l]) > upper_limit[l]) {
00930             k[l] = 0;
00931             if (l != 0)
00932                 --l;
00933             else {
00934                 done = true;
00935                 break;
00936             }
00937         }
00938         if (done)
00939             break;
00940 
00941         // recalc k_cum[] and upper_limit[]
00942         k_cum[l] = (l==0 ? k[0] : k_cum[l-1]+k[l]);
00943 
00944         for (size_t i=l+1; i<m-1; ++i)
00945             k_cum[i] = k_cum[i-1]+k[i];
00946 
00947         for (size_t i=l+1; i<m-1; ++i)
00948             upper_limit[i] = n-k_cum[i-1];
00949     }
00950 
00951     return (new add(result))->setflag(status_flags::dynallocated |
00952                                       status_flags::expanded);
00953 }
00954 
00955 
00958 ex power::expand_add_2(const add & a, unsigned options) const
00959 {
00960     epvector sum;
00961     size_t a_nops = a.nops();
00962     sum.reserve((a_nops*(a_nops+1))/2);
00963     epvector::const_iterator last = a.seq.end();
00964 
00965     // power(+(x,...,z;c),2)=power(+(x,...,z;0),2)+2*c*+(x,...,z;0)+c*c
00966     // first part: ignore overall_coeff and expand other terms
00967     for (epvector::const_iterator cit0=a.seq.begin(); cit0!=last; ++cit0) {
00968         const ex & r = cit0->rest;
00969         const ex & c = cit0->coeff;
00970         
00971         GINAC_ASSERT(!is_exactly_a<add>(r));
00972         GINAC_ASSERT(!is_exactly_a<power>(r) ||
00973                      !is_exactly_a<numeric>(ex_to<power>(r).exponent) ||
00974                      !ex_to<numeric>(ex_to<power>(r).exponent).is_pos_integer() ||
00975                      !is_exactly_a<add>(ex_to<power>(r).basis) ||
00976                      !is_exactly_a<mul>(ex_to<power>(r).basis) ||
00977                      !is_exactly_a<power>(ex_to<power>(r).basis));
00978         
00979         if (c.is_equal(_ex1)) {
00980             if (is_exactly_a<mul>(r)) {
00981                 sum.push_back(expair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
00982                                      _ex1));
00983             } else {
00984                 sum.push_back(expair((new power(r,_ex2))->setflag(status_flags::dynallocated),
00985                                      _ex1));
00986             }
00987         } else {
00988             if (is_exactly_a<mul>(r)) {
00989                 sum.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
00990                                      ex_to<numeric>(c).power_dyn(*_num2_p)));
00991             } else {
00992                 sum.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
00993                                      ex_to<numeric>(c).power_dyn(*_num2_p)));
00994             }
00995         }
00996 
00997         for (epvector::const_iterator cit1=cit0+1; cit1!=last; ++cit1) {
00998             const ex & r1 = cit1->rest;
00999             const ex & c1 = cit1->coeff;
01000             sum.push_back(a.combine_ex_with_coeff_to_pair((new mul(r,r1))->setflag(status_flags::dynallocated),
01001                                                           _num2_p->mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
01002         }
01003     }
01004     
01005     GINAC_ASSERT(sum.size()==(a.seq.size()*(a.seq.size()+1))/2);
01006     
01007     // second part: add terms coming from overall_factor (if != 0)
01008     if (!a.overall_coeff.is_zero()) {
01009         epvector::const_iterator i = a.seq.begin(), end = a.seq.end();
01010         while (i != end) {
01011             sum.push_back(a.combine_pair_with_coeff_to_pair(*i, ex_to<numeric>(a.overall_coeff).mul_dyn(*_num2_p)));
01012             ++i;
01013         }
01014         sum.push_back(expair(ex_to<numeric>(a.overall_coeff).power_dyn(*_num2_p),_ex1));
01015     }
01016     
01017     GINAC_ASSERT(sum.size()==(a_nops*(a_nops+1))/2);
01018     
01019     return (new add(sum))->setflag(status_flags::dynallocated | status_flags::expanded);
01020 }
01021 
01024 ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool from_expand) const
01025 {
01026     GINAC_ASSERT(n.is_integer());
01027 
01028     if (n.is_zero()) {
01029         return _ex1;
01030     }
01031 
01032     // do not bother to rename indices if there are no any.
01033     if ((!(options & expand_options::expand_rename_idx)) 
01034             && m.info(info_flags::has_indices))
01035         options |= expand_options::expand_rename_idx;
01036     // Leave it to multiplication since dummy indices have to be renamed
01037     if ((options & expand_options::expand_rename_idx) &&
01038         (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
01039         ex result = m;
01040         exvector va = get_all_dummy_indices(m);
01041         sort(va.begin(), va.end(), ex_is_less());
01042 
01043         for (int i=1; i < n.to_int(); i++)
01044             result *= rename_dummy_indices_uniquely(va, m);
01045         return result;
01046     }
01047 
01048     epvector distrseq;
01049     distrseq.reserve(m.seq.size());
01050     bool need_reexpand = false;
01051 
01052     epvector::const_iterator last = m.seq.end();
01053     epvector::const_iterator cit = m.seq.begin();
01054     while (cit!=last) {
01055         expair p = m.combine_pair_with_coeff_to_pair(*cit, n);
01056         if (from_expand && is_exactly_a<add>(cit->rest) && ex_to<numeric>(p.coeff).is_pos_integer()) {
01057             // this happens when e.g. (a+b)^(1/2) gets squared and
01058             // the resulting product needs to be reexpanded
01059             need_reexpand = true;
01060         }
01061         distrseq.push_back(p);
01062         ++cit;
01063     }
01064 
01065     const mul & result = static_cast<const mul &>((new mul(distrseq, ex_to<numeric>(m.overall_coeff).power_dyn(n)))->setflag(status_flags::dynallocated));
01066     if (need_reexpand)
01067         return ex(result).expand(options);
01068     if (from_expand)
01069         return result.setflag(status_flags::expanded);
01070     return result;
01071 }
01072 
01073 GINAC_BIND_UNARCHIVER(power);
01074 
01075 } // namespace GiNaC

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.