* methods for series expansion. */
/*
- * GiNaC Copyright (C) 1999-2007 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <numeric>
-#include <stdexcept>
-#include <limits>
-
#include "pseries.h"
#include "add.h"
#include "inifcns.h" // for Order function
#include "archive.h"
#include "utils.h"
+#include <limits>
+#include <numeric>
+#include <stdexcept>
+
namespace GiNaC {
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(pseries, basic,
* Default constructor
*/
-pseries::pseries() : inherited(&pseries::tinfo_static) { }
+pseries::pseries() { }
/*
* @param rel_ expansion variable and point (must hold a relational)
* @param ops_ vector of {coefficient, power} pairs (coefficient must not be zero)
* @return newly constructed pseries */
-pseries::pseries(const ex &rel_, const epvector &ops_) : basic(&pseries::tinfo_static), seq(ops_)
+pseries::pseries(const ex &rel_, const epvector &ops_) : seq(ops_)
{
GINAC_ASSERT(is_a<relational>(rel_));
GINAC_ASSERT(is_a<symbol>(rel_.lhs()));
* Archiving
*/
-pseries::pseries(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
+void pseries::read_archive(const archive_node &n, lst &sym_lst)
{
+ inherited::read_archive(n, sym_lst);
archive_node::archive_node_cit first = n.find_first("coeff");
archive_node::archive_node_cit last = n.find_last("power");
++last;
n.add_ex("point", point);
}
-DEFAULT_UNARCHIVE(pseries)
//////////
// functions overriding virtual functions from base classes
epvector * newseq = conjugateepvector(seq);
ex newpoint = point.conjugate();
- if (!newseq && are_ex_trivially_equal(point, newpoint)) {
+ 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;
- }
+ delete newseq;
return result;
}
orderloop++;
real_ldegree = buf.series(r, orderloop, options).ldegree(sym);
} while ((real_ldegree == orderloop)
- && ( factor*real_ldegree < degbound));
+ && (factor*real_ldegree < degbound));
ldegrees[j] = factor * real_ldegree;
degbound -= factor * real_ldegree;
}
must_expand_basis = true;
}
+ bool exponent_is_regular = true;
+ try {
+ exponent.subs(r, subs_options::no_pattern);
+ } catch (pole_error) {
+ exponent_is_regular = false;
+ }
+
+ if (!exponent_is_regular) {
+ ex l = exponent*log(basis);
+ // this == exp(l);
+ ex le = l.series(r, order, options);
+ // Note: expanding exp(l) won't help, since that will attempt
+ // Taylor expansion, and fail (because exponent is "singular")
+ // Still l itself might be expanded in Taylor series.
+ // Examples:
+ // sin(x)/x*log(cos(x))
+ // 1/x*log(1 + x)
+ return exp(le).series(r, order, options);
+ // Note: if l happens to have a Laurent expansion (with
+ // negative powers of (var - point)), expanding exp(le)
+ // will barf (which is The Right Thing).
+ }
+
// Is the expression of type something^(-int)?
if (!must_expand_basis && !exponent.info(info_flags::negint)
&& (!is_a<add>(basis) || !is_a<numeric>(exponent)))
if (x.subs(r) != x)
throw std::logic_error("Cannot series expand wrt dummy variable");
- // Expanding integrant with r substituted taken in boundaries.
+ // Expanding integrand with r substituted taken in boundaries.
ex fseries = f.series(r, order, options);
epvector fexpansion;
fexpansion.reserve(fseries.nops());
else
throw (std::logic_error("ex::series(): expansion point has unknown type"));
- try {
- e = bp->series(rel_, order, options);
- } catch (std::exception &x) {
- throw (std::logic_error(std::string("unable to compute series (") + x.what() + ")"));
- }
+ e = bp->series(rel_, order, options);
return e;
}
+GINAC_BIND_UNARCHIVER(pseries);
+
} // namespace GiNaC