[GiNaC-list] Re: Defining a new symbol class (mysymbol.cpp)

Alexei Sheplyakov varg at theor.jinr.ru
Tue Nov 13 19:46:04 CET 2007


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.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-list/attachments/20071113/c56e0649/attachment.pgp


More information about the GiNaC-list mailing list