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))
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)
263 c.s << class_name() <<
'(';
265 for (
size_t i=1; i<
nops(); ++i) {
287 for (
auto & it :
seq) {
305 for (
auto & it :
seq) {
323 for (
auto & it :
seq) {
337 for (
auto & it :
seq) {
354 for (
auto & it :
seq) {
374 for (
auto & it :
seq) {
383 return inherited::info(inf);
388 for (
auto & it :
seq) {
389 if (!it.rest.is_polynomial(var) ||
401 for (
auto & it :
seq) {
402 if (ex_to<numeric>(it.coeff).is_integer())
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())
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)
438 return dynallocate<mul>(coeffseq);
441 bool coeff_found =
false;
442 for (
auto & it :
seq) {
446 coeffseq.push_back(
c);
449 coeffseq.push_back(t);
454 return dynallocate<mul>(coeffseq);
482 size_t seq_size =
seq.size();
486 }
else if (seq_size==0) {
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),
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);
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));
591 for (
auto & it :
seq) {
599 ex temp = rp*new_rp - ip*new_ip;
600 ip = ip*new_rp + rp*new_ip;
625 if (
seq.size() == 1 &&
seq[0].coeff.is_equal(
_ex1)
626 && is_a<matrix>(
seq[0].rest))
633 s.reserve(
seq.size());
635 bool have_matrix =
false;
636 epvector::iterator the_matrix;
638 for (
auto & it :
seq) {
641 if (is_a<matrix>(
m)) {
643 the_matrix = s.
end() - 1;
651 matrix m = ex_to<matrix>(the_matrix->rest);
654 return m.mul_scalar(scalar);
663 return inherited::eval_ncmul(v);
666 for (
auto & it :
seq)
668 return it.rest.eval_ncmul(v);
669 return inherited::eval_ncmul(v);
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;
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;
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++)
792 divide_by *=
pow(subsed_pattern, nummatches);
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)){
807 divide_by *=
pow(subsed_pattern, nummatches);
810 multiply_by *=
pow(subsed_result, nummatches);
816 bool subsfound =
false;
817 for (
size_t i=0; i<subsed.size(); i++) {
826 return ((*
this)/divide_by)*multiply_by;
833 std::unique_ptr<epvector> newepv(
nullptr);
834 for (
auto i=
seq.begin(); i!=
seq.end(); ++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);
865 size_t num =
seq.size();
871 auto i =
seq.begin(), end =
seq.end();
872 auto i2 = mulseq.begin();
881 return dynallocate<add>(addseq);
886 return inherited::compare_same_type(other);
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();
906 noncommutative_element = i;
907 all_commutative =
false;
911 if (noncommutative_element->rest.return_type_tinfo() != i->rest.return_type_tinfo()) {
925 return make_return_type_t<mul>();
928 for (
auto & it :
seq)
930 return it.rest.return_type_tinfo();
933 return make_return_type_t<mul>();
938 return dynallocate<mul>(v, oc, do_index_renaming);
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))
962 if (is_exactly_a<symbol>(e))
966 if (
c.is_equal(
_ex1))
983 if (is_exactly_a<symbol>(p.
rest))
987 if (
c.is_equal(
_ex1))
1004 return dynallocate<power>(p.
rest, p.
coeff);
1009 if (is_exactly_a<mul>(it->rest) &&
1010 ex_to<numeric>(it->coeff).is_integer()) {
1015 if (is_exactly_a<numeric>(it->rest)) {
1016 if (it->coeff.is_equal(
_ex1)) {
1060 if (is_exactly_a<mul>(e)) {
1061 for (
auto & it : ex_to<mul>(e).
seq) {
1065 }
else if (is_exactly_a<power>(e)) {
1075 bool monomial_case =
true;
1076 for (
const auto & i :
seq) {
1078 monomial_case =
false;
1082 if (monomial_case) {
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)),
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;
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)
1217 distrseq.push_back(term.
expand());
1221 distrseq.push_back(term);
1268 s.reserve(
seq.size());
1271 auto cit2 =
seq.begin();
1282 while (cit2!=
last) {
Interface to GiNaC's sums of expressions.
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
expair combine_pair_with_coeff_to_pair(const expair &p, const ex &c) const override
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
const basic & clearflag(unsigned f) const
Clear some status_flags.
const basic & setflag(unsigned f) const
Set some status_flags.
ex diff(const symbol &s, unsigned nth=1) const
Default interface of nth derivative ex::diff(s, n).
virtual bool has(const ex &other, unsigned options=0) const
Test for occurrence of a pattern.
unsigned flags
of type status_flags
virtual void print(const print_context &c, unsigned level=0) const
Output to stream.
ex subs_one_level(const exmap &m, unsigned options) const
Helper function for subs().
const basic & hold() const
Stop further evaluation.
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Wrapper template for making GiNaC classes out of STL containers.
ex op(size_t i) const override
Return operand/member at position i.
Lightweight wrapper for GiNaC's symbolic objects.
bool match(const ex &pattern) const
Check whether expression matches a specified pattern.
ex expand(unsigned options=0) const
Expand an expression.
bool is_equal(const ex &other) const
int degree(const ex &s) const
const_iterator end() const noexcept
ex subs(const exmap &m, unsigned options=0) const
bool info(unsigned inf) const
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
int ldegree(const ex &s) const
ex coeff(const ex &s, int n=1) const
void swap(expair &other)
Swap contents with other expair.
ex rest
first member of pair, an arbitrary expression
ex coeff
second member of pair, must be numeric
bool is_equal(const expair &other) const
Member-wise check for canonical ordering equality.
A sequence of class expair.
size_t nops() const override
Number of operands/members.
void construct_from_epvector(const epvector &v, bool do_index_renaming=false)
void construct_from_2_ex(const ex &lh, const ex &rh)
bool is_canonical() const
Check if this expairseq is in sorted (canonical) form.
void construct_from_exvector(const exvector &v)
epvector evalchildren() const
Member-wise evaluate the expairs in this sequence.
ex op(size_t i) const override
Return operand/member at position i.
void do_print_tree(const print_tree &c, unsigned level) const
@ expand_rename_idx
used internally by mul::expand()
@ algebraic
enable algebraic matching
ex thisexpairseq(const epvector &v, const ex &oc, bool do_index_renaming=false) const override
Create an object of this type.
bool info(unsigned inf) const override
Information about the object.
ex real_part() const override
bool expair_needs_further_processing(epp it) override
ex evalf() const override
Evaluate object numerically.
epvector expandchildren(unsigned options) const
Member-wise expand the expairs representing this sequence.
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
bool is_polynomial(const ex &var) const override
Check whether this is a polynomial in the given variables.
return_type_t return_type_tinfo() const override
ex default_overall_coeff() const override
void do_print_csrc(const print_csrc &c, unsigned level) const
unsigned return_type() const override
void do_print(const print_context &c, unsigned level) const
void do_print_python_repr(const print_python_repr &c, unsigned level) const
ex conjugate() const override
bool can_make_flat(const expair &p) const override
ex imag_part() const override
expair combine_ex_with_coeff_to_pair(const ex &e, const ex &c) const override
void combine_overall_coeff(const ex &c) override
int ldegree(const ex &s) const override
Return degree of lowest power in object s.
ex eval() const override
Perform automatic term rewriting rules in this class.
expair split_ex_to_pair(const ex &e) const override
Form an expair from an ex, using the corresponding semantics.
ex expand(unsigned options=0) const override
Expand expression, i.e.
int degree(const ex &s) const override
Return degree of highest power in object s.
void do_print_latex(const print_latex &c, unsigned level) const
static bool can_be_further_expanded(const ex &e)
ex derivative(const symbol &s) const override
Implementation of ex::diff() for a product.
void find_real_imag(ex &, ex &) const
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in object s.
ex recombine_pair_to_ex(const expair &p) const override
Form an ex out of an expair, using the corresponding semantics.
ex evalm() const override
Evaluate sums, products and integer powers of matrices.
void print_overall_coeff(const print_context &c, const char *mul_sym) const
expair combine_pair_with_coeff_to_pair(const expair &p, const ex &c) const override
ex algebraic_subs_mul(const exmap &m, unsigned options) const
ex eval_ncmul(const exvector &v) const override
bool has(const ex &other, unsigned options=0) const override
Test for occurrence of a pattern.
mul(const ex &lh, const ex &rh)
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
bool is_pos_integer() const
True if object is an exact integer greater than zero.
bool is_integer() const
True if object is a non-complex integer.
const numeric mul(const numeric &other) const
Numerical multiplication method.
const numeric div(const numeric &other) const
Numerical division method.
This class holds a two-component object, a basis and and exponent representing exponentiation.
Base class for print_contexts.
Base context for C source output.
Context for latex-parsable output.
Context for python-parsable output.
@ noncommutative_composite
@ expanded
.expand(0) has already done its job (other expand() options ignore this flag)
@ evaluated
.eval() has already done its job
@ hash_calculated
.calchash() has already done its job
@ no_pattern
disable pattern matching
@ algebraic
enable algebraic substitutions
Definition of optimizing macros.
Interface to GiNaC's indexed expressions.
Definition of GiNaC's lst.
Interface to symbolic matrices.
Interface to GiNaC's products of expressions.
const numeric pow(const numeric &x, const numeric &y)
std::map< ex, ex, ex_is_less > exmap
std::vector< expair > epvector
expair-vector
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
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...
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
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
epvector::iterator epp
expair-vector pointer
ex factor(const ex &poly, unsigned options)
Interface function to the outside world.
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...
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.
bool tryfactsubs(const ex &origfactor, const ex &patternfactor, int &nummatches, exmap &repls)
std::vector< ex > exvector
exvector get_all_dummy_indices_safely(const ex &e)
More reliable version of the form.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
To distinguish between different kinds of non-commutative objects.
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...