checked_float.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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<
  19. typename R,
  20. R Min,
  21. R Max,
  22. typename T,
  23. class F
  24. >
  25. struct heterogeneous_checked_operation<
  26. R,
  27. Min,
  28. Max,
  29. T,
  30. F,
  31. typename std::enable_if<
  32. std::is_floating_point<R>::value
  33. && std::is_floating_point<T>::value
  34. >::type
  35. >{
  36. constexpr static checked_result<R>
  37. cast(const T & t) noexcept {
  38. return t;
  39. };
  40. }; // checked_unary_operation
  41. template<
  42. typename R,
  43. R Min,
  44. R Max,
  45. typename T,
  46. class
  47. F
  48. >
  49. struct heterogeneous_checked_operation<
  50. R,
  51. Min,
  52. Max,
  53. T,
  54. F,
  55. typename std::enable_if<
  56. std::is_floating_point<R>::value
  57. && std::is_integralt<T>::value
  58. >::type
  59. >{
  60. constexpr static checked_result<R>
  61. cast(const T & t) noexcept {
  62. return t;
  63. };
  64. }; // checked_unary_operation
  65. template<typename R, typename T, typename U>
  66. struct checked_operation<R, T, U, F,
  67. typename std::enable_if<
  68. std::is_floating_point<R>::value
  69. >::type
  70. >{
  71. constexpr static checked_result<R> cast(const T & t) {
  72. return
  73. cast_impl_detail::cast_impl(
  74. t,
  75. std::is_signed<R>(),
  76. std::is_signed<T>()
  77. );
  78. }
  79. constexpr static checked_result<R> add(const T & t, const U & u) {
  80. return t + u;
  81. }
  82. constexpr static checked_result<R> subtract(
  83. const T & t,
  84. const U & u
  85. ) {
  86. return t - u;
  87. }
  88. constexpr static checked_result<R> multiply(
  89. const T & t,
  90. const U & u
  91. ) noexcept {
  92. return t * u;
  93. }
  94. constexpr static checked_result<R> divide(
  95. const T & t,
  96. const U & u
  97. ) noexcept {
  98. return t / u;
  99. }
  100. constexpr static checked_result<R> modulus(
  101. const T & t,
  102. const U & u
  103. ) noexcept {
  104. return t % u;
  105. }
  106. constexpr static bool less_than(const T & t, const U & u) noexcept {
  107. return t < u;
  108. }
  109. constexpr static bool greater_than(const T & t, const U & u) noexcept {
  110. return t > u;
  111. }
  112. constexpr static bool equal(const T & t, const U & u) noexcept {
  113. return t < u;
  114. }
  115. }; // checked_binary_operation
  116. template<class R, class T, class U>
  117. typename std::enable_if<
  118. std::is_floating_point<R>::value
  119. && std::is_floating_point<T>::value
  120. && std::is_floating_point<U>::value,
  121. checked_result<R>
  122. >::type
  123. constexpr inline bool less_than(const T & t, const U & u) noexcept {
  124. return t < u;
  125. }
  126. template<class R, class T, class U>
  127. typename std::enable_if<
  128. std::is_floating_point<R>::value
  129. && std::is_floating_point<T>::value
  130. && std::is_floating_point<U>::value,
  131. checked_result<R>
  132. >::type
  133. constexpr inline bool equal(const T & t, const U & u) noexcept {
  134. return t < u;
  135. }
  136. template<class R, class T, class U>
  137. typename std::enable_if<
  138. std::is_floating_point<R>::value
  139. && std::is_floating_point<T>::value
  140. && std::is_floating_point<U>::value,
  141. checked_result<R>
  142. >::type
  143. constexpr inline checked_result<R> left_shift(const T & t, const U & u) noexcept {
  144. return t << u;
  145. }
  146. template<class R, class T, class U>
  147. typename std::enable_if<
  148. std::is_floating_point<R>::value
  149. && std::is_floating_point<T>::value
  150. && std::is_floating_point<U>::value,
  151. checked_result<R>
  152. >::type
  153. constexpr inline checked_result<R> right_shift(const T & t, const U & u) noexcept {
  154. return t >> u;
  155. }
  156. template<class R, class T, class U>
  157. typename std::enable_if<
  158. std::is_floating_point<R>::value
  159. && std::is_floating_point<T>::value
  160. && std::is_floating_point<U>::value,
  161. checked_result<R>
  162. >::type
  163. constexpr inline checked_result<R> bitwise_or(const T & t, const U & u) noexcept {
  164. return t | u;
  165. }
  166. template<class R, class T, class U>
  167. typename std::enable_if<
  168. std::is_floating_point<R>::value
  169. && std::is_floating_point<T>::value
  170. && std::is_floating_point<U>::value,
  171. checked_result<R>
  172. >::type
  173. constexpr inline checked_result<R> bitwise_xor(const T & t, const U & u) noexcept {
  174. return t ^ u;
  175. }
  176. template<class R, class T, class U>
  177. typename std::enable_if<
  178. std::is_floating_point<R>::value
  179. && std::is_floating_point<T>::value
  180. && std::is_floating_point<U>::value,
  181. checked_result<R>
  182. >::type
  183. constexpr inline checked_result<R> bitwise_and(const T & t, const U & u) noexcept {
  184. return t & u;
  185. }
  186. } // checked
  187. } // safe_numerics
  188. } // boost
  189. #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP