GiNaC 1.8.10
power.cpp
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2026 Johannes Gutenberg University Mainz, Germany
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "power.h"
23#include "expairseq.h"
24#include "add.h"
25#include "mul.h"
26#include "ncmul.h"
27#include "numeric.h"
28#include "constant.h"
29#include "operators.h"
30#include "inifcns.h" // for log() in power::derivative()
31#include "matrix.h"
32#include "indexed.h"
33#include "symbol.h"
34#include "lst.h"
35#include "archive.h"
36#include "utils.h"
37#include "relational.h"
38#include "compiler.h"
39
40#include <limits>
41#include <stdexcept>
42#include <vector>
43#include <algorithm>
44
45namespace GiNaC {
46
49 print_func<print_latex>(&power::do_print_latex).
50 print_func<print_csrc>(&power::do_print_csrc).
51 print_func<print_python>(&power::do_print_python).
52 print_func<print_python_repr>(&power::do_print_python_repr).
53 print_func<print_csrc_cl_N>(&power::do_print_csrc_cl_N))
54
55
56// default constructor
58
59power::power() { }
60
62// other constructors
64
65// all inlined
66
68// archiving
70
71void power::read_archive(const archive_node &n, lst &sym_lst)
72{
73 inherited::read_archive(n, sym_lst);
74 n.find_ex("basis", basis, sym_lst);
75 n.find_ex("exponent", exponent, sym_lst);
76}
77
79{
80 inherited::archive(n);
81 n.add_ex("basis", basis);
82 n.add_ex("exponent", exponent);
83}
84
86// functions overriding virtual functions from base classes
88
89// public
90
91void power::print_power(const print_context & c, const char *powersymbol, const char *openbrace, const char *closebrace, unsigned level) const
92{
93 // Ordinary output of powers using '^' or '**'
94 if (precedence() <= level)
95 c.s << openbrace << '(';
97 c.s << powersymbol;
98 c.s << openbrace;
100 c.s << closebrace;
101 if (precedence() <= level)
102 c.s << ')' << closebrace;
103}
104
105void power::do_print_dflt(const print_dflt & c, unsigned level) const
106{
107 if (exponent.is_equal(_ex1_2)) {
108
109 // Square roots are printed in a special way
110 c.s << "sqrt(";
111 basis.print(c);
112 c.s << ')';
113
114 } else
115 print_power(c, "^", "", "", level);
116}
117
118void power::do_print_latex(const print_latex & c, unsigned level) const
119{
120 if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_negative()) {
121
122 // Powers with negative numeric exponents are printed as fractions
123 c.s << "\\frac{1}{";
125 c.s << '}';
126
127 } else if (exponent.is_equal(_ex1_2)) {
128
129 // Square roots are printed in a special way
130 c.s << "\\sqrt{";
131 basis.print(c);
132 c.s << '}';
133
134 } else
135 print_power(c, "^", "{", "}", level);
136}
137
138static void print_sym_pow(const print_context & c, const symbol &x, int exp)
139{
140 // Optimal output of integer powers of symbols to aid compiler CSE.
141 // C.f. ISO/IEC 14882:2011, section 1.9 [intro.execution], paragraph 15
142 // to learn why such a parenthesation is really necessary.
143 if (exp == 1) {
144 x.print(c);
145 } else if (exp == 2) {
146 x.print(c);
147 c.s << "*";
148 x.print(c);
149 } else if (exp & 1) {
150 x.print(c);
151 c.s << "*";
152 print_sym_pow(c, x, exp-1);
153 } else {
154 c.s << "(";
155 print_sym_pow(c, x, exp >> 1);
156 c.s << ")*(";
157 print_sym_pow(c, x, exp >> 1);
158 c.s << ")";
159 }
160}
161
162void power::do_print_csrc_cl_N(const print_csrc_cl_N& c, unsigned level) const
163{
164 if (exponent.is_equal(_ex_1)) {
165 c.s << "recip(";
166 basis.print(c);
167 c.s << ')';
168 return;
169 }
170 c.s << "expt(";
171 basis.print(c);
172 c.s << ", ";
174 c.s << ')';
175}
176
177void power::do_print_csrc(const print_csrc & c, unsigned level) const
178{
179 // Integer powers of symbols are printed in a special, optimized way
181 (is_a<symbol>(basis) || is_a<constant>(basis))) {
182 int exp = ex_to<numeric>(exponent).to_int();
183 if (exp > 0)
184 c.s << '(';
185 else {
186 exp = -exp;
187 c.s << "1.0/(";
188 }
189 print_sym_pow(c, ex_to<symbol>(basis), exp);
190 c.s << ')';
191
192 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
193 } else if (exponent.is_equal(_ex_1)) {
194 c.s << "1.0/(";
195 basis.print(c);
196 c.s << ')';
197
198 // Otherwise, use the pow() function
199 } else {
200 c.s << "pow(";
201 basis.print(c);
202 c.s << ',';
204 c.s << ')';
205 }
206}
207
208void power::do_print_python(const print_python & c, unsigned level) const
209{
210 print_power(c, "**", "", "", level);
211}
212
213void power::do_print_python_repr(const print_python_repr & c, unsigned level) const
214{
215 c.s << class_name() << '(';
216 basis.print(c);
217 c.s << ',';
219 c.s << ')';
220}
221
260
261size_t power::nops() const
262{
263 return 2;
264}
265
266ex power::op(size_t i) const
267{
268 GINAC_ASSERT(i<2);
269
270 return i==0 ? basis : exponent;
271}
272
274{
275 const ex &mapped_basis = f(basis);
276 const ex &mapped_exponent = f(exponent);
277
278 if (!are_ex_trivially_equal(basis, mapped_basis)
279 || !are_ex_trivially_equal(exponent, mapped_exponent))
280 return dynallocate<power>(mapped_basis, mapped_exponent);
281 else
282 return *this;
283}
284
285bool power::is_polynomial(const ex & var) const
286{
287 if (basis.is_polynomial(var)) {
288 if (basis.has(var))
289 // basis is non-constant polynomial in var
291 else
292 // basis is constant in var
293 return !exponent.has(var);
294 }
295 // basis is a non-polynomial function of var
296 return false;
297}
298
299int power::degree(const ex & s) const
300{
301 if (is_equal(ex_to<basic>(s)))
302 return 1;
303 else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
304 if (basis.is_equal(s))
305 return ex_to<numeric>(exponent).to_int();
306 else
307 return basis.degree(s) * ex_to<numeric>(exponent).to_int();
308 } else if (basis.has(s))
309 throw(std::runtime_error("power::degree(): undefined degree because of non-integer exponent"));
310 else
311 return 0;
312}
313
314int power::ldegree(const ex & s) const
315{
316 if (is_equal(ex_to<basic>(s)))
317 return 1;
318 else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
319 if (basis.is_equal(s))
320 return ex_to<numeric>(exponent).to_int();
321 else
322 return basis.ldegree(s) * ex_to<numeric>(exponent).to_int();
323 } else if (basis.has(s))
324 throw(std::runtime_error("power::ldegree(): undefined degree because of non-integer exponent"));
325 else
326 return 0;
327}
328
329ex power::coeff(const ex & s, int n) const
330{
331 if (is_equal(ex_to<basic>(s)))
332 return n==1 ? _ex1 : _ex0;
333 else if (!basis.is_equal(s)) {
334 // basis not equal to s
335 if (n == 0)
336 return *this;
337 else
338 return _ex0;
339 } else {
340 // basis equal to s
341 if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
342 // integer exponent
343 int int_exp = ex_to<numeric>(exponent).to_int();
344 if (n == int_exp)
345 return _ex1;
346 else
347 return _ex0;
348 } else {
349 // non-integer exponents are treated as zero
350 if (n == 0)
351 return *this;
352 else
353 return _ex0;
354 }
355 }
356}
357
373{
375 return *this;
376
377 const numeric *num_basis = nullptr;
378 const numeric *num_exponent = nullptr;
379
380 if (is_exactly_a<numeric>(basis)) {
381 num_basis = &ex_to<numeric>(basis);
382 }
383 if (is_exactly_a<numeric>(exponent)) {
384 num_exponent = &ex_to<numeric>(exponent);
385 }
386
387 // ^(x,0) -> 1 (0^0 also handled here)
388 if (exponent.is_zero()) {
389 if (basis.is_zero())
390 throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
391 else
392 return _ex1;
393 }
394
395 // ^(x,1) -> x
397 return basis;
398
399 // ^(0,c1) -> 0 or exception (depending on real value of c1)
400 if (basis.is_zero() && num_exponent) {
401 if ((num_exponent->real()).is_zero())
402 throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
403 else if ((num_exponent->real()).is_negative())
404 throw (pole_error("power::eval(): division by zero",1));
405 else
406 return _ex0;
407 }
408
409 // ^(1,x) -> 1
410 if (basis.is_equal(_ex1))
411 return _ex1;
412
413 // power of a function calculated by separate rules defined for this function
414 if (is_exactly_a<function>(basis))
415 return ex_to<function>(basis).power(exponent);
416
417 // Turn (x^c)^d into x^(c*d) in the case that x is positive and c is real.
418 if (is_exactly_a<power>(basis) && basis.op(0).info(info_flags::positive) && basis.op(1).info(info_flags::real))
419 return dynallocate<power>(basis.op(0), basis.op(1) * exponent);
420
421 if ( num_exponent ) {
422
423 // ^(c1,c2) -> c1^c2 (c1, c2 numeric(),
424 // except if c1,c2 are rational, but c1^c2 is not)
425 if ( num_basis ) {
426 const bool basis_is_crational = num_basis->is_crational();
427 const bool exponent_is_crational = num_exponent->is_crational();
428 if (!basis_is_crational || !exponent_is_crational) {
429 // return a plain float
430 return dynallocate<numeric>(num_basis->power(*num_exponent));
431 }
432
433 const numeric res = num_basis->power(*num_exponent);
434 if (res.is_crational()) {
435 return res;
436 }
437 GINAC_ASSERT(!num_exponent->is_integer()); // has been handled by now
438
439 // ^(c1,n/m) -> *(c1^q,c1^(n/m-q)), 0<(n/m-q)<1, q integer
440 if (basis_is_crational && exponent_is_crational
441 && num_exponent->is_real()
442 && !num_exponent->is_integer()) {
443 const numeric n = num_exponent->numer();
444 const numeric m = num_exponent->denom();
445 numeric r;
446 numeric q = iquo(n, m, r);
447 if (r.is_negative()) {
448 r += m;
449 --q;
450 }
451 if (q.is_zero()) { // the exponent was in the allowed range 0<(n/m)<1
452 if (num_basis->is_rational() && !num_basis->is_integer()) {
453 // try it for numerator and denominator separately, in order to
454 // partially simplify things like (5/8)^(1/3) -> 1/2*5^(1/3)
455 const numeric bnum = num_basis->numer();
456 const numeric bden = num_basis->denom();
457 const numeric res_bnum = bnum.power(*num_exponent);
458 const numeric res_bden = bden.power(*num_exponent);
459 if (res_bnum.is_integer())
460 return dynallocate<mul>(dynallocate<power>(bden,-*num_exponent),res_bnum).setflag(status_flags::evaluated);
461 if (res_bden.is_integer())
462 return dynallocate<mul>(dynallocate<power>(bnum,*num_exponent),res_bden.inverse()).setflag(status_flags::evaluated);
463 }
464 return this->hold();
465 } else {
466 // assemble resulting product, but allowing for a re-evaluation,
467 // because otherwise we'll end up with something like
468 // (7/8)^(4/3) -> 7/8*(1/2*7^(1/3))
469 // instead of 7/16*7^(1/3).
470 return pow(basis, r.div(m)) * pow(basis, q);
471 }
472 }
473 }
474
475 // ^(^(x,c1),c2) -> ^(x,c1*c2)
476 // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1 or (c1=-1 and c2>0),
477 // case c1==1 should not happen, see below!)
478 if (is_exactly_a<power>(basis)) {
479 const power & sub_power = ex_to<power>(basis);
480 const ex & sub_basis = sub_power.basis;
481 const ex & sub_exponent = sub_power.exponent;
482 if (is_exactly_a<numeric>(sub_exponent)) {
483 const numeric & num_sub_exponent = ex_to<numeric>(sub_exponent);
484 GINAC_ASSERT(num_sub_exponent!=numeric(1));
485 if (num_exponent->is_integer() || (abs(num_sub_exponent) - (*_num1_p)).is_negative() ||
486 (num_sub_exponent == *_num_1_p && num_exponent->is_positive())) {
487 return dynallocate<power>(sub_basis, num_sub_exponent.mul(*num_exponent));
488 }
489 }
490 }
491
492 // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
493 if (num_exponent->is_integer() && is_exactly_a<mul>(basis)) {
494 return expand_mul(ex_to<mul>(basis), *num_exponent, false);
495 }
496
497 // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4)
498 if (num_exponent->is_integer() && is_exactly_a<add>(basis)) {
499 numeric icont = basis.integer_content();
500 const numeric lead_coeff =
501 ex_to<numeric>(ex_to<add>(basis).seq.begin()->coeff).div(icont);
502
503 const bool canonicalizable = lead_coeff.is_integer();
504 const bool unit_normal = lead_coeff.is_pos_integer();
505 if (canonicalizable && (! unit_normal))
506 icont = icont.mul(*_num_1_p);
507
508 if (canonicalizable && (icont != *_num1_p)) {
509 const add& addref = ex_to<add>(basis);
510 add & addp = dynallocate<add>(addref);
512 addp.overall_coeff = ex_to<numeric>(addp.overall_coeff).div_dyn(icont);
513 for (auto & i : addp.seq)
514 i.coeff = ex_to<numeric>(i.coeff).div_dyn(icont);
515
516 const numeric c = icont.power(*num_exponent);
517 if (likely(c != *_num1_p))
518 return dynallocate<mul>(dynallocate<power>(addp, *num_exponent), c);
519 else
520 return dynallocate<power>(addp, *num_exponent);
521 }
522 }
523
524 // ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2) (c1, c2 numeric(), c1>0)
525 // ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2) (c1, c2 numeric(), c1<0)
526 if (is_exactly_a<mul>(basis)) {
527 GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
528 const mul & mulref = ex_to<mul>(basis);
529 if (!mulref.overall_coeff.is_equal(_ex1)) {
530 const numeric & num_coeff = ex_to<numeric>(mulref.overall_coeff);
531 if (num_coeff.is_real()) {
532 if (num_coeff.is_positive()) {
533 mul & mulp = dynallocate<mul>(mulref);
534 mulp.overall_coeff = _ex1;
536 return dynallocate<mul>(dynallocate<power>(mulp, exponent),
537 dynallocate<power>(num_coeff, *num_exponent));
538 } else {
539 GINAC_ASSERT(num_coeff.compare(*_num0_p)<0);
540 if (!num_coeff.is_equal(*_num_1_p)) {
541 mul & mulp = dynallocate<mul>(mulref);
542 mulp.overall_coeff = _ex_1;
544 return dynallocate<mul>(dynallocate<power>(mulp, exponent),
545 dynallocate<power>(abs(num_coeff), *num_exponent));
546 }
547 }
548 }
549 }
550 }
551
552 // ^(nc,c1) -> ncmul(nc,nc,...) (c1 positive integer, unless nc is a matrix)
553 if (num_exponent->is_pos_integer() &&
555 !is_a<matrix>(basis)) {
556 return ncmul(exvector(num_exponent->to_int(), basis));
557 }
558 }
559
560 return this->hold();
561}
562
564{
565 ex ebasis = basis.evalf();
566 ex eexponent;
567
568 if (!is_exactly_a<numeric>(exponent))
569 eexponent = exponent.evalf();
570 else
571 eexponent = exponent;
572
573 return dynallocate<power>(ebasis, eexponent);
574}
575
577{
578 const ex ebasis = basis.evalm();
579 const ex eexponent = exponent.evalm();
580 if (is_a<matrix>(ebasis)) {
581 if (is_exactly_a<numeric>(eexponent)) {
582 return dynallocate<matrix>(ex_to<matrix>(ebasis).pow(eexponent));
583 }
584 }
585 return dynallocate<power>(ebasis, eexponent);
586}
587
588bool power::has(const ex & other, unsigned options) const
589{
591 return basic::has(other, options);
592 if (!is_a<power>(other))
593 return basic::has(other, options);
595 !other.op(1).info(info_flags::integer))
596 return basic::has(other, options);
598 other.op(1).info(info_flags::posint) &&
599 ex_to<numeric>(exponent) > ex_to<numeric>(other.op(1)) &&
600 basis.match(other.op(0)))
601 return true;
603 other.op(1).info(info_flags::negint) &&
604 ex_to<numeric>(exponent) < ex_to<numeric>(other.op(1)) &&
605 basis.match(other.op(0)))
606 return true;
607 return basic::has(other, options);
608}
609
610// from mul.cpp
611extern bool tryfactsubs(const ex &, const ex &, int &, exmap&);
612
613ex power::subs(const exmap & m, unsigned options) const
614{
615 const ex &subsed_basis = basis.subs(m, options);
616 const ex &subsed_exponent = exponent.subs(m, options);
617
618 if (!are_ex_trivially_equal(basis, subsed_basis)
619 || !are_ex_trivially_equal(exponent, subsed_exponent))
620 return dynallocate<power>(subsed_basis, subsed_exponent);
621
623 return subs_one_level(m, options);
624
625 for (auto & it : m) {
626 int nummatches = std::numeric_limits<int>::max();
627 exmap repls;
628 if (tryfactsubs(*this, it.first, nummatches, repls)) {
629 ex anum = it.second.subs(repls, subs_options::no_pattern);
630 ex aden = it.first.subs(repls, subs_options::no_pattern);
631 ex result = (*this) * pow(anum/aden, nummatches);
632 return (ex_to<basic>(result)).subs_one_level(m, options);
633 }
634 }
635
636 return subs_one_level(m, options);
637}
638
640{
641 return inherited::eval_ncmul(v);
642}
643
645{
646 // conjugate(pow(x,y))==pow(conjugate(x),conjugate(y)) unless on the
647 // branch cut which runs along the negative real axis.
649 ex newexponent = exponent.conjugate();
650 if (are_ex_trivially_equal(exponent, newexponent)) {
651 return *this;
652 }
653 return dynallocate<power>(basis, newexponent);
654 }
656 ex newbasis = basis.conjugate();
657 if (are_ex_trivially_equal(basis, newbasis)) {
658 return *this;
659 }
660 return dynallocate<power>(newbasis, exponent);
661 }
662 return conjugate_function(*this).hold();
663}
664
666{
667 // basis == a+I*b, exponent == c+I*d
668 const ex a = basis.real_part();
669 const ex c = exponent.real_part();
670 if (basis.is_equal(a) && exponent.is_equal(c) &&
672 // Re(a^c)
673 return *this;
674 }
675
676 const ex b = basis.imag_part();
678 // Re((a+I*b)^c) w/ c ∈ ℤ
679 long N = ex_to<numeric>(c).to_long();
680 // Use real terms in Binomial expansion to construct
681 // Re(expand(pow(a+I*b, N))).
682 long NN = N > 0 ? N : -N;
683 ex numer = N > 0 ? _ex1 : pow(pow(a,2) + pow(b,2), NN);
684 ex result = 0;
685 for (long n = 0; n <= NN; n += 2) {
686 ex term = binomial(NN, n) * pow(a, NN-n) * pow(b, n) / numer;
687 if (n % 4 == 0) {
688 result += term; // sign: I^n w/ n == 4*m
689 } else {
690 result -= term; // sign: I^n w/ n == 4*m+2
691 }
692 }
693 return result;
694 }
695
696 // Re((a+I*b)^(c+I*d))
697 const ex d = exponent.imag_part();
698 return pow(abs(basis),c) * exp(-d*atan2(b,a)) * cos(c*atan2(b,a)+d*log(abs(basis)));
699}
700
702{
703 // basis == a+I*b, exponent == c+I*d
704 const ex a = basis.real_part();
705 const ex c = exponent.real_part();
706 if (basis.is_equal(a) && exponent.is_equal(c) &&
708 // Im(a^c)
709 return 0;
710 }
711
712 const ex b = basis.imag_part();
714 // Im((a+I*b)^c) w/ c ∈ ℤ
715 long N = ex_to<numeric>(c).to_long();
716 // Use imaginary terms in Binomial expansion to construct
717 // Im(expand(pow(a+I*b, N))).
718 long p = N > 0 ? 1 : 3; // modulus for positive sign
719 long NN = N > 0 ? N : -N;
720 ex numer = N > 0 ? _ex1 : pow(pow(a,2) + pow(b,2), NN);
721 ex result = 0;
722 for (long n = 1; n <= NN; n += 2) {
723 ex term = binomial(NN, n) * pow(a, NN-n) * pow(b, n) / numer;
724 if (n % 4 == p) {
725 result += term; // sign: I^n w/ n == 4*m+p
726 } else {
727 result -= term; // sign: I^n w/ n == 4*m+2+p
728 }
729 }
730 return result;
731 }
732
733 // Im((a+I*b)^(c+I*d))
734 const ex d = exponent.imag_part();
735 return pow(abs(basis),c) * exp(-d*atan2(b,a)) * sin(c*atan2(b,a)+d*log(abs(basis)));
736}
737
738// protected
739
743{
744 if (is_a<numeric>(exponent)) {
745 // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below)
746 const epvector newseq = {expair(basis, exponent - _ex1), expair(basis.diff(s), _ex1)};
747 return dynallocate<mul>(std::move(newseq), exponent);
748 } else {
749 // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b)
750 return *this * (exponent.diff(s)*log(basis) + exponent*basis.diff(s)*pow(basis, _ex_1));
751 }
752}
753
754int power::compare_same_type(const basic & other) const
755{
756 GINAC_ASSERT(is_exactly_a<power>(other));
757 const power &o = static_cast<const power &>(other);
758
759 int cmpval = basis.compare(o.basis);
760 if (cmpval)
761 return cmpval;
762 else
763 return exponent.compare(o.exponent);
764}
765
766unsigned power::return_type() const
767{
768 return basis.return_type();
769}
770
775
776ex power::expand(unsigned options) const
777{
778 if (is_a<symbol>(basis) && exponent.info(info_flags::integer)) {
779 // A special case worth optimizing.
781 return *this;
782 }
783
784 // (x*p)^c -> x^c * p^c, if p>0
785 // makes sense before expanding the basis
786 if (is_exactly_a<mul>(basis) && !basis.info(info_flags::indefinite)) {
787 const mul &m = ex_to<mul>(basis);
788 exvector prodseq;
789 epvector powseq;
790 prodseq.reserve(m.seq.size() + 1);
791 powseq.reserve(m.seq.size() + 1);
792 bool possign = true;
793
794 // search for positive/negative factors
795 for (auto & cit : m.seq) {
796 ex e=m.recombine_pair_to_ex(cit);
798 prodseq.push_back(pow(e, exponent).expand(options));
799 else if (e.info(info_flags::negative)) {
800 prodseq.push_back(pow(-e, exponent).expand(options));
801 possign = !possign;
802 } else
803 powseq.push_back(cit);
804 }
805
806 // take care on the numeric coefficient
807 ex coeff=(possign? _ex1 : _ex_1);
808 if (m.overall_coeff.info(info_flags::positive) && m.overall_coeff != _ex1)
809 prodseq.push_back(pow(m.overall_coeff, exponent));
810 else if (m.overall_coeff.info(info_flags::negative) && m.overall_coeff != _ex_1) {
811 prodseq.push_back(pow(-m.overall_coeff, exponent));
812 coeff = -coeff;
813 } else
814 coeff *= m.overall_coeff;
815
816 // If positive/negative factors are found, then extract them.
817 // In either case we set a flag to avoid the second run on a part
818 // which does not have positive/negative terms.
819 if (prodseq.size() > 0) {
820 ex newbasis = dynallocate<mul>(std::move(powseq), coeff);
821 ex_to<basic>(newbasis).setflag(status_flags::purely_indefinite);
822 return dynallocate<mul>(std::move(prodseq)) * pow(newbasis, exponent);
823 } else
824 ex_to<basic>(basis).setflag(status_flags::purely_indefinite);
825 }
826
827 const ex expanded_basis = basis.expand(options);
828 const ex expanded_exponent = exponent.expand(options);
829
830 // x^(a+b) -> x^a * x^b
831 if (is_exactly_a<add>(expanded_exponent)) {
832 const add &a = ex_to<add>(expanded_exponent);
833 exvector distrseq;
834 distrseq.reserve(a.seq.size() + 1);
835 for (auto & cit : a.seq) {
836 distrseq.push_back(pow(expanded_basis, a.recombine_pair_to_ex(cit)));
837 }
838
839 // Make sure that e.g. (x+y)^(2+a) expands the (x+y)^2 factor
840 if (ex_to<numeric>(a.overall_coeff).is_integer()) {
841 const numeric &num_exponent = ex_to<numeric>(a.overall_coeff);
842 long int_exponent = num_exponent.to_int();
843 if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
844 distrseq.push_back(expand_add(ex_to<add>(expanded_basis), int_exponent, options));
845 else
846 distrseq.push_back(pow(expanded_basis, a.overall_coeff));
847 } else
848 distrseq.push_back(pow(expanded_basis, a.overall_coeff));
849
850 // Make sure that e.g. (x+y)^(1+a) -> x*(x+y)^a + y*(x+y)^a
851 ex r = dynallocate<mul>(distrseq);
852 return r.expand(options);
853 }
854
855 if (!is_exactly_a<numeric>(expanded_exponent) ||
856 !ex_to<numeric>(expanded_exponent).is_integer()) {
857 if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) {
858 return this->hold();
859 } else {
860 return dynallocate<power>(expanded_basis, expanded_exponent).setflag(options == 0 ? status_flags::expanded : 0);
861 }
862 }
863
864 // integer numeric exponent
865 const numeric & num_exponent = ex_to<numeric>(expanded_exponent);
866 long int_exponent = num_exponent.to_long();
867
868 // (x+y)^n, n>0
869 if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
870 return expand_add(ex_to<add>(expanded_basis), int_exponent, options);
871
872 // (x*y)^n -> x^n * y^n
873 if (is_exactly_a<mul>(expanded_basis))
874 return expand_mul(ex_to<mul>(expanded_basis), num_exponent, options, true);
875
876 // cannot expand further
877 if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent))
878 return this->hold();
879 else
880 return dynallocate<power>(expanded_basis, expanded_exponent).setflag(options == 0 ? status_flags::expanded : 0);
881}
882
884// new virtual functions which can be overridden by derived classes
886
887// none
888
890// non-virtual functions in this class
892
895ex power::expand_add(const add & a, long n, unsigned options)
896{
897 // The special case power(+(x,...y;x),2) can be optimized better.
898 if (n==2)
899 return expand_add_2(a, options);
900
901 // method:
902 //
903 // Consider base as the sum of all symbolic terms and the overall numeric
904 // coefficient and apply the binomial theorem:
905 // S = power(+(x,...,z;c),n)
906 // = power(+(+(x,...,z;0);c),n)
907 // = sum(binomial(n,k)*power(+(x,...,z;0),k)*c^(n-k), k=1..n) + c^n
908 // Then, apply the multinomial theorem to expand all power(+(x,...,z;0),k):
909 // The multinomial theorem is computed by an outer loop over all
910 // partitions of the exponent and an inner loop over all compositions of
911 // that partition. This method makes the expansion a combinatorial
912 // problem and allows us to directly construct the expanded sum and also
913 // to re-use the multinomial coefficients (since they depend only on the
914 // partition, not on the composition).
915 //
916 // multinomial power(+(x,y,z;0),3) example:
917 // partition : compositions : multinomial coefficient
918 // [0,0,3] : [3,0,0],[0,3,0],[0,0,3] : 3!/(3!*0!*0!) = 1
919 // [0,1,2] : [2,1,0],[1,2,0],[2,0,1],... : 3!/(2!*1!*0!) = 3
920 // [1,1,1] : [1,1,1] : 3!/(1!*1!*1!) = 6
921 // => (x + y + z)^3 =
922 // x^3 + y^3 + z^3
923 // + 3*x^2*y + 3*x*y^2 + 3*y^2*z + 3*y*z^2 + 3*x*z^2 + 3*x^2*z
924 // + 6*x*y*z
925 //
926 // multinomial power(+(x,y,z;0),4) example:
927 // partition : compositions : multinomial coefficient
928 // [0,0,4] : [4,0,0],[0,4,0],[0,0,4] : 4!/(4!*0!*0!) = 1
929 // [0,1,3] : [3,1,0],[1,3,0],[3,0,1],... : 4!/(3!*1!*0!) = 4
930 // [0,2,2] : [2,2,0],[2,0,2],[0,2,2] : 4!/(2!*2!*0!) = 6
931 // [1,1,2] : [2,1,1],[1,2,1],[1,1,2] : 4!/(2!*1!*1!) = 12
932 // (no [1,1,1,1] partition since it has too many parts)
933 // => (x + y + z)^4 =
934 // x^4 + y^4 + z^4
935 // + 4*x^3*y + 4*x*y^3 + 4*y^3*z + 4*y*z^3 + 4*x*z^3 + 4*x^3*z
936 // + 6*x^2*y^2 + 6*y^2*z^2 + 6*x^2*z^2
937 // + 12*x^2*y*z + 12*x*y^2*z + 12*x*y*z^2
938 //
939 // Summary:
940 // r = 0
941 // for k from 0 to n:
942 // f = c^(n-k)*binomial(n,k)
943 // for p in all partitions of n with m parts (including zero parts):
944 // h = f * multinomial coefficient of p
945 // for c in all compositions of p:
946 // t = 1
947 // for e in all elements of c:
948 // t = t * a[e]^e
949 // r = r + h*t
950 // return r
951
952 epvector result;
953 // The number of terms will be the number of combinatorial compositions,
954 // i.e. the number of unordered arrangements of m nonnegative integers
955 // which sum up to n. It is frequently written as C_n(m) and directly
956 // related with binomial coefficients: binomial(n+m-1,m-1).
957 size_t result_size = binomial(numeric(n+a.nops()-1), numeric(a.nops()-1)).to_long();
958 if (!a.overall_coeff.is_zero()) {
959 // the result's overall_coeff is one of the terms
960 --result_size;
961 }
962 result.reserve(result_size);
963
964 // Iterate over all terms in binomial expansion of
965 // S = power(+(x,...,z;c),n)
966 // = sum(binomial(n,k)*power(+(x,...,z;0),k)*c^(n-k), k=1..n) + c^n
967 for (int k = 1; k <= n; ++k) {
968 numeric binomial_coefficient; // binomial(n,k)*c^(n-k)
969 if (a.overall_coeff.is_zero()) {
970 // degenerate case with zero overall_coeff:
971 // apply multinomial theorem directly to power(+(x,...z;0),n)
972 binomial_coefficient = 1;
973 if (k < n) {
974 continue;
975 }
976 } else {
977 binomial_coefficient = binomial(numeric(n), numeric(k)) * pow(ex_to<numeric>(a.overall_coeff), numeric(n-k));
978 }
979
980 // Multinomial expansion of power(+(x,...,z;0),k)*c^(n-k):
981 // Iterate over all partitions of k with exactly as many parts as
982 // there are symbolic terms in the basis (including zero parts).
983 partition_with_zero_parts_generator partitions(k, a.seq.size());
984 do {
985 const std::vector<unsigned>& partition = partitions.get();
986 // All monomials of this partition have the same number of terms and the same coefficient.
987 const unsigned msize = std::count_if(partition.begin(), partition.end(), [](int i) { return i > 0; });
988 const numeric coeff = multinomial_coefficient(partition) * binomial_coefficient;
989
990 // Iterate over all compositions of the current partition.
991 composition_generator compositions(partition);
992 do {
993 const std::vector<unsigned>& exponent = compositions.get();
994 epvector monomial;
995 monomial.reserve(msize);
997 for (unsigned i = 0; i < exponent.size(); ++i) {
998 const ex & r = a.seq[i].rest;
999 GINAC_ASSERT(!is_exactly_a<add>(r));
1000 GINAC_ASSERT(!is_exactly_a<power>(r) ||
1001 !is_exactly_a<numeric>(ex_to<power>(r).exponent) ||
1002 !ex_to<numeric>(ex_to<power>(r).exponent).is_pos_integer() ||
1003 !is_exactly_a<add>(ex_to<power>(r).basis) ||
1004 !is_exactly_a<mul>(ex_to<power>(r).basis) ||
1005 !is_exactly_a<power>(ex_to<power>(r).basis));
1006 GINAC_ASSERT(is_exactly_a<numeric>(a.seq[i].coeff));
1007 const numeric & c = ex_to<numeric>(a.seq[i].coeff);
1008 if (exponent[i] == 0) {
1009 // optimize away
1010 } else if (exponent[i] == 1) {
1011 // optimized
1012 monomial.emplace_back(expair(r, _ex1));
1013 if (c != *_num1_p)
1014 factor = factor.mul(c);
1015 } else { // general case exponent[i] > 1
1016 monomial.emplace_back(expair(r, exponent[i]));
1017 if (c != *_num1_p)
1018 factor = factor.mul(c.power(exponent[i]));
1019 }
1020 }
1021 result.emplace_back(expair(mul(std::move(monomial)).expand(options), factor));
1022 } while (compositions.next());
1023 } while (partitions.next());
1024 }
1025
1026 GINAC_ASSERT(result.size() == result_size);
1027 if (a.overall_coeff.is_zero()) {
1028 return dynallocate<add>(std::move(result)).setflag(status_flags::expanded);
1029 } else {
1030 return dynallocate<add>(std::move(result), ex_to<numeric>(a.overall_coeff).power(n)).setflag(status_flags::expanded);
1031 }
1032}
1033
1034
1037ex power::expand_add_2(const add & a, unsigned options)
1038{
1039 epvector result;
1040 size_t result_size = (a.nops() * (a.nops()+1)) / 2;
1041 if (!a.overall_coeff.is_zero()) {
1042 // the result's overall_coeff is one of the terms
1043 --result_size;
1044 }
1045 result.reserve(result_size);
1046
1047 auto last = a.seq.end();
1048
1049 // power(+(x,...,z;c),2)=power(+(x,...,z;0),2)+2*c*+(x,...,z;0)+c*c
1050 // first part: ignore overall_coeff and expand other terms
1051 for (auto cit0=a.seq.begin(); cit0!=last; ++cit0) {
1052 const ex & r = cit0->rest;
1053 const ex & c = cit0->coeff;
1054
1055 GINAC_ASSERT(!is_exactly_a<add>(r));
1056 GINAC_ASSERT(!is_exactly_a<power>(r) ||
1057 !is_exactly_a<numeric>(ex_to<power>(r).exponent) ||
1058 !ex_to<numeric>(ex_to<power>(r).exponent).is_pos_integer() ||
1059 !is_exactly_a<add>(ex_to<power>(r).basis) ||
1060 !is_exactly_a<mul>(ex_to<power>(r).basis) ||
1061 !is_exactly_a<power>(ex_to<power>(r).basis));
1062
1063 if (c.is_equal(_ex1)) {
1064 if (is_exactly_a<mul>(r)) {
1065 result.emplace_back(expair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
1066 _ex1));
1067 } else {
1068 result.emplace_back(expair(dynallocate<power>(r, _ex2),
1069 _ex1));
1070 }
1071 } else {
1072 if (is_exactly_a<mul>(r)) {
1073 result.emplace_back(expair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
1074 ex_to<numeric>(c).power_dyn(*_num2_p)));
1075 } else {
1076 result.emplace_back(expair(dynallocate<power>(r, _ex2),
1077 ex_to<numeric>(c).power_dyn(*_num2_p)));
1078 }
1079 }
1080
1081 for (auto cit1=cit0+1; cit1!=last; ++cit1) {
1082 const ex & r1 = cit1->rest;
1083 const ex & c1 = cit1->coeff;
1084 result.emplace_back(expair(mul(r,r1).expand(options),
1085 _num2_p->mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
1086 }
1087 }
1088
1089 // second part: add terms coming from overall_coeff (if != 0)
1090 if (!a.overall_coeff.is_zero()) {
1091 for (auto & i : a.seq)
1092 result.push_back(a.combine_pair_with_coeff_to_pair(i, ex_to<numeric>(a.overall_coeff).mul_dyn(*_num2_p)));
1093 }
1094
1095 GINAC_ASSERT(result.size() == result_size);
1096
1097 if (a.overall_coeff.is_zero()) {
1098 return dynallocate<add>(std::move(result)).setflag(status_flags::expanded);
1099 } else {
1100 return dynallocate<add>(std::move(result), ex_to<numeric>(a.overall_coeff).power(2)).setflag(status_flags::expanded);
1101 }
1102}
1103
1106ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool from_expand)
1107{
1108 GINAC_ASSERT(n.is_integer());
1109
1110 if (n.is_zero()) {
1111 return _ex1;
1112 }
1113
1114 // do not bother to rename indices if there are no any.
1118 // Leave it to multiplication since dummy indices have to be renamed
1120 (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
1121 ex result = m;
1123 sort(va.begin(), va.end(), ex_is_less());
1124
1125 for (int i=1; i < n.to_int(); i++)
1126 result *= rename_dummy_indices_uniquely(va, m);
1127 return result;
1128 }
1129
1130 epvector distrseq;
1131 distrseq.reserve(m.seq.size());
1132 bool need_reexpand = false;
1133
1134 for (auto & cit : m.seq) {
1135 expair p = m.combine_pair_with_coeff_to_pair(cit, n);
1136 if (from_expand && is_exactly_a<add>(cit.rest) && ex_to<numeric>(p.coeff).is_pos_integer()) {
1137 // this happens when e.g. (a+b)^(1/2) gets squared and
1138 // the resulting product needs to be reexpanded
1139 need_reexpand = true;
1140 }
1141 distrseq.push_back(p);
1142 }
1143
1144 const mul & result = dynallocate<mul>(std::move(distrseq), ex_to<numeric>(m.overall_coeff).power_dyn(n));
1145 if (need_reexpand)
1146 return ex(result).expand(options);
1147 if (from_expand)
1148 return result.setflag(status_flags::expanded);
1149 return result;
1150}
1151
1153
1154} // namespace GiNaC
Interface to GiNaC's sums of expressions.
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition assertion.h:32
Sum of expressions.
Definition add.h:31
ex recombine_pair_to_ex(const expair &p) const override
Form an ex out of an expair, using the corresponding semantics.
Definition add.cpp:561
expair combine_pair_with_coeff_to_pair(const expair &p, const ex &c) const override
Definition add.cpp:547
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Definition archive.h:48
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition basic.h:104
const basic & clearflag(unsigned f) const
Clear some status_flags.
Definition basic.h:290
const basic & setflag(unsigned f) const
Set some status_flags.
Definition basic.h:287
virtual bool has(const ex &other, unsigned options=0) const
Test for occurrence of a pattern.
Definition basic.cpp:279
friend class ex
Definition basic.h:107
unsigned flags
of type status_flags
Definition basic.h:301
ex subs_one_level(const exmap &m, unsigned options) const
Helper function for subs().
Definition basic.cpp:584
const basic & hold() const
Stop further evaluation.
Definition basic.cpp:886
bool is_equal(const basic &other) const
Test for syntactic equality.
Definition basic.cpp:862
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition basic.cpp:718
virtual ex expand(unsigned options=0) const
Expand expression, i.e.
Definition basic.cpp:795
Generate all compositions of a partition of an integer n, starting with the compositions which has no...
Definition utils.h:394
const std::vector< unsigned > & get() const
Definition utils.h:459
Wrapper template for making GiNaC classes out of STL containers.
Definition container.h:72
Lightweight wrapper for GiNaC's symbolic objects.
Definition ex.h:72
numeric integer_content() const
Compute the integer content (= GCD of all numeric coefficients) of an expanded polynomial.
Definition normal.cpp:317
bool match(const ex &pattern) const
Check whether expression matches a specified pattern.
Definition ex.cpp:95
bool is_polynomial(const ex &vars) const
Check whether expression is a polynomial.
Definition ex.cpp:241
ex diff(const symbol &s, unsigned nth=1) const
Compute partial derivative of an expression.
Definition ex.cpp:86
ex expand(unsigned options=0) const
Expand an expression.
Definition ex.cpp:73
bool is_equal(const ex &other) const
Definition ex.h:345
int degree(const ex &s) const
Definition ex.h:173
bool has(const ex &pattern, unsigned options=0) const
Definition ex.h:151
ex evalf() const
Definition ex.h:121
ex conjugate() const
Definition ex.h:146
unsigned return_type() const
Definition ex.h:230
return_type_t return_type_tinfo() const
Definition ex.h:231
ex imag_part() const
Definition ex.h:148
ex subs(const exmap &m, unsigned options=0) const
Definition ex.h:841
bool info(unsigned inf) const
Definition ex.h:132
int compare(const ex &other) const
Definition ex.h:322
bool is_zero() const
Definition ex.h:213
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Definition ex.cpp:54
ex op(size_t i) const
Definition ex.h:136
int ldegree(const ex &s) const
Definition ex.h:174
ex real_part() const
Definition ex.h:147
ex evalm() const
Definition ex.h:122
ex coeff(const ex &s, int n=1) const
Definition ex.h:175
A pair of expressions.
Definition expair.h:37
ex coeff
second member of pair, must be numeric
Definition expair.h:90
size_t nops() const override
Number of operands/members.
@ expand_rename_idx
used internally by mul::expand()
Definition flags.h:33
@ algebraic
enable algebraic matching
Definition flags.h:42
Product of expressions.
Definition mul.h:31
Non-commutative product of expressions.
Definition ncmul.h:32
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Definition numeric.h:81
bool is_pos_integer() const
True if object is an exact integer greater than zero.
Definition numeric.cpp:1160
const numeric & mul_dyn(const numeric &other) const
Numerical multiplication method.
Definition numeric.cpp:956
bool is_crational() const
True if object is an exact rational number, may even be complex (denominator may be unity).
Definition numeric.cpp:1242
bool is_rational() const
True if object is an exact rational number, may even be complex (denominator may be unity).
Definition numeric.cpp:1200
const numeric real() const
Real part of a number.
Definition numeric.cpp:1338
long to_long() const
Converts numeric types to machine's long.
Definition numeric.cpp:1312
int compare(const numeric &other) const
This method establishes a canonical order on all numbers.
Definition numeric.cpp:1103
bool is_positive() const
True if object is not complex and greater than zero.
Definition numeric.cpp:1135
bool is_real() const
True if object is a real integer, rational or float (but not complex).
Definition numeric.cpp:1207
const numeric numer() const
Numerator.
Definition numeric.cpp:1355
bool is_integer() const
True if object is a non-complex integer.
Definition numeric.cpp:1153
const numeric power(const numeric &other) const
Numerical exponentiation.
Definition numeric.cpp:899
const numeric denom() const
Denominator.
Definition numeric.cpp:1386
const numeric mul(const numeric &other) const
Numerical multiplication method.
Definition numeric.cpp:879
bool is_equal(const numeric &other) const
Definition numeric.cpp:1121
int to_int() const
Converts numeric types to machine's int.
Definition numeric.cpp:1302
const numeric inverse() const
Inverse of a number.
Definition numeric.cpp:1052
bool is_zero() const
True if object is zero.
Definition numeric.cpp:1128
const numeric div(const numeric &other) const
Numerical division method.
Definition numeric.cpp:889
Generate all bounded combinatorial partitions of an integer n with exactly m parts (including zero pa...
Definition utils.h:326
const std::vector< unsigned > & get() const
Definition utils.h:336
Exception class thrown when a singularity is encountered.
Definition numeric.h:69
This class holds a two-component object, a basis and and exponent representing exponentiation.
Definition power.h:38
static ex expand_mul(const mul &m, const numeric &n, unsigned options, bool from_expand=false)
Expand factors of m in m^n where m is a mul and n is an integer.
Definition power.cpp:1106
void do_print_dflt(const print_dflt &c, unsigned level) const
Definition power.cpp:105
void do_print_csrc(const print_csrc &c, unsigned level) const
Definition power.cpp:177
static ex expand_add(const add &a, long n, unsigned options)
expand a^n where a is an add and n is a positive integer.
Definition power.cpp:895
int degree(const ex &s) const override
Return degree of highest power in object s.
Definition power.cpp:299
void read_archive(const archive_node &n, lst &syms) override
Read (a.k.a.
Definition power.cpp:71
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
Definition power.cpp:613
int ldegree(const ex &s) const override
Return degree of lowest power in object s.
Definition power.cpp:314
static ex expand_add_2(const add &a, unsigned options)
Special case of power::expand_add.
Definition power.cpp:1037
ex real_part() const override
Definition power.cpp:665
void archive(archive_node &n) const override
Save (a.k.a.
Definition power.cpp:78
ex derivative(const symbol &s) const override
Implementation of ex::diff() for a power.
Definition power.cpp:742
friend class mul
Definition power.h:41
ex map(map_function &f) const override
Construct new expression by applying the specified function to all sub-expressions (one level only,...
Definition power.cpp:273
ex eval() const override
Perform automatic term rewriting rules in this class.
Definition power.cpp:372
void do_print_python(const print_python &c, unsigned level) const
Definition power.cpp:208
void print_power(const print_context &c, const char *powersymbol, const char *openbrace, const char *closebrace, unsigned level) const
Definition power.cpp:91
void do_print_python_repr(const print_python_repr &c, unsigned level) const
Definition power.cpp:213
ex exponent
Definition power.h:105
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Definition power.h:52
ex op(size_t i) const override
Return operand/member at position i.
Definition power.cpp:266
power(const ex &lh, const ex &rh)
Definition power.h:47
void do_print_latex(const print_latex &c, unsigned level) const
Definition power.cpp:118
ex conjugate() const override
Definition power.cpp:644
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in object s.
Definition power.cpp:329
bool has(const ex &other, unsigned options=0) const override
Test for occurrence of a pattern.
Definition power.cpp:588
ex evalm() const override
Evaluate sums, products and integer powers of matrices.
Definition power.cpp:576
return_type_t return_type_tinfo() const override
Definition power.cpp:771
size_t nops() const override
Number of operands/members.
Definition power.cpp:261
ex expand(unsigned options=0) const override
Expand expression, i.e.
Definition power.cpp:776
bool info(unsigned inf) const override
Information about the object.
Definition power.cpp:222
ex eval_ncmul(const exvector &v) const override
Definition power.cpp:639
void do_print_csrc_cl_N(const print_csrc_cl_N &c, unsigned level) const
Definition power.cpp:162
unsigned return_type() const override
Definition power.cpp:766
ex imag_part() const override
Definition power.cpp:701
bool is_polynomial(const ex &var) const override
Check whether this is a polynomial in the given variables.
Definition power.cpp:285
ex evalf() const override
Evaluate object numerically.
Definition power.cpp:563
Base class for print_contexts.
Definition print.h:101
Context for C source output using CLN numbers.
Definition print.h:180
Base context for C source output.
Definition print.h:156
Context for default (ginsh-parsable) output.
Definition print.h:113
Context for latex-parsable output.
Definition print.h:121
Context for python-parsable output.
Definition print.h:137
Context for python pretty-print output.
Definition print.h:129
@ expanded
.expand(0) has already done its job (other expand() options ignore this flag)
Definition flags.h:203
@ evaluated
.eval() has already done its job
Definition flags.h:202
@ hash_calculated
.calchash() has already done its job
Definition flags.h:204
@ no_pattern
disable pattern matching
Definition flags.h:50
@ algebraic
enable algebraic substitutions
Definition flags.h:52
Basic CAS symbol.
Definition symbol.h:38
Definition of optimizing macros.
#define likely(cond)
Definition compiler.h:31
Interface to GiNaC's constant types and some special constants.
Interface to sequences of expression pairs.
unsigned options
Definition factor.cpp:2473
vector< int > k
Definition factor.cpp:1434
size_t n
Definition factor.cpp:1431
size_t c
Definition factor.cpp:756
ex x
Definition factor.cpp:1609
size_t r
Definition factor.cpp:756
mvec m
Definition factor.cpp:757
size_t last
Definition factor.cpp:1433
Interface to GiNaC's indexed expressions.
Interface to GiNaC's initially known functions.
Definition of GiNaC's lst.
Interface to symbolic matrices.
Interface to GiNaC's products of expressions.
Definition add.cpp:35
const numeric * _num_1_p
Definition utils.cpp:350
const ex _ex2
Definition utils.cpp:388
const numeric pow(const numeric &x, const numeric &y)
Definition numeric.h:250
const ex _ex1_2
Definition utils.cpp:380
std::map< ex, ex, ex_is_less > exmap
Definition basic.h:49
std::vector< expair > epvector
expair-vector
Definition expairseq.h:32
const numeric abs(const numeric &x)
Absolute value.
Definition numeric.cpp:2319
bool is_negative(const numeric &x)
Definition numeric.h:268
const ex _ex1
Definition utils.cpp:384
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
Definition ex.h:699
const numeric binomial(const numeric &n, const numeric &k)
The Binomial coefficients.
Definition numeric.cpp:2144
print_func< print_dflt >(&diracone::do_print). print_func< print_latex >(&diracone
Definition clifford.cpp:51
const numeric * _num2_p
Definition utils.cpp:387
const numeric exp(const numeric &x)
Exponential function.
Definition numeric.cpp:1438
const numeric cos(const numeric &x)
Numeric cosine (trigonometric function).
Definition numeric.cpp:1469
const ex _ex_1
Definition utils.cpp:351
const numeric iquo(const numeric &a, const numeric &b)
Numeric integer quotient.
Definition numeric.cpp:2408
bool is_pos_integer(const numeric &x)
Definition numeric.h:274
const numeric log(const numeric &x)
Natural logarithm.
Definition numeric.cpp:1449
const numeric sin(const numeric &x)
Numeric sine (trigonometric function).
Definition numeric.cpp:1460
const numeric * _num1_p
Definition utils.cpp:383
ex numer(const ex &thisex)
Definition ex.h:760
ex factor(const ex &poly, unsigned options)
Interface function to the outside world.
Definition factor.cpp:2574
bool is_integer(const numeric &x)
Definition numeric.h:271
static void print_sym_pow(const print_context &c, const symbol &x, int exp)
Definition power.cpp:138
lst rename_dummy_indices_uniquely(const exvector &va, const exvector &vb)
Similar to above, where va and vb are the same and the return value is a list of two lists for substi...
Definition indexed.cpp:1460
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT_T(lst, basic, print_func< print_context >(&lst::do_print). print_func< print_tree >(&lst::do_print_tree)) template<> bool lst GINAC_BIND_UNARCHIVER(lst)
Specialization of container::info() for lst.
Definition lst.cpp:41
const ex _ex0
Definition utils.cpp:368
bool tryfactsubs(const ex &origfactor, const ex &patternfactor, int &nummatches, exmap &repls)
Definition mul.cpp:670
std::vector< ex > exvector
Definition basic.h:47
exvector get_all_dummy_indices(const ex &e)
Returns all dummy indices from the exvector.
Definition indexed.cpp:1435
const numeric multinomial_coefficient(const std::vector< unsigned > &p)
Compute the multinomial coefficient n!/(p1!*p2!*...*pk!) where n = p1+p2+...+pk, i....
Definition utils.cpp:59
const numeric * _num0_p
Definition utils.cpp:366
Interface to GiNaC's non-commutative products of expressions.
Makes the interface to the underlying bignum package available.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
Definition registrar.h:183
Interface to relations between expressions.
Function object for map().
Definition basic.h:84
To distinguish between different kinds of non-commutative objects.
Definition registrar.h:42
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...

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