74 while (i !=
seq.end()) {
77 GINAC_ASSERT(!is_order_function(i->rest));
80 GINAC_ASSERT(is_a<numeric>(i->coeff));
81 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
95 while (i !=
seq.end()) {
98 GINAC_ASSERT(!is_order_function(i->rest));
101 GINAC_ASSERT(is_a<numeric>(i->coeff));
102 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
119 inherited::read_archive(n, sym_lst);
121 seq.reserve((range.end-range.begin)/2);
123 for (
auto loc = range.begin; loc < range.end;) {
137 inherited::archive(n);
138 for (
auto & it :
seq) {
139 n.
add_ex(
"coeff", it.rest);
140 n.
add_ex(
"power", it.coeff);
161 auto i =
seq.begin(), end =
seq.end();
165 if (i !=
seq.begin())
175 c.
s << openbrace <<
'(';
177 c.
s <<
')' << closebrace;
181 if (!i->coeff.is_zero()) {
183 if (!
point.is_zero()) {
184 c.
s << openbrace <<
'(';
186 c.
s <<
')' << closebrace;
189 if (i->coeff.compare(
_ex1)) {
227 c.
s << std::string(level,
' ') << class_name() <<
" @" <<
this
228 << std::hex <<
", hash=0x" <<
hashvalue <<
", flags=0x" <<
flags << std::dec
230 size_t num =
seq.size();
231 for (
size_t i=0; i<num; ++i) {
234 c.
s << std::string(level + c.
delta_indent,
' ') <<
"-----" << std::endl;
242 c.
s << class_name() <<
"(relational(";
247 size_t num =
seq.size();
248 for (
size_t i=0; i<num; ++i) {
252 seq[i].rest.print(c);
254 seq[i].coeff.print(c);
266 if (
seq.size()>o.
seq.size())
268 if (
seq.size()<o.
seq.size())
280 auto it =
seq.begin(), o_it = o.
seq.begin();
281 while (it!=
seq.end() && o_it!=o.
seq.end()) {
282 cmpval = it->compare(*o_it);
303 throw (std::out_of_range(
"op() out of range"));
322 int max_pow = std::numeric_limits<int>::min();
323 for (
auto & it :
seq)
324 max_pow = std::max(max_pow, it.rest.degree(s));
342 int min_pow = std::numeric_limits<int>::max();
343 for (
auto & it :
seq)
344 min_pow = std::min(min_pow, it.rest.degree(s));
357 if (
var.is_equal(s)) {
363 int lo = 0, hi =
seq.size() - 1;
365 int mid = (lo + hi) / 2;
373 return seq[mid].rest;
378 throw(std::logic_error(
"pseries::coeff: compare() didn't return -1, 0 or 1"));
403 new_seq.reserve(
seq.size());
404 for (
auto & it :
seq)
405 new_seq.emplace_back(
expair(it.rest.evalf(), it.coeff));
413 return conjugate_function(*this).hold();
416 ex newpoint =
point.conjugate();
428 return real_part_function(*this).hold();
429 ex newpoint =
point.real_part();
430 if(newpoint !=
point)
431 return real_part_function(*this).hold();
434 v.reserve(
seq.size());
435 for (
auto & it :
seq)
436 v.emplace_back(
expair(it.rest.real_part(), it.coeff));
443 return imag_part_function(*this).hold();
444 ex newpoint =
point.real_part();
445 if(newpoint !=
point)
446 return imag_part_function(*this).hold();
449 v.reserve(
seq.size());
450 for (
auto & it :
seq)
451 v.emplace_back(
expair(it.rest.imag_part(), it.coeff));
457 std::unique_ptr<epvector> newseq(
nullptr);
458 for (
auto i=
seq.begin(); i!=
seq.end(); ++i) {
460 newseq->emplace_back(
expair(i->rest.eval_integ(), i->coeff));
463 ex newterm = i->rest.eval_integ();
466 newseq->reserve(
seq.size());
467 for (
auto j=
seq.begin(); j!=i; ++j)
468 newseq->push_back(*j);
473 ex newpoint =
point.eval_integ();
483 bool something_changed =
false;
484 for (
auto i=
seq.begin(); i!=
seq.end(); ++i) {
485 if (something_changed) {
486 ex newcoeff = i->rest.evalm();
490 ex newcoeff = i->rest.evalm();
492 something_changed =
true;
493 newseq.reserve(
seq.size());
494 std::copy(
seq.begin(), i, std::back_inserter<epvector>(newseq));
500 if (something_changed)
511 if (m.find(
var) != m.end())
517 newseq.reserve(
seq.size());
518 for (
auto & it :
seq)
519 newseq.emplace_back(
expair(it.rest.subs(m, options), it.coeff));
528 for (
auto & it :
seq) {
529 ex restexp = it.rest.expand();
545 for (
auto & it :
seq) {
547 new_seq.emplace_back(
expair(it.rest, it.coeff - 1));
549 ex c = it.rest * it.coeff;
557 for (
auto & it :
seq) {
559 new_seq.push_back(it);
561 ex c = it.rest.diff(s);
574 for (
auto & it :
seq) {
592 throw (std::out_of_range(
"coeffop() out of range"));
599 throw (std::out_of_range(
"exponop() out of range"));
616 if ((order <= 0) && this->
has(s)) {
618 return pseries(r, std::move(seq));
626 if (!
coeff.is_zero()) {
631 for (n=1; n<order; ++n) {
638 return pseries(r, std::move(seq));
641 if (!
coeff.is_zero())
646 deriv = deriv.
diff(s);
649 return pseries(r, std::move(seq));
658 const ex point = r.
rhs();
662 if (order > 0 && !point.
is_zero())
670 return pseries(r, std::move(seq));
690 auto a =
seq.begin(), a_end =
seq.end();
691 auto b = other.
seq.begin(), b_end = other.
seq.end();
692 int pow_a = std::numeric_limits<int>::max(), pow_b = std::numeric_limits<int>::max();
697 new_seq.push_back(*b);
707 new_seq.push_back(*a);
717 new_seq.push_back(*a);
721 }
else if (pow_b < pow_a) {
723 new_seq.push_back(*b);
730 new_seq.emplace_back(
expair(Order(
_ex1), (*a).coeff));
733 ex sum = (*a).rest + (*b).rest;
756 for (
auto & it :
seq) {
761 op = it.rest.series(r, order, options);
762 if (!it.coeff.is_equal(
_ex1))
780 new_seq.reserve(
seq.size());
782 for (
auto & it :
seq) {
784 new_seq.emplace_back(
expair(it.rest * other, it.
coeff));
786 new_seq.push_back(it);
806 if (
seq.empty() || other.
seq.empty()) {
816 const int cdeg_min = a_min + b_min;
817 int cdeg_max = a_max + b_max;
819 int higher_order_a = std::numeric_limits<int>::max();
820 int higher_order_b = std::numeric_limits<int>::max();
822 higher_order_a = a_max + b_min;
824 higher_order_b = b_max + a_min;
825 const int higher_order_c = std::min(higher_order_a, higher_order_b);
826 if (cdeg_max >= higher_order_c)
827 cdeg_max = higher_order_c - 1;
829 std::map<int, ex> rest_map_a, rest_map_b;
830 for (
const auto& it :
seq)
834 for (
const auto& it : other.
seq)
837 for (
int cdeg=cdeg_min; cdeg<=cdeg_max; ++cdeg) {
840 for (
int i=a_min; cdeg-i>=b_min; ++i) {
841 const auto& ita = rest_map_a.find(i);
842 if (ita == rest_map_a.end())
844 const auto& itb = rest_map_b.find(cdeg-i);
845 if (itb == rest_map_b.end())
848 co += ita->second * itb->second;
853 if (higher_order_c < std::numeric_limits<int>::max())
867 const ex& sym = r.
lhs();
870 std::vector<int> ldegrees;
871 std::vector<bool> ldegree_redo;
876 for (
auto & it :
seq) {
888 int real_ldegree = 0;
889 bool flag_redo =
false;
892 }
catch (std::runtime_error &) {}
894 if (real_ldegree == 0) {
901 real_ldegree = buf.
series(r, orderloop, options).
ldegree(sym);
902 }
while (real_ldegree == orderloop);
908 if (real_ldegree == 0)
913 ldegrees.push_back(
factor * real_ldegree);
914 ldegree_redo.push_back(flag_redo);
917 int degbound = order-std::accumulate(ldegrees.begin(), ldegrees.end(), 0);
922 for (
auto & it :
seq) {
923 if ( ldegree_redo[j] ) {
933 int real_ldegree = 0;
937 real_ldegree = buf.
series(r, orderloop, options).
ldegree(sym);
938 }
while ((real_ldegree == orderloop)
939 && (
factor*real_ldegree < degbound));
940 ldegrees[j] =
factor * real_ldegree;
941 degbound -=
factor * real_ldegree;
946 int degsum = std::accumulate(ldegrees.begin(), ldegrees.end(), 0);
948 if (degsum > order) {
953 auto itd = ldegrees.begin();
954 for (
auto it=
seq.begin(), itend=
seq.end(); it!=itend; ++it, ++itd) {
960 if (it ==
seq.begin())
1001 throw std::domain_error(
"pseries::power_const(): pow(0,I) is undefined");
1003 throw pole_error(
"pseries::power_const(): division by zero",1);
1010 throw std::runtime_error(
"pseries::power_const(): trying to assemble a Puiseux series");
1011 int new_ldeg = (p*base_ldeg).
to_int();
1017 new_deg = std::min((p*base_deg).
to_int(), deg);
1021 int numcoeff = new_deg - new_ldeg;
1025 if (numcoeff <= 0) {
1032 throw pole_error(
"pseries::power_const(): division by zero",1);
1036 co.reserve(numcoeff);
1038 for (
int i=1; i<numcoeff; ++i) {
1040 for (
int j=1; j<=i; ++j) {
1043 co.push_back(Order(
_ex1));
1046 sum += (p * j - (i - j)) * co[i - j] * c;
1048 co.push_back(sum /
coeff(
var, base_ldeg) / i);
1053 bool higher_order =
false;
1054 for (
int i=0; i<numcoeff; ++i) {
1056 new_seq.emplace_back(
expair(co[i], new_ldeg + i));
1059 higher_order =
true;
1063 if (!higher_order && new_deg == deg) {
1064 new_seq.emplace_back(
expair{Order(
_ex1), new_deg});
1075 for (
auto & it : newseq)
1091 bool must_expand_basis =
false;
1095 must_expand_basis =
true;
1098 bool exponent_is_regular =
true;
1102 exponent_is_regular =
false;
1105 if (!exponent_is_regular) {
1108 ex le = l.
series(r, order, options);
1115 return exp(le).
series(r, order, options);
1138 return pseries(r, std::move(new_seq));
1149 const ex& sym = r.
lhs();
1152 int real_ldegree = 0;
1155 if (real_ldegree == 0) {
1159 real_ldegree =
basis.series(r, orderloop, options).ldegree(sym);
1160 }
while (real_ldegree == orderloop);
1164 throw std::runtime_error(
"pseries::power_const(): trying to assemble a Puiseux series");
1165 int extra_terms = (real_ldegree*(1-numexp)).
to_int();
1166 ex e =
basis.series(r, order + std::max(0, extra_terms), options);
1173 result =
pseries(r, std::move(ser));
1183 const ex p = r.
rhs();
1187 if (
var.is_equal(s) &&
point.is_equal(p)) {
1192 for (
auto & it :
seq) {
1195 new_seq.emplace_back(
expair(Order(
_ex1), o));
1198 new_seq.push_back(it);
1200 return pseries(r, std::move(new_seq));
1209 throw std::logic_error(
"Cannot series expand wrt dummy variable");
1212 ex fseries =
f.series(r, order, options);
1214 fexpansion.reserve(fseries.
nops());
1215 for (
size_t i=0; i<fseries.
nops(); ++i) {
1217 currcoeff = (currcoeff == Order(
_ex1))
1221 fexpansion.emplace_back(
1227 ex aseries = (
a-
a.subs(r)).series(r, order, options);
1228 fseries =
f.series(
x == (
a.subs(r)), order, options);
1229 for (
size_t i=0; i<fseries.
nops(); ++i) {
1235 currcoeff = currcoeff.
series(r, orderforf);
1243 ex bseries = (
b-
b.subs(r)).series(r, order, options);
1244 fseries =
f.series(
x == (
b.subs(r)), order, options);
1245 for (
size_t i=0; i<fseries.
nops(); ++i) {
1251 currcoeff = currcoeff.
series(r, orderforf);
1281 throw (std::logic_error(
"ex::series(): expansion point has unknown type"));
1283 e =
bp->series(rel_, order, options);
Interface to GiNaC's sums of expressions.
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
ex series(const relational &r, int order, unsigned options=0) const override
Implementation of ex::series() for sums.
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
bool find_ex(const std::string &name, ex &ret, lst &sym_lst, unsigned index=0) const
Retrieve property of type "ex" from node.
void find_ex_by_loc(archive_node_cit loc, ex &ret, lst &sym_lst) const
Retrieve property of type "ex" from the node if it is known that this node in fact contains such a pr...
void add_ex(const std::string &name, const ex &value)
Add property of type "ex" to node.
archive_node_cit_range find_property_range(const std::string &name1, const std::string &name2) const
Find a range of locations in the vector of properties.
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
unsigned hashvalue
hash value
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.
const basic & hold() const
Stop further evaluation.
virtual ex series(const relational &r, int order, unsigned options=0) const
Default implementation of ex::series().
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.
Lightweight wrapper for GiNaC's symbolic objects.
ex diff(const symbol &s, unsigned nth=1) const
Compute partial derivative of an expression.
ex expand(unsigned options=0) const
Expand an expression.
bool is_equal(const ex &other) const
ptr< basic > bp
pointer to basic object managed by this
friend const T & ex_to(const ex &)
Return a reference to the basic-derived class T object embedded in an expression.
ex series(const ex &r, int order, unsigned options=0) const
Compute the truncated series expansion of an expression.
ex subs(const exmap &m, unsigned options=0) const
bool info(unsigned inf) const
int compare(const ex &other) const
friend bool is_a(const ex &)
Check if ex is a handle to a T, including base classes.
ex lhs() const
Left hand side of relational expression.
int ldegree(const ex &s) const
ex rhs() const
Right hand side of relational expression.
ex coeff(const ex &s, int n=1) const
ex op(size_t i) const override
Return operand/member at position i.
integral(const ex &x_, const ex &a_, const ex &b_, const ex &f_)
ex series(const relational &r, int order, unsigned options=0) const override
Default implementation of ex::series().
ex series(const relational &s, int order, unsigned options=0) const override
Implementation of ex::series() for product.
ex recombine_pair_to_ex(const expair &p) const override
Form an ex out of an expair, using the corresponding semantics.
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.
const numeric real() const
Real part of a number.
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in object s.
bool is_negative() const
True if object is not complex and less than zero.
bool is_zero() const
True if object is zero.
const numeric div(const numeric &other) const
Numerical division method.
Exception class thrown when a singularity is encountered.
ex series(const relational &s, int order, unsigned options=0) const override
Implementation of ex::series() for powers.
Base class for print_contexts.
std::ostream & s
stream to output to
Context for latex-parsable output.
Context for python-parsable output.
Context for python pretty-print output.
Context for tree-like output for debugging.
const unsigned delta_indent
size of indentation step
This class holds a extended truncated power series (positive and negative integer powers).
int ldegree(const ex &s) const override
Return degree of lowest power of the series.
ex evalf() const override
Evaluate coefficients numerically.
ex var
Series variable (holds a symbol).
bool is_zero() const
Check whether series has the value zero.
pseries shift_exponents(int deg) const
Return a new pseries object with the powers shifted by deg.
void do_print(const print_context &c, unsigned level) const
ex op(size_t i) const override
Return the ith term in the series when represented as a sum.
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
void do_print_latex(const print_latex &c, unsigned level) const
ex mul_const(const numeric &other) const
Multiply a pseries object with a numeric constant, producing a pseries object that represents the pro...
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in power series if s is the expansion variable.
void do_print_tree(const print_tree &c, unsigned level) const
ex convert_to_poly(bool no_order=false) const
Convert the pseries object to an ordinary polynomial.
size_t nops() const override
Return the number of operands including a possible order term.
void read_archive(const archive_node &n, lst &syms) override
Read (a.k.a.
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
pseries(const ex &rel_, const epvector &ops_)
Construct pseries from a vector of coefficients and powers.
ex eval_integ() const override
Evaluate integrals, if result is known.
ex expand(unsigned options=0) const override
Implementation of ex::expand() for a power series.
ex derivative(const symbol &s) const override
Implementation of ex::diff() for a power series.
ex real_part() const override
ex evalm() const override
Evaluate sums, products and integer powers of matrices.
epvector seq
Vector of {coefficient, power} pairs.
bool is_compatible_to(const pseries &other) const
Check whether series is compatible to another series (expansion variable and point are the same.
ex exponop(size_t i) const
ex coeffop(size_t i) const
Get coefficients and exponents.
void archive(archive_node &n) const override
Save (a.k.a.
void print_series(const print_context &c, const char *openbrace, const char *closebrace, const char *mul_sym, const char *pow_sym, unsigned level) const
ex series(const relational &r, int order, unsigned options=0) const override
Re-expansion of a pseries object.
void do_print_python(const print_python &c, unsigned level) const
ex imag_part() const override
void do_print_python_repr(const print_python_repr &c, unsigned level) const
bool is_terminating() const
Returns true if there is no order term, i.e.
ex conjugate() const override
ex mul_series(const pseries &other) const
Multiply one pseries object to another, producing a pseries object that represents the product.
ex power_const(const numeric &p, int deg) const
Compute the p-th power of a series.
int degree(const ex &s) const override
Return degree of highest power of the series.
ex add_series(const pseries &other) const
Add one series object to another, producing a pseries object that represents the sum.
ex collect(const ex &s, bool distributed=false) const override
Does nothing.
ex eval() const override
Perform coefficient-wise automatic term rewriting rules in this class.
This class holds a relation consisting of two expressions and a logical relation between them.
@ expanded
.expand(0) has already done its job (other expand() options ignore this flag)
@ evaluated
.eval() has already done its job
@ no_pattern
disable pattern matching
bool is_equal_same_type(const basic &other) const override
Returns true if two objects of same type are equal.
ex series(const relational &s, int order, unsigned options=0) const override
Implementation of ex::series() for symbols.
Interface to GiNaC's initially known functions.
Interface to GiNaC's symbolic integral.
Definition of GiNaC's lst.
Interface to GiNaC's products of expressions.
const numeric pow(const numeric &x, const numeric &y)
container< std::list > lst
std::map< ex, ex, ex_is_less > exmap
B & dynallocate(Args &&... args)
Constructs a new (class basic or derived) B object on the heap.
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.
attribute_pure const T & ex_to(const ex &e)
Return a reference to the basic-derived class T object embedded in an expression.
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 ls GINAC_BIND_UNARCHIVER)(lst)
Specialization of container::info() for lst.
const numeric exp(const numeric &x)
Exponential function.
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
bool is_a(const basic &obj)
Check if obj is a T, including base classes.
const numeric log(const numeric &x)
Natural logarithm.
ex factor(const ex &poly, unsigned options)
Interface function to the outside world.
int to_int(const numeric &x)
bool is_integer(const numeric &x)
bool is_exactly_a(const basic &obj)
Check if obj is a T, not including base classes.
std::vector< ex > exvector
bool is_order_function(const ex &e)
Check whether a function is the Order (O(n)) function.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to class for extended truncated power series.
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
Interface to relations between expressions.
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...