- if (level == 1)
- return *this;
-
- if (level == -max_recursion_level)
- throw (std::runtime_error("pseries::evalf(): recursion limit exceeded"));
-
- // Construct a new series with evaluated coefficients
- epvector new_seq;
- new_seq.reserve(seq.size());
- epvector::const_iterator it = seq.begin(), itend = seq.end();
- while (it != itend) {
- new_seq.push_back(expair(it->rest.evalf(level-1), it->coeff));
- it++;
- }
- return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated);
-}
-
-ex pseries::subs(const lst & ls, const lst & lr) const
-{
- // If expansion variable is being substituted, convert the series to a
- // polynomial and do the substitution there because the result might
- // no longer be a power series
- if (ls.has(var))
- return convert_to_poly(true).subs(ls, lr);
-
- // Otherwise construct a new series with substituted coefficients and
- // expansion point
- epvector new_seq;
- new_seq.reserve(seq.size());
- epvector::const_iterator it = seq.begin(), itend = seq.end();
- while (it != itend) {
- new_seq.push_back(expair(it->rest.subs(ls, lr), it->coeff));
- it++;
- }
- return (new pseries(relational(var,point.subs(ls, lr)), new_seq))->setflag(status_flags::dynallocated);
-}
-
-/** Implementation of ex::diff() for a power series. It treats the series as a
- * polynomial.
+ if (level == 1)
+ return *this;
+
+ if (level == -max_recursion_level)
+ throw (std::runtime_error("pseries::evalf(): recursion limit exceeded"));
+
+ // Construct a new series with evaluated coefficients
+ epvector new_seq;
+ new_seq.reserve(seq.size());
+ epvector::const_iterator it = seq.begin(), itend = seq.end();
+ while (it != itend) {
+ new_seq.push_back(expair(it->rest.evalf(level-1), it->coeff));
+ ++it;
+ }
+ return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated);
+}
+
+ex pseries::conjugate() const
+{
+ if(!var.info(info_flags::real))
+ return conjugate_function(*this).hold();
+
+ epvector * newseq = conjugateepvector(seq);
+ ex newpoint = point.conjugate();
+
+ if (!newseq && are_ex_trivially_equal(point, newpoint)) {
+ return *this;
+ }
+
+ ex result = (new pseries(var==newpoint, newseq ? *newseq : seq))->setflag(status_flags::dynallocated);
+ if (newseq) {
+ delete newseq;
+ }
+ return result;
+}
+
+ex pseries::real_part() const
+{
+ if(!var.info(info_flags::real))
+ return real_part_function(*this).hold();
+ ex newpoint = point.real_part();
+ if(newpoint != point)
+ return real_part_function(*this).hold();
+
+ epvector v;
+ v.reserve(seq.size());
+ for(epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+ v.push_back(expair((i->rest).real_part(), i->coeff));
+ return (new pseries(var==point, v))->setflag(status_flags::dynallocated);
+}
+
+ex pseries::imag_part() const
+{
+ if(!var.info(info_flags::real))
+ return imag_part_function(*this).hold();
+ ex newpoint = point.real_part();
+ if(newpoint != point)
+ return imag_part_function(*this).hold();
+
+ epvector v;
+ v.reserve(seq.size());
+ for(epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+ v.push_back(expair((i->rest).imag_part(), i->coeff));
+ return (new pseries(var==point, v))->setflag(status_flags::dynallocated);
+}
+
+ex pseries::eval_integ() const
+{
+ epvector *newseq = NULL;
+ for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+ if (newseq) {
+ newseq->push_back(expair(i->rest.eval_integ(), i->coeff));
+ continue;
+ }
+ ex newterm = i->rest.eval_integ();
+ if (!are_ex_trivially_equal(newterm, i->rest)) {
+ newseq = new epvector;
+ newseq->reserve(seq.size());
+ for (epvector::const_iterator j=seq.begin(); j!=i; ++j)
+ newseq->push_back(*j);
+ newseq->push_back(expair(newterm, i->coeff));
+ }
+ }
+
+ ex newpoint = point.eval_integ();
+ if (newseq || !are_ex_trivially_equal(newpoint, point))
+ return (new pseries(var==newpoint, *newseq))
+ ->setflag(status_flags::dynallocated);
+ return *this;
+}
+
+ex pseries::evalm() const
+{
+ // evalm each coefficient
+ epvector newseq;
+ bool something_changed = false;
+ for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+ if (something_changed) {
+ ex newcoeff = i->rest.evalm();
+ if (!newcoeff.is_zero())
+ newseq.push_back(expair(newcoeff, i->coeff));
+ }
+ else {
+ ex newcoeff = i->rest.evalm();
+ if (!are_ex_trivially_equal(newcoeff, i->rest)) {
+ something_changed = true;
+ newseq.reserve(seq.size());
+ std::copy(seq.begin(), i, std::back_inserter<epvector>(newseq));
+ if (!newcoeff.is_zero())
+ newseq.push_back(expair(newcoeff, i->coeff));
+ }
+ }
+ }
+ if (something_changed)
+ return (new pseries(var==point, newseq))->setflag(status_flags::dynallocated);
+ else
+ return *this;
+}
+
+ex pseries::subs(const exmap & m, unsigned options) const
+{
+ // If expansion variable is being substituted, convert the series to a
+ // polynomial and do the substitution there because the result might
+ // no longer be a power series
+ if (m.find(var) != m.end())
+ return convert_to_poly(true).subs(m, options);
+
+ // Otherwise construct a new series with substituted coefficients and
+ // expansion point
+ epvector newseq;
+ newseq.reserve(seq.size());
+ epvector::const_iterator it = seq.begin(), itend = seq.end();
+ while (it != itend) {
+ newseq.push_back(expair(it->rest.subs(m, options), it->coeff));
+ ++it;
+ }
+ return (new pseries(relational(var,point.subs(m, options)), newseq))->setflag(status_flags::dynallocated);
+}
+
+/** Implementation of ex::expand() for a power series. It expands all the
+ * terms individually and returns the resulting series as a new pseries. */
+ex pseries::expand(unsigned options) const
+{
+ epvector newseq;
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ ex restexp = i->rest.expand();
+ if (!restexp.is_zero())
+ newseq.push_back(expair(restexp, i->coeff));
+ ++i;
+ }
+ return (new pseries(relational(var,point), newseq))
+ ->setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
+}
+
+/** Implementation of ex::diff() for a power series.