Hi Ondrej! Ondrej Certik wrote:
Hi, this is the reason why GiNaC is using ex - so that it automatically calls eval(). We had this discussion already - it's because of C++, memory handling, speed and automatic evaluation.
But in Python I recently found a very elegant solution to this (in SymPy): I also have eval() but it's called automatically right after the construtor and if it returns a different instance, then that instance is returned. Example:
e = Add(x,x)
however "e" contains Mul(2,x), because in python you can make the Add.eval() get called right after the Add constructor. Thus Add.eval() evaluates x+x to 2*x and returns Mul(2,x). So in the end Add(x,x) is in fact the same as Mul(2,x).
And in the end, you don't have to think about eval() at all. And you don't need ex (python is handling the garbage collection automatically).
But soon I would like to implement the core of SymPy in C++ for speed and I am curious, if my system is going to be faster or slower than GiNaC.
I gather that you can already tell us something about the speed of the pure-Python SymPy compared to GiNaC. We are so curious!
my question is this: do you know, if it is possible to implement the above procedure in C++? and how? maybe using some macros? Because it is certainly non standard, that you construct an instance of some class Add(x,x) and it returns an instance of a completely different class Mul(2,x).
In the end, it all boils down to the question how much you are willing to do statically (at compile time) as opposed to dynamically (at run time). If you want the degree of flexibility of GiNaC or a language like Python that features duck typing, where x-x can evaluate to a simple number at run time, then I don't see how macros, templates, covariant return types, and all the tricks you can read about in books on C++ can ever be helpful. Think about the eval() trick as GiNaC's way of doing duck typing in the C++ language! Please drop me a note if you happen to know a more straightforward way. I may be very biased, but I see two ways for you: Stick with Python, live happy, and don't be concerned about an occasional performance drop. Or reimplement (a possibly better) GiNaC and do Python bindings (again). But implementing the core of SymPy in C++ just for the sake of speed is probably not worth worrying about. But back to the original topic: I do hope that the sum-of-matrices evaluation thingie is no reason for despair. Way back, that was a deliberte decision. But maybe it was a mistake to place matrices in the type hierarchy at all. Maybe they would be less confusing if they were not subtypes of basic, managed by ex, but classes standing apart from the rest of the hierarchy. That would duplicate some code, however. From past discussions, my impression is that this idea would have some followers on this list. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>