ppc_rounding_control.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
  12. #define BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
  13. #if !defined(powerpc) && !defined(__powerpc__) && !defined(__ppc__)
  14. #error This header only works on PPC CPUs.
  15. #endif
  16. #if defined(__GNUC__ ) || (__IBMCPP__ >= 700)
  17. namespace boost {
  18. namespace numeric {
  19. namespace interval_lib {
  20. namespace detail {
  21. typedef union {
  22. ::boost::long_long_type imode;
  23. double dmode;
  24. } rounding_mode_struct;
  25. static const rounding_mode_struct mode_upward = { 0xFFF8000000000002LL };
  26. static const rounding_mode_struct mode_downward = { 0xFFF8000000000003LL };
  27. static const rounding_mode_struct mode_to_nearest = { 0xFFF8000000000000LL };
  28. static const rounding_mode_struct mode_toward_zero = { 0xFFF8000000000001LL };
  29. struct ppc_rounding_control
  30. {
  31. typedef double rounding_mode;
  32. static void set_rounding_mode(const rounding_mode mode)
  33. { __asm__ __volatile__ ("mtfsf 255,%0" : : "f"(mode)); }
  34. static void get_rounding_mode(rounding_mode& mode)
  35. { __asm__ __volatile__ ("mffs %0" : "=f"(mode)); }
  36. static void downward() { set_rounding_mode(mode_downward.dmode); }
  37. static void upward() { set_rounding_mode(mode_upward.dmode); }
  38. static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); }
  39. static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); }
  40. };
  41. } // namespace detail
  42. // Do not declare the following C99 symbols if <math.h> provides them.
  43. // Otherwise, conflicts may occur, due to differences between prototypes.
  44. #if !defined(_ISOC99_SOURCE) && !defined(__USE_ISOC99)
  45. extern "C" {
  46. float rintf(float);
  47. double rint(double);
  48. }
  49. #endif
  50. template<>
  51. struct rounding_control<float>:
  52. detail::ppc_rounding_control
  53. {
  54. static float force_rounding(const float r)
  55. {
  56. float tmp;
  57. __asm__ __volatile__ ("frsp %0, %1" : "=f" (tmp) : "f" (r));
  58. return tmp;
  59. }
  60. static float to_int(const float& x) { return rintf(x); }
  61. };
  62. template<>
  63. struct rounding_control<double>:
  64. detail::ppc_rounding_control
  65. {
  66. static const double & force_rounding(const double& r) { return r; }
  67. static double to_int(const double& r) { return rint(r); }
  68. };
  69. template<>
  70. struct rounding_control<long double>:
  71. detail::ppc_rounding_control
  72. {
  73. static const long double & force_rounding(const long double& r) { return r; }
  74. static long double to_int(const long double& r) { return rint(r); }
  75. };
  76. } // namespace interval_lib
  77. } // namespace numeric
  78. } // namespace boost
  79. #undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
  80. #endif
  81. #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP */