74 while (i !=
seq.end()) {
81 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
91 : seq(
std::move(ops_))
95 while (i !=
seq.end()) {
102 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
119 inherited::read_archive(
n, sym_lst);
120 auto range =
n.find_property_range(
"coeff",
"power");
121 seq.reserve((range.end-range.begin)/2);
123 for (
auto loc = range.begin; loc < range.end;) {
126 n.find_ex_by_loc(loc++, rest, sym_lst);
127 n.find_ex_by_loc(loc++,
coeff, sym_lst);
131 n.find_ex(
"var",
var, sym_lst);
132 n.find_ex(
"point",
point, sym_lst);
137 inherited::archive(
n);
138 for (
auto & it :
seq) {
139 n.add_ex(
"coeff", it.rest);
140 n.add_ex(
"power", it.coeff);
142 n.add_ex(
"var",
var);
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()) {
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) {
232 seq[i].rest.print(
c, level +
c.delta_indent);
233 seq[i].coeff.print(
c, level +
c.delta_indent);
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"));
320 return ex_to<numeric>((
seq.end()-1)->coeff).to_int();
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));
340 return ex_to<numeric>((
seq.begin())->coeff).to_int();
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));
363 int lo = 0, hi =
seq.size() - 1;
365 int mid = (lo + hi) / 2;
367 int cmp = ex_to<numeric>(
seq[mid].
coeff).compare(looking_for);
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();
422 return dynallocate<pseries>(
var==newpoint, newseq ? std::move(*newseq) :
seq);
428 return real_part_function(*this).hold();
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));
437 return dynallocate<pseries>(
var==
point, std::move(v));
443 return imag_part_function(*this).hold();
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));
452 return dynallocate<pseries>(
var==
point, std::move(v));
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));
466 newseq->reserve(
seq.size());
467 for (
auto j=
seq.begin(); j!=i; ++j)
468 newseq->push_back(*j);
475 return dynallocate<pseries>(
var==newpoint, std::move(*newseq));
483 bool something_changed =
false;
484 for (
auto i=
seq.begin(); i!=
seq.end(); ++i) {
485 if (something_changed) {
492 something_changed =
true;
493 newseq.reserve(
seq.size());
494 std::copy(
seq.begin(), i, std::back_inserter<epvector>(newseq));
500 if (something_changed)
501 return dynallocate<pseries>(
var==
point, std::move(newseq));
511 if (
m.find(
var) !=
m.end())
517 newseq.reserve(
seq.size());
518 for (
auto & it :
seq)
528 for (
auto & it :
seq) {
545 for (
auto & it :
seq) {
547 new_seq.emplace_back(
expair(it.rest, it.coeff - 1));
551 new_seq.emplace_back(
expair(
c, it.coeff - 1));
557 for (
auto & it :
seq) {
559 new_seq.push_back(it);
563 new_seq.emplace_back(
expair(
c, it.coeff));
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"));
613 const symbol &s = ex_to<symbol>(
r.lhs());
646 deriv = deriv.
diff(s);
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);
702 pow_a = ex_to<numeric>((*a).coeff).to_int();
707 new_seq.push_back(*a);
712 pow_b = ex_to<numeric>((*b).coeff).to_int();
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) {
758 if (is_exactly_a<pseries>(it.rest))
762 if (!it.coeff.is_equal(
_ex1))
763 op = ex_to<pseries>(
op).mul_const(ex_to<numeric>(it.coeff));
766 acc = ex_to<pseries>(acc).add_series(ex_to<pseries>(
op));
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)
831 rest_map_a[ex_to<numeric>(it.coeff).to_int()] = it.rest;
834 for (
const auto& it : other.
seq)
835 rest_map_b[ex_to<numeric>(it.coeff).to_int()] = it.rest;
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())
870 std::vector<int> ldegrees;
871 std::vector<bool> ldegree_redo;
876 for (
auto & it :
seq) {
883 factor = ex_to<numeric>(expon).to_int();
888 int real_ldegree = 0;
889 bool flag_redo =
false;
892 }
catch (std::runtime_error &) {}
894 if (real_ldegree == 0) {
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] ) {
929 factor = ex_to<numeric>(expon).to_int();
933 int real_ldegree = 0;
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())
961 acc = ex_to<pseries>(
op);
963 acc = ex_to<pseries>(acc.
mul_series(ex_to<pseries>(
op)));
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)
1087 if (is_exactly_a<pseries>(
basis))
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) {
1138 return pseries(
r, std::move(new_seq));
1152 int real_ldegree = 0;
1155 if (real_ldegree == 0) {
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();
1170 result = ex_to<pseries>(e).power_const(numexp,
order);
1173 result =
pseries(
r, std::move(ser));
1185 const symbol &s = ex_to<symbol>(
r.lhs());
1192 for (
auto & it :
seq) {
1193 int o = ex_to<numeric>(it.coeff).to_int();
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");
1214 fexpansion.reserve(fseries.
nops());
1215 for (
size_t i=0; i<fseries.
nops(); ++i) {
1216 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1217 currcoeff = (currcoeff == Order(
_ex1))
1221 fexpansion.emplace_back(
1222 expair(currcoeff, ex_to<pseries>(fseries).exponop(i)));
1226 ex result = dynallocate<pseries>(
r, std::move(fexpansion));
1229 for (
size_t i=0; i<fseries.
nops(); ++i) {
1230 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1233 ex currexpon = ex_to<pseries>(fseries).exponop(i);
1234 int orderforf =
order-ex_to<numeric>(currexpon).to_int()-1;
1235 currcoeff = currcoeff.
series(
r, orderforf);
1236 ex term = ex_to<pseries>(aseries).power_const(ex_to<numeric>(currexpon+1),
order);
1237 term = ex_to<pseries>(term).mul_const(ex_to<numeric>(-1/(currexpon+1)));
1238 term = ex_to<pseries>(term).mul_series(ex_to<pseries>(currcoeff));
1239 result = ex_to<pseries>(result).add_series(ex_to<pseries>(term));
1245 for (
size_t i=0; i<fseries.
nops(); ++i) {
1246 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1249 ex currexpon = ex_to<pseries>(fseries).exponop(i);
1250 int orderforf =
order-ex_to<numeric>(currexpon).to_int()-1;
1251 currcoeff = currcoeff.
series(
r, orderforf);
1252 ex term = ex_to<pseries>(bseries).power_const(ex_to<numeric>(currexpon+1),
order);
1253 term = ex_to<pseries>(term).mul_const(ex_to<numeric>(1/(currexpon+1)));
1254 term = ex_to<pseries>(term).mul_series(ex_to<pseries>(currcoeff));
1255 result = ex_to<pseries>(result).add_series(ex_to<pseries>(term));
1276 if (is_a<relational>(
r))
1277 rel_ = ex_to<relational>(
r);
1278 else if (is_a<symbol>(
r))
1281 throw (std::logic_error(
"ex::series(): expansion point has unknown type"));
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...
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.
Wrapper template for making GiNaC classes out of STL containers.
Lightweight wrapper for GiNaC's symbolic objects.
bool find(const ex &pattern, exset &found) const
Find all occurrences of a pattern.
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
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
ex lhs() const
Left hand side of relational expression.
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
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.
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.
Context for latex-parsable output.
Context for python-parsable output.
Context for python pretty-print output.
Context for tree-like output for debugging.
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)
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.
const numeric exp(const numeric &x)
Exponential function.
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
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)
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.
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...