Dear all, I think the following should added to the FAQ. Q: I am getting an error message that looks more or less like Internal error: statement in file real/conv/cl_R_to_double.cc, line 55 has been reached!! Please send the authors of the program a description how you produced this error! What should I do? A: This is an error message of the CLN library that GiNaC uses to handle its numerics. The problem usually is that an object was passed to a CLN-function that should have been a number but is not. Your best bet is to check for code that looks like ex_to<numeric>(x) and to check whether x really is a number. The just given code fragment cannot be right if is_a<numeric>(x) yields false. Thanks! Chris
Hello, On Wed, Oct 11, 2006 at 01:20:34PM +0200, Chris Dams wrote:
I think the following should added to the FAQ.
Q: I am getting an error message that looks more or less like
Internal error: statement in file real/conv/cl_R_to_double.cc, line 55 has been reached!! Please send the authors of the program a description how you produced this error!
What should I do?
A: Modify ex_to<T> to check if it is actually possible to convert the argument to type T (and add ex_to_unsafe<T> for those who *really* know what they are doing)? and/or Fix/improve CLN to give less cryptic error message? Something like 'the number can not be converted to double' would be much better. Best regards, Alexei -- All science is either physics or stamp collecting.
Sheplyakov Alexei wrote:
Modify ex_to<T> to check if it is actually possible to convert the argument to type T (and add ex_to_unsafe<T> for those who *really* know what they are doing)?
ex_to<T> is documented as being unsafe. However. that doesn't appear to be enough. I actually like Alexei's suggestion. The ca. 800 occurrences of ex_to<T> inside the library would have to be converted, though. What do others think? -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On 10/11/06, Richard B. Kreckel <kreckel@ginac.de> wrote:
Sheplyakov Alexei wrote:
Modify ex_to<T> to check if it is actually possible to convert the argument to type T (and add ex_to_unsafe<T> for those who *really* know what they are doing)?
ex_to<T> is documented as being unsafe. However. that doesn't appear to be enough. I actually like Alexei's suggestion. The ca. 800 occurrences of ex_to<T> inside the library would have to be converted, though. What do others think?
Perhaps better to keep ex_to as it is and add f.ex. convert_ex_to<T> as a new safe variant. martin
Hello, On Wed, Oct 11, 2006 at 10:17:55PM +0200, Richard B. Kreckel wrote:
ex_to<T> is documented as being unsafe. However. that doesn't appear to be enough.
The point is that there is no safe variant. Moreover, conversion into built-in numeric types (or cl_N) is quite a frequent operation (egrep "ex_to<numeric>" ginac/*), but unfortunatelly it is quite cumbersome. I've introduced the `numconv_to' functions for this purpose. It works also with expressions which evalf() to numeric, e.g. sqrt(2)*Pi, zeta(3), etc. --- doc/tutorial/ginac.texi | 19 ++++++------- ginac/numeric.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 0c36461..3370213 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -4182,7 +4182,7 @@ which can be assigned an integer value. is 17. @xref{Numbers}, for more information and examples. To evaluate an expression to a @code{double} floating-point number you can -call @code{evalf()} followed by @code{numeric::to_double()}, like this: +call @code{numconv_to}, like this: @example @{ @@ -4191,15 +4191,14 @@ call @code{evalf()} followed by @code{nu ex e = series(sin(x/Pi), x == 0, 6); // Evaluate numerically at x=0.1 - ex f = evalf(e.subs(x == 0.1)); - - // ex_to<numeric> is an unsafe cast, so check the type first - if (is_a<numeric>(f)) @{ - double d = ex_to<numeric>(f).to_double(); - cout << d << endl; - // -> 0.0318256 - @} else - // error + ex f = e.subs(x == 0.1); + + double d(0); + if (numconv_to(f, d)) @{ + cout << d << endl; + // -> 0.0318256 + @} else @{ + // error @} @end example diff --git a/ginac/numeric.h b/ginac/numeric.h index 09603f6..59e41f1 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -247,6 +247,76 @@ const numeric iquo(const numeric &a, con const numeric gcd(const numeric &a, const numeric &b); const numeric lcm(const numeric &a, const numeric &b); +/** conversion functions for interfacing with numeric libraries */ +template<typename T> inline bool numconv_to(const ex& e, T& val); + + +/** convert expression to double. + * Expression must be either numeric or evalf() to numeric */ +template<> inline bool numconv_to<double>(const ex& e, double& val) +{ + if (__builtin_expect(is_a<numeric>(e), 1)) + { + val = ex_to<numeric>(e).to_double(); + return true; + } + + // to deal with expressions like sqrt(2), Pi^2, etc. + ex evalf_me = e.evalf(); + if (__builtin_expect(is_a<numeric>(evalf_me), 1)) + { + val = ex_to<numeric>(evalf_me).to_double(); + return true; + } else + return false; +} + +/** convert expression to cl_N. + * Expression must be either numeric or evalf() to numeric */ +template<> inline bool numconv_to<cln::cl_N>(const ex& e, cln::cl_N& val) +{ + if (__builtin_expect(is_a<numeric>(e), 1)) + { + val = ex_to<numeric>(e).to_cl_N(); + return true; + } + ex evalf_me = e.evalf(); + if (__builtin_expect(is_a<numeric>(evalf_me), 1)) + { + val = ex_to<numeric>(evalf_me).to_cl_N(); + return true; + } else + return false; +} + +/** convert expression to int */ +template<> inline bool numconv_to<int>(const ex& e, int& val) +{ + if (__builtin_expect(! e.info(info_flags::integer), 0)) + return false; + // XXX: should check for overflow here. + val = ex_to<numeric>(e).to_int(); + return true; +} +/** convert expression to long */ +template<> inline bool numconv_to<long>(const ex& e, long& val) +{ + if (__builtin_expect(! e.info(info_flags::integer), 0)) + return false; + // XXX: should check for overflow here. + val = ex_to<numeric>(e).to_long(); + return true; +} + +template<typename T> inline T numconv_to(const ex& e) +{ + T val; + if (__builtin_expect(numconv_to(e, val), 1)) + return val; + else + throw std::invalid_argument("expression is not numeric"); +} + // wrapper functions around member functions inline const numeric pow(const numeric &x, const numeric &y) { return x.power(y); } -- 1.4.2.3 Best regards, Alexei -- All science is either physics or stamp collecting.
participants (4)
-
Chris Dams
-
Martin Sandve Alnæs
-
Richard B. Kreckel
-
varg@theor.jinr.ru