summaryrefslogtreecommitdiff
path: root/boost/numeric/interval/detail/msvc_rounding_control.hpp
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/numeric/interval/detail/msvc_rounding_control.hpp
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/numeric/interval/detail/msvc_rounding_control.hpp')
-rw-r--r--boost/numeric/interval/detail/msvc_rounding_control.hpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/boost/numeric/interval/detail/msvc_rounding_control.hpp b/boost/numeric/interval/detail/msvc_rounding_control.hpp
new file mode 100644
index 0000000000..95c790fe72
--- /dev/null
+++ b/boost/numeric/interval/detail/msvc_rounding_control.hpp
@@ -0,0 +1,100 @@
+/* Boost interval/detail/msvc_rounding_control.hpp file
+ *
+ * Copyright 2000 Maarten Keijzer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or
+ * copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
+
+#ifndef _MSC_VER
+# error This header is only intended for MSVC, but might work for Borland as well
+#endif
+
+#include <float.h> // MSVC rounding control
+
+// Although the function is called _control87, it seems to work for
+// other FPUs too, so it does not have to be changed to _controlfp.
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+#if BOOST_MSVC < 1400 || defined(WIN64)
+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) {
+ unsigned int n = 0;
+ if (m & 0x01) n |= _EM_INVALID;
+ if (m & 0x02) n |= _EM_DENORMAL;
+ if (m & 0x04) n |= _EM_ZERODIVIDE;
+ if (m & 0x08) n |= _EM_OVERFLOW;
+ if (m & 0x10) n |= _EM_UNDERFLOW;
+ if (m & 0x20) n |= _EM_INEXACT;
+ switch (m & 0x300) {
+ case 0x000: n |= _PC_24; break;
+ case 0x200: n |= _PC_53; break;
+ case 0x300: n |= _PC_64; break;
+ }
+ switch (m & 0xC00) {
+ case 0x000: n |= _RC_NEAR; break;
+ case 0x400: n |= _RC_DOWN; break;
+ case 0x800: n |= _RC_UP; break;
+ case 0xC00: n |= _RC_CHOP; break;
+ }
+ if (m & 0x1000) n |= _IC_AFFINE; // only useful on 287
+ return n;
+ }
+
+ static unsigned short msvc2hard(unsigned int n) {
+ unsigned short m = 0;
+ if (n & _EM_INVALID) m |= 0x01;
+ if (n & _EM_DENORMAL) m |= 0x02;
+ if (n & _EM_ZERODIVIDE) m |= 0x04;
+ if (n & _EM_OVERFLOW) m |= 0x08;
+ if (n & _EM_UNDERFLOW) m |= 0x10;
+ if (n & _EM_INEXACT) m |= 0x20;
+ switch (n & _MCW_RC) {
+ case _RC_NEAR: m |= 0x000; break;
+ case _RC_DOWN: m |= 0x400; break;
+ case _RC_UP: m |= 0x800; break;
+ case _RC_CHOP: m |= 0xC00; break;
+ }
+ switch (n & _MCW_PC) {
+ case _PC_24: m |= 0x000; break;
+ case _PC_53: m |= 0x200; break;
+ case _PC_64: m |= 0x300; break;
+ }
+ if ((n & _MCW_IC) == _IC_AFFINE) m |= 0x1000;
+ return m;
+ }
+
+ typedef unsigned short rounding_mode;
+ static void get_rounding_mode(rounding_mode& mode)
+ { mode = msvc2hard(_control87(0, 0)); }
+ static void set_rounding_mode(const rounding_mode mode)
+ { _control87(hard2msvc(mode), _MCW_EM | _MCW_RC | _MCW_PC | _MCW_IC); }
+ static double to_int(const double& x) { return rint(x); }
+};
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP */