Re: Problem compiling mystring.cpp
Hello! On Mon, Nov 12, 2007 at 05:29:51PM +0100, jros wrote:
I have a problem compiling
http://www.ginac.de/viewcvs/GiNaC/doc/examples/mystring.cpp?rev=1.1
[snipped the error messages] This example is for GiNaC version 1.4. If you want to compile it with older version[s], apply the following patch: --- mystring.cpp 2007-11-05 12:28:19.062020000 +0300 +++ mystring_o.cpp 2007-11-12 20:52:20.752501247 +0300 @@ -9,6 +9,9 @@ #include <ginac/ginac.h> using namespace GiNaC; +// Make sure this does not collide with other classes' TINFOs. +static const unsigned TINFO_mystring = 666U; + class mystring : public basic { GINAC_DECLARE_REGISTERED_CLASS(mystring, basic) @@ -29,9 +32,9 @@ print_func<print_context>(&mystring::do_print)) // ctors -mystring::mystring() : inherited(&mystring::tinfo_static) { } -mystring::mystring(const string &s) : inherited(&mystring::tinfo_static), str(s) { } -mystring::mystring(const char *s) : inherited(&mystring::tinfo_static), str(s) { } +mystring::mystring() : inherited(TINFO_mystring) { } +mystring::mystring(const string &s) : inherited(TINFO_mystring), str(s) { } +mystring::mystring(const char *s) : inherited(TINFO_mystring), str(s) { } // comparison int mystring::compare_same_type(const basic &other) const Best regards, Alexei -- All science is either physics or stamp collecting.
Hello :) ! After a year using GiNaC, we are thinking now that using classes can improve a lot our programming efforts. I think this is my n-th atempt to define a new class, but I'm having (again) some troubles. 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) just to see if it compiles, with 1.4 or 1.3.6... But no success. 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. So we do not know why it works, and if teh strategy we are usin to derive is correct. What is the logic?; Is mystring tutorial only valid when deriving from basic?. The code is just a copy paste of symbol.cpp symbol.h sections related to realsymbol, I rename realsymbol to mysymbol. 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?. Should we use a new type of ex also?. Perhaps this is a C++ question but I'm not sure right now,... (sorry if this is the case) Is there a documented example appart from mystring.cpp at the tutorial?. We are workin wit 1.4 GiNaC version. Thanks in advance Javier Ros mysymbol.cpp listing ------------------------------------------------------------------------------- /** Specialization of symbol to suit my own needs */ #include <iostream> #include <string> #include <stdexcept> using namespace std; #include <ginac/ginac.h> using namespace GiNaC; namespace GiNaC { class mysymbol : public symbol { // constructors public: mysymbol(); explicit mysymbol(const std::string & initname, unsigned domain = domain::real); mysymbol(const std::string & initname, const std::string & texname, unsigned domain = domain::real); mysymbol(const std::string & initname, unsigned rt, tinfo_t rtt, unsigned domain = domain::real); mysymbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain = domain::real); protected: ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; }; // mysymbol mysymbol::mysymbol() { domain = domain::real; } // mysymbol mysymbol::mysymbol(const std::string & initname, unsigned domain) : symbol(initname, domain) { } mysymbol::mysymbol(const std::string & initname, const std::string & texname, unsigned domain) : symbol(initname, texname, domain) { } mysymbol::mysymbol(const std::string & initname, unsigned rt, tinfo_t rtt, unsigned domain) : symbol(initname, rt, rtt, domain) { } mysymbol::mysymbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain) : symbol(initname, texname, rt, rtt, domain) { } } ex mysymbol::derivative(const symbol & s) const { cout << "Here I'm\n"; if (compare_same_type(s)) return 0; else return 2; } int mysymbol::compare_same_type(const basic & other) const { GINAC_ASSERT(is_a<mysymbol>(other)); const mysymbol *o = static_cast<const mysymbol *>(&other); if (serial==o->serial) return 0; return serial < o->serial ? -1 : 1; } int main(int argc, char** argv) { symbol a("a"), b("b"), c("c"); mysymbol e("e1"); cout << diff((e*(a+e*(b+c*e)) - (a*e+b*e*e)).expand(),e) << endl; cout << diff((e*(a+e*(b+c*e)) - (a*e+b*e*e)).expand(),c) << endl; return 0; }
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 -- All science is either physics or stamp collecting.
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
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)
and also class mysymbol : public string becomes class mysymbol : public symbol
This is not enough. Did you change the constructors?
I leave the constructors as they are // ctors mystring::mystring() : inherited(&mystring::tinfo_static) { } mystring::mystring(const string &s) : inherited(&mystring::tinfo_static), str(s) { } mystring::mystring(const char *s) : inherited(&mystring::tinfo_static), str(s) { } then error is: $ g++ -o mystring mystring.cpp `pkg-config --cflags --libs ginac` mystring.cpp: In constructor ‘mystring::mystring()’: mystring.cpp:32: error: no matching function for call to ‘GiNaC::symbol::symbol(const GiNaC::tinfo_static_t*)’ ... The manual implicitly suggesst that this should not be a problem, so I were confused. Thanks to you, I can now see that changing them to // ctors mystring::mystring() { tinfo_key = MYSTRING_RTTI; } mystring::mystring(const string &s) : str(s) { tinfo_key = MYSTRING_RTTI; } mystring::mystring(const char *s) : str(s) { tinfo_key = MYSTRING_RTTI; } It works. I think it can be beneficial for the Tutorial (I think you are one of the developers), more pedagogical, to define the constructors in this way, because I think that they will work allways in this form, and obiously the reverse is not true, the posibility used right now calling the inherited method could be a footnote. Just for curiosity what does it means: // ctors, and w.r.t. Also I see that the archiving constructor, now in your yesterday's mysymbol.cpp, do not need to set tinfo_key this mysymbol::mysymbol(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) { //tinfo_key = MYSYMBOL_RTTI; } compiles and executes OK. Is this correct in general terms?, the manual does not say anything about having to set tinfo_key in the archiving constructor. Also it would be beneficial to have a second example like mysymbol.cpp this in the tutorial, perhaps adding a numeric representing the value of the symbol, and redefining the evalf() method so that evaluation of the symbol uses the numeric field to compute the value, like for constants. If the derivative overloading is maintained, It would be preferable if it does something useful, as returning for symbol "e" the symbol "de" that represents its derivative with respect to symbol time "t". This way total derivatives with "t" like in clasic mechanics (my field) can be done for expresions. This has the drawback, that "t" should be a global variable in the example, and "de" a mysymbol member of mysymbol, so new constructor needed, or a mysymbol created on the fly. I hope this helps, and again, thanks a lot. I wan't to ask also about dealing with non-conmutativity of a defined symbol -something that is no clear in the Tutorial- but I will postpone the subjet. Thanks Javier Ros
participants (2)
-
Alexei Sheplyakov
-
jros