- const ex x_pt = x.subs(rel);
- if (x_pt.info(info_flags::numeric)) {
- // First special case: x==0 (derivatives have poles)
- if (x_pt.is_zero()) {
- // method:
- // The problem is that in d/dx Li2(x==0) == -log(1-x)/x we cannot
- // simply substitute x==0. The limit, however, exists: it is 1.
- // We also know all higher derivatives' limits:
- // (d/dx)^n Li2(x) == n!/n^2.
- // So the primitive series expansion is
- // Li2(x==0) == x + x^2/4 + x^3/9 + ...
- // and so on.
- // We first construct such a primitive series expansion manually in
- // a dummy symbol s and then insert the argument's series expansion
- // for s. Reexpanding the resulting series returns the desired
- // result.
- const symbol s;
- ex ser;
- // manually construct the primitive expansion
- for (int i=1; i<order; ++i)
- ser += pow(s,i) / pow(numeric(i), _num2());
- // substitute the argument's series expansion
- ser = ser.subs(s==x.series(rel, order));
- // maybe that was terminating, so add a proper order term
- epvector nseq;
- nseq.push_back(expair(Order(_ex1()), order));
- ser += pseries(rel, nseq);
- // reexpanding it will collapse the series again
- return ser.series(rel, order);
- // NB: Of course, this still does not allow us to compute anything
- // like sin(Li2(x)).series(x==0,2), since then this code here is
- // not reached and the derivative of sin(Li2(x)) doesn't allow the
- // substitution x==0. Probably limits *are* needed for the general
- // cases. In case L'Hospital's rule is implemented for limits and
- // basic::series() takes care of this, this whole block is probably
- // obsolete!
- }
- // second special case: x==1 (branch point)
- if (x_pt == _ex1()) {
- // method:
- // construct series manually in a dummy symbol s
- const symbol s;
- ex ser = zeta(2);
- // manually construct the primitive expansion
- for (int i=1; i<order; ++i)
- ser += pow(1-s,i) * (numeric(1,i)*(I*Pi+log(s-1)) - numeric(1,i*i));
- // substitute the argument's series expansion
- ser = ser.subs(s==x.series(rel, order));
- // maybe that was terminating, so add a proper order term
- epvector nseq;
- nseq.push_back(expair(Order(_ex1()), order));
- ser += pseries(rel, nseq);
- // reexpanding it will collapse the series again
- return ser.series(rel, order);
- }
- // third special case: x real, >=1 (branch cut)
- if (!(options & series_options::suppress_branchcut) &&
- ex_to_numeric(x_pt).is_real() && ex_to_numeric(x_pt)>1) {
- // method:
- // This is the branch cut: assemble the primitive series manually
- // and then add the corresponding complex step function.
- const symbol *s = static_cast<symbol *>(rel.lhs().bp);
- const ex point = rel.rhs();
- const symbol foo;
- epvector seq;
- // zeroth order term:
- seq.push_back(expair(Li2(x_pt), _ex0()));
- // compute the intermediate terms:
- ex replarg = series(Li2(x), *s==foo, order);
- for (unsigned i=1; i<replarg.nops()-1; ++i)
- seq.push_back(expair((replarg.op(i)/power(*s-foo,i)).series(foo==point,1,options).op(0).subs(foo==*s),i));
- // append an order term:
- seq.push_back(expair(Order(_ex1()), replarg.nops()-1));
- return pseries(rel, seq);
- }
- }
- // all other cases should be safe, by now:
- throw do_taylor(); // caught by function::series()
+ const ex x_pt = x.subs(rel);
+ if (x_pt.info(info_flags::numeric)) {
+ // First special case: x==0 (derivatives have poles)
+ if (x_pt.is_zero()) {
+ // method:
+ // The problem is that in d/dx Li2(x==0) == -log(1-x)/x we cannot
+ // simply substitute x==0. The limit, however, exists: it is 1.
+ // We also know all higher derivatives' limits:
+ // (d/dx)^n Li2(x) == n!/n^2.
+ // So the primitive series expansion is
+ // Li2(x==0) == x + x^2/4 + x^3/9 + ...
+ // and so on.
+ // We first construct such a primitive series expansion manually in
+ // a dummy symbol s and then insert the argument's series expansion
+ // for s. Reexpanding the resulting series returns the desired
+ // result.
+ const symbol s;
+ ex ser;
+ // manually construct the primitive expansion
+ for (int i=1; i<order; ++i)
+ ser += pow(s,i) / pow(numeric(i), _num2());
+ // substitute the argument's series expansion
+ ser = ser.subs(s==x.series(rel, order));
+ // maybe that was terminating, so add a proper order term
+ epvector nseq;
+ nseq.push_back(expair(Order(_ex1()), order));
+ ser += pseries(rel, nseq);
+ // reexpanding it will collapse the series again
+ return ser.series(rel, order);
+ // NB: Of course, this still does not allow us to compute anything
+ // like sin(Li2(x)).series(x==0,2), since then this code here is
+ // not reached and the derivative of sin(Li2(x)) doesn't allow the
+ // substitution x==0. Probably limits *are* needed for the general
+ // cases. In case L'Hospital's rule is implemented for limits and
+ // basic::series() takes care of this, this whole block is probably
+ // obsolete!
+ }
+ // second special case: x==1 (branch point)
+ if (x_pt == _ex1()) {
+ // method:
+ // construct series manually in a dummy symbol s
+ const symbol s;
+ ex ser = zeta(2);
+ // manually construct the primitive expansion
+ for (int i=1; i<order; ++i)
+ ser += pow(1-s,i) * (numeric(1,i)*(I*Pi+log(s-1)) - numeric(1,i*i));
+ // substitute the argument's series expansion
+ ser = ser.subs(s==x.series(rel, order));
+ // maybe that was terminating, so add a proper order term
+ epvector nseq;
+ nseq.push_back(expair(Order(_ex1()), order));
+ ser += pseries(rel, nseq);
+ // reexpanding it will collapse the series again
+ return ser.series(rel, order);
+ }
+ // third special case: x real, >=1 (branch cut)
+ if (!(options & series_options::suppress_branchcut) &&
+ ex_to_numeric(x_pt).is_real() && ex_to_numeric(x_pt)>1) {
+ // method:
+ // This is the branch cut: assemble the primitive series manually
+ // and then add the corresponding complex step function.
+ const symbol *s = static_cast<symbol *>(rel.lhs().bp);
+ const ex point = rel.rhs();
+ const symbol foo;
+ epvector seq;
+ // zeroth order term:
+ seq.push_back(expair(Li2(x_pt), _ex0()));
+ // compute the intermediate terms:
+ ex replarg = series(Li2(x), *s==foo, order);
+ for (unsigned i=1; i<replarg.nops()-1; ++i)
+ seq.push_back(expair((replarg.op(i)/power(*s-foo,i)).series(foo==point,1,options).op(0).subs(foo==*s),i));
+ // append an order term:
+ seq.push_back(expair(Order(_ex1()), replarg.nops()-1));
+ return pseries(rel, seq);
+ }
+ }
+ // all other cases should be safe, by now:
+ throw do_taylor(); // caught by function::series()