alpha_rounding_control.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP
  10. #define BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP
  11. #if !defined(alpha) && !defined(__alpha__)
  12. #error This header only works on Alpha CPUs.
  13. #endif
  14. #if defined(__GNUC__) || defined(__digital__) || defined(__DECCXX)
  15. #include <float.h> // write_rnd() and read_rnd()
  16. namespace boost {
  17. namespace numeric {
  18. namespace interval_lib {
  19. namespace detail {
  20. #if defined(__GNUC__ )
  21. typedef union {
  22. ::boost::long_long_type imode;
  23. double dmode;
  24. } rounding_mode_struct;
  25. // set bits 59-58 (DYN),
  26. // clear all exception bits and disable overflow (51) and inexact exceptions (62)
  27. static const rounding_mode_struct mode_upward = { 0x4C08000000000000LL };
  28. static const rounding_mode_struct mode_downward = { 0x4408000000000000LL };
  29. static const rounding_mode_struct mode_to_nearest = { 0x4808000000000000LL };
  30. static const rounding_mode_struct mode_toward_zero = { 0x4008000000000000LL };
  31. struct alpha_rounding_control
  32. {
  33. typedef double rounding_mode;
  34. static void set_rounding_mode(const rounding_mode mode)
  35. { __asm__ __volatile__ ("mt_fpcr %0" : : "f"(mode)); }
  36. static void get_rounding_mode(rounding_mode& mode)
  37. { __asm__ __volatile__ ("mf_fpcr %0" : "=f"(mode)); }
  38. static void downward() { set_rounding_mode(mode_downward.dmode); }
  39. static void upward() { set_rounding_mode(mode_upward.dmode); }
  40. static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); }
  41. static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); }
  42. };
  43. #elif defined(__digital__) || defined(__DECCXX)
  44. #if defined(__DECCXX) && !(defined(__FLT_ROUNDS) && __FLT_ROUNDS == -1)
  45. #error Dynamic rounding mode not enabled. See cxx man page for details.
  46. #endif
  47. struct alpha_rounding_control
  48. {
  49. typedef unsigned int rounding_mode;
  50. static void set_rounding_mode(const rounding_mode& mode) { write_rnd(mode); }
  51. static void get_rounding_mode(rounding_mode& mode) { mode = read_rnd(); }
  52. static void downward() { set_rounding_mode(FP_RND_RM); }
  53. static void upward() { set_rounding_mode(FP_RND_RP); }
  54. static void to_nearest() { set_rounding_mode(FP_RND_RN); }
  55. static void toward_zero() { set_rounding_mode(FP_RND_RZ); }
  56. };
  57. #endif
  58. } // namespace detail
  59. extern "C" {
  60. float rintf(float);
  61. double rint(double);
  62. long double rintl(long double);
  63. }
  64. template<>
  65. struct rounding_control<float>:
  66. detail::alpha_rounding_control
  67. {
  68. static float force_rounding(const float r)
  69. { volatile float _r = r; return _r; }
  70. static float to_int(const float& x) { return rintf(x); }
  71. };
  72. template<>
  73. struct rounding_control<double>:
  74. detail::alpha_rounding_control
  75. {
  76. static const double & force_rounding(const double& r) { return r; }
  77. static double to_int(const double& r) { return rint(r); }
  78. };
  79. template<>
  80. struct rounding_control<long double>:
  81. detail::alpha_rounding_control
  82. {
  83. static const long double & force_rounding(const long double& r) { return r; }
  84. static long double to_int(const long double& r) { return rintl(r); }
  85. };
  86. } // namespace interval_lib
  87. } // namespace numeric
  88. } // namespace boost
  89. #undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
  90. #endif
  91. #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP */