X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fpseries.cpp;h=4491915841b1cd746d32cde71c8effc395257d4c;hp=ff39d24fb07a656b20d986c0641150e9ec6d4b00;hb=21ebb806befcb3873d58074454fcf8dcba138fa9;hpb=0a1b35cf1e59c9e3aae33de8febaa1c8f4bbe630;ds=inline diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index ff39d24f..44919158 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -21,6 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + #include "pseries.h" #include "add.h" #include "inifcns.h" @@ -33,9 +35,9 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_GINAC_NAMESPACE +#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_GINAC_NAMESPACE +#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic) @@ -54,13 +56,13 @@ pseries::~pseries() destroy(false); } -pseries::pseries(pseries const &other) +pseries::pseries(const pseries &other) { debugmsg("pseries copy constructor", LOGLEVEL_CONSTRUCT); copy(other); } -pseries const &pseries::operator=(pseries const & other) +const pseries &pseries::operator=(const pseries & other) { debugmsg("pseries operator=", LOGLEVEL_ASSIGNMENT); if (this != &other) { @@ -70,7 +72,7 @@ pseries const &pseries::operator=(pseries const & other) return *this; } -void pseries::copy(pseries const &other) +void pseries::copy(const pseries &other) { inherited::copy(other); seq = other.seq; @@ -99,7 +101,7 @@ void pseries::destroy(bool call_parent) * @param point_ expansion point * @param ops_ vector of {coefficient, power} pairs (coefficient must not be zero) * @return newly constructed pseries */ -pseries::pseries(ex const &var_, ex const &point_, epvector const &ops_) +pseries::pseries(const ex &var_, const ex &point_, const epvector &ops_) : basic(TINFO_pseries), seq(ops_), var(var_), point(point_) { debugmsg("pseries constructor from ex,ex,epvector", LOGLEVEL_CONSTRUCT); @@ -160,13 +162,13 @@ basic *pseries::duplicate() const void pseries::print(ostream &os, unsigned upper_precedence) const { - debugmsg("symbol print", LOGLEVEL_PRINT); - convert_to_poly().print(os, upper_precedence); + debugmsg("pseries print", LOGLEVEL_PRINT); + convert_to_poly().print(os, upper_precedence); } void pseries::printraw(ostream &os) const { - debugmsg("symbol printraw", LOGLEVEL_PRINT); + debugmsg("pseries printraw", LOGLEVEL_PRINT); os << "pseries(" << var << ";" << point << ";"; for (epvector::const_iterator i=seq.begin(); i!=seq.end(); i++) { os << "(" << (*i).rest << "," << (*i).coeff << "),"; @@ -174,7 +176,24 @@ void pseries::printraw(ostream &os) const os << ")"; } -int pseries::degree(symbol const &s) const +unsigned pseries::nops(void) const +{ + return seq.size(); +} + +ex pseries::op(int i) const +{ + if (i < 0 || unsigned(i) >= seq.size()) + throw (std::out_of_range("op() out of range")); + return seq[i].rest * power(var - point, seq[i].coeff); +} + +ex &pseries::let_op(int i) +{ + throw (std::logic_error("let_op not defined for pseries")); +} + +int pseries::degree(const symbol &s) const { if (var.is_equal(s)) { // Return last exponent @@ -197,7 +216,7 @@ int pseries::degree(symbol const &s) const } } -int pseries::ldegree(symbol const &s) const +int pseries::ldegree(const symbol &s) const { if (var.is_equal(s)) { // Return first exponent @@ -220,7 +239,7 @@ int pseries::ldegree(symbol const &s) const } } -ex pseries::coeff(symbol const &s, int const n) const +ex pseries::coeff(const symbol &s, int n) const { if (var.is_equal(s)) { epvector::const_iterator it = seq.begin(), itend = seq.end(); @@ -237,6 +256,14 @@ ex pseries::coeff(symbol const &s, int const n) const return convert_to_poly().coeff(s, n); } +ex pseries::collect(const symbol &s) const +{ + if (var.is_equal(s)) + return convert_to_poly(); + else + return inherited::collect(s); +} + ex pseries::eval(int level) const { if (level == 1) @@ -259,7 +286,7 @@ ex pseries::evalf(int level) const return convert_to_poly().evalf(level); } -ex pseries::subs(lst const & ls, lst const & lr) const +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 @@ -279,6 +306,32 @@ ex pseries::subs(lst const & ls, lst const & lr) const return (new pseries(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. + * @see ex::diff */ +ex pseries::derivative(const symbol & s) const +{ + if (s == var) { + epvector new_seq; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + + // FIXME: coeff might depend on var + while (it != itend) { + if (is_order_function(it->rest)) { + new_seq.push_back(expair(it->rest, it->coeff - 1)); + } else { + ex c = it->rest * it->coeff; + if (!c.is_zero()) + new_seq.push_back(expair(c, it->coeff - 1)); + } + it++; + } + return pseries(var, point, new_seq); + } else { + return *this; + } +} + /* * Construct ordinary polynomial out of series @@ -310,7 +363,7 @@ ex pseries::convert_to_poly(bool no_order) const /** Default implementation of ex::series(). This performs Taylor expansion. * @see ex::series */ -ex basic::series(symbol const & s, ex const & point, int order) const +ex basic::series(const symbol & s, const ex & point, int order) const { epvector seq; numeric fac(1); @@ -342,7 +395,7 @@ ex basic::series(symbol const & s, ex const & point, int order) const /** Implementation of ex::series() for symbols. * @see ex::series */ -ex symbol::series(symbol const & s, ex const & point, int order) const +ex symbol::series(const symbol & s, const ex & point, int order) const { epvector seq; if (is_equal(s)) { @@ -358,8 +411,8 @@ ex symbol::series(symbol const & s, ex const & point, int order) const } -/** Add one series object to another, producing a pseries object that represents - * the sum. +/** Add one series object to another, producing a pseries object that + * represents the sum. * * @param other pseries object to add with * @return the sum as a pseries */ @@ -435,7 +488,7 @@ ex pseries::add_series(const pseries &other) const /** Implementation of ex::series() for sums. This performs series addition when * adding pseries objects. * @see ex::series */ -ex add::series(symbol const & s, ex const & point, int order) const +ex add::series(const symbol & s, const ex & point, int order) const { ex acc; // Series accumulator @@ -461,8 +514,8 @@ ex add::series(symbol const & s, ex const & point, int order) const } -/** Multiply a pseries object with a numeric constant, producing a pseries object - * that represents the product. +/** Multiply a pseries object with a numeric constant, producing a pseries + * object that represents the product. * * @param other constant to multiply with * @return the product as a pseries */ @@ -540,7 +593,7 @@ ex pseries::mul_series(const pseries &other) const /** Implementation of ex::series() for product. This performs series * multiplication when multiplying series. * @see ex::series */ -ex mul::series(symbol const & s, ex const & point, int order) const +ex mul::series(const symbol & s, const ex & point, int order) const { ex acc; // Series accumulator @@ -620,7 +673,7 @@ ex pseries::power_const(const numeric &p, int deg) const /** Implementation of ex::series() for powers. This performs Laurent expansion * of reciprocals of series at singularities. * @see ex::series */ -ex power::series(symbol const & s, ex const & point, int order) const +ex power::series(const symbol & s, const ex & point, int order) const { ex e; if (!is_ex_exactly_of_type(basis, pseries)) { @@ -644,6 +697,31 @@ ex power::series(symbol const & s, ex const & point, int order) const } +/** Re-expansion of a pseries object. */ +ex pseries::series(const symbol & s, const ex & p, int order) const +{ + if (var.is_equal(s) && point.is_equal(p)) { + if (order > degree(s)) + return *this; + else { + epvector new_seq; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + int o = ex_to_numeric(it->coeff).to_int(); + if (o >= order) { + new_seq.push_back(expair(Order(_ex1()), o)); + break; + } + new_seq.push_back(*it); + it++; + } + return pseries(var, point, new_seq); + } + } else + return convert_to_poly().series(s, p, order); +} + + /** Compute the truncated series expansion of an expression. * This function returns an expression containing an object of class pseries to * represent the series. If the series does not terminate within the given @@ -653,7 +731,7 @@ ex power::series(symbol const & s, ex const & point, int order) const * @param point expansion point * @param order truncation order of series calculations * @return an expression holding a pseries object */ -ex ex::series(symbol const &s, ex const &point, int order) const +ex ex::series(const symbol &s, const ex &point, int order) const { GINAC_ASSERT(bp!=0); return bp->series(s, point, order); @@ -662,8 +740,8 @@ ex ex::series(symbol const &s, ex const &point, int order) const // Global constants const pseries some_pseries; -type_info const & typeid_pseries = typeid(some_pseries); +const type_info & typeid_pseries = typeid(some_pseries); -#ifndef NO_GINAC_NAMESPACE +#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_GINAC_NAMESPACE +#endif // ndef NO_NAMESPACE_GINAC