Hi, I want to share some findungs about the new tinfo mechanism I proposed lately: In principle, it works! The return_type_tinfo() methods have to be changed a little bit, because the bit pattern arithmetics done for clifford and color classes (there, tinfo is combined with the representation label) are no longer possible. The quick and dirty fix I made for that should cause a slight performance loss, but I was not able to measure one, yet. In practice, there is a problem: Two checks fail. One check is the normalization check: e = (pow(x, 2) - pow(y, 2)) / pow(x-y, 3); d = (x + y) / pow(x - y, 2); result += check_normal(e, d); Since now the tinfos do change from compilation to compilation, also the hash values do change. So the canonical ordering can be different and normal seems to be very dependent on that ordering. In 50% of the cases the check fails, because the normalization returns (x+y) * pow(-x+y,-2), which is correct but doesn't compare well. The second check that fails is from the clifford checks: e = dirac_gamma(mu, 0) * dirac_gamma(mu.toggle_variance(), 1) * dirac_gamma(nu, 0) * dirac_gamma(nu.toggle_variance(), 1); result += check_equal_simplify(dirac_trace(e, 2), canonicalize_clifford(e)); // e will be canonicalized by the calculation of the trace Here sometimes (like every third invocation) canonicalize_clifford(e) returns a wrong result: (dirac_gamma.nu*dirac_gamma.mu)*(dirac_gamma^nu*dirac_gamma^mu) The mu and nu are swapped! I don't know how to interpret these failures. Is the new tinfo mechanism doomed? Is there a bug in canonicalize_clifford and the normalization check is flawed? The reason to think about a new tinfo mechnism for me is the idea to get rid of the current function class and replace it by a every-ginac-function-is-class way of doing it. Regards, Jens
Hi! Jens Vollinga wrote:
In practice, there is a problem: Two checks fail. One check is the normalization check:
e = (pow(x, 2) - pow(y, 2)) / pow(x-y, 3); d = (x + y) / pow(x - y, 2); result += check_normal(e, d);
Since now the tinfos do change from compilation to compilation, also the hash values do change. So the canonical ordering can be different and normal seems to be very dependent on that ordering. In 50% of the cases the check fails, because the normalization returns (x+y) * pow(-x+y,-2), which is correct but doesn't compare well.
The second check that fails is from the clifford checks:
e = dirac_gamma(mu, 0) * dirac_gamma(mu.toggle_variance(), 1) * dirac_gamma(nu, 0) * dirac_gamma(nu.toggle_variance(), 1); result += check_equal_simplify(dirac_trace(e, 2), canonicalize_clifford(e)); // e will be canonicalized by the calculation of the trace
Here sometimes (like every third invocation) canonicalize_clifford(e) returns a wrong result: (dirac_gamma.nu*dirac_gamma.mu)*(dirac_gamma^nu*dirac_gamma^mu) The mu and nu are swapped!
I don't know how to interpret these failures. Is the new tinfo mechanism doomed? Is there a bug in canonicalize_clifford and the normalization check is flawed?
Failures that can be traced to changes in the actual hash values are not serious. This is the same issue that was brought up by Jonathan Brandmeyer recently, where he wondered why the PyGiNaC testsuite failed sometimes: <http://www.ginac.de/pipermail/ginac-list/2005-October/000748.html>. The same can happen when the serial numbers of symbols change because an additional symbol is created earlier on in the program. Or one symbol less. This has nothing to do with your tinfo-ideas: I would suggest to change these exams in the testsuite by calling expand(), normal() or doing additional index contraction, respectively. The way they are written right now is not good, especially from a didactical point of view. People should learn not to rely on random behavior.
The reason to think about a new tinfo mechnism for me is the idea to get rid of the current function class and replace it by a every-ginac-function-is-class way of doing it.
I made an attempt in that direction several years ago. It didn't go too well: <http://www.ginac.de/pipermail/ginac-devel/2001-June/000259.html>. But then, maybe you're up to something different. Could you elaborate a little on your ideas? Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi, Richard B. Kreckel wrote:
I don't know how to interpret these failures. Is the new tinfo mechanism doomed? Is there a bug in canonicalize_clifford and the normalization check is flawed?
The same can happen when the serial numbers of symbols change because an additional symbol is created earlier on in the program. Or one symbol less. This has nothing to do with your tinfo-ideas: I would suggest to change these exams in the testsuite by calling expand(), normal() or doing additional index contraction, respectively. The way they are written right now is not good, especially from a didactical point of view. People should learn not to rely on random behavior.
Good. Then I only have to re-examine the canonicalize_clifford difference.
The reason to think about a new tinfo mechnism for me is the idea to get rid of the current function class and replace it by a every-ginac-function-is-class way of doing it.
I made an attempt in that direction several years ago. It didn't go too well: <http://www.ginac.de/pipermail/ginac-devel/2001-June/000259.html>. But then, maybe you're up to something different. Could you elaborate a little on your ideas?
I am just starting to think about it. Arguments like 'no advantage' and 'no hierarchy' aren't valid anymore, I think. Whether the complexity to define such a class-function is lower, equal or higher than the current one has to be evaluated. I haven't figured out the exact way how such a class-function could be implemented, though. Stupid question: what are the numeric SOMEFUNC(const numeric& ...) functions good for? Is it performance? Is it a way to try to separate cln stuff from ginac stuff? I don't know how to solve the problem of namespace collision/ambiguity with built-in function like sin,cos,... yet. But even in the current implementation a get an ambiguity for stuff like cout << sin(1) << endl; when both cmath and GiNaC are included and all their namespace members are us'ing'ed. Regards, Jens
Hi, Jens Vollinga wrote:
I don't know how to solve the problem of namespace collision/ambiguity with built-in function like sin,cos,... yet. But even in the current implementation a get an ambiguity for stuff like cout << sin(1) << endl; when both cmath and GiNaC are included and all their namespace members are us'ing'ed.
just to fill the void: 1. We could rename the functions: tan->Tan,... etc. (I don't like this. It's cowardice.) 2. We could write some pre-processor definitions like #define sin GiNaC::sin ... (Well, maybe. These definition could be packed in a convenience header for the user like #include <GiNaC/GiNaC_with_cmath>. But better not to include this header multiple times ...) 3. Don't avoid the ambiguities and force the user to explicitly write the namespace for such functions (and make lots of comments about it in the manual/tutorial). (Yes, use the force! Maybe give the user some extra header like in 2. to ease the situation). Regards, Jens
Hi! Jens Vollinga wrote:
I don't know how to solve the problem of namespace collision/ambiguity with built-in function like sin,cos,... yet. But even in the current implementation a get an ambiguity for stuff like cout << sin(1) << endl; when both cmath and GiNaC are included and all their namespace members are us'ing'ed.
just to fill the void:
1. We could rename the functions: tan->Tan,... etc. (I don't like this. It's cowardice.)
2. We could write some pre-processor definitions like #define sin GiNaC::sin ... (Well, maybe. These definition could be packed in a convenience header for the user like #include <GiNaC/GiNaC_with_cmath>. But better not to include this header multiple times ...)
I fear this will cause even more problems.
3. Don't avoid the ambiguities and force the user to explicitly write the namespace for such functions (and make lots of comments about it in the manual/tutorial). (Yes, use the force! Maybe give the user some extra header like in 2. to ease the situation).
This is a patch to the wrong location, since function.h is generated. But doesn't it resolve the worst ambiguities where there is a conflict with cmath's template<typename _Tp> typename __enable_if<double, __is_integer<_Tp>::__value>::__type sin(_Tp)? --- function.h.old 2005-11-21 21:43:16.063691034 +0100 +++ function.h 2005-11-21 21:42:19.964061214 +0100 @@ -39,6 +39,15 @@ #define DECLARE_FUNCTION_1P(NAME) \ class NAME##_SERIAL { public: static unsigned serial; }; \ const unsigned NAME##_NPARAMS = 1; \ +const GiNaC::function NAME(const ex & p1) { \ + return GiNaC::function(NAME##_SERIAL::serial, p1); \ +} \ +const GiNaC::function NAME(int p1) { \ + return GiNaC::function(NAME##_SERIAL::serial, GiNaC::ex(p1)); \ +} \ template<typename T1> const GiNaC::function NAME(const T1 & p1) { \ return GiNaC::function(NAME##_SERIAL::serial, GiNaC::ex(p1)); \ } Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi, Richard B. Kreckel wrote:
3. Don't avoid the ambiguities and force the user to explicitly write the namespace for such functions (and make lots of comments about it in the manual/tutorial). (Yes, use the force! Maybe give the user some extra header like in 2. to ease the situation).
This is a patch to the wrong location, since function.h is generated. But doesn't it resolve the worst ambiguities where there is a conflict with cmath's template<typename _Tp> typename __enable_if<double,
... the more I think about it the more I like my proposal no.3. Maybe GiNaC shouldn't read the programmer's mind and try to "fix" the ambiguities. In C++ grammar school they always warn you about using using namespace std; using namespace cmath; and the like. They tell you something about avoiding evil errors by sacrificing some additional key strokes in order to put std:: or GiNaC:: in front of names. While I hate typing such extra I do appreciate the argument: If some user really needs to include cmath AND ginac AND wants to have "using namespace std;" at the top (and not locally in some function ...) of his file (does anybody know this user?!?), HE should make clear which sin or log from which library he actually wants. I will prepare a small code example during the next days to offer a better foundation for the discussion. Maybe I see the problems with "class sin : public classfunc {}" clearer then. Regards, Jens
Hi! Jens Vollinga wrote:
I am just starting to think about it. Arguments like 'no advantage' and 'no hierarchy' aren't valid anymore, I think.
Well, is there a useful type-hiearchy one could build out of functions? And: what could be the advantage of such an approach? Please show us! The wrapper functions are there because you cannot define classes of name sin, cos, etc. without running into tons of resolution problems. You would have to call the classes differently and add convenient functions that return those classes. That's what we already have, except they always return the same type.
Whether the complexity to define such a class-function is lower, equal or higher than the current one has to be evaluated. I haven't figured out the exact way how such a class-function could be implemented, though.
Stupid question: what are the numeric SOMEFUNC(const numeric& ...) functions good for? Is it performance? Is it a way to try to separate cln stuff from ginac stuff?
Oh, that is only a more direct evaluation when only numeric evaluation is called for. It's got nothing to do with CLN. Rather, performance. And maybe it's not terribly useful. But isn't this the same question: what is numeric operator+(const numeric&, const numeric&) good for?
I don't know how to solve the problem of namespace collision/ambiguity with built-in function like sin,cos,... yet. But even in the current implementation a get an ambiguity for stuff like cout << sin(1) << endl; when both cmath and GiNaC are included and all their namespace members are us'ing'ed.
But that is just a problem with our implementation of ginac/function.h! CLN has no such problem, even with newer versions of GCC. If that is really a concern, I suggest simply adding disambiguating explicit signatures to the templates that DECLARE_FUNCTION_nP expand to. It cannot be done for all and every combination of them because that would be too much code. But then, we really only need it for DECLARE_FUNCTION_1P and DECLARE_FUNCTION_2P, right? Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (2)
-
Jens Vollinga
-
Richard B. Kreckel