129 if (
coeff.csgn() == -1)
133 if (
coeff.is_rational()) {
134 if (
coeff.is_negative())
139 if (
coeff.csgn() == -1)
156 for (
auto & it :
seq) {
178 for (
auto & it :
seq) {
180 if (ex_to<numeric>(it.coeff).is_negative())
186 if (!neg_powers.empty()) {
190 mul(others).eval().print(
c);
192 mul(neg_powers).eval().print(
c);
198 for (
auto & vit : others) {
223 auto it = seq.begin(), itend = seq.end();
224 while (it != itend) {
227 bool needclosingparenthesis =
false;
229 if (is_a<print_csrc_cl_N>(
c)) {
231 needclosingparenthesis =
true;
237 if (it->coeff.is_equal(
_ex1) || it->coeff.is_equal(
_ex_1))
238 it->rest.print(
c, precedence());
240 ex(power(it->rest, -ex_to<numeric>(it->coeff))).print(
c, level);
242 ex(power(it->rest, ex_to<numeric>(it->coeff))).print(
c, level);
244 if (needclosingparenthesis)
257 if (precedence() <= level)
263 c.s << class_name() <<
'(';
265 for (
size_t i=1; i<
nops(); ++i) {
272 bool mul::info(
unsigned inf)
const 275 case info_flags::polynomial:
276 case info_flags::integer_polynomial:
277 case info_flags::cinteger_polynomial:
278 case info_flags::rational_polynomial:
280 case info_flags::rational:
281 case info_flags::integer:
282 case info_flags::crational:
283 case info_flags::cinteger:
284 case info_flags::even:
285 case info_flags::crational_polynomial:
286 case info_flags::rational_function: {
287 for (
auto & it : seq) {
288 if (!recombine_pair_to_ex(it).info(inf))
291 if (overall_coeff.is_equal(*
_num1_p) && inf == info_flags::even)
293 return overall_coeff.
info(inf);
295 case info_flags::positive:
296 case info_flags::negative: {
301 if (flags & status_flags::purely_indefinite)
305 for (
auto & it : seq) {
306 const ex&
factor = recombine_pair_to_ex(it);
314 if (overall_coeff.info(info_flags::negative))
317 return (inf == info_flags::positive? pos : !pos);
319 case info_flags::nonnegative: {
323 for (
auto & it : seq) {
324 const ex&
factor = recombine_pair_to_ex(it);
332 return (overall_coeff.info(info_flags::negative)? !pos : pos);
334 case info_flags::posint:
335 case info_flags::negint: {
337 for (
auto & it : seq) {
338 const ex&
factor = recombine_pair_to_ex(it);
346 if (overall_coeff.info(info_flags::negint))
348 else if (!overall_coeff.info(info_flags::posint))
350 return (inf ==info_flags::posint? pos : !pos);
352 case info_flags::nonnegint: {
354 for (
auto & it : seq) {
355 const ex&
factor = recombine_pair_to_ex(it);
363 if (overall_coeff.info(info_flags::negint))
365 else if (!overall_coeff.info(info_flags::posint))
369 case info_flags::indefinite: {
370 if (flags & status_flags::purely_indefinite)
374 for (
auto & it : seq) {
375 const ex& term = recombine_pair_to_ex(it);
376 if (term.
info(info_flags::positive) || term.
info(info_flags::negative))
379 setflag(status_flags::purely_indefinite);
383 return inherited::info(inf);
388 for (
auto & it : seq) {
389 if (!it.rest.is_polynomial(var) ||
390 (it.rest.has(var) && !it.coeff.info(info_flags::nonnegint))) {
401 for (
auto & it : seq) {
402 if (ex_to<numeric>(it.coeff).is_integer())
403 deg_sum += recombine_pair_to_ex(it).degree(s);
406 throw std::runtime_error(
"mul::degree() undefined degree because of non-integer exponent");
416 for (
auto & it : seq) {
417 if (ex_to<numeric>(it.coeff).is_integer())
418 deg_sum += recombine_pair_to_ex(it).ldegree(s);
421 throw std::runtime_error(
"mul::ldegree() undefined degree because of non-integer exponent");
430 coeffseq.reserve(seq.size()+1);
435 for (
auto & it : seq)
436 coeffseq.push_back(recombine_pair_to_ex(it).
coeff(s,
n));
437 coeffseq.push_back(overall_coeff);
438 return dynallocate<mul>(coeffseq);
441 bool coeff_found =
false;
442 for (
auto & it : seq) {
443 ex t = recombine_pair_to_ex(it);
446 coeffseq.push_back(
c);
449 coeffseq.push_back(t);
453 coeffseq.push_back(overall_coeff);
454 return dynallocate<mul>(coeffseq);
470 if (flags & status_flags::evaluated) {
476 const epvector evaled = evalchildren();
479 return dynallocate<mul>(std::move(evaled), overall_coeff);
482 size_t seq_size = seq.size();
483 if (overall_coeff.is_zero()) {
486 }
else if (seq_size==0) {
488 return overall_coeff;
489 }
else if (seq_size==1 && overall_coeff.is_equal(
_ex1)) {
491 return recombine_pair_to_ex(*(seq.begin()));
492 }
else if ((seq_size==1) &&
493 is_exactly_a<add>((*seq.begin()).rest) &&
494 ex_to<numeric>((*seq.begin()).
coeff).is_equal(*
_num1_p)) {
496 const add & addref = ex_to<add>((*seq.begin()).rest);
498 distrseq.reserve(addref.
seq.size());
499 for (
auto & it : addref.
seq) {
502 return dynallocate<add>(std::move(distrseq),
503 ex_to<numeric>(addref.
overall_coeff).mul_dyn(ex_to<numeric>(overall_coeff)))
504 .setflag(status_flags::evaluated);
505 }
else if ((seq_size >= 2) && (! (flags & status_flags::expanded))) {
509 auto i = seq.begin(),
last = seq.end();
510 auto j = seq.begin();
513 bool something_changed =
false;
515 if (
likely(! (is_a<add>(i->rest) && i->coeff.is_equal(
_ex1)))) {
522 numeric c = i->rest.integer_content();
524 ex_to<numeric>(ex_to<add>(i->rest).seq.begin()->coeff).div(
c);
525 const bool canonicalizable = lead_coeff.
is_integer();
532 if (
likely((
c == *
_num1_p) && ((! canonicalizable) || unit_normal))) {
537 if (! something_changed) {
539 something_changed =
true;
542 while ((j!=i) && (j!=
last)) {
553 const add& addref = ex_to<add>(i->rest);
554 add & primitive = dynallocate<add>(addref);
555 primitive.
clearflag(status_flags::hash_calculated);
556 primitive.overall_coeff = ex_to<numeric>(primitive.overall_coeff).div_dyn(
c);
557 for (
auto & ai : primitive.seq)
558 ai.coeff = ex_to<numeric>(ai.coeff).div_dyn(
c);
565 if (something_changed) {
570 return dynallocate<mul>(std::move(s), ex_to<numeric>(overall_coeff).mul_dyn(oc));
580 s.reserve(seq.size());
582 for (
auto & it : seq)
583 s.push_back(
expair(it.rest.evalf(), it.coeff));
584 return dynallocate<mul>(std::move(s), overall_coeff.evalf());
587 void mul::find_real_imag(
ex & rp,
ex & ip)
const 591 for (
auto & it : seq) {
592 ex factor = recombine_pair_to_ex(it);
599 ex temp = rp*new_rp - ip*new_ip;
600 ip = ip*new_rp + rp*new_ip;
611 find_real_imag(rp, ip);
618 find_real_imag(rp, ip);
625 if (seq.size() == 1 && seq[0].coeff.is_equal(
_ex1)
626 && is_a<matrix>(seq[0].rest))
627 return ex_to<matrix>(seq[0].rest).
mul(ex_to<numeric>(overall_coeff));
633 s.reserve(seq.size());
635 bool have_matrix =
false;
636 epvector::iterator the_matrix;
638 for (
auto & it : seq) {
639 const ex &
m = recombine_pair_to_ex(it).evalm();
640 s.push_back(split_ex_to_pair(
m));
641 if (is_a<matrix>(
m)) {
643 the_matrix = s.end() - 1;
651 matrix m = ex_to<matrix>(the_matrix->rest);
653 ex scalar = dynallocate<mul>(std::move(s), overall_coeff);
654 return m.mul_scalar(scalar);
657 return dynallocate<mul>(std::move(s), overall_coeff);
663 return inherited::eval_ncmul(v);
666 for (
auto & it : seq)
667 if (it.rest.return_type() == return_types::noncommutative)
669 return inherited::eval_ncmul(v);
678 if (is_exactly_a<power>(origfactor) && origfactor.
op(1).
info(info_flags::integer)) {
679 origbase = origfactor.
op(0);
680 int expon = ex_to<numeric>(origfactor.
op(1)).
to_int();
681 origexponent = expon > 0 ? expon : -expon;
682 origexpsign = expon > 0 ? 1 : -1;
684 origbase = origfactor;
693 if (is_exactly_a<power>(patternfactor) && patternfactor.
op(1).
info(info_flags::integer)) {
694 patternbase = patternfactor.
op(0);
695 int expon = ex_to<numeric>(patternfactor.
op(1)).
to_int();
696 patternexponent = expon > 0 ? expon : -expon;
697 patternexpsign = expon > 0 ? 1 : -1;
699 patternbase = patternfactor;
704 exmap saverepls = repls;
705 if (origexponent < patternexponent || origexpsign != patternexpsign || !origbase.
match(patternbase,saverepls))
709 int newnummatches = origexponent / patternexponent;
710 if (newnummatches < nummatches)
711 nummatches = newnummatches;
724 int factor,
int &nummatches,
const std::vector<bool> &subsed,
725 std::vector<bool> &matched)
733 for (
size_t i=0; i<e.
nops(); ++i) {
734 if(subsed[i] || matched[i])
736 exmap newrepls = repls;
737 int newnummatches = nummatches;
741 newnummatches, subsed, matched)) {
743 nummatches = newnummatches;
756 if(!(
options & has_options::algebraic))
758 if(is_a<mul>(pattern)) {
760 int nummatches = std::numeric_limits<int>::max();
761 std::vector<bool> subsed(
nops(),
false);
762 std::vector<bool> matched(
nops(),
false);
772 std::vector<bool> subsed(
nops(),
false);
776 for (
auto & it :
m) {
778 if (is_exactly_a<mul>(it.first)) {
780 int nummatches = std::numeric_limits<int>::max();
781 std::vector<bool> currsubsed(
nops(),
false);
787 for (
size_t j=0; j<subsed.size(); j++)
791 = it.first.
subs(repls, subs_options::no_pattern);
792 divide_by *=
pow(subsed_pattern, nummatches);
794 = it.second.
subs(repls, subs_options::no_pattern);
795 multiply_by *=
pow(subsed_result, nummatches);
800 for (
size_t j=0; j<this->
nops(); j++) {
801 int nummatches = std::numeric_limits<int>::max();
803 if (!subsed[j] &&
tryfactsubs(
op(j), it.first, nummatches, repls)){
806 = it.first.
subs(repls, subs_options::no_pattern);
807 divide_by *=
pow(subsed_pattern, nummatches);
809 = it.second.
subs(repls, subs_options::no_pattern);
810 multiply_by *=
pow(subsed_result, nummatches);
816 bool subsfound =
false;
817 for (
size_t i=0; i<subsed.size(); i++) {
824 return subs_one_level(
m,
options | subs_options::algebraic);
826 return ((*
this)/divide_by)*multiply_by;
833 std::unique_ptr<epvector> newepv(
nullptr);
834 for (
auto i=seq.begin(); i!=seq.end(); ++i) {
836 newepv->push_back(split_ex_to_pair(recombine_pair_to_ex(*i).conjugate()));
839 ex x = recombine_pair_to_ex(*i);
840 ex c =
x.conjugate();
845 newepv->reserve(seq.size());
846 for (
auto j=seq.begin(); j!=i; ++j) {
847 newepv->push_back(*j);
849 newepv->push_back(split_ex_to_pair(
c));
851 ex x = overall_coeff.conjugate();
855 return thisexpairseq(newepv ? std::move(*newepv) : seq,
x);
865 size_t num = seq.size();
871 auto i = seq.
begin(), end = seq.end();
872 auto i2 = mulseq.begin();
877 addseq.push_back(dynallocate<mul>(mulseq, overall_coeff * i->coeff));
881 return dynallocate<add>(addseq);
884 int mul::compare_same_type(
const basic & other)
const 886 return inherited::compare_same_type(other);
889 unsigned mul::return_type()
const 893 return return_types::commutative;
896 bool all_commutative =
true;
897 epvector::const_iterator noncommutative_element;
899 epvector::const_iterator i = seq.begin(), end = seq.end();
901 unsigned rt = i->rest.return_type();
902 if (rt == return_types::noncommutative_composite)
904 if ((rt == return_types::noncommutative) && (all_commutative)) {
906 noncommutative_element = i;
907 all_commutative =
false;
909 if ((rt == return_types::noncommutative) && (!all_commutative)) {
911 if (noncommutative_element->rest.return_type_tinfo() != i->rest.return_type_tinfo()) {
913 return return_types::noncommutative_composite;
919 return all_commutative ? return_types::commutative : return_types::noncommutative;
925 return make_return_type_t<mul>();
928 for (
auto & it : seq)
929 if (it.rest.return_type() == return_types::noncommutative)
930 return it.rest.return_type_tinfo();
933 return make_return_type_t<mul>();
936 ex mul::thisexpairseq(
const epvector & v,
const ex & oc,
bool do_index_renaming)
const 938 return dynallocate<mul>(v, oc, do_index_renaming);
941 ex mul::thisexpairseq(
epvector && vp,
const ex & oc,
bool do_index_renaming)
const 943 return dynallocate<mul>(std::move(vp), oc, do_index_renaming);
948 if (is_exactly_a<power>(e)) {
949 const power & powerref = ex_to<power>(e);
950 if (is_exactly_a<numeric>(powerref.
exponent))
956 expair mul::combine_ex_with_coeff_to_pair(
const ex & e,
962 if (is_exactly_a<symbol>(e))
966 if (
c.is_equal(
_ex1))
967 return split_ex_to_pair(e);
973 return split_ex_to_pair(
pow(e,
c));
983 if (is_exactly_a<symbol>(p.
rest))
987 if (
c.is_equal(
_ex1))
996 return split_ex_to_pair(
pow(recombine_pair_to_ex(p),
c));
999 ex mul::recombine_pair_to_ex(
const expair & p)
const 1004 return dynallocate<power>(p.
rest, p.
coeff);
1007 bool mul::expair_needs_further_processing(
epp it)
1009 if (is_exactly_a<mul>(it->rest) &&
1010 ex_to<numeric>(it->coeff).is_integer()) {
1012 *it = split_ex_to_pair(recombine_pair_to_ex(*it));
1015 if (is_exactly_a<numeric>(it->rest)) {
1016 if (it->coeff.is_equal(
_ex1)) {
1020 expair ep = split_ex_to_pair(recombine_pair_to_ex(*it));
1030 ex mul::default_overall_coeff()
const 1035 void mul::combine_overall_coeff(
const ex &
c)
1039 overall_coeff = ex_to<numeric>(overall_coeff).mul_dyn(ex_to<numeric>(
c));
1042 void mul::combine_overall_coeff(
const ex & c1,
const ex & c2)
1047 overall_coeff = ex_to<numeric>(overall_coeff).mul_dyn(ex_to<numeric>(c1).power(ex_to<numeric>(c2)));
1050 bool mul::can_make_flat(
const expair & p)
const 1055 return p.
coeff.
info(info_flags::integer);
1058 bool mul::can_be_further_expanded(
const ex & e)
1060 if (is_exactly_a<mul>(e)) {
1061 for (
auto & it : ex_to<mul>(e).seq) {
1062 if (is_exactly_a<add>(it.rest) && it.coeff.info(info_flags::posint))
1065 }
else if (is_exactly_a<power>(e)) {
1066 if (is_exactly_a<add>(e.
op(0)) && e.
op(1).
info(info_flags::posint))
1075 bool monomial_case =
true;
1076 for (
const auto & i : seq) {
1077 if (!is_a<symbol>(i.rest) || !i.coeff.info(info_flags::integer)) {
1078 monomial_case =
false;
1082 if (monomial_case) {
1083 setflag(status_flags::expanded);
1088 if ((!(
options & expand_options::expand_rename_idx)) &&
1089 this->info(info_flags::has_indices))
1090 options |= expand_options::expand_rename_idx;
1092 const bool skip_idx_rename = !(
options & expand_options::expand_rename_idx);
1096 const epvector & expanded_seq = (expanded.empty() ? seq : expanded);
1104 non_adds.reserve(expanded_seq.size());
1106 for (
const auto & cit : expanded_seq) {
1107 if (is_exactly_a<add>(cit.rest) &&
1108 (cit.coeff.is_equal(
_ex1))) {
1109 if (is_exactly_a<add>(last_expanded)) {
1115 const int sizedifference = ex_to<add>(last_expanded).seq.size()-ex_to<add>(cit.rest).seq.size();
1118 const add& add1 = (sizedifference<0 ? ex_to<add>(last_expanded) : ex_to<add>(cit.rest));
1119 const add& add2 = (sizedifference<0 ? ex_to<add>(cit.rest) : ex_to<add>(last_expanded));
1121 distrseq.reserve(add1.
seq.size()+add2.
seq.size());
1126 distrseq.insert(distrseq.end(), add2.
seq.begin(), add2.
seq.end());
1128 for (
const auto & i : add2.
seq)
1129 distrseq.push_back(
expair(i.rest, ex_to<numeric>(i.coeff).mul_dyn(ex_to<numeric>(add1.
overall_coeff))));
1135 distrseq.insert(distrseq.end(), add1.
seq.begin(), add1.
seq.end());
1137 for (
const auto & i : add1.
seq)
1138 distrseq.push_back(
expair(i.rest, ex_to<numeric>(i.coeff).mul_dyn(ex_to<numeric>(add2.
overall_coeff))));
1144 exvector add1_dummy_indices, add2_dummy_indices, add_indices;
1147 if (!skip_idx_rename) {
1148 for (
const auto & i : add1.
seq) {
1150 add1_dummy_indices.insert(add1_dummy_indices.end(), add_indices.begin(), add_indices.end());
1152 for (
const auto & i : add2.
seq) {
1154 add2_dummy_indices.insert(add2_dummy_indices.end(), add_indices.begin(), add_indices.end());
1157 sort(add1_dummy_indices.begin(), add1_dummy_indices.end(),
ex_is_less());
1158 sort(add2_dummy_indices.begin(), add2_dummy_indices.end(),
ex_is_less());
1163 for (
const auto & i2 : add2.
seq) {
1168 distrseq2.reserve(add1.
seq.size());
1169 const ex i2_new = (skip_idx_rename || (dummy_subs.
op(0).
nops() == 0) ?
1171 i2.rest.subs(ex_to<lst>(dummy_subs.
op(0)),
1172 ex_to<lst>(dummy_subs.
op(1)), subs_options::no_pattern));
1173 for (
const auto & i1 : add1.
seq) {
1176 const ex rest = dynallocate<mul>(i1.rest, i2_new);
1177 if (is_exactly_a<numeric>(rest)) {
1178 oc += ex_to<numeric>(rest).
mul(ex_to<numeric>(i1.coeff).mul(ex_to<numeric>(i2.coeff)));
1180 distrseq2.push_back(
expair(rest, ex_to<numeric>(i1.coeff).mul_dyn(ex_to<numeric>(i2.coeff))));
1183 tmp_accu += dynallocate<add>(std::move(distrseq2), oc);
1185 last_expanded = tmp_accu;
1188 non_adds.push_back(split_ex_to_pair(last_expanded));
1189 last_expanded = cit.rest;
1193 non_adds.push_back(cit);
1199 if (is_exactly_a<add>(last_expanded)) {
1200 size_t n = last_expanded.
nops();
1202 distrseq.reserve(
n);
1204 if (! skip_idx_rename) {
1209 for (
size_t i=0; i<
n; ++i) {
1211 if (skip_idx_rename)
1212 factors.push_back(split_ex_to_pair(last_expanded.
op(i)));
1215 ex term = dynallocate<mul>(
factors, overall_coeff);
1216 if (can_be_further_expanded(term)) {
1217 distrseq.push_back(term.
expand());
1220 ex_to<basic>(term).setflag(status_flags::expanded);
1221 distrseq.push_back(term);
1225 return dynallocate<add>(distrseq).setflag(
options == 0 ? status_flags::expanded : 0);
1228 non_adds.push_back(split_ex_to_pair(last_expanded));
1229 ex result = dynallocate<mul>(non_adds, overall_coeff);
1230 if (can_be_further_expanded(result)) {
1234 ex_to<basic>(result).setflag(status_flags::expanded);
1260 auto cit = seq.
begin(),
last = seq.end();
1262 const ex &
factor = recombine_pair_to_ex(*cit);
1268 s.reserve(seq.size());
1271 auto cit2 = seq.
begin();
1278 s.push_back(split_ex_to_pair(expanded_factor));
1282 while (cit2!=
last) {
1283 s.push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(
options)));
size_t nops(const ex &thisex)
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to GiNaC's indexed expressions.
ex coeff(const ex &s, int n=1) const
A sequence of class expair.
Interface to GiNaC's symbolic objects.
ex op(size_t i) const override
Return operand/member at position i.
exvector get_all_dummy_indices_safely(const ex &e)
More reliable version of the form.
int to_int(const numeric &x)
ex subs(const exmap &m, unsigned options=0) const
bool is_pos_integer() const
True if object is an exact integer greater than zero.
bool has(const ex &thisex, const ex &pattern, unsigned options=0)
bool is_equal(const ex &other) const
ex expand(unsigned options=0) const
ex diff(const symbol &s, unsigned nth=1) const
Default interface of nth derivative ex::diff(s, n).
bool is_equal(const expair &other) const
Member-wise check for canonical ordering equality.
ex eval_ncmul(const exvector &v) const
int ldegree(const ex &thisex, const ex &s)
Archiving of GiNaC expressions.
Interface to GiNaC's sums of expressions.
bool is_negative(const numeric &x)
void do_print_tree(const print_tree &c, unsigned level) const
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Context for python-parsable output.
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Interface to GiNaC's products of expressions.
ex evalf(const ex &thisex)
bool info(unsigned inf) const
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...
bool info(unsigned inf) const override
Information about the object.
ex recombine_pair_to_ex(const expair &p) const override
Definition of optimizing macros.
int degree(const ex &thisex, const ex &s)
const_iterator begin() const noexcept
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Context for latex-parsable output.
#define GINAC_BIND_UNARCHIVER(classname)
ex conjugate(const ex &thisex)
bool is_integer() const
True if object is a non-complex integer.
const numeric mul(const numeric &other) const
Numerical multiplication method.
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
void construct_from_epvector(const epvector &v, bool do_index_renaming=false)
bool match(const ex &pattern) const
Check whether expression matches a specified pattern.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
ex imag_part(const ex &thisex)
expair combine_pair_with_coeff_to_pair(const expair &p, const ex &c) const override
void do_print_python_repr(const print_python_repr &c, unsigned level) const
void do_print_latex(const print_latex &c, unsigned level) const
void construct_from_2_ex(const ex &lh, const ex &rh)
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq, print_func< print_context >(&add::do_print). print_func< print_latex >(&add::do_print_latex). print_func< print_csrc >(&add::do_print_csrc). print_func< print_tree >(&add::do_print_tree). print_func< print_python_repr >(&add::do_print_python_repr)) add
To distinguish between different kinds of non-commutative objects.
ex op(const ex &thisex, size_t i)
void do_print_csrc(const print_csrc &c, unsigned level) const
Interface to symbolic matrices.
bool tryfactsubs(const ex &origfactor, const ex &patternfactor, int &nummatches, exmap &repls)
std::vector< ex > exvector
std::map< ex, ex, ex_is_less > exmap
epvector::iterator epp
expair-vector pointer
Interface to GiNaC's overloaded operators.
void print_overall_coeff(const print_context &c, const char *mul_sym) const
void do_print(const print_context &c, unsigned level) const
mul(const ex &lh, const ex &rh)
ex factor(const ex &poly, unsigned options)
Interface function to the outside world.
Base class for print_contexts.
Definition of GiNaC's lst.
ex op(size_t i) const override
Return operand/member at position i.
const numeric pow(const numeric &x, const numeric &y)
const basic & clearflag(unsigned f) const
Clear some status_flags.
ex coeff
second member of pair, must be numeric
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Lightweight wrapper for GiNaC's symbolic objects.
This class holds a two-component object, a basis and and exponent representing exponentiation.
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...
ex evalm(const ex &thisex)
ex coeff(const ex &thisex, const ex &s, int n=1)
Wrapper template for making GiNaC classes out of STL containers.
Base context for C source output.
const numeric real(const numeric &x)
std::vector< expair > epvector
expair-vector
bool is_polynomial(const ex &thisex, const ex &vars)
bool is_canonical() const
ex rest
first member of pair, an arbitrary expression
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in object s.
size_t nops() const override
Number of operands/members.
void construct_from_exvector(const exvector &v)
bool algebraic_match_mul_with_mul(const mul &e, const ex &pat, exmap &repls, int factor, int &nummatches, const std::vector< bool > &subsed, std::vector< bool > &matched)
Checks whether e matches to the pattern pat and the (possibly to be updated) list of replacements rep...
ex real_part(const ex &thisex)
void swap(expair &other)
Swap contents with other expair.
ex eval(const ex &thisex)
ex expand(const ex &thisex, unsigned options=0)
bool is_positive(const numeric &x)