[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