[GiNaC-list] [PATCH] Add `numconv_to' functions for conversion into
(non-GiNaC) numeric types.
Sheplyakov Alexei
varg at theor.jinr.ru
Tue Oct 17 15:54:51 CEST 2006
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-list/attachments/20061017/43cc2ba9/attachment.pgp
More information about the GiNaC-list
mailing list