Dear all, I recently had a look at the ginac 'function' class and at the corresponding REGISTER_FUNCTION mechanism. (background: I want to use ginac to represent fuzzy membership functions, i.e. essentially functions R -> [0,1]). Newbie question: Why was the design made as it is? For instance, why are all functions stored in a vector<function_options>, instead of deriving them from class function? Sure, when dealing with functions like exp, sin, ..., it is clear that there is just *one* instance of each such function. (Singleton pattern?) But how to deal with parametrized functions when parameters are specified at runtime? For instance, it would be nice to implement splines s.t. it is possible to specify two coordinates (x1,y1), (x2,y2) s.t. spline(x1) = y1, spline(x2) = y2, and first derivates are 0 at x1 and x2 ... Does that fit into the framework, too? Any hints and comments are appreciated, - Roland - To UNSUBSCRIBE, email to ginac-list@ginac.de with a subject of "unsubscribe".
Dear Roland, Let's see if we can resurrect this thread... On Thu, 11 Jan 2001, Roland Richter wrote:
I recently had a look at the ginac 'function' class and at the corresponding REGISTER_FUNCTION mechanism. (background: I want to use ginac to represent fuzzy membership functions, i.e. essentially functions R -> [0,1]).
Newbie question: Why was the design made as it is?
For instance, why are all functions stored in a vector<function_options>, instead of deriving them from class function?
We had the design you suggest before we switched to the current one. One drawback is that you cannot have classes share the name of global functions. Instead of writing sin(x) we had to write Sin(x). IIRC the code was much uglier with the old design and things got clearer when Alex came up with the cpp-register-functions-in-a-vector design. Alex, do you remember the precise circumstances?
Sure, when dealing with functions like exp, sin, ..., it is clear that there is just *one* instance of each such function. (Singleton pattern?)
No, it has nothing to do with the Singleton pattern. Singleton pattern means that there is only one object of a class at a time. This is not the case. We can have exp(x)+exp(y), an object of class add and two objects of class function corresponding to exp. In an object-oriented world, Singleton classes take the place of global variables.
But how to deal with parametrized functions when parameters are specified at runtime?
For instance, it would be nice to implement splines s.t. it is possible to specify two coordinates (x1,y1), (x2,y2) s.t. spline(x1) = y1, spline(x2) = y2, and first derivates are 0 at x1 and x2 ...
Does that fit into the framework, too?
Frankly, we never had generation of functions at runtime in mind. OTOH I don't see why you wouldn't be able to do just what you want to do with additional function arguments. What's the difference between a parameter and an argument anyways? Regards -richy. -- Richard Kreckel <Richard.Kreckel@Uni-Mainz.DE> <http://wwwthep.physik.uni-mainz.de/~kreckel/> - To UNSUBSCRIBE, email to ginac-list@ginac.de with a subject of "unsubscribe".
On Mon, 29 Jan 2001, Richard B. Kreckel wrote:
We had the design you suggest before we switched to the current one. One drawback is that you cannot have classes share the name of global functions. Instead of writing sin(x) we had to write Sin(x). IIRC the code was much uglier with the old design and things got clearer when Alex came up with the cpp-register-functions-in-a-vector design. Alex, do you remember the precise circumstances?
Since this decision was made nearly two years ago, I don't remember the arguments exactly any more. It is possible to write sin(x)+y if sin is a class, since this is just a constructor call. However it would not be possible to pass a function pointer as a function argument (although we don't use such a construct). IIRC one of the main reasons against the one-class-per-function scheme was that that the preprocessor is not very powerful. Since a function can have either default or user implemented diff, series, evalf etc. methods, one would need many macros implementing all possible combinations. The notation for the user to define his own functions would look horrible (at least we could not find a better one). Further each GiNaC class unfortunately needs some supporting code (copy(), destroy(), duplicate() etc.) which would have to be generated for each class representing a function again and again blowing up code size. OTOH I don't see any advantages using classes for functions. Mathematical functions rarely inherit something from other functions, so a flat hierarchy as implemented with the register function seems to be more natural to me. Best regards, Alex -- Alexander Frink E-Mail: Alexander.Frink@Uni-Mainz.DE Institut fuer Physik Phone: +49-6131-3923391 Johannes-Gutenberg-Universitaet D-55099 Mainz, Germany - To UNSUBSCRIBE, email to ginac-list@ginac.de with a subject of "unsubscribe".
On Wed, 31 Jan 2001, Alexander Frink wrote:
IIRC one of the main reasons against the one-class-per-function scheme was that that the preprocessor is not very powerful. Since a function can have either default or user implemented diff, series, evalf etc. methods, one would need many macros implementing all possible combinations. The notation for the user to define his own functions would look horrible (at least we could not find a better one).
Further each GiNaC class unfortunately needs some supporting code (copy(), destroy(), duplicate() etc.) which would have to be generated for each class representing a function again and again blowing up code size.
I do not see why all this could not be done by virtual functions. Am I to be missing some obvious point? Cheers -richy. -- Richard Kreckel <Richard.Kreckel@Uni-Mainz.DE> <http://wwwthep.physik.uni-mainz.de/~kreckel/> - To UNSUBSCRIBE, email to ginac-list@ginac.de with a subject of "unsubscribe".
On Wed, 31 Jan 2001, Richard B. Kreckel wrote:
Further each GiNaC class unfortunately needs some supporting code (copy(), destroy(), duplicate() etc.) which would have to be generated for each class representing a function again and again blowing up code size.
I do not see why all this could not be done by virtual functions. Am I to be missing some obvious point?
You need at least duplicate(), a default constructor and a constructor from the function arguments. For consistency all other GiNaC classes also have a destructor, copy(), destroy(), a copy constructor and operator=(), which are not mandatory if the derived class does not add any new members. Further you need to implement the type info stuff. All this is not too much code. But still I do not see what you could do with classes instead of the current scheme. Alex -- Alexander Frink E-Mail: Alexander.Frink@Uni-Mainz.DE Institut fuer Physik Phone: +49-6131-3923391 Johannes-Gutenberg-Universitaet D-55099 Mainz, Germany - To UNSUBSCRIBE, email to ginac-list@ginac.de with a subject of "unsubscribe".
participants (3)
-
Alexander Frink
-
Richard B. Kreckel
-
Roland Richter