Dear Richy, On Thu, 6 Jan 2005, Richard B. Kreckel wrote:
But wait a minute! The problem comes from ex::is_zero() const in ex.h:208: There we have the inline member function
bool is_zero() const { extern const ex _ex0; return is_equal(_ex0); }
But have a look at utils.cpp. Initialization jumps from all the modules that include ex.h into the ctor of library_init and there all the numeric objects are initialized. But _ex0 is declared above that ctor and it is not initialized until the module utils.o is initialized itself! Just the jumps into that ctor do not as a by-product initialize all the static objects.
Ah! Now, after some thinking, I think I understand it. _ex0 is initialized at the point when utils.o is initialized, which may well be after integral::relative_integration_error is intialized.
If that analysis is correct there appears to be a loophole in the initialization order scheme. I wonder how that can be fixed without creating a big mess in utils.cpp...
Well, it makes me wonder why there is such a thing as a library_init. After all, it appears that just writing ex integral::relative_integration_error = 1e-8; is also allowed. Why is not that done for all static objects, such as _ex0? The only thing is that other static objects, should not be using _ex0, as I did with my .evalf(). As far as I understand library_init was introduced to solve this "problem", however is the problem solvable at all? After all, _ex0 exists because it is initialized in some *.o file and, I think, it should not be initialized in multiple *.o files, because that would cause errors for multiple definitions. Since nobody appears to be guaranteeing anything about the order in which the different *.o files are intialized, _ex0 should not be used in a static object anywhere, no matter what kind of initialization gymnastics you are going to add to this.
Your patch seems to work, thanks a lot! The patch below seems to fix the problem just as well. By virtue of ex::construct_from_double(double) it should be equivalent to your patch. If you have no objections, I'll commit it.
+ex integral::relative_integration_error = 1e-8;
Fine with me! Best wishes, Chris