[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