Hi folks, I'm going to ask a very basic question, namely if you can point me to a tutorial where GiNaC's memory managment is described. I read the tutorial from your website but I could not find any info on this. I am familiar with the retain/release mechanism of used by Cocoa and GNUstep, and the use of autorelease pools. If you could compare these concepts to their GiNaC equivalents, that would be of great help. E.g. in Objective C I can create a tree of objects and either free them myself or put them into an autorelease pool that will be emptied by the runloop. How would I do this in GiNaC? Suppose I create a matrix of rational functions, a single entry of which I'm interested in retaining. I would like to free the matrix and retain that one function. Can you provide a code snippet that does this? I would also like to know what the limitations of the linear equation solver are. How many variables can it handle? What are the time and space complexities of the solver in terms of the number of variables and the number of equations? Thanks in advance for any help you may be able to give. Best regards, Marko Riedel +-------------------------------------------------------------+ | Marko Riedel, EDV Neue Arbeit gGmbH, mriedel@lsi.upc.es | | http://www.geocities.com/markoriedelde/index.html | +-------------------------------------------------------------+
Hi! Marko Riedel wrote:
I'm going to ask a very basic question, namely if you can point me to a tutorial where GiNaC's memory managment is described. I read the tutorial from your website but I could not find any info on this.
I am familiar with the retain/release mechanism of used by Cocoa and GNUstep, and the use of autorelease pools. If you could compare these concepts to their GiNaC equivalents, that would be of great help. E.g. in Objective C I can create a tree of objects and either free them myself or put them into an autorelease pool that will be emptied by the runloop. How would I do this in GiNaC?
The objects behind a GiNaC::ex are generally trees, but you just deal with the top-level thing and everything else happens automatically. Its up to you whether to allocate that top-level thing on the stack or on the heap. It will maintain its subobjects on the heap, but you don't have to care about that.
Suppose I create a matrix of rational functions, a single entry of which I'm interested in retaining. I would like to free the matrix and retain that one function. Can you provide a code snippet that does this?
// ... ex interesting_element; { GiNaC::matrix mybigmatrix(100,100); // construct mybigmatrix interesting_element = mybigmatrix(47,11); } // use interesting_element here... At the closing brace, mybigmatrix goes out of scope. The destructor incurs derementing the refcount of all 10000 elements, which get deleted if their refcount reaches zero. The refcount of the element of interest, however, was two (at least). So it continues to exist and you can use it afterwards.
I would also like to know what the limitations of the linear equation solver are. How many variables can it handle? What are the time and space complexities of the solver in terms of the number of variables and the number of equations?
Asking for complexity in symbolic algorithms in such a general way does not make sense. An algorithm which is O(n^2) over the integers does not have to be so in any integral domain. It may be O(d*n^2) over univariate polynomials of degree d or even much worse. You have to try it out in order to find the practical limitations in your particular case. Several alternative elimination algorithms are implemented. There is a crude heuristic that decides which one to pick. But, as any heuristic, it can fail. You can always override the heuristics and do your own experiments: <http://www.ginac.de/reference/classGiNaC_1_1solve__algo.html>. Generally, the Bareiss algorithm is superior to the other ones, but if there are many symbols, it gets bogged down early because it incurs huge GCD computations. We've had cases where the Gauss algorithm was superior when the elements were rational functions. Please, try which works best for your problem. Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello there, Richard B. Kreckel writes:
Hi!
Marko Riedel wrote:
I'm going to ask a very basic question, namely if you can point me to a tutorial where GiNaC's memory managment is described. I read the tutorial from your website but I could not find any info on this.
I am familiar with the retain/release mechanism of used by Cocoa and GNUstep, and the use of autorelease pools. If you could compare these concepts to their GiNaC equivalents, that would be of great help. E.g. in Objective C I can create a tree of objects and either free them myself or put them into an autorelease pool that will be emptied by the runloop. How would I do this in GiNaC?
[...]
// ... ex interesting_element; { GiNaC::matrix mybigmatrix(100,100); // construct mybigmatrix interesting_element = mybigmatrix(47,11); } // use interesting_element here...
At the closing brace, mybigmatrix goes out of scope. The destructor incurs derementing the refcount of all 10000 elements, which get deleted if their refcount reaches zero. The refcount of the element of interest, however, was two (at least). So it continues to exist and you can use it afterwards.
Thank you for the concise explanation. I plan on mixing Objective C and C++ and this leads to another question. Suppose I store a GiNaC object in an instance variable of an Objective C object. This operation should increment the referene count of the GiNaC object, right? Next suppose that the deallocation method of the Objective C object is invoked. Now I need an explicit release of the GiNaC object. How would I do this? Do GiNaC objects have a method that retrieves the reference count?
I would also like to know what the limitations of the linear equation solver are. How many variables can it handle? What are the time and space complexities of the solver in terms of the number of variables and the number of equations?
Asking for complexity in symbolic algorithms in such a general way does not make sense. An algorithm which is O(n^2) over the integers does not have to be so in any integral domain. It may be O(d*n^2) over univariate polynomials of degree d or even much worse. You have to try it out in order to find the practical limitations in your particular case.
Do you have concrete experience with systems of equations whose coefficients are univariate polynomials with integer coefficients? Thanks! Best regards, Marko
Hi, Sorry, most of what you say about mixing Objective C and C++ sounds obscure to me, since I don't know any Objective C. Marko Riedel wrote:
Thank you for the concise explanation. I plan on mixing Objective C and C++ and this leads to another question. Suppose I store a GiNaC object in an instance variable of an Objective C object. This operation should increment the referene count of the GiNaC object, right?
If this storing in an instance variable involves calling a constructor or assingment operator, which I do hope, then the answer is yes.
Next suppose that the deallocation method of the Objective C object is invoked. Now I need an explicit release of the GiNaC object. How would I do this?
Wouldn't deallocation invoke the destructor ex::~ex()?
Do GiNaC objects have a method that retrieves the reference count?
There are no private methods.
Do you have concrete experience with systems of equations whose coefficients are univariate polynomials with integer coefficients?
Experience, well, some, but not very systematic experience. I would say that Bareiss is the method of choice here, but I recall having seen problems where Gauss was way superior due to some non-obvious cancellations. (Markus Knodel had such cases, but I'm unable to google it on this list's archives.) Still, talking about algorithmic complexity would require us to first determine that of polynomial multiplication (still obvious) and then that of polynomial long division (not so obvious) and then ask about the size of coefficients and whatnot. Instead, I would just go ahead and try it. Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel writes:
Hi,
Sorry, most of what you say about mixing Objective C and C++ sounds obscure to me, since I don't know any Objective C.
Marko Riedel wrote:
Thank you for the concise explanation. I plan on mixing Objective C and C++ and this leads to another question. Suppose I store a GiNaC object in an instance variable of an Objective C object. This operation should increment the referene count of the GiNaC object, right?
If this storing in an instance variable involves calling a constructor or assingment operator, which I do hope, then the answer is yes.
Next suppose that the deallocation method of the Objective C object is invoked. Now I need an explicit release of the GiNaC object. How would I do this?
Wouldn't deallocation invoke the destructor ex::~ex()?
Greetings. I have an additional question. Can you present me with a list of scenarios in which I would need to manually invoke ex::~ex(), including a few examples? Deallocation in Objective C is not quite the same as in C++. Best regards, Marko +-------------------------------------------------------------+ | Marko Riedel, EDV Neue Arbeit gGmbH, mriedel@lsi.upc.edu | | http://www.geocities.com/markoriedelde/index.html | +-------------------------------------------------------------+
Hi! Marko Riedel wrote:
I have an additional question. Can you present me with a list of scenarios in which I would need to manually invoke ex::~ex(), including a few examples?
In C++, you should never invoke dtors explicitly, unless you do such dirty tricks as discussed in June on this list: <http://www.ginac.de/pipermail/ginac-list/2006-June/thread.html>. Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel writes:
Hi!
Marko Riedel wrote:
I have an additional question. Can you present me with a list of scenarios in which I would need to manually invoke ex::~ex(), including a few examples?
In C++, you should never invoke dtors explicitly, unless you do such dirty tricks as discussed in June on this list: <http://www.ginac.de/pipermail/ginac-list/2006-June/thread.html>.
Greetings. Thanks! This thread is exactly what I was looking for. Can you briefly explain the meaning of reinterpret_cast<GiNaC::ex*>? Wouldn't <GiNaC::ex*> be sufficient? Also, in GiNaC, if I have an expression that is actually a symbol, say, how do I determine at compile time what destructor to call, ~ex or ~symbol? I will need to invoke the destructor explicitly in the deallocation code of my Objective C object. Best regards, Marko +-------------------------------------------------------------+ | Marko Riedel, EDV Neue Arbeit gGmbH, mriedel@lsi.upc.edu | | http://www.geocities.com/markoriedelde/index.html | +-------------------------------------------------------------+
Hi! Marko Riedel wrote:
Thanks! This thread is exactly what I was looking for. Can you briefly explain the meaning of reinterpret_cast<GiNaC::ex*>? Wouldn't <GiNaC::ex*> be sufficient?
The way you write it is not valid. I suppose you mean C-style cast (GiNaC::ex*) instead. Yes, you can as well write it using C-style cast. But you may wish to read a little bit in any textbook about C++ about arguments against C-style cast. The point is that reinterpret_cast<T*> is telling the reader a little bit more than (T*).
Also, in GiNaC, if I have an expression that is actually a symbol, say, how do I determine at compile time what destructor to call, ~ex or ~symbol?
I am not sure if it is such a good idea to do that with objects of class symbol. Why not always wrap the symbols in an ex in your code? The ex are supposed to be helpful when interfacing to environments where one has to give up on C++ types. Anyway: If the object was constructed as a symbol statically, then you have to destroy it as a symbol. If the ex at compile time turns out to be a symbol, then, well, it's still just an ex holding a symbol and you have to destroy it as an ex.
I will need to invoke the destructor explicitly in the deallocation code of my Objective C object.
Ugh! -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi,
In C++, you should never invoke dtors explicitly, unless you do such dirty tricks as discussed in June on this list: <http://www.ginac.de/pipermail/ginac-list/2006-June/thread.html>.
Another place where one might explicitly call dtors is when writing placement new/delete operators in C++. But let's not get too carried away on that subject...
Thanks! This thread is exactly what I was looking for. Can you briefly explain the meaning of reinterpret_cast<GiNaC::ex*>? Wouldn't <GiNaC::ex*> be sufficient? Also, in GiNaC, if I have an expression that is actually a symbol, say, how do I determine at compile time what destructor to call, ~ex or ~symbol?
libstdc++ often uses a helper function to deduce the argument type, and hence its destructor (copied straight from gcc's <bits/stl_construct.h>): namespace std { template <class _Tp> inline void _Destroy(_Tp* __pointer) { __pointer->~_Tp(); } } Then "std::_Destroy(&your_object);" will call the appropriate in-charge destructor, be it virtual or non-virtual. For maximum portability, I wouldn't count on std::_Destroy existing, you you might as well define your own, until such a function is standardized.
I will need to invoke the destructor explicitly in the deallocation code of my Objective C object.
However, I don't know the syntax in Objective C. Fang
participants (3)
-
David Fang
-
Marko Riedel
-
Richard B. Kreckel