59 bool operator()(
const epp &lh,
const epp &rh)
const
61 return (*lh).is_less(*rh);
114 inherited::read_archive(
n, sym_lst);
115 auto range =
n.find_property_range(
"rest",
"coeff");
116 seq.reserve((range.end-range.begin)/2);
118 for (
auto loc = range.begin; loc < range.end;) {
121 n.find_ex_by_loc(loc++, rest, sym_lst);
122 n.find_ex_by_loc(loc++,
coeff, sym_lst);
134 inherited::archive(
n);
135 for (
auto & i :
seq) {
136 n.add_ex(
"rest", i.rest);
137 n.add_ex(
"coeff", i.coeff);
158 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this
159 << std::hex <<
", hash=0x" <<
hashvalue <<
", flags=0x" <<
flags << std::dec
160 <<
", nops=" <<
nops()
162 size_t num =
seq.size();
163 for (
size_t i=0; i<num; ++i) {
164 seq[i].rest.print(
c, level +
c.delta_indent);
165 seq[i].coeff.print(
c, level +
c.delta_indent);
167 c.s << std::string(level +
c.delta_indent,
' ') <<
"-----" << std::endl;
170 c.s << std::string(level +
c.delta_indent,
' ') <<
"-----" << std::endl
171 << std::string(level +
c.delta_indent,
' ') <<
"overall_coeff" << std::endl;
174 c.s << std::string(level +
c.delta_indent,
' ') <<
"=====" << std::endl;
187 for (
auto & i :
seq) {
189 this->
setflag(status_flags::has_indices);
190 this->
clearflag(status_flags::has_no_indices);
194 this->
clearflag(status_flags::has_indices);
195 this->
setflag(status_flags::has_no_indices);
199 return inherited::info(inf);
221 v.reserve(
seq.size()+1);
223 for (
auto & it :
seq)
230 if(is_a<numeric>(newcoeff))
255 for (
auto i=epv.begin(); i!=epv.end(); ++i) {
257 newepv->push_back(i->conjugate());
265 newepv->reserve(epv.size());
266 for (
auto j=epv.begin(); j!=i; ++j) {
267 newepv->push_back(*j);
269 newepv->push_back(
x);
292 if (
typeid(*
this) ==
typeid(ex_to<basic>(pattern))) {
296 bool has_global_wildcard =
false;
298 for (
size_t i=0; i<pattern.
nops(); i++) {
299 if (is_exactly_a<wildcard>(pattern.
op(i))) {
300 has_global_wildcard =
true;
301 global_wildcard = pattern.
op(i);
310 exmap tmp_repl = repl_lst;
318 for (
size_t i=0; i<
nops(); i++)
319 ops.push_back(
op(i));
323 for (
size_t i=0; i<pattern.
nops(); i++) {
324 ex p = pattern.
op(i);
325 if (has_global_wildcard && p.
is_equal(global_wildcard))
327 auto it = ops.
begin(), itend = ops.end();
328 while (it != itend) {
329 if (it->match(p, tmp_repl)) {
339 if (has_global_wildcard) {
344 size_t num = ops.size();
347 for (
size_t i=0; i<num; i++)
350 for (
auto & it : tmp_repl) {
351 if (it.first.is_equal(global_wildcard)) {
360 repl_lst[global_wildcard] = rest;
383 return static_cast<const mul *
>(
this)->algebraic_subs_mul(
m,
options);
398 if (
seq.size() != o.
seq.size())
399 return (
seq.size()<o.
seq.size()) ? -1 : 1;
406 auto cit1 =
seq.begin(), last1 =
seq.end();
407 auto cit2 = o.
seq.begin(), last2 = o.
seq.end();
408 for (; (cit1!=last1) && (cit2!=last2); ++cit1, ++cit2) {
409 cmpval = (*cit1).compare(*cit2);
410 if (cmpval!=0)
return cmpval;
424 if (
seq.size()!=o.
seq.size())
431 auto cit2 = o.
seq.begin();
432 for (
auto & cit1 :
seq) {
433 if (!cit1.is_equal(*cit2))
449 for (
auto & i :
seq) {
450 v ^= i.rest.gethash();
452 v ^= i.coeff.gethash();
469 if (!expanded.empty()) {
491 return expairseq(v, oc, do_index_renaming);
496 return expairseq(std::move(vp), oc, do_index_renaming);
509 unsigned this_precedence,
510 unsigned upper_precedence)
const
512 if (this_precedence <= upper_precedence)
514 auto it =
seq.begin(), it_last =
seq.end() - 1;
515 for (; it!=it_last; ++it) {
525 if (this_precedence <= upper_precedence)
566 if (is_exactly_a<numeric>(it->rest) &&
567 it->coeff.is_equal(
_ex1)) {
592 add_dyn(ex_to<numeric>(c1).
mul(ex_to<numeric>(c2)));
607 const std::type_info& typeid_this =
typeid(*this);
608 if (
typeid(ex_to<basic>(lh)) == typeid_this) {
609 if (
typeid(ex_to<basic>(rh)) == typeid_this) {
614 ex_to<expairseq>(newrh));
618 ex_to<expairseq>(rh));
624 }
else if (
typeid(ex_to<basic>(rh)) == typeid_this) {
629 if (is_exactly_a<numeric>(lh)) {
630 if (is_exactly_a<numeric>(rh)) {
638 if (is_exactly_a<numeric>(rh)) {
648 if (!ex_to<numeric>(p1.
coeff).is_zero()) {
673 auto first1 = s1.
seq.begin(), last1 = s1.
seq.end();
674 auto first2 = s2.
seq.begin(), last2 = s2.
seq.end();
676 seq.reserve(s1.
seq.size()+s2.
seq.size());
678 bool needs_further_processing=
false;
680 while (first1!=last1 && first2!=last2) {
681 int cmpval = (*first1).rest.compare((*first2).rest);
685 const numeric &newcoeff = ex_to<numeric>(first1->coeff).
686 add(ex_to<numeric>(first2->coeff));
688 seq.push_back(
expair(first1->rest,newcoeff));
690 needs_further_processing =
true;
695 }
else if (cmpval<0) {
696 seq.push_back(*first1);
699 seq.push_back(*first2);
704 while (first1!=last1) {
705 seq.push_back(*first1);
708 while (first2!=last2) {
709 seq.push_back(*first2);
713 if (needs_further_processing) {
724 if (is_exactly_a<numeric>(e)) {
730 auto first = s.
seq.begin(),
last = s.
seq.end();
733 seq.reserve(s.
seq.size()+1);
734 bool p_pushed =
false;
736 bool needs_further_processing=
false;
739 while (first!=
last) {
740 int cmpval = (*first).rest.compare(p.
rest);
743 const numeric &newcoeff = ex_to<numeric>(first->coeff).
746 seq.push_back(
expair(first->rest,newcoeff));
748 needs_further_processing =
true;
753 }
else if (cmpval<0) {
754 seq.push_back(*first);
765 while (first!=
last) {
766 seq.push_back(*first);
774 if (needs_further_processing) {
812 make_flat(std::move(v), do_index_renaming);
825 bool do_idx_rename =
false;
827 const std::type_info& typeid_this =
typeid(*this);
828 for (
auto & cit : v) {
829 if (
typeid(ex_to<basic>(cit)) == typeid_this) {
831 noperands += ex_to<expairseq>(cit).seq.size();
833 if (is_a<mul>(*
this) && (!do_idx_rename) &&
835 do_idx_rename =
true;
839 seq.reserve(v.size()+noperands-nexpairseqs);
843 for (
auto & cit : v) {
844 if (
typeid(ex_to<basic>(cit)) == typeid_this) {
846 const expairseq &subseqref = ex_to<expairseq>(newfactor);
848 for (
auto & cit_s : subseqref.
seq) {
849 seq.push_back(cit_s);
852 if (is_exactly_a<numeric>(cit))
870 bool really_need_rename_inds =
false;
872 const std::type_info& typeid_this =
typeid(*this);
873 for (
auto & cit : v) {
874 if (
typeid(ex_to<basic>(cit.rest)) == typeid_this) {
876 noperands += ex_to<expairseq>(cit.rest).seq.size();
878 if ((!really_need_rename_inds) && is_a<mul>(*
this) &&
880 really_need_rename_inds =
true;
882 do_index_renaming = do_index_renaming && really_need_rename_inds;
885 seq.reserve(v.size()+noperands-nexpairseqs);
889 for (
auto & cit : v) {
890 if (
typeid(ex_to<basic>(cit.rest)) == typeid_this &&
891 this->can_make_flat(cit)) {
893 const expairseq &subseqref = ex_to<expairseq>(newrest);
895 for (
auto & cit_s : subseqref.
seq) {
897 ex_to<numeric>(cit_s.coeff).mul_dyn(ex_to<numeric>(cit.coeff))));
900 if (cit.is_canonical_numeric())
929 bool needs_further_processing =
false;
931 auto itin1 =
seq.begin();
932 auto itin2 = itin1 + 1;
937 bool must_copy =
false;
938 while (itin2!=
last) {
939 if (itin1->rest.compare(itin2->rest)==0) {
940 itin1->coeff = ex_to<numeric>(itin1->coeff).
941 add_dyn(ex_to<numeric>(itin2->coeff));
943 needs_further_processing =
true;
946 if (!ex_to<numeric>(itin1->coeff).is_zero()) {
955 if (!ex_to<numeric>(itin1->coeff).is_zero()) {
963 if (needs_further_processing) {
977 auto it =
seq.begin(), itend =
seq.end();
979 for (++it; it!=itend; it_last=it, ++it) {
980 if (!(it_last->is_less(*it) || it_last->is_equal(*it))) {
981 if (!is_exactly_a<numeric>(it_last->rest) ||
982 !is_exactly_a<numeric>(it->rest)) {
984 if (!is_exactly_a<numeric>(it_last->rest) ||
985 !is_exactly_a<numeric>(it->rest)) {
990 std::clog <<
"pair1:" << std::endl;
993 std::clog <<
"pair2:" << std::endl;
1018 s.reserve(
seq.size());
1021 s.insert(s.begin(),
seq.begin(), cit);
1028 while (cit !=
last) {
1056 s.reserve(
seq.size());
1059 s.insert(s.begin(),
seq.begin(), cit);
1062 s.push_back(evaled_pair);
1066 while (cit !=
last) {
1092 for (
auto & it :
m) {
1093 if (is_exactly_a<mul>(it.first) || is_exactly_a<power>(it.first)) {
1106 while (cit !=
last) {
1114 s.reserve(
seq.size());
1117 s.insert(s.begin(),
seq.begin(), cit);
1124 while (cit !=
last) {
1138 while (cit !=
last) {
1146 s.reserve(
seq.size());
1149 s.insert(s.begin(),
seq.begin(), cit);
1152 s.push_back(subsed_pair);
1156 while (cit !=
last) {
Interface to GiNaC's sums of expressions.
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
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.
unsigned hashvalue
hash value
unsigned flags
of type status_flags
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.
virtual ex coeff(const ex &s, int n=1) const
Return coefficient of degree n in object s.
Wrapper template for making GiNaC classes out of STL containers.
Lightweight wrapper for GiNaC's symbolic objects.
const_iterator begin() const noexcept
ex expand(unsigned options=0) const
Expand an expression.
bool is_equal(const ex &other) const
ex subs(const exmap &m, unsigned options=0) const
bool info(unsigned inf) const
int compare(const ex &other) const
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
ex coeff(const ex &s, int n=1) const
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.
ex eval() const override
Perform coefficient-wise automatic term rewriting rules in this class.
epvector subschildren(const exmap &m, unsigned options=0) const
Member-wise substitute in this sequence.
void combine_same_terms_sorted_seq()
Compact a presorted expairseq by combining all matching expairs to one each.
size_t nops() const override
Number of operands/members.
bool is_equal_same_type(const basic &other) const override
Returns true if two objects of same type are equal.
expairseq(const ex &lh, const ex &rh)
virtual bool expair_needs_further_processing(epp it)
ex conjugate() const override
void construct_from_2_expairseq(const expairseq &s1, const expairseq &s2)
bool match(const ex &pattern, exmap &repl_lst) const override
Check whether the expression matches a given pattern.
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
unsigned return_type() const override
void construct_from_epvector(const epvector &v, bool do_index_renaming=false)
void construct_from_2_ex(const ex &lh, const ex &rh)
virtual ex default_overall_coeff() const
void archive(archive_node &n) const override
Save (serialize) the object into archive node.
virtual void printpair(const print_context &c, const expair &p, unsigned upper_precedence) const
bool is_canonical() const
Check if this expairseq is in sorted (canonical) form.
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
virtual ex thisexpairseq(const epvector &v, const ex &oc, bool do_index_renaming=false) const
Create an object of this type.
virtual expair combine_pair_with_coeff_to_pair(const expair &p, const ex &c) const
bool info(unsigned inf) const override
Information about the object.
void construct_from_exvector(const exvector &v)
void read_archive(const archive_node &n, lst &syms) override
Load (deserialize) the object from an archive node.
virtual expair combine_ex_with_coeff_to_pair(const ex &e, const ex &c) const
void make_flat(const exvector &v)
Combine this expairseq with argument exvector.
virtual void printseq(const print_context &c, char delim, unsigned this_precedence, unsigned upper_precedence) const
virtual bool can_make_flat(const expair &p) const
ex expand(unsigned options=0) const override
Expand expression, i.e.
void construct_from_expairseq_ex(const expairseq &s, const ex &e)
void do_print(const print_context &c, unsigned level) const
epvector evalchildren() const
Member-wise evaluate the expairs in this sequence.
ex op(size_t i) const override
Return operand/member at position i.
virtual ex recombine_pair_to_ex(const expair &p) const
Form an ex out of an expair, using the corresponding semantics.
void do_print_tree(const print_tree &c, unsigned level) const
virtual void combine_overall_coeff(const ex &c)
ex map(map_function &f) const override
Construct new expression by applying the specified function to all sub-expressions (one level only,...
epvector expandchildren(unsigned options) const
Member-wise expand the expairs in this sequence.
void canonicalize()
Brings this expairseq into a sorted (canonical) form.
unsigned calchash() const override
Compute the hash value of an object and if it makes sense to store it in the objects status_flags,...
virtual expair split_ex_to_pair(const ex &e) const
Form an expair from an ex, using the corresponding semantics.
Class to handle the renaming of dummy indices.
ex handle_factor(const ex &x, const ex &coeff)
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
bool is_zero() const
True if object is zero.
Base class for print_contexts.
Context for tree-like output for debugging.
@ 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
@ pattern_is_not_product
used internally by expairseq::subschildren()
@ pattern_is_product
used internally by expairseq::subschildren()
@ algebraic
enable algebraic substitutions
Definition of optimizing macros.
Interface to sequences of expression pairs.
Interface to GiNaC's indexed expressions.
Definition of GiNaC's lst.
Interface to GiNaC's products of expressions.
std::map< ex, ex, ex_is_less > exmap
std::vector< expair > epvector
expair-vector
epvector * conjugateepvector(const epvector &epv)
Complex conjugate every element of an epvector.
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
bool match(const ex &thisex, const ex &pattern, exmap &repl_lst)
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
static unsigned make_hash_seed(const std::type_info &tinfo)
We need a hash function which gives different values for objects of different types.
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
epvector::iterator epp
expair-vector pointer
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...
std::vector< ex > exvector
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to relations between expressions.
Function object not caring about the numerical coefficients for insertion into third argument of STL'...
Function object for map().
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...
Interface to GiNaC's wildcard objects.