checked_default.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP
  2. #define BOOST_NUMERIC_CHECKED_DEFAULT_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 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. // implement the equivant of template partial specialization for functions
  13. // what we need is
  14. // a) a default implementation of add, subtract, etc which just
  15. // implements the standard operations and returns the result
  16. // b) specific implementations to be called from safe implementation
  17. // such as safe<int> ... and someday maybe money<T, D> ...
  18. //
  19. // What we need is partial function specialization - but this doesn't
  20. // exist in C++ (yet?). But particial specialization of structures DOES
  21. // exist. So put our functions into a class which can then be
  22. // partially specialized. Finally. add a function interface to so that
  23. // data types can be deduced from the function call. We now have
  24. // the equivalent of partial function template specialization.
  25. // usage example: checked<int>::add(t, u) ...
  26. #include <boost/logic/tribool.hpp>
  27. #include "checked_result.hpp"
  28. namespace boost {
  29. namespace safe_numerics {
  30. // main function object which contains functions which handle
  31. // primitives which haven't been overriden. For now, these
  32. // implement the default operation. But I see this as an indicator
  33. // that there is more work to be done. For example float * int should
  34. // never be called because promotions on operands should occur before
  35. // the operation is invoked. So rather than returning the default operation
  36. // it should trap with a static_assert. This occurs at compile time while
  37. // calculating result interval. This needs more investigation.
  38. template<
  39. typename R,
  40. R Min,
  41. R Max,
  42. typename T,
  43. class F = make_checked_result<R>,
  44. class Default = void
  45. >
  46. struct heterogeneous_checked_operation {
  47. constexpr static checked_result<R>
  48. cast(const T & t) /* noexcept */ {
  49. return static_cast<R>(t);
  50. }
  51. };
  52. template<
  53. typename R,
  54. class F = make_checked_result<R>,
  55. class Default = void
  56. >
  57. struct checked_operation{
  58. constexpr static checked_result<R>
  59. minus(const R & t) noexcept {
  60. return - t;
  61. }
  62. constexpr static checked_result<R>
  63. add(const R & t, const R & u) noexcept {
  64. return t + u;
  65. }
  66. constexpr static checked_result<R>
  67. subtract(const R & t, const R & u) noexcept {
  68. return t - u;
  69. }
  70. constexpr static checked_result<R>
  71. multiply(const R & t, const R & u) noexcept {
  72. return t * u;
  73. }
  74. constexpr static checked_result<R>
  75. divide(const R & t, const R & u) noexcept {
  76. return t / u;
  77. }
  78. constexpr static checked_result<R>
  79. modulus(const R & t, const R & u) noexcept {
  80. return t % u;
  81. }
  82. constexpr static boost::logic::tribool
  83. less_than(const R & t, const R & u) noexcept {
  84. return t < u;
  85. }
  86. constexpr static boost::logic::tribool
  87. greater_than(const R & t, const R & u) noexcept {
  88. return t > u;
  89. }
  90. constexpr static boost::logic::tribool
  91. equal(const R & t, const R & u) noexcept {
  92. return t < u;
  93. }
  94. constexpr static checked_result<R>
  95. left_shift(const R & t, const R & u) noexcept {
  96. return t << u;
  97. }
  98. constexpr static checked_result<R>
  99. right_shift(const R & t, const R & u) noexcept {
  100. return t >> u;
  101. }
  102. constexpr static checked_result<R>
  103. bitwise_or(const R & t, const R & u) noexcept {
  104. return t | u;
  105. }
  106. constexpr static checked_result<R>
  107. bitwise_xor(const R & t, const R & u) noexcept {
  108. return t ^ u;
  109. }
  110. constexpr static checked_result<R>
  111. bitwise_and(const R & t, const R & u) noexcept {
  112. return t & u;
  113. }
  114. constexpr static checked_result<R>
  115. bitwise_not(const R & t) noexcept {
  116. return ~t;
  117. }
  118. };
  119. namespace checked {
  120. // implement function call interface so that types other than
  121. // the result type R can be deduced from the function parameters.
  122. template<typename R, typename T>
  123. constexpr inline checked_result<R> cast(const T & t) /* noexcept */ {
  124. return heterogeneous_checked_operation<
  125. R,
  126. std::numeric_limits<R>::min(),
  127. std::numeric_limits<R>::max(),
  128. T
  129. >::cast(t);
  130. }
  131. template<typename R>
  132. constexpr inline checked_result<R> minus(const R & t) noexcept {
  133. return checked_operation<R>::minus(t);
  134. }
  135. template<typename R>
  136. constexpr inline checked_result<R> add(const R & t, const R & u) noexcept {
  137. return checked_operation<R>::add(t, u);
  138. }
  139. template<typename R>
  140. constexpr inline checked_result<R> subtract(const R & t, const R & u) noexcept {
  141. return checked_operation<R>::subtract(t, u);
  142. }
  143. template<typename R>
  144. constexpr inline checked_result<R> multiply(const R & t, const R & u) noexcept {
  145. return checked_operation<R>::multiply(t, u);
  146. }
  147. template<typename R>
  148. constexpr inline checked_result<R> divide(const R & t, const R & u) noexcept {
  149. return checked_operation<R>::divide(t, u);
  150. }
  151. template<typename R>
  152. constexpr inline checked_result<R> modulus(const R & t, const R & u) noexcept {
  153. return checked_operation<R>::modulus(t, u);
  154. }
  155. template<typename R>
  156. constexpr inline checked_result<bool> less_than(const R & t, const R & u) noexcept {
  157. return checked_operation<R>::less_than(t, u);
  158. }
  159. template<typename R>
  160. constexpr inline checked_result<bool> greater_than_equal(const R & t, const R & u) noexcept {
  161. return ! checked_operation<R>::less_than(t, u);
  162. }
  163. template<typename R>
  164. constexpr inline checked_result<bool> greater_than(const R & t, const R & u) noexcept {
  165. return checked_operation<R>::greater_than(t, u);
  166. }
  167. template<typename R>
  168. constexpr inline checked_result<bool> less_than_equal(const R & t, const R & u) noexcept {
  169. return ! checked_operation<R>::greater_than(t, u);
  170. }
  171. template<typename R>
  172. constexpr inline checked_result<bool> equal(const R & t, const R & u) noexcept {
  173. return checked_operation<R>::equal(t, u);
  174. }
  175. template<typename R>
  176. constexpr inline checked_result<R> left_shift(const R & t, const R & u) noexcept {
  177. return checked_operation<R>::left_shift(t, u);
  178. }
  179. template<typename R>
  180. constexpr inline checked_result<R> right_shift(const R & t, const R & u) noexcept {
  181. return checked_operation<R>::right_shift(t, u);
  182. }
  183. template<typename R>
  184. constexpr inline checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
  185. return checked_operation<R>::bitwise_or(t, u);
  186. }
  187. template<typename R>
  188. constexpr inline checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
  189. return checked_operation<R>::bitwise_xor(t, u);
  190. }
  191. template<typename R>
  192. constexpr inline checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
  193. return checked_operation<R>::bitwise_and(t, u);
  194. }
  195. template<typename R>
  196. constexpr inline checked_result<R> bitwise_not(const R & t) noexcept {
  197. return checked_operation<R>::bitwise_not(t);
  198. }
  199. } // checked
  200. } // safe_numerics
  201. } // boost
  202. #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP