1 /* Boost interval/detail/x86_rounding_control.hpp file 2 * 3 * Copyright 2000 Jens Maurer 4 * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion 5 * 6 * Distributed under the Boost Software License, Version 1.0. 7 * (See accompanying file LICENSE_1_0.txt or 8 * copy at http://www.boost.org/LICENSE_1_0.txt) 9 */ 10 11 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP 12 #define BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP 13 14 #if defined(__GNUC__) || defined(__BORLANDC__) && defined(__clang__) 15 # include <boost/numeric/interval/detail/x86gcc_rounding_control.hpp> 16 #elif defined(__BORLANDC__) 17 # include <boost/numeric/interval/detail/bcc_rounding_control.hpp> 18 #elif defined(_MSC_VER) 19 # include <boost/numeric/interval/detail/msvc_rounding_control.hpp> 20 #elif defined(__MWERKS__) || defined(__ICC) || defined (__SUNPRO_CC) 21 # define BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM 22 # include <boost/numeric/interval/detail/c99sub_rounding_control.hpp> 23 #else 24 # error Unsupported C++ compiler. 25 #endif 26 27 namespace boost { 28 namespace numeric { 29 namespace interval_lib { 30 31 namespace detail { 32 33 #ifdef BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM 34 typedef c99_rounding_control x86_rounding_control; 35 #undef BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM 36 #else 37 struct fpu_rounding_modes 38 { 39 unsigned short to_nearest; 40 unsigned short downward; 41 unsigned short upward; 42 unsigned short toward_zero; 43 }; 44 45 // exceptions masked, extended precision 46 // hardware default is 0x037f (0x1000 only has a meaning on 287) 47 static const fpu_rounding_modes rnd_mode = { 0x137f, 0x177f, 0x1b7f, 0x1f7f }; 48 49 struct x86_rounding_control: x86_rounding 50 { 51 static void to_nearest() { set_rounding_mode(rnd_mode.to_nearest); } 52 static void downward() { set_rounding_mode(rnd_mode.downward); } 53 static void upward() { set_rounding_mode(rnd_mode.upward); } 54 static void toward_zero() { set_rounding_mode(rnd_mode.toward_zero); } 55 }; 56 #endif // BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM 57 58 } // namespace detail 59 60 template<> 61 struct rounding_control<float>: detail::x86_rounding_control 62 { force_roundingboost::numeric::interval_lib::rounding_control63 static float force_rounding(const float& r) 64 { volatile float r_ = r; return r_; } 65 }; 66 67 template<> 68 struct rounding_control<double>: detail::x86_rounding_control 69 { 70 /*static double force_rounding(double r) 71 { asm volatile ("" : "+m"(r) : ); return r; }*/ force_roundingboost::numeric::interval_lib::rounding_control72 static double force_rounding(const double& r) 73 { volatile double r_ = r; return r_; } 74 }; 75 76 namespace detail { 77 78 template<bool> 79 struct x86_rounding_control_long_double; 80 81 template<> 82 struct x86_rounding_control_long_double<false>: x86_rounding_control 83 { force_roundingboost::numeric::interval_lib::detail::x86_rounding_control_long_double84 static long double force_rounding(long double const &r) 85 { volatile long double r_ = r; return r_; } 86 }; 87 88 template<> 89 struct x86_rounding_control_long_double<true>: x86_rounding_control 90 { force_roundingboost::numeric::interval_lib::detail::x86_rounding_control_long_double91 static long double const &force_rounding(long double const &r) 92 { return r; } 93 }; 94 95 } // namespace detail 96 97 template<> 98 struct rounding_control<long double>: 99 detail::x86_rounding_control_long_double< (sizeof(long double) >= 10) > 100 {}; 101 102 } // namespace interval_lib 103 } // namespace numeric 104 } // namespace boost 105 106 #undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE 107 108 #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP */ 109