75 while (i !=
seq.end()) {
82 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
92 : seq(
std::move(ops_))
96 while (i !=
seq.end()) {
103 GINAC_ASSERT(ex_to<numeric>(i->coeff) < ex_to<numeric>(ip1->coeff));
120 inherited::read_archive(
n, sym_lst);
121 auto range =
n.find_property_range(
"coeff",
"power");
122 seq.reserve((range.end-range.begin)/2);
124 for (
auto loc = range.begin; loc < range.end;) {
127 n.find_ex_by_loc(loc++, rest, sym_lst);
128 n.find_ex_by_loc(loc++,
coeff, sym_lst);
132 n.find_ex(
"var",
var, sym_lst);
133 n.find_ex(
"point",
point, sym_lst);
138 inherited::archive(
n);
139 for (
auto & it :
seq) {
140 n.add_ex(
"coeff", it.rest);
141 n.add_ex(
"power", it.coeff);
143 n.add_ex(
"var",
var);
162 auto i =
seq.begin(), end =
seq.end();
166 if (i !=
seq.begin())
176 c.s << openbrace <<
'(';
178 c.s <<
')' << closebrace;
182 if (!i->coeff.is_zero()) {
185 c.s << openbrace <<
'(';
187 c.s <<
')' << closebrace;
190 if (i->coeff.compare(
_ex1)) {
228 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this
229 << std::hex <<
", hash=0x" <<
hashvalue <<
", flags=0x" <<
flags << std::dec
231 size_t num =
seq.size();
232 for (
size_t i=0; i<num; ++i) {
233 seq[i].rest.print(
c, level +
c.delta_indent);
234 seq[i].coeff.print(
c, level +
c.delta_indent);
235 c.s << std::string(level +
c.delta_indent,
' ') <<
"-----" << std::endl;
243 c.s << class_name() <<
"(relational(";
248 size_t num =
seq.size();
249 for (
size_t i=0; i<num; ++i) {
253 seq[i].rest.print(
c);
255 seq[i].coeff.print(
c);
267 if (
seq.size()>o.
seq.size())
269 if (
seq.size()<o.
seq.size())
281 auto it =
seq.begin(), o_it = o.
seq.begin();
282 while (it!=
seq.end() && o_it!=o.
seq.end()) {
283 cmpval = it->compare(*o_it);
304 throw (std::out_of_range(
"op() out of range"));
321 return ex_to<numeric>((
seq.end()-1)->coeff).to_int();
323 int max_pow = std::numeric_limits<int>::min();
324 for (
auto & it :
seq)
325 max_pow = std::max(max_pow, it.rest.degree(s));
341 return ex_to<numeric>((
seq.begin())->coeff).to_int();
343 int min_pow = std::numeric_limits<int>::max();
344 for (
auto & it :
seq)
345 min_pow = std::min(min_pow, it.rest.degree(s));
364 int lo = 0, hi =
seq.size() - 1;
366 int mid = (lo + hi) / 2;
368 int cmp = ex_to<numeric>(
seq[mid].
coeff).compare(looking_for);
374 return seq[mid].rest;
379 throw(std::logic_error(
"pseries::coeff: compare() didn't return -1, 0 or 1"));
404 new_seq.reserve(
seq.size());
405 for (
auto & it :
seq)
406 new_seq.emplace_back(
expair(it.rest.evalf(), it.coeff));
414 return conjugate_function(*this).hold();
423 return dynallocate<pseries>(
var==newpoint, newseq ? std::move(*newseq) :
seq);
429 return real_part_function(*this).hold();
431 if(newpoint !=
point)
432 return real_part_function(*this).hold();
435 v.reserve(
seq.size());
436 for (
auto & it :
seq)
437 v.emplace_back(
expair(it.rest.real_part(), it.coeff));
438 return dynallocate<pseries>(
var==
point, std::move(v));
444 return imag_part_function(*this).hold();
446 if(newpoint !=
point)
447 return imag_part_function(*this).hold();
450 v.reserve(
seq.size());
451 for (
auto & it :
seq)
452 v.emplace_back(
expair(it.rest.imag_part(), it.coeff));
453 return dynallocate<pseries>(
var==
point, std::move(v));
458 std::unique_ptr<epvector> newseq(
nullptr);
459 for (
auto i=
seq.begin(); i!=
seq.end(); ++i) {
461 newseq->emplace_back(
expair(i->rest.eval_integ(), i->coeff));
467 newseq->reserve(
seq.size());
468 for (
auto j=
seq.begin(); j!=i; ++j)
469 newseq->push_back(*j);
476 return dynallocate<pseries>(
var==newpoint, std::move(*newseq));
484 bool something_changed =
false;
485 for (
auto i=
seq.begin(); i!=
seq.end(); ++i) {
486 if (something_changed) {
493 something_changed =
true;
494 newseq.reserve(
seq.size());
495 std::copy(
seq.begin(), i, std::back_inserter<epvector>(newseq));
501 if (something_changed)
502 return dynallocate<pseries>(
var==
point, std::move(newseq));
512 if (
m.find(
var) !=
m.end())
518 newseq.reserve(
seq.size());
519 for (
auto & it :
seq)
529 for (
auto & it :
seq) {
546 for (
auto & it :
seq) {
548 new_seq.emplace_back(
expair(it.rest, it.coeff - 1));
550 ex c = it.rest * it.coeff;
552 new_seq.emplace_back(
expair(
c, it.coeff - 1));
558 for (
auto & it :
seq) {
560 new_seq.push_back(it);
562 ex c = it.rest.diff(s);
564 new_seq.emplace_back(
expair(
c, it.coeff));
575 for (
auto & it :
seq) {
593 throw (std::out_of_range(
"coeffop() out of range"));
600 throw (std::out_of_range(
"exponop() out of range"));
614 const symbol &s = ex_to<symbol>(
r.lhs());
647 deriv = deriv.
diff(s);
659 const ex point =
r.rhs();
691 auto a =
seq.begin(), a_end =
seq.end();
692 auto b = other.
seq.begin(), b_end = other.
seq.end();
693 int pow_a = std::numeric_limits<int>::max(), pow_b = std::numeric_limits<int>::max();
698 new_seq.push_back(*b);
703 pow_a = ex_to<numeric>((*a).coeff).to_int();
708 new_seq.push_back(*a);
713 pow_b = ex_to<numeric>((*b).coeff).to_int();
718 new_seq.push_back(*a);
722 }
else if (pow_b < pow_a) {
724 new_seq.push_back(*b);
731 new_seq.emplace_back(
expair(Order(
_ex1), (*a).coeff));
734 ex sum = (*a).rest + (*b).rest;
757 for (
auto & it :
seq) {
759 if (is_exactly_a<pseries>(it.rest))
763 if (!it.coeff.is_equal(
_ex1))
764 op = ex_to<pseries>(
op).mul_const(ex_to<numeric>(it.coeff));
767 acc = ex_to<pseries>(acc).add_series(ex_to<pseries>(
op));
781 new_seq.reserve(
seq.size());
783 for (
auto & it :
seq) {
785 new_seq.emplace_back(
expair(it.rest * other, it.
coeff));
787 new_seq.push_back(it);
807 if (
seq.empty() || other.
seq.empty()) {
817 const int cdeg_min = a_min + b_min;
818 int cdeg_max = a_max + b_max;
820 int higher_order_a = std::numeric_limits<int>::max();
821 int higher_order_b = std::numeric_limits<int>::max();
823 higher_order_a = a_max + b_min;
825 higher_order_b = b_max + a_min;
826 const int higher_order_c = std::min(higher_order_a, higher_order_b);
827 if (cdeg_max >= higher_order_c)
828 cdeg_max = higher_order_c - 1;
830 std::map<int, ex> rest_map_a, rest_map_b;
831 for (
const auto& it :
seq)
832 rest_map_a[ex_to<numeric>(it.coeff).to_int()] = it.rest;
835 for (
const auto& it : other.
seq)
836 rest_map_b[ex_to<numeric>(it.coeff).to_int()] = it.rest;
838 for (
int cdeg=cdeg_min; cdeg<=cdeg_max; ++cdeg) {
841 for (
int i=a_min; cdeg-i>=b_min; ++i) {
842 const auto& ita = rest_map_a.
find(i);
843 if (ita == rest_map_a.end())
845 const auto& itb = rest_map_b.find(cdeg-i);
846 if (itb == rest_map_b.end())
849 co += ita->second * itb->second;
854 if (higher_order_c < std::numeric_limits<int>::max())
868 const ex& sym =
r.lhs();
871 std::vector<int> ldegrees;
872 std::vector<bool> ldegree_redo;
877 for (
auto & it :
seq) {
884 factor = ex_to<numeric>(expon).to_int();
889 int real_ldegree = 0;
890 bool flag_redo =
false;
893 }
catch (std::runtime_error &) {}
895 if (real_ldegree == 0) {
903 }
while (real_ldegree == orderloop);
909 if (real_ldegree == 0)
914 ldegrees.push_back(
factor * real_ldegree);
915 ldegree_redo.push_back(flag_redo);
918 int degbound =
order-std::accumulate(ldegrees.begin(), ldegrees.end(), 0);
923 for (
auto & it :
seq) {
924 if ( ldegree_redo[j] ) {
930 factor = ex_to<numeric>(expon).to_int();
934 int real_ldegree = 0;
939 }
while ((real_ldegree == orderloop)
940 && (
factor*real_ldegree < degbound));
941 ldegrees[j] =
factor * real_ldegree;
942 degbound -=
factor * real_ldegree;
947 int degsum = std::accumulate(ldegrees.begin(), ldegrees.end(), 0);
949 if (degsum >
order) {
954 auto itd = ldegrees.begin();
955 for (
auto it=
seq.begin(), itend=
seq.end(); it!=itend; ++it, ++itd) {
961 if (it ==
seq.begin())
962 acc = ex_to<pseries>(
op);
964 acc = ex_to<pseries>(acc.
mul_series(ex_to<pseries>(
op)));
1002 throw std::domain_error(
"pseries::power_const(): pow(0,I) is undefined");
1004 throw pole_error(
"pseries::power_const(): division by zero",1);
1011 throw std::runtime_error(
"pseries::power_const(): trying to assemble a Puiseux series");
1012 int new_ldeg = (p*base_ldeg).
to_int();
1018 new_deg = std::min((p*base_deg).
to_int(), deg);
1022 int numcoeff = new_deg - new_ldeg;
1026 if (numcoeff <= 0) {
1033 throw pole_error(
"pseries::power_const(): division by zero",1);
1037 co.reserve(numcoeff);
1039 for (
int i=1; i<numcoeff; ++i) {
1041 for (
int j=1; j<=i; ++j) {
1044 co.push_back(Order(
_ex1));
1047 sum += (p * j - (i - j)) * co[i - j] *
c;
1049 co.push_back(sum /
coeff(
var, base_ldeg) / i);
1054 bool higher_order =
false;
1055 for (
int i=0; i<numcoeff; ++i) {
1057 new_seq.emplace_back(
expair(co[i], new_ldeg + i));
1060 higher_order =
true;
1064 if (!higher_order && new_deg == deg) {
1065 new_seq.emplace_back(
expair{Order(
_ex1), new_deg});
1076 for (
auto & it : newseq)
1088 if (is_exactly_a<pseries>(
basis))
1092 bool must_expand_basis =
false;
1096 must_expand_basis =
true;
1099 bool exponent_is_regular =
true;
1103 exponent_is_regular =
false;
1106 if (!exponent_is_regular) {
1139 return pseries(
r, std::move(new_seq));
1150 const ex& sym =
r.lhs();
1153 int real_ldegree = 0;
1155 real_ldegree = eb.
ldegree(sym-
r.rhs());
1156 if (real_ldegree == 0) {
1161 }
while (real_ldegree == orderloop);
1165 throw std::runtime_error(
"pseries::power_const(): trying to assemble a Puiseux series");
1166 int extra_terms = (real_ldegree*(1-numexp)).to_int();
1171 result = ex_to<pseries>(e).power_const(numexp,
order);
1174 result =
pseries(
r, std::move(ser));
1184 const ex p =
r.rhs();
1186 const symbol &s = ex_to<symbol>(
r.lhs());
1193 for (
auto & it :
seq) {
1194 int o = ex_to<numeric>(it.coeff).to_int();
1196 new_seq.emplace_back(
expair(Order(
_ex1), o));
1199 new_seq.push_back(it);
1201 return pseries(
r, std::move(new_seq));
1210 throw std::logic_error(
"Cannot series expand wrt dummy variable");
1215 fexpansion.reserve(fseries.
nops());
1216 for (
size_t i=0; i<fseries.
nops(); ++i) {
1217 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1218 currcoeff = (currcoeff == Order(
_ex1))
1222 fexpansion.emplace_back(
1223 expair(currcoeff, ex_to<pseries>(fseries).exponop(i)));
1227 ex result = dynallocate<pseries>(
r, std::move(fexpansion));
1230 for (
size_t i=0; i<fseries.
nops(); ++i) {
1231 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1234 ex currexpon = ex_to<pseries>(fseries).exponop(i);
1235 int orderforf =
order-ex_to<numeric>(currexpon).to_int()-1;
1236 currcoeff = currcoeff.
series(
r, orderforf);
1237 ex term = ex_to<pseries>(aseries).power_const(ex_to<numeric>(currexpon+1),
order);
1238 term = ex_to<pseries>(term).mul_const(ex_to<numeric>(-1/(currexpon+1)));
1239 term = ex_to<pseries>(term).mul_series(ex_to<pseries>(currcoeff));
1240 result = ex_to<pseries>(result).add_series(ex_to<pseries>(term));
1246 for (
size_t i=0; i<fseries.
nops(); ++i) {
1247 ex currcoeff = ex_to<pseries>(fseries).coeffop(i);
1250 ex currexpon = ex_to<pseries>(fseries).exponop(i);
1251 int orderforf =
order-ex_to<numeric>(currexpon).to_int()-1;
1252 currcoeff = currcoeff.
series(
r, orderforf);
1253 ex term = ex_to<pseries>(bseries).power_const(ex_to<numeric>(currexpon+1),
order);
1254 term = ex_to<pseries>(term).mul_const(ex_to<numeric>(1/(currexpon+1)));
1255 term = ex_to<pseries>(term).mul_series(ex_to<pseries>(currcoeff));
1256 result = ex_to<pseries>(result).add_series(ex_to<pseries>(term));
1277 if (is_a<relational>(
r))
1278 rel_ = ex_to<relational>(
r);
1279 else if (is_a<symbol>(
r))
1282 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.
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.
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
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
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.
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...