1 /* Boost interval/detail/ppc_rounding_control.hpp file 2 * 3 * Copyright 2000 Jens Maurer 4 * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion 5 * Copyright 2005 Guillaume Melquiond 6 * 7 * Distributed under the Boost Software License, Version 1.0. 8 * (See accompanying file LICENSE_1_0.txt or 9 * copy at http://www.boost.org/LICENSE_1_0.txt) 10 */ 11 12 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP 13 #define BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP 14 15 #if !defined(powerpc) && !defined(__powerpc__) && !defined(__ppc__) 16 #error This header only works on PPC CPUs. 17 #endif 18 19 #if defined(__GNUC__ ) || (__IBMCPP__ >= 700) 20 21 namespace boost { 22 namespace numeric { 23 namespace interval_lib { 24 namespace detail { 25 26 typedef union { 27 ::boost::long_long_type imode; 28 double dmode; 29 } rounding_mode_struct; 30 31 static const rounding_mode_struct mode_upward = { 0xFFF8000000000002LL }; 32 static const rounding_mode_struct mode_downward = { 0xFFF8000000000003LL }; 33 static const rounding_mode_struct mode_to_nearest = { 0xFFF8000000000000LL }; 34 static const rounding_mode_struct mode_toward_zero = { 0xFFF8000000000001LL }; 35 36 struct ppc_rounding_control 37 { 38 typedef double rounding_mode; 39 set_rounding_modeboost::numeric::interval_lib::detail::ppc_rounding_control40 static void set_rounding_mode(const rounding_mode mode) 41 { __asm__ __volatile__ ("mtfsf 255,%0" : : "f"(mode)); } 42 get_rounding_modeboost::numeric::interval_lib::detail::ppc_rounding_control43 static void get_rounding_mode(rounding_mode& mode) 44 { __asm__ __volatile__ ("mffs %0" : "=f"(mode)); } 45 downwardboost::numeric::interval_lib::detail::ppc_rounding_control46 static void downward() { set_rounding_mode(mode_downward.dmode); } upwardboost::numeric::interval_lib::detail::ppc_rounding_control47 static void upward() { set_rounding_mode(mode_upward.dmode); } to_nearestboost::numeric::interval_lib::detail::ppc_rounding_control48 static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); } toward_zeroboost::numeric::interval_lib::detail::ppc_rounding_control49 static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); } 50 }; 51 52 } // namespace detail 53 54 // Do not declare the following C99 symbols if <math.h> provides them. 55 // Otherwise, conflicts may occur, due to differences between prototypes. 56 #if !defined(_ISOC99_SOURCE) && !defined(__USE_ISOC99) 57 extern "C" { 58 float rintf(float); 59 double rint(double); 60 } 61 #endif 62 63 template<> 64 struct rounding_control<float>: 65 detail::ppc_rounding_control 66 { force_roundingboost::numeric::interval_lib::rounding_control67 static float force_rounding(const float r) 68 { 69 float tmp; 70 __asm__ __volatile__ ("frsp %0, %1" : "=f" (tmp) : "f" (r)); 71 return tmp; 72 } to_intboost::numeric::interval_lib::rounding_control73 static float to_int(const float& x) { return rintf(x); } 74 }; 75 76 template<> 77 struct rounding_control<double>: 78 detail::ppc_rounding_control 79 { force_roundingboost::numeric::interval_lib::rounding_control80 static const double & force_rounding(const double& r) { return r; } to_intboost::numeric::interval_lib::rounding_control81 static double to_int(const double& r) { return rint(r); } 82 }; 83 84 template<> 85 struct rounding_control<long double>: 86 detail::ppc_rounding_control 87 { force_roundingboost::numeric::interval_lib::rounding_control88 static const long double & force_rounding(const long double& r) { return r; } to_intboost::numeric::interval_lib::rounding_control89 static long double to_int(const long double& r) { return rint(r); } 90 }; 91 92 } // namespace interval_lib 93 } // namespace numeric 94 } // namespace boost 95 96 #undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE 97 #endif 98 99 #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP */ 100