Hi, i'm working in three classes to generate the legendre polynomial, and the chebyshev of first and second kind, in chebyshev i define the derivative in terms of chebyshev polynomials, but it get messy when is expanded because the polynomials at numerator and denominator are not factorized, and then the expression is complex that it should. What do you think is better, to let the derivatives of the polynomials in terms on the same polynomials, and expaned as like the users, or always expand at the derivative and return the polynomial expanded at the derivative (as in the legendre polynomial)? This is the code: / Chebyshev polynomial of first kind class chebyshev_1 : public basic { GINAC_DECLARE_REGISTERED_CLASS(chebyshev_1, basic) public: // Constructor of chebyshev of first kind chebyshev_1(numeric n, symbol x); ex derivative(const symbol & s) const; ex expand(unsigned options) const; protected: void do_print(const print_context & c, unsigned level = 0) const; private: numeric n; symbol x; }; // Chebyshev polynomial of second kind class chebyshev_2 : public basic { GINAC_DECLARE_REGISTERED_CLASS(chebyshev_2, basic) public: // Constructor of chebyshev of first kind chebyshev_2(numeric n, symbol x); ex derivative(const symbol & s) const; ex expand(unsigned options) const; protected: void do_print(const print_context & c, unsigned level = 0) const; private: numeric n; symbol x; }; // Legendre polynomial class legendre : public basic { GINAC_DECLARE_REGISTERED_CLASS(legendre, basic) public: // Constructor of chebyshev of first kind legendre(numeric n, symbol x); ex derivative(const symbol & s) const; ex expand(unsigned options) const; protected: void do_print(const print_context & c, unsigned level = 0) const; private: numeric n; symbol x; }; /*************************************************************** * Chebyshev polynomial of first kind ****************************************************************/ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(chebyshev_1, basic, print_func<print_context>(&chebyshev_1::do_print)) // Default constructor chebyshev_1::chebyshev_1() {} // Print the function void chebyshev_1::do_print(const print_context & c, unsigned level) const { c.s << "Tn(" << n << "," << x << ")"; } int chebyshev_1::compare_same_type(const basic & other) const { const chebyshev_1 &o = static_cast<const chebyshev_1 &>(other); if (x.is_equal(o.x) and (n == o.n)) return 0; return 1; } ex chebyshev_1::expand(unsigned options) const { if (n == 0) return 1; if (n == 1) return x; exvector e; numeric m = n / 2; if (n.is_odd()) m = (n-1)/2; e.reserve(m.to_long()); ex tmp = pow(2 * x,n) / 2; e.push_back(tmp); for(numeric i = 1; i <= m; i++) { tmp *= -(n - 2*i + 2) * (n - 2*i + 1); tmp /= (4 * i * pow(x,2) * (n-i)); e.push_back(tmp); } return add(e); } ex chebyshev_1::derivative(const symbol & s) const { if(s.is_equal(x) and (n!=0)) return n * chebyshev_2(n-1,x); return 0; } chebyshev_1::chebyshev_1(numeric n, symbol x) : n(n), x(x){} /*************************************************************** * Chebyshev polynomial of second kind ****************************************************************/ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(chebyshev_2, basic, print_func<print_context>(&chebyshev_2::do_print)) // Default constructor chebyshev_2::chebyshev_2() {} // Print the function void chebyshev_2::do_print(const print_context & c, unsigned level) const { c.s << "Un(" << n << "," << x << ")"; } int chebyshev_2::compare_same_type(const basic & other) const { const chebyshev_2 &o = static_cast<const chebyshev_2 &>(other); if (x.is_equal(o.x) and (n == o.n)) return 0; return 1; } ex chebyshev_2::expand(unsigned options) const { if (n == 0) return 1; if (n == 1) return 2*x; exvector e; numeric m = n / 2; if (n.is_odd()) m = (n-1)/2; e.reserve(m.to_long()); ex tmp = pow(2 * x,n); e.push_back(tmp); for(numeric i = 1; i <= m; i++) { tmp *= -(n - 2*i + 2) * (n - 2*i + 1); tmp /= (4 * i * pow(x,2) * (n - i + 1)); e.push_back(tmp); } return add(e); } ex chebyshev_2::derivative(const symbol & s) const { if(s.is_equal(x) and (n!=0)) return ((n+1) * chebyshev_1(n+1,x) - x * chebyshev_2(n,x)) / (pow(x,2) - 1); return 0; } chebyshev_2::chebyshev_2(numeric n, symbol x) : n(n), x(x){} /*************************************************************** * Legendre polynomial ****************************************************************/ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(legendre, basic, print_func<print_context>(&legendre::do_print)) // Default constructor legendre::legendre() {} // Print the function void legendre::do_print(const print_context & c, unsigned level) const { c.s << "Pn(" << n << "," << x << ")"; } int legendre::compare_same_type(const basic & other) const { const legendre &o = static_cast<const legendre &>(other); if (x.is_equal(o.x) and (n == o.n)) return 0; return 1; } ex legendre::expand(unsigned options) const { if (n == 0) return 1; if (n == 1) return x; exvector e; numeric m = n / 2; if (n.is_odd()) m = (n-1)/2; e.reserve(m.to_long()); ex tmp = factorial(2*n) * pow(x,n) /(pow(2,n) * pow(factorial(n),2)); e.push_back(tmp); for(numeric i = 1; i <= m; i++) { tmp *= -(n - 2 * i + 1) * (n - 2 * i + 2); tmp /= (4 * n -4 * i + 2) * i * pow(x,2); e.push_back(tmp); } return add(e); } ex legendre::derivative(const symbol & s) const { return (this->expand(0)).diff(s); //if(s.is_equal(x) and (n!=0)) // return ((n+1) * chebyshev_1(n+1,x) - x * legendre(n,x)) / (pow(x,2) - 1); //return 0; } legendre::legendre(numeric n, symbol x) : n(n), x(x){} -- Jorge Eduardo Cardona jorgeecardona@gmail.com jorgeecardona.blogspot.com ------------------------------------------------ Linux registered user #391186 Registered machine #291871 ------------------------------------------------
Hi, Jorge Cardona schrieb:
What do you think is better, to let the derivatives of the polynomials in terms on the same polynomials, and expaned as like the users, or always expand at the derivative and return the polynomial expanded at the derivative (as in the legendre polynomial)?
well, I don't know. Maybe give a option? Anyway, it sounds like it can be changed easily later on when the advantages and disadvantaged become more clear. Just wondering: why you don't use const references in the ctors?
// Constructor of chebyshev of first kind chebyshev_1(numeric n, symbol x);
Regards, Jens
2009/7/10 Jens Vollinga <jensv@nikhef.nl>:
Hi,
Jorge Cardona schrieb:
What do you think is better, to let the derivatives of the polynomials in terms on the same polynomials, and expaned as like the users, or always expand at the derivative and return the polynomial expanded at the derivative (as in the legendre polynomial)?
well, I don't know. Maybe give a option? Anyway, it sounds like it can be changed easily later on when the advantages and disadvantaged become more clear.
Just wondering: why you don't use const references in the ctors?
// Constructor of chebyshev of first kind chebyshev_1(numeric n, symbol x);
:) I will change it to const references, thanks.
Regards, Jens _______________________________________________ GiNaC-list mailing list GiNaC-list@ginac.de https://www.cebix.net/mailman/listinfo/ginac-list
-- Jorge Eduardo Cardona jorgeecardona@gmail.com jorgeecardona.blogspot.com ------------------------------------------------ Linux registered user #391186 Registered machine #291871 ------------------------------------------------
participants (2)
-
Jens Vollinga
-
Jorge Cardona