1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/* Boost interval/detail/ppc_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
* Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
* Copyright 2005 Guillaume Melquiond
*
* 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 GECODE_BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
#define GECODE_BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
#if !defined(powerpc) && !defined(__powerpc__) && !defined(__ppc__)
#error This header only works on PPC CPUs.
#endif
#if defined(__GNUC__ ) || (__IBMCPP__ >= 700)
namespace gecode_boost {
namespace numeric {
namespace interval_lib {
namespace detail {
typedef union {
::gecode_boost::ulong_long_type imode;
double dmode;
} rounding_mode_struct;
static const rounding_mode_struct mode_upward = {
static_cast< ::gecode_boost::long_long_type >(0xFFF8000000000002LL)
};
static const rounding_mode_struct mode_downward = {
static_cast< ::gecode_boost::long_long_type >(0xFFF8000000000003LL)
};
static const rounding_mode_struct mode_to_nearest = {
static_cast< ::gecode_boost::long_long_type >(0xFFF8000000000000LL)
};
static const rounding_mode_struct mode_toward_zero = {
static_cast< ::gecode_boost::long_long_type >(0xFFF8000000000001LL)
};
struct ppc_rounding_control
{
typedef double rounding_mode;
static void set_rounding_mode(const rounding_mode mode)
{ __asm__ __volatile__ ("mtfsf 255,%0" : : "f"(mode)); }
static void get_rounding_mode(rounding_mode& mode)
{ __asm__ __volatile__ ("mffs %0" : "=f"(mode)); }
static void downward() { set_rounding_mode(mode_downward.dmode); }
static void upward() { set_rounding_mode(mode_upward.dmode); }
static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); }
static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); }
};
} // namespace detail
// Do not declare the following C99 symbols if <math.h> provides them.
// Otherwise, conflicts may occur, due to differences between prototypes.
#if !defined(_ISOC99_SOURCE) && !defined(__USE_ISOC99)
extern "C" {
float rintf(float);
double rint(double);
}
#endif
template<>
struct rounding_control<float>:
detail::ppc_rounding_control
{
static float force_rounding(const float r)
{
float tmp;
__asm__ __volatile__ ("frsp %0, %1" : "=f" (tmp) : "f" (r));
return tmp;
}
static float to_int(const float& x) { return rintf(x); }
};
template<>
struct rounding_control<double>:
detail::ppc_rounding_control
{
static const double & force_rounding(const double& r) { return r; }
static double to_int(const double& r) { return rint(r); }
};
template<>
struct rounding_control<long double>:
detail::ppc_rounding_control
{
static const long double & force_rounding(const long double& r) { return r; }
static long double to_int(const long double& r) { return rint(r); }
};
} // namespace interval_lib
} // namespace numeric
} // namespace gecode_boost
#undef GECODE_BOOST_NUMERIC_INTERVAL_NO_HARDWARE
#endif
#endif /* GECODE_BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP */
|