|
GiNaC
1.6.2
|
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