Boost logo

Boost-Commit :

From: john_at_[hidden]
Date: 2008-01-03 12:32:37


Author: johnmaddock
Date: 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
New Revision: 42438
URL: http://svn.boost.org/trac/boost/changeset/42438

Log:
Added additional operator overloads to support mixed integer and interval arithmetic.
Suppress some pesky msvc warnings.
Fix conversion from unsigned integer types so that unsigned types don't ever get negated.
Added rint implementation for msvc versions that don't have one.
Added support for pow as a core function.
Added "nearest rounded" transcendental function support for approximate intervals.
Text files modified:
   sandbox/interval_math_toolkit/boost/numeric/interval/arith.hpp | 52 ++++++++++++++++++++++++++++
   sandbox/interval_math_toolkit/boost/numeric/interval/detail/msvc_rounding_control.hpp | 13 +++++++
   sandbox/interval_math_toolkit/boost/numeric/interval/detail/test_input.hpp | 10 ++--
   sandbox/interval_math_toolkit/boost/numeric/interval/interval.hpp | 2
   sandbox/interval_math_toolkit/boost/numeric/interval/rounded_arith.hpp | 18 +++++++--
   sandbox/interval_math_toolkit/boost/numeric/interval/rounded_transc.hpp | 73 ++++++++++++++++++++++++++++++++++++++++
   6 files changed, 158 insertions(+), 10 deletions(-)

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/arith.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/arith.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/arith.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -132,10 +132,23 @@
                               rnd.add_up (x, y.upper()), true);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator+(const T2& x, const interval<T, Policies>& y)
+{
+ interval<T, Policies> result(x);
+ return result += y;
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y)
 { return y + x; }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator+(const interval<T, Policies>& x, const T2& y)
+{
+ return y + interval<T, Policies>(x);
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator-(const interval<T, Policies>& x,
                                 const interval<T, Policies>& y)
@@ -157,6 +170,13 @@
                               rnd.sub_up (x, y.lower()), true);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator-(const T2& x, const interval<T, Policies>& y)
+{
+ interval<T, Policies> result(x);
+ return result -= y;
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y)
 {
@@ -167,6 +187,13 @@
                               rnd.sub_up (x.upper(), y), true);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator-(const interval<T, Policies>& x, const T2& y)
+{
+ interval<T, Policies> result(x);
+ return result -= interval<T, Policies>(y);
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator*(const interval<T, Policies>& x,
                                 const interval<T, Policies>& y)
@@ -240,10 +267,21 @@
     return I(rnd.mul_down(x, yl), rnd.mul_up(x, yu), true);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator*(const T2& x, const interval<T, Policies>& y)
+{
+ interval<T, Policies> result(x);
+ return result *= y;
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y)
 { return y * x; }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator*(const interval<T, Policies>& x, const T2& y)
+{ return y * interval<T, Policies>(x); }
+
 template<class T, class Policies> inline
 interval<T, Policies> operator/(const interval<T, Policies>& x,
                                 const interval<T, Policies>& y)
@@ -285,6 +323,13 @@
     return interval_lib::detail::div_non_zero(x, y);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator/(const T2& x, const interval<T, Policies>& y)
+{
+ interval<T, Policies> result(x);
+ return result /= y;
+}
+
 template<class T, class Policies> inline
 interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y)
 {
@@ -299,6 +344,13 @@
     return interval<T, Policies>(rnd.div_down(xl, y), rnd.div_up(xu, y), true);
 }
 
+template<class T, class Policies, class T2> inline
+interval<T, Policies> operator/(const interval<T, Policies>& x, const T2& y)
+{
+ interval<T, Policies> result(x);
+ return result /= interval<T, Policies>(y);
+}
+
 } // namespace numeric
 } // namespace boost
 

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/detail/msvc_rounding_control.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/detail/msvc_rounding_control.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/detail/msvc_rounding_control.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -25,8 +25,21 @@
 namespace interval_lib {
 namespace detail {
 
+#if BOOST_MSVC < 1400
+
 extern "C" { double rint(double); }
 
+#else
+
+inline double rint(double x)
+{
+ _asm FLD [x] ;
+ _asm FRNDINT ;
+ //_asm RET ;
+}
+
+#endif
+
 struct x86_rounding
 {
   static unsigned int hard2msvc(unsigned short m) {

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/detail/test_input.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/detail/test_input.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/detail/test_input.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -44,14 +44,14 @@
          checking2::is_empty(y.lower(), y.upper());
 }
 
-template<class T, class Policies> inline
-bool test_input(const T& x, const interval<T, Policies>& y) {
+template<class T2, class T, class Policies> inline
+bool test_input(const T2& x, const interval<T, Policies>& y) {
   typedef typename Policies::checking checking;
- return checking::is_nan(x) || checking::is_empty(y.lower(), y.upper());
+ return checking::is_nan(static_cast<T>(x)) || checking::is_empty(y.lower(), y.upper());
 }
 
-template<class T, class Policies> inline
-bool test_input(const interval<T, Policies>& x, const T& y) {
+template<class T, class Policies, class T2> inline
+bool test_input(const interval<T, Policies>& x, const T2& y) {
   typedef typename Policies::checking checking;
   return checking::is_empty(x.lower(), x.upper()) || checking::is_nan(y);
 }

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/interval.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/interval.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/interval.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -145,7 +145,7 @@
 template<class T, class Policies> template<class T1> inline
 interval<T, Policies>::interval(T1 const &v)
 {
- if (checking::is_nan(v)) set_empty();
+ if (checking::is_nan(static_cast<T>(v))) set_empty();
   else {
     rounding rnd;
     low = rnd.conv_down(v);

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/rounded_arith.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/rounded_arith.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/rounded_arith.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -12,6 +12,10 @@
 
 #include <boost/numeric/interval/rounding.hpp>
 #include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/type_traits/make_signed.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
 #include <cmath>
 
 namespace boost {
@@ -26,8 +30,8 @@
 template<class T, class Rounding>
 struct rounded_arith_exact: Rounding {
   void init() { }
- template<class U> T conv_down(U const &v) { return v; }
- template<class U> T conv_up (U const &v) { return v; }
+ template<class U> T conv_down(U const &v) { return static_cast<T>(v); }
+ template<class U> T conv_up (U const &v) { return static_cast<T>(v); }
   T add_down (const T& x, const T& y) { return x + y; }
   T add_up (const T& x, const T& y) { return x + y; }
   T sub_down (const T& x, const T& y) { return x - y; }
@@ -90,8 +94,14 @@
     return r
 # define BOOST_UP(EXPR) return this->force_rounding(EXPR)
 # define BOOST_UP_NEG(EXPR) return -this->force_rounding(EXPR)
- template<class U> T conv_down(U const &v) { BOOST_UP_NEG(-v); }
- template<class U> T conv_up (U const &v) { BOOST_UP(v); }
+ template<class U> T conv_down(U const &v)
+ {
+ typedef typename mpl::eval_if<
+ is_integral<U>, make_signed<U>, mpl::identity<U> >::type signed_type;
+
+ BOOST_UP_NEG(static_cast<T>(-static_cast<signed_type>(v)));
+ }
+ template<class U> T conv_up (U const &v) { BOOST_UP(static_cast<T>(v)); }
   T add_down(const T& x, const T& y) { BOOST_UP_NEG((-x) - y); }
   T sub_down(const T& x, const T& y) { BOOST_UP_NEG(y - x); }
   T mul_down(const T& x, const T& y) { BOOST_UP_NEG(x * (-y)); }

Modified: sandbox/interval_math_toolkit/boost/numeric/interval/rounded_transc.hpp
==============================================================================
--- sandbox/interval_math_toolkit/boost/numeric/interval/rounded_transc.hpp (original)
+++ sandbox/interval_math_toolkit/boost/numeric/interval/rounded_transc.hpp 2008-01-03 12:32:36 EST (Thu, 03 Jan 2008)
@@ -43,6 +43,60 @@
   BOOST_NUMERIC_INTERVAL_new_func(acosh)
   BOOST_NUMERIC_INTERVAL_new_func(atanh)
 # undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x, const T& y) { BOOST_NUMERIC_INTERVAL_using_math(f); return f(x, y); } \
+ T f##_up (const T& x, const T& y) { BOOST_NUMERIC_INTERVAL_using_math(f); return f(x, y); }
+ BOOST_NUMERIC_INTERVAL_new_func(pow)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+};
+
+namespace detail{
+
+template <class Rounding>
+struct round_nearest_state_saver
+{
+ round_nearest_state_saver(Rounding& r_) : r(r_) {
+ r.get_rounding_mode(mode);
+ r.to_nearest();
+ }
+ ~round_nearest_state_saver() { r.set_rounding_mode(mode); }
+private:
+ typename Rounding::rounding_mode mode;
+ Rounding& r;
+};
+
+}
+
+template<class T, class Rounding>
+struct rounded_transc_nearest: Rounding
+{
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) { BOOST_NUMERIC_INTERVAL_using_math(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x); } \
+ T f##_up (const T& x) { BOOST_NUMERIC_INTERVAL_using_math(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x); }
+ BOOST_NUMERIC_INTERVAL_new_func(exp)
+ BOOST_NUMERIC_INTERVAL_new_func(log)
+ BOOST_NUMERIC_INTERVAL_new_func(sin)
+ BOOST_NUMERIC_INTERVAL_new_func(cos)
+ BOOST_NUMERIC_INTERVAL_new_func(tan)
+ BOOST_NUMERIC_INTERVAL_new_func(asin)
+ BOOST_NUMERIC_INTERVAL_new_func(acos)
+ BOOST_NUMERIC_INTERVAL_new_func(atan)
+ BOOST_NUMERIC_INTERVAL_new_func(sinh)
+ BOOST_NUMERIC_INTERVAL_new_func(cosh)
+ BOOST_NUMERIC_INTERVAL_new_func(tanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) { BOOST_NUMERIC_INTERVAL_using_ahyp(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x); } \
+ T f##_up (const T& x) { BOOST_NUMERIC_INTERVAL_using_ahyp(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x); }
+ BOOST_NUMERIC_INTERVAL_new_func(asinh)
+ BOOST_NUMERIC_INTERVAL_new_func(acosh)
+ BOOST_NUMERIC_INTERVAL_new_func(atanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x, const T& y) { BOOST_NUMERIC_INTERVAL_using_math(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x, y); } \
+ T f##_up (const T& x, const T& y) { BOOST_NUMERIC_INTERVAL_using_math(f); detail::round_nearest_state_saver<Rounding> r(*this); return f(x, y); }
+ BOOST_NUMERIC_INTERVAL_new_func(pow)
+# undef BOOST_NUMERIC_INTERVAL_new_func
 };
   
 template<class T, class Rounding>
@@ -78,6 +132,15 @@
   BOOST_NUMERIC_INTERVAL_new_func(acosh)
   BOOST_NUMERIC_INTERVAL_new_func(atanh)
 # undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x, const T& y) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->downward(); return this->force_rounding(f(x, y)); } \
+ T f##_up (const T& x, const T& y) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->upward(); return this->force_rounding(f(x, y)); }
+ BOOST_NUMERIC_INTERVAL_new_func(pow)
+# undef BOOST_NUMERIC_INTERVAL_new_func
 };
 
 template<class T, class Rounding>
@@ -98,6 +161,16 @@
   BOOST_NUMERIC_INTERVAL_new_func(cosh)
 # undef BOOST_NUMERIC_INTERVAL_new_func
 # define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x, const T& y) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->downward(); T z = this->force_rounding(f(x, y)); \
+ this->upward(); return z; } \
+ T f##_up (const T& x, const T& y) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ return this->force_rounding(f(x, y)); }
+ BOOST_NUMERIC_INTERVAL_new_func(pow)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
     T f##_down(const T& x) \
     { BOOST_NUMERIC_INTERVAL_using_math(f); \
       return -this->force_rounding(-f(x)); } \


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk