[GiNaC-list] Re: Defining a new symbol class (mysymbol.cpp)
jros
jros at unavarra.es
Tue Nov 13 22:18:24 CET 2007
I've just compiled your code
diff(y*cos(S*x)+S*x^2+S^2*y*x, S) = 2*x^2+4*S*y*x-2*sin(S*x)*y*x !!!!
:)) . I'love GiNaC and their supporters.
Thanks, I'll be playing with this next days, to get
the derivative that I need. I hope I'll achieve it given your gidance.
Thanks a lot for your time/work
Javier
El mar, 13-11-2007 a las 21:46 +0300, Alexei Sheplyakov escribió:
> Hi!
>
> On Tue, Nov 13, 2007 at 02:30:21PM +0100, jros wrote:
>
> > I've proposed to derive a new class that represents a new type of
> > symbol, for example a symbol that has a special derivative
> > (just as an example assume we want to get something like
> >
> > mysymbol e("e");
> > symbol c("c");
> > cout<<diff(e,e)<<endl;
> > //->2
>
> > I know it is not very logical).
>
> > I want to derive from symbol.
> >
> > But if I follow mystring.cpp example, and I try to change
> >
> > GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mystring, basic,
> > print_func<print_context>(&mystring::do_print))
> >
> > to
> >
> > GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mystring, symbol,
> > print_func<print_context>(&mystring::do_print))
> >
> > (analogously with GINAC_IMPLEMENT_REGISTERED_CLASS_OPT)
>
> This is not enough. Did you change the constructors?
>
> > just to see if it compiles, with 1.4 or 1.3.6...
> >
> > But no success.
>
> I guess you did not, but I need to see the source to be sure.
>
> > Second and last atempt has been to look for a descendant of symbol in
> > GiNaC code.
> >
> > I've taken realsymbol as an starting point. The code is copy/pasted at
> > the end. And it compiles and executes.
> >
> > The question is, OK it works, but the strategy to derive such a class
> > is not related to the one of the mystring.cpp tutorial.
>
> I admit symbol subclasses are a bit hackish, but I can't see any fundamental
> difference. Could you elaborate, please?
>
> Anyway, one could subclass the symbol class in the following way:
>
> /**
> * @file mysymbol.cpp Example of extending GiNaC: writing new classes
> * A weird symbol subclass with unusual derivative w.r.t. itself.
> */
> #include <iostream>
> #include <string>
> #include <stdexcept>
> using namespace std;
>
> #include <ginac/ginac.h>
> using namespace GiNaC;
>
> #if (GINACLIB_MAJOR_VERSION == 1) && (GINACLIB_MINOR_VERSION <= 3)
> // make sure this does not collide with others classes' TINFOs.
> static const unsigned TINFO_mysymbol = 666666U;
> #define MYSYMBOL_RTTI TINFO_mysymbol
> #else
> #define MYSYMBOL_RTTI (&mysymbol::tinfo_static)
> #endif
>
> class mysymbol : public symbol
> {
> GINAC_DECLARE_REGISTERED_CLASS(mysymbol, symbol)
> public:
> mysymbol(const string &s);
> ex derivative(const symbol& s) const;
>
> protected:
> void do_print(const print_context &c, unsigned level = 0) const;
>
> };
>
> GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mysymbol, symbol,
> print_func<print_context>(&mysymbol::do_print))
>
> ex mysymbol::derivative(const symbol& s) const {
> if (compare(s))
> return 0;
> else
> return 2;
> }
>
> // ctors. Make sure all of them set tinfo_key.
> mysymbol::mysymbol() { tinfo_key = MYSYMBOL_RTTI; }
> mysymbol::mysymbol(const string &s) : inherited(s) { tinfo_key = MYSYMBOL_RTTI; }
>
> // comparison
> int mysymbol::compare_same_type(const basic &other) const
> {
> return inherited::compare_same_type(other);
> }
>
> // archiving/unarchiving
> mysymbol::mysymbol(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
> {
> tinfo_key = MYSYMBOL_RTTI;
> }
>
> void mysymbol::archive(archive_node &n) const
> {
> inherited::archive(n);
> }
>
> ex mysymbol::unarchive(const archive_node &n, lst &sym_lst)
> {
> return (new mysymbol(n, sym_lst))->setflag(status_flags::dynallocated);
> }
>
> // printing
> void mysymbol::do_print(const print_context &c, unsigned level) const
> {
> inherited::do_print(c, level);
> }
>
> int main(int argc, char** argv)
> {
> mysymbol S("S");
> symbol x("x"), y("y");
> ex e = pow(x, 2)*S + pow(S, 2)*y*x + y*cos(x*S);
> cout << "diff(" << e << ", " << S << ") = " << e.diff(S) << endl;
> // prints
> // diff(y*x*S^2+cos(x*S)*y+x^2*S, S) = -2*y*x*sin(x*S)+4*y*x*S+2*x^2
> return 0;
> }
>
> > Is mystring tutorial only valid when deriving from basic?.
>
> You can derive from any class using that example as a template. Obviously
> you need to change some things, in particular constructors (see the mysymbol
> example above).
>
> > Nevertheless we dont achieve to output the desired derivarive, buit a
> > logical one, the method
> >
> > mysymbol::derivative
> >
> > Is not called, and we don't know why?.
>
> Your ctors do not set tinfo_key, hence the problem. This is explained
> in the manual:
>
> "The golden rule is that in all constructors you have to set the
> tinfo_key member to the &your_class_name::tinfo_static. Otherwise
> it will be set by the constructor of the superclass and all hell will break
> loose in the RTTI."
>
> BTW, I'd expect your code to segfault or something like that, but it happens
> to work.
>
> Best regards,
> Alexei
>
More information about the GiNaC-list
mailing list