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