checked_float.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #ifndef BOOST_NUMERIC_CHECKED_FLOAT_HPP
  2. #define BOOST_NUMERIC_CHECKED_FLOAT_HPP
  3. // Copyright (c) 2017 Robert Ramey
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. // contains operation implementation of arithmetic operators
  9. // on built-in floating point types. The default implementation is to just
  10. // invoke the operation with no checking. These are overloaded
  11. // for specific types such as integer, etc.
  12. #include <type_traits> // std::is_floating_point, make_unsigned
  13. namespace boost {
  14. namespace safe_numerics {
  15. namespace checked {
  16. ////////////////////////////////////////////////////
  17. // layer 0 - implement safe operations for floating
  18. template<typename R, typename T, class F>
  19. struct heterogeneous_checked_operation<R, T, F,
  20. typename std::enable_if<
  21. std::is_floating_point<R>::value
  22. && std::is_floating_point<T>::value
  23. >::type
  24. >{
  25. constexpr static checked_result<R>
  26. cast(const T & t) noexcept {
  27. return t;
  28. };
  29. }; // checked_unary_operation
  30. template<typename R, typename T, class F>
  31. struct heterogeneous_checked_operation<R, T, F,
  32. typename std::enable_if<
  33. std::is_floating_point<R>::value
  34. && std::is_integralt<T>::value
  35. >::type
  36. >{
  37. constexpr static checked_result<R>
  38. cast(const T & t) noexcept {
  39. return t;
  40. };
  41. }; // checked_unary_operation
  42. template<typename R, typename T, typename U>
  43. struct checked_operation<R, T, U, F,
  44. typename std::enable_if<
  45. std::is_floating_point<R>::value
  46. >::type
  47. >{
  48. constexpr static checked_result<R> cast(const T & t) {
  49. return
  50. cast_impl_detail::cast_impl(
  51. t,
  52. std::is_signed<R>(),
  53. std::is_signed<T>()
  54. );
  55. }
  56. constexpr static checked_result<R> add(const T & t, const U & u) {
  57. return t + u;
  58. }
  59. constexpr static checked_result<R> subtract(
  60. const T & t,
  61. const U & u
  62. ) {
  63. return t - u;
  64. }
  65. constexpr static checked_result<R> multiply(
  66. const T & t,
  67. const U & u
  68. ) noexcept {
  69. return t * u;
  70. }
  71. constexpr static checked_result<R> divide(
  72. const T & t,
  73. const U & u
  74. ) noexcept {
  75. return t / u;
  76. }
  77. constexpr static checked_result<R> modulus(
  78. const T & t,
  79. const U & u
  80. ) noexcept {
  81. return t % u;
  82. }
  83. constexpr static bool less_than(const T & t, const U & u) noexcept {
  84. return t < u;
  85. }
  86. constexpr static bool greater_than(const T & t, const U & u) noexcept {
  87. return t > u;
  88. }
  89. constexpr static bool equal(const T & t, const U & u) noexcept {
  90. return t < u;
  91. }
  92. }; // checked_binary_operation
  93. template<class R, class T, class U>
  94. typename std::enable_if<
  95. std::is_floating_point<R>::value
  96. && std::is_floating_point<T>::value
  97. && std::is_floating_point<U>::value,
  98. checked_result<R>
  99. >::type
  100. constexpr bool less_than(const T & t, const U & u) noexcept {
  101. return t < u;
  102. }
  103. template<class R, class T, class U>
  104. typename std::enable_if<
  105. std::is_floating_point<R>::value
  106. && std::is_floating_point<T>::value
  107. && std::is_floating_point<U>::value,
  108. checked_result<R>
  109. >::type
  110. constexpr bool equal(const T & t, const U & u) noexcept {
  111. return t < u;
  112. }
  113. template<class R, class T, class U>
  114. typename std::enable_if<
  115. std::is_floating_point<R>::value
  116. && std::is_floating_point<T>::value
  117. && std::is_floating_point<U>::value,
  118. checked_result<R>
  119. >::type
  120. constexpr checked_result<R> left_shift(const T & t, const U & u) noexcept {
  121. return t << u;
  122. }
  123. template<class R, class T, class U>
  124. typename std::enable_if<
  125. std::is_floating_point<R>::value
  126. && std::is_floating_point<T>::value
  127. && std::is_floating_point<U>::value,
  128. checked_result<R>
  129. >::type
  130. constexpr checked_result<R> right_shift(const T & t, const U & u) noexcept {
  131. return t >> u;
  132. }
  133. template<class R, class T, class U>
  134. typename std::enable_if<
  135. std::is_floating_point<R>::value
  136. && std::is_floating_point<T>::value
  137. && std::is_floating_point<U>::value,
  138. checked_result<R>
  139. >::type
  140. constexpr checked_result<R> bitwise_or(const T & t, const U & u) noexcept {
  141. return t | u;
  142. }
  143. template<class R, class T, class U>
  144. typename std::enable_if<
  145. std::is_floating_point<R>::value
  146. && std::is_floating_point<T>::value
  147. && std::is_floating_point<U>::value,
  148. checked_result<R>
  149. >::type
  150. constexpr checked_result<R> bitwise_xor(const T & t, const U & u) noexcept {
  151. return t ^ u;
  152. }
  153. template<class R, class T, class U>
  154. typename std::enable_if<
  155. std::is_floating_point<R>::value
  156. && std::is_floating_point<T>::value
  157. && std::is_floating_point<U>::value,
  158. checked_result<R>
  159. >::type
  160. constexpr checked_result<R> bitwise_and(const T & t, const U & u) noexcept {
  161. return t & u;
  162. }
  163. } // checked
  164. } // safe_numerics
  165. } // boost
  166. #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP