1 /* Boost interval/detail/alpha_rounding_control.hpp file 2 * 3 * Copyright 2005 Felix Höfling, Guillaume Melquiond 4 * 5 * Distributed under the Boost Software License, Version 1.0. 6 * (See accompanying file LICENSE_1_0.txt or 7 * copy at http://www.boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP 11 #define BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP 12 13 #if !defined(alpha) && !defined(__alpha__) 14 #error This header only works on Alpha CPUs. 15 #endif 16 17 #if defined(__GNUC__) || defined(__digital__) || defined(__DECCXX) 18 19 #include <float.h> // write_rnd() and read_rnd() 20 21 namespace boost { 22 namespace numeric { 23 namespace interval_lib { 24 25 namespace detail { 26 #if defined(__GNUC__ ) 27 typedef union { 28 ::boost::long_long_type imode; 29 double dmode; 30 } rounding_mode_struct; 31 32 // set bits 59-58 (DYN), 33 // clear all exception bits and disable overflow (51) and inexact exceptions (62) 34 static const rounding_mode_struct mode_upward = { 0x4C08000000000000LL }; 35 static const rounding_mode_struct mode_downward = { 0x4408000000000000LL }; 36 static const rounding_mode_struct mode_to_nearest = { 0x4808000000000000LL }; 37 static const rounding_mode_struct mode_toward_zero = { 0x4008000000000000LL }; 38 39 struct alpha_rounding_control 40 { 41 typedef double rounding_mode; 42 set_rounding_modeboost::numeric::interval_lib::detail::alpha_rounding_control43 static void set_rounding_mode(const rounding_mode mode) 44 { __asm__ __volatile__ ("mt_fpcr %0" : : "f"(mode)); } 45 get_rounding_modeboost::numeric::interval_lib::detail::alpha_rounding_control46 static void get_rounding_mode(rounding_mode& mode) 47 { __asm__ __volatile__ ("mf_fpcr %0" : "=f"(mode)); } 48 downwardboost::numeric::interval_lib::detail::alpha_rounding_control49 static void downward() { set_rounding_mode(mode_downward.dmode); } upwardboost::numeric::interval_lib::detail::alpha_rounding_control50 static void upward() { set_rounding_mode(mode_upward.dmode); } to_nearestboost::numeric::interval_lib::detail::alpha_rounding_control51 static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); } toward_zeroboost::numeric::interval_lib::detail::alpha_rounding_control52 static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); } 53 }; 54 #elif defined(__digital__) || defined(__DECCXX) 55 56 #if defined(__DECCXX) && !(defined(__FLT_ROUNDS) && __FLT_ROUNDS == -1) 57 #error Dynamic rounding mode not enabled. See cxx man page for details. 58 #endif 59 60 struct alpha_rounding_control 61 { 62 typedef unsigned int rounding_mode; 63 64 static void set_rounding_mode(const rounding_mode& mode) { write_rnd(mode); } 65 static void get_rounding_mode(rounding_mode& mode) { mode = read_rnd(); } 66 67 static void downward() { set_rounding_mode(FP_RND_RM); } 68 static void upward() { set_rounding_mode(FP_RND_RP); } 69 static void to_nearest() { set_rounding_mode(FP_RND_RN); } 70 static void toward_zero() { set_rounding_mode(FP_RND_RZ); } 71 }; 72 #endif 73 } // namespace detail 74 75 extern "C" { 76 float rintf(float); 77 double rint(double); 78 long double rintl(long double); 79 } 80 81 template<> 82 struct rounding_control<float>: 83 detail::alpha_rounding_control 84 { force_roundingboost::numeric::interval_lib::rounding_control85 static float force_rounding(const float r) 86 { volatile float _r = r; return _r; } to_intboost::numeric::interval_lib::rounding_control87 static float to_int(const float& x) { return rintf(x); } 88 }; 89 90 template<> 91 struct rounding_control<double>: 92 detail::alpha_rounding_control 93 { force_roundingboost::numeric::interval_lib::rounding_control94 static const double & force_rounding(const double& r) { return r; } to_intboost::numeric::interval_lib::rounding_control95 static double to_int(const double& r) { return rint(r); } 96 }; 97 98 template<> 99 struct rounding_control<long double>: 100 detail::alpha_rounding_control 101 { force_roundingboost::numeric::interval_lib::rounding_control102 static const long double & force_rounding(const long double& r) { return r; } to_intboost::numeric::interval_lib::rounding_control103 static long double to_int(const long double& r) { return rintl(r); } 104 }; 105 106 } // namespace interval_lib 107 } // namespace numeric 108 } // namespace boost 109 110 #undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE 111 #endif 112 113 #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP */ 114