rounded_arith.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Boost interval/rounded_arith.hpp template implementation file
  2. *
  3. * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
  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_ROUNDED_ARITH_HPP
  10. #define BOOST_NUMERIC_INTERVAL_ROUNDED_ARITH_HPP
  11. #include <boost/numeric/interval/rounding.hpp>
  12. #include <boost/numeric/interval/detail/bugs.hpp>
  13. #include <boost/config/no_tr1/cmath.hpp>
  14. namespace boost {
  15. namespace numeric {
  16. namespace interval_lib {
  17. /*
  18. * Three classes of rounding: exact, std, opp
  19. * See documentation for details.
  20. */
  21. template<class T, class Rounding>
  22. struct rounded_arith_exact: Rounding {
  23. void init() { }
  24. template<class U> T conv_down(U const &v) { return v; }
  25. template<class U> T conv_up (U const &v) { return v; }
  26. T add_down (const T& x, const T& y) { return x + y; }
  27. T add_up (const T& x, const T& y) { return x + y; }
  28. T sub_down (const T& x, const T& y) { return x - y; }
  29. T sub_up (const T& x, const T& y) { return x - y; }
  30. T mul_down (const T& x, const T& y) { return x * y; }
  31. T mul_up (const T& x, const T& y) { return x * y; }
  32. T div_down (const T& x, const T& y) { return x / y; }
  33. T div_up (const T& x, const T& y) { return x / y; }
  34. T median (const T& x, const T& y) { return (x + y) / 2; }
  35. T sqrt_down(const T& x)
  36. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); return sqrt(x); }
  37. T sqrt_up (const T& x)
  38. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); return sqrt(x); }
  39. T int_down (const T& x)
  40. { BOOST_NUMERIC_INTERVAL_using_math(floor); return floor(x); }
  41. T int_up (const T& x)
  42. { BOOST_NUMERIC_INTERVAL_using_math(ceil); return ceil(x); }
  43. };
  44. template<class T, class Rounding>
  45. struct rounded_arith_std: Rounding {
  46. # define BOOST_DN(EXPR) this->downward(); return this->force_rounding(EXPR)
  47. # define BOOST_NR(EXPR) this->to_nearest(); return this->force_rounding(EXPR)
  48. # define BOOST_UP(EXPR) this->upward(); return this->force_rounding(EXPR)
  49. void init() { }
  50. template<class U> T conv_down(U const &v) { BOOST_DN(v); }
  51. template<class U> T conv_up (U const &v) { BOOST_UP(v); }
  52. T add_down(const T& x, const T& y) { BOOST_DN(x + y); }
  53. T sub_down(const T& x, const T& y) { BOOST_DN(x - y); }
  54. T mul_down(const T& x, const T& y) { BOOST_DN(x * y); }
  55. T div_down(const T& x, const T& y) { BOOST_DN(x / y); }
  56. T add_up (const T& x, const T& y) { BOOST_UP(x + y); }
  57. T sub_up (const T& x, const T& y) { BOOST_UP(x - y); }
  58. T mul_up (const T& x, const T& y) { BOOST_UP(x * y); }
  59. T div_up (const T& x, const T& y) { BOOST_UP(x / y); }
  60. T median(const T& x, const T& y) { BOOST_NR((x + y) / 2); }
  61. T sqrt_down(const T& x)
  62. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_DN(sqrt(x)); }
  63. T sqrt_up (const T& x)
  64. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_UP(sqrt(x)); }
  65. T int_down(const T& x) { this->downward(); return this->to_int(x); }
  66. T int_up (const T& x) { this->upward(); return this->to_int(x); }
  67. # undef BOOST_DN
  68. # undef BOOST_NR
  69. # undef BOOST_UP
  70. };
  71. template<class T, class Rounding>
  72. struct rounded_arith_opp: Rounding {
  73. void init() { this->upward(); }
  74. # define BOOST_DN(EXPR) \
  75. this->downward(); \
  76. T r = this->force_rounding(EXPR); \
  77. this->upward(); \
  78. return r
  79. # define BOOST_NR(EXPR) \
  80. this->to_nearest(); \
  81. T r = this->force_rounding(EXPR); \
  82. this->upward(); \
  83. return r
  84. # define BOOST_UP(EXPR) return this->force_rounding(EXPR)
  85. # define BOOST_UP_NEG(EXPR) return -this->force_rounding(EXPR)
  86. template<class U> T conv_down(U const &v) { BOOST_UP_NEG(-v); }
  87. template<class U> T conv_up (U const &v) { BOOST_UP(v); }
  88. T add_down(const T& x, const T& y) { BOOST_UP_NEG((-x) - y); }
  89. T sub_down(const T& x, const T& y) { BOOST_UP_NEG(y - x); }
  90. T mul_down(const T& x, const T& y) { BOOST_UP_NEG(x * (-y)); }
  91. T div_down(const T& x, const T& y) { BOOST_UP_NEG(x / (-y)); }
  92. T add_up (const T& x, const T& y) { BOOST_UP(x + y); }
  93. T sub_up (const T& x, const T& y) { BOOST_UP(x - y); }
  94. T mul_up (const T& x, const T& y) { BOOST_UP(x * y); }
  95. T div_up (const T& x, const T& y) { BOOST_UP(x / y); }
  96. T median (const T& x, const T& y) { BOOST_NR((x + y) / 2); }
  97. T sqrt_down(const T& x)
  98. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_DN(sqrt(x)); }
  99. T sqrt_up (const T& x)
  100. { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_UP(sqrt(x)); }
  101. T int_down(const T& x) { return -this->to_int(-x); }
  102. T int_up (const T& x) { return this->to_int(x); }
  103. # undef BOOST_DN
  104. # undef BOOST_NR
  105. # undef BOOST_UP
  106. # undef BOOST_UP_NEG
  107. };
  108. } // namespace interval_lib
  109. } // namespace numeric
  110. } // namespace boost
  111. #endif // BOOST_NUMERIC_INTERVAL_ROUNDED_ARITH_HPP