Dear All, I propose to change all test for an argument type lst as follows: is_a<lst>(e) --> e.info(info_flags::list) The former tests fail with lst created by boostPython (e.g. pyGiNaC) and the later are passed. I did the change in clifford.cpp and wondering if it should be applied everywhere. The included patch is cumulative from my previous two messages. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ /home/amsta/kisilv/GiNaC Index: debian/changelog =================================================================== RCS file: /home/cvs/GiNaC/debian/changelog,v retrieving revision 1.36 diff -u -r1.36 changelog --- debian/changelog 20 Apr 2006 22:59:39 -0000 1.36 +++ debian/changelog 10 May 2006 12:16:15 -0000 @@ -3,7 +3,7 @@ * New upstream release; binary incompatible, so it's libginac1.4 now. * debian/*: Streamlining by Peter Eisentraut <petere@debian.org>. - -- Richard Kreckel <kreckel@ginac.de> <DATE> + -- Richard Kreckel <kreckel@ginac.de> Mon, 17 Apr 2006 22:25:48 +0200 ginac (1.3.4-1) unstable; urgency=low Index: doc/tutorial/ginac.texi =================================================================== RCS file: /home/cvs/GiNaC/doc/tutorial/ginac.texi,v retrieving revision 1.185 diff -u -r1.185 ginac.texi --- doc/tutorial/ginac.texi 22 Apr 2006 15:42:57 -0000 1.185 +++ doc/tutorial/ginac.texi 10 May 2006 12:16:15 -0000 @@ -2053,6 +2053,12 @@ @} @end example +@cindex @code{is_zero_matrix()} +The method @code{matrix::is_zero_matrix()} returns @code{true} only if +all entries of the matrix are zeros. There is also method +@code{ex::is_zero_matrix()} which returns @code{true} only if the +expression is zero or a zero matrix. + @cindex @code{transpose()} There are three ways to do arithmetic with matrices. The first (and most direct one) is to use the methods provided by the @code{matrix} class: @@ -3545,9 +3551,10 @@ the matrix @samp{M = [[a, b], [c, d]]}. The parameter @code{G} defines the metric of the surrounding (pseudo-)Euclidean space. This can be an indexed object, tensormetric, matrix or a Clifford unit, in the later -case the optional parameters @code{rl} and @code{anticommuting} are ignored -even if supplied. The returned value of this function is a list of -components of the resulting vector. +case the optional parameters @code{rl} and @code{anticommuting} are +ignored even if supplied. Depending from the type of @code{v} the +returned value of this function is either a vector or a list holding vector's +components. @cindex @code{clifford_max_label()} Finally the function @@ -4097,7 +4104,8 @@ @end example for checking whether one expression is equal to another, or equal to zero, -respectively. +respectively. See also the method @code{ex::is_zero_matrix()}, +@pxref{Matrices}. @subsection Ordering expressions Index: ginac/clifford.cpp =================================================================== RCS file: /home/cvs/GiNaC/ginac/clifford.cpp,v retrieving revision 1.95 diff -u -r1.95 clifford.cpp --- ginac/clifford.cpp 22 Feb 2006 14:52:07 -0000 1.95 +++ ginac/clifford.cpp 10 May 2006 12:16:15 -0000 @@ -1053,7 +1053,7 @@ pointer_to_map_function fcn(canonicalize_clifford); if (is_a<matrix>(e_) // || is_a<pseries>(e) || is_a<integral>(e) - || is_a<lst>(e_)) { + || e_.info(info_flags::list)) { return e_.map(fcn); } else { ex e=simplify_indexed(e_); @@ -1120,7 +1120,7 @@ if (is_a<clifford>(e) && is_a<cliffordunit>(e.op(0))) { return -e; } else if (is_a<add>(e) || is_a<ncmul>(e) || is_a<mul>(e) //|| is_a<pseries>(e) || is_a<integral>(e) - || is_a<matrix>(e) || is_a<lst>(e)) { + || is_a<matrix>(e) || e.info(info_flags::list)) { return e.map(fcn); } else if (is_a<power>(e)) { return pow(clifford_prime(e.op(0)), e.op(1)); @@ -1145,7 +1145,7 @@ else throw(std::invalid_argument("remove_dirac_ONE(): expression is a non-scalar Clifford number!")); } else if (is_a<add>(e1) || is_a<ncmul>(e1) || is_a<mul>(e1) - || is_a<matrix>(e1) || is_a<lst>(e1)) { + || is_a<matrix>(e1) || e1.info(info_flags::list)) { if (options & 3) // is a child or was already expanded return e1.map(fcn); else @@ -1227,8 +1227,8 @@ else throw(std::invalid_argument("lst_to_clifford(): dimensions of vector and clifford unit mismatch")); } else - throw(std::invalid_argument("lst_to_clifford(): first argument should be a vector vector")); - } else if (is_a<lst>(v)) { + throw(std::invalid_argument("lst_to_clifford(): first argument should be a vector (nx1 or 1xn matrix)")); + } else if (v.info(info_flags::list)) { if (dim == ex_to<lst>(v).nops()) return indexed(matrix(dim, 1, ex_to<lst>(v)), ex_to<varidx>(mu).toggle_variance()) * e; else @@ -1246,7 +1246,7 @@ pointer_to_map_function_1arg<const ex &> fcn(get_clifford_comp, c); int ival = ex_to<numeric>(ex_to<varidx>(c.op(1)).get_value()).to_int(); - if (is_a<add>(e) || is_a<lst>(e) // || is_a<pseries>(e) || is_a<integral>(e) + if (is_a<add>(e) || e.info(info_flags::list) // || is_a<pseries>(e) || is_a<integral>(e) || is_a<matrix>(e)) return e.map(fcn); else if (is_a<ncmul>(e) || is_a<mul>(e)) { @@ -1335,7 +1335,7 @@ { ex x, D, cu; - if (! is_a<matrix>(v) && ! is_a<lst>(v)) + if (! is_a<matrix>(v) && ! v.info(info_flags::list)) throw(std::invalid_argument("clifford_moebius_map(): parameter v should be either vector or list")); if (is_a<clifford>(G)) { @@ -1352,8 +1352,8 @@ } x = lst_to_clifford(v, cu); - ex e = simplify_indexed(canonicalize_clifford((a * x + b) * clifford_inverse(c * x + d))); - return clifford_to_lst(e, cu, false); + ex e = clifford_to_lst(simplify_indexed(canonicalize_clifford((a * x + b) * clifford_inverse(c * x + d))), cu, false); + return (is_a<matrix>(v) ? matrix(ex_to<matrix>(v).rows(), ex_to<matrix>(v).cols(), ex_to<lst>(e)) : e); } ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl, bool anticommuting) Index: ginac/ex.h =================================================================== RCS file: /home/cvs/GiNaC/ginac/ex.h,v retrieving revision 1.87 diff -u -r1.87 ex.h --- ginac/ex.h 21 Apr 2006 12:16:01 -0000 1.87 +++ ginac/ex.h 10 May 2006 12:16:15 -0000 @@ -205,6 +205,7 @@ int compare(const ex & other) const; bool is_equal(const ex & other) const; bool is_zero() const { extern const ex _ex0; return is_equal(_ex0); } + bool is_zero_matrix() const; // symmetry ex symmetrize() const; Index: ginac/ex.cpp =================================================================== RCS file: /home/cvs/GiNaC/ginac/ex.cpp,v retrieving revision 1.60 diff -u -r1.60 ex.cpp --- ginac/ex.cpp 27 Mar 2006 15:13:22 -0000 1.60 +++ ginac/ex.cpp 10 May 2006 12:16:16 -0000 @@ -28,6 +28,7 @@ #include "mul.h" #include "ncmul.h" #include "numeric.h" +#include "matrix.h" #include "power.h" #include "lst.h" #include "relational.h" @@ -254,6 +255,17 @@ return bp->is_polynomial(vars); } +/** Check whether expression is zero or zero matrix. */ +bool ex::is_zero_matrix() const +{ + if (is_zero()) + return true; + else { + ex e = evalm(); + return is_a<matrix>(e) && ex_to<matrix>(e).is_zero_matrix(); + } +} + // private /** Make this ex writable (if more than one ex handle the same basic) by Index: ginac/matrix.h =================================================================== RCS file: /home/cvs/GiNaC/ginac/matrix.h,v retrieving revision 1.71 diff -u -r1.71 matrix.h --- ginac/matrix.h 21 Apr 2006 12:16:01 -0000 1.71 +++ ginac/matrix.h 10 May 2006 12:16:16 -0000 @@ -151,6 +151,7 @@ matrix solve(const matrix & vars, const matrix & rhs, unsigned algo = solve_algo::automatic) const; unsigned rank() const; + bool is_zero_matrix() const; protected: ex determinant_minor() const; int gauss_elimination(const bool det = false); Index: ginac/matrix.cpp =================================================================== RCS file: /home/cvs/GiNaC/ginac/matrix.cpp,v retrieving revision 1.108 diff -u -r1.108 matrix.cpp --- ginac/matrix.cpp 21 Apr 2006 12:16:01 -0000 1.108 +++ ginac/matrix.cpp 10 May 2006 12:16:16 -0000 @@ -1527,6 +1527,16 @@ return k; } +/** Function to check that all elements of the matrix are zero. + */ +bool matrix::is_zero_matrix() const +{ + bool result = true; + for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i) + result = result && (*i).is_zero(); + return result; +} + ex lst_to_matrix(const lst & l) { lst::const_iterator itr, itc;
Dear Vladimir and others, On Wed, 10 May 2006, Vladimir Kisil wrote:
is_a<lst>(e) --> e.info(info_flags::list)
The former tests fail with lst created by boostPython (e.g. pyGiNaC) and the later are passed. I did the change in clifford.cpp and wondering if it should be applied everywhere.
Shouldn't this be considered a problem that is to be solved in pyGiNaC instead of in GiNaC? After all I think that users of pyGiNaC should be able to use is_a<lst> for the lists that they create. Does it also go wrong in user code? Does it go wrong with other types than lst? Another point against this is that I just measured that is_a<lst> is faster if one uses -O2 optimization than .info(info_flags::list) (but slower if -O2 is not used). This could, however, be platform/compiler/whatnot-dependent. Best wishes, Chris
"CD" == Chris Dams <Chris.Dams@mi.infn.it> writes: >> (e.g. pyGiNaC) and the later are passed. I did the change in >> clifford.cpp and wondering if it should be applied everywhere.
CD> Shouldn't this be considered a problem that is to be solved in CD> pyGiNaC instead of in GiNaC? I do not understand all internals deeply, but this may be a problem with the BoostPython, which is the engine of pyGiNaC. In this case it may be rather difficult to correct. On the other hand I really enjoy the interactivity of pyGiNaC and think its is worth for GiNaC to make a small step towards it. CD> Does it go wrong with other types than lst? It seems like the root of problem in the GiNaC::lst itself, since this is the only(?) class in GiNaC which is not a child of basic. So far I did not notice problems with other GiNaC derived classes. CD> After all I think that users of pyGiNaC should be able CD> to use is_a<lst> for the lists that they CD> create. There two level there. First it is necessary to write a C++ wrapper in BoostPython for any class derived from GiNaC (we are doing it now for my library for cycles). For some reasons which I do not understand this does not work for lst. Hence each time the wrapper should explicitly convert Python lists to GiNaC::lst, and the later fail to pass is_a<lst> test. ;-( CD> Does it also go wrong in user code? After a library is already wrapped the user code is written in Python, and is_a<lst> is not required anymore. CD> Another point against this is that I just measured that CD> is_a<lst> is faster if one uses -O2 optimization than CD> .info(info_flags::list) (but slower if -O2 is not used). This CD> could, however, be platform/compiler/whatnot-dependent. However there is no consistency in the GiNaC code which method should be used to test lst class. For example, lsolve() uses info_keys... Best, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/
Dear Vladimir, On Thu, 11 May 2006, Vladimir Kisil wrote:
"CD" == Chris Dams <Chris.Dams@mi.infn.it> writes: >> (e.g. pyGiNaC) and the later are passed. I did the change in >> clifford.cpp and wondering if it should be applied everywhere.
CD> Shouldn't this be considered a problem that is to be solved in CD> pyGiNaC instead of in GiNaC?
I do not understand all internals deeply, but this may be a problem with the BoostPython, which is the engine of pyGiNaC. In this case it may be rather difficult to correct. On the other hand I really enjoy the interactivity of pyGiNaC and think its is worth for GiNaC to make a small step towards it.
I am very much in favour of interactive programs based on GiNaC but am a bit afraid that solving this problem within GiNaC (1) fixes something in GiNaC that is not a bug and (2) fails to fix something that is a bug in another package. Did you try to contact the autor/mailing list of pyGiNaC on this?
CD> Does it go wrong with other types than lst?
It seems like the root of problem in the GiNaC::lst itself, since this is the only(?) class in GiNaC which is not a child of basic. So far I did not notice problems with other GiNaC derived classes.
Well, lst is a child of basic but Maybe the problem is that container is a child class of both basic and container_storage. Maybe you could test whether this is the case by trying an example for yourself where you try to wrap a class that is multiply inherited. This could give an idea whether the problem with pyGiNaC or with BoostPython.
CD> After all I think that users of pyGiNaC should be able CD> to use is_a<lst> for the lists that they CD> create.
There two level there. First it is necessary to write a C++ wrapper in BoostPython for any class derived from GiNaC (we are doing it now for my library for cycles). For some reasons which I do not understand this does not work for lst. Hence each time the wrapper should explicitly convert Python lists to GiNaC::lst, and the later fail to pass is_a<lst> test. ;-(
Maybe you could try to construct a minimal example that exhibits the problem and mail that to the PyGiNaC mailing list or author. Best, Chris
participants (2)
-
Chris Dams
-
Vladimir Kisil