Hoi GiNaC people, On Fri, 6 Apr 2001, Christian Bauer wrote:
Log Message: - replaced the various print*() member functions by a single print() that takes a print_context object that determines the output formatting; this should make it easier to add more output types
In Python standard there are two output types: one for pretty print (str), e.g. str(add(power(2,symbol('n')),3)) -> "2**n+3" and another for reproducible print (repr), e.g. repr(add(power(2,symbol('n')),3)) -> "add(power(numeric('2'),symbol('n')),numeric('3'))" In order to use GiNaC from Python, I used print() function for str() and printraw() function for repr(). For that I re-implemented GiNaC::*::print*() functions, and when linking, I used their compiled codes before -lginac. This hacky method worked perfectly and it was the only way to introduce a new output type (for Python) without modifying GiNaC sources. Now, with this new print() standard, nothing has changed. I still have to re-implement print() function in the same way again:(. But looking forward to future where you might support output types such as LaTeX, MathML, etc. that could be useful also from Python, my approach doesn't feel right. And on the other hand, you hardly want to support Python (or any other third party language) output formats. So, I am wondering if it would be possible for GiNaC to support *external* output types? For example, by a special print_context object, say, print_callback, that contains an user-defined function for printing ex object and it is called from print() function with an additional argument (TINFO_*) saying who called it (e.g. symbol::print or matrix::print). In this way all printing stuff could be collected in a separate file and it should be possible to define optional output formats without modifying GiNaC sources. What do you think? Regards, Pearu
Hi! On Sat, Apr 07, 2001 at 05:18:42PM +0200, Pearu Peterson wrote:
For example, by a special print_context object, say, print_callback, that contains an user-defined function
This doesn't sound different from a general tree-traversal function like this one: static void traverse(const ex & e) { cout << e.bp->class_name() << "("; unsigned n = e.nops(); if (n) for (unsigned i=0; i<n; i++) { traverse(e.op(i)); if (i != n-1) cout << ","; } else cout << "'" << e << "'"; cout << ")"; } "traverse(pow(2, n) + 3)" will produce add(power(numeric('2'),symbol('n')),numeric('3')) The traverse() function needs further refinement because some classes have additional properties that are not accessible via op() (the most noticable error is that all functions are printed as "function(...)" instead of with their real name; and there doesn't seem to be a way to get the name from a function object (this will be corrected shortly)), but basically it seems to be what you want. Bye, Christian -- / Coding on PowerPC and proud of it \/ http://www.uni-mainz.de/~bauec002/
On Sat, 7 Apr 2001, Christian Bauer wrote:
The traverse() function needs further refinement because some classes have additional properties that are not accessible via op() (the most noticable error is that all functions are printed as "function(...)" instead of with their real name; and there doesn't seem to be a way to get the name from a function object (this will be corrected shortly)), but basically it seems to be what you want.
Thanks for the hint! I'll give it a try: this function is going to be lengthy but at least there is no need to change GiNaC for that. On Sat, 7 Apr 2001, Richard B. Kreckel wrote:
On Sat, 7 Apr 2001, Pearu Peterson wrote:
feel right. And on the other hand, you hardly want to support Python (or any other third party language) output formats.
Why not? Isn't this exactly what class print_context and decendants are supposed to be good for provided we get the right patches for inclusion into the GiNaC::*::print() methods?
Right, but I doubt that it will hold for the Python interface (pyGiNaC) that I am working on, because 1) Python output format is useful **only** if one is actually going to use pyGiNaC, not just Python. 2) pyGiNaC unfortunately depends on Boost.Python (www.boost.org, which greatly simplifies wrapping C++ classes to Python) and therefore I cannot expect that you want to include all this stuff to GiNaC. Thanks for you replies, Pearu
On Sat, 7 Apr 2001, Christian Bauer wrote:
The traverse() function needs further refinement because some classes have additional properties that are not accessible via op() (the most noticable
Indeed, in addition I had to use intermediate classes (that implement some `inline const * & get_*(void) const;' methods) to get the following protected members (in order to use them in a function for Python output format): basic::precedence pseries::seq pseries::var pseries::point relational::o expairseq::seq expairseq::overall_coeff Some of them can be determined indirectly (e.g. relational::o -- by info method, basic::precedence -- look-the-source), some not (e.g. pseries::var). It would be great if GiNaC could provide the corresponding getters. If not, not a problem -- one can use varios work-arounds. Regards, Pearu
Hi! On Sun, Apr 08, 2001 at 06:17:50PM +0200, Pearu Peterson wrote:
basic::precedence
Why do you need this?
pseries::seq pseries::var pseries::point
These are theoretically accessible with op() but you will have to extract the expansion variable and point manually. I will add get_var() and get_point() methods. Then you can get the coefficients by iterating over coeff() from ldegree() to degree() (and ignoring zero coefficients).
expairseq::seq expairseq::overall_coeff
These are accessible with op(). You don't need (and don't want) to access seq/overall_coeff directly. Here's another idea for finding all properties of all objects of a GiNaC expression: if you archive the expression, all relevant information will be stored inside an archive object. Currently, it's all safely hidden inside, but I see no problem in making the data available for public read access. It should then be easy to, e.g., convert an archived expression to a Python initializer. Bye, Christian -- / Coding on PowerPC and proud of it \/ http://www.uni-mainz.de/~bauec002/
Hi! On Sun, 8 Apr 2001, Christian Bauer wrote:
On Sun, Apr 08, 2001 at 06:17:50PM +0200, Pearu Peterson wrote:
basic::precedence
Why do you need this?
basic::precedence (that is, basic::get_precedence() virtual) is needed for Python `str' representation. It is very close to ginsh output type but has the following differences: 1) a^b is a**b in Python, 2) [[ [[a]], [[b]] ]] is [ [a], [b] ] (matrix) 3) For GiNaC function objects I needed a special trick to support their creation and calling from Python. The trick includes a special class that contains information about Python functions and its instance is past to GiNaC function as an additional argument that the end-user should *not* see. 4) Some additional tricks were needed for constant objects in order to support Python callbacks for evaluation. Because of all this I separated the code generating Python `str' and `repr' representation from GiNaC and it is now (almost) independent of GiNaC.print functions.
Here's another idea for finding all properties of all objects of a GiNaC expression: if you archive the expression, all relevant information will be stored inside an archive object. Currently, it's all safely hidden inside, but I see no problem in making the data available for public read access. It should then be easy to, e.g., convert an archived expression to a Python initializer.
I guess (never tried), it means extra work/code. But not all properties are needed, just those that were used in *constructing* the object. In order words, just getter methods inline const * get_<what's-in-constructor-arguments>() const; In addtion, I found that color::representation_label is private. Could you make it at least protected or provide get_representation_label() function? Because it is explicitely used in construction of an color object and therefore is crucial to know for reproducibility in Python interface. The same holds for minkmetric::pos_sig tensepsilon::minkowski tensepsilon::pos_sig Thanks for your other hints as well, Pearu
Hi! On Mon, Apr 09, 2001 at 09:44:45AM +0200, Pearu Peterson wrote:
But not all properties are needed, just those that were used in *constructing* the object.
Which is precisely the set of properties stored in archives. That's what they were designed for. Bye, Christian -- / Coding on PowerPC and proud of it \/ http://www.uni-mainz.de/~bauec002/
Hanoi, On Sat, 7 Apr 2001, Pearu Peterson wrote:
Now, with this new print() standard, nothing has changed. I still have to re-implement print() function in the same way again:(. But looking forward to future where you might support output types such as LaTeX, MathML, etc. that could be useful also from Python, my approach doesn't feel right. And on the other hand, you hardly want to support Python (or any other third party language) output formats.
Why not? Isn't this exactly what class print_context and decendants are supposed to be good for provided we get the right patches for inclusion into the GiNaC::*::print() methods? Regards -richy. -- Richard Kreckel <Richard.Kreckel@Uni-Mainz.DE> <http://wwwthep.physik.uni-mainz.de/~kreckel/>
participants (3)
-
Christian Bauer
-
Pearu Peterson
-
Richard B. Kreckel