123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP
- #define BOOST_NUMERIC_CHECKED_DEFAULT_HPP
- // Copyright (c) 2017 Robert Ramey
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // contains operation implementation of arithmetic operators
- // on built-in types. The default implementation is to just
- // invoke the operation with no checking. These are overloaded
- // for specific types such as integer, etc.
- // implement the equivant of template partial specialization for functions
- // what we need is
- // a) a default implementation of add, subtract, etc which just
- // implements the standard operations and returns the result
- // b) specific implementations to be called from safe implementation
- // such as safe<int> ... and someday maybe money<T, D> ...
- //
- // What we need is partial function specialization - but this doesn't
- // exist in C++ (yet?). But particial specialization of structures DOES
- // exist. So put our functions into a class which can then be
- // partially specialized. Finally. add a function interface to so that
- // data types can be deduced from the function call. We now have
- // the equivalent of partial function template specialization.
- // usage example: checked<int>::add(t, u) ...
- #include <boost/logic/tribool.hpp>
- #include "checked_result.hpp"
- namespace boost {
- namespace safe_numerics {
- // main function object which contains functions which handle
- // primitives which haven't been overriden. For now, these
- // implement the default operation. But I see this as an indicator
- // that there is more work to be done. For example float * int should
- // never be called because promotions on operands should occur before
- // the operation is invoked. So rather than returning the default operation
- // it should trap with a static_assert. This occurs at compile time while
- // calculating result interval. This needs more investigation.
- template<
- typename R,
- R Min,
- R Max,
- typename T,
- class F = make_checked_result<R>,
- class Default = void
- >
- struct heterogeneous_checked_operation {
- constexpr static checked_result<R>
- cast(const T & t) /* noexcept */ {
- return static_cast<R>(t);
- }
- };
- template<
- typename R,
- class F = make_checked_result<R>,
- class Default = void
- >
- struct checked_operation{
- constexpr static checked_result<R>
- minus(const R & t) noexcept {
- return - t;
- }
- constexpr static checked_result<R>
- add(const R & t, const R & u) noexcept {
- return t + u;
- }
- constexpr static checked_result<R>
- subtract(const R & t, const R & u) noexcept {
- return t - u;
- }
- constexpr static checked_result<R>
- multiply(const R & t, const R & u) noexcept {
- return t * u;
- }
- constexpr static checked_result<R>
- divide(const R & t, const R & u) noexcept {
- return t / u;
- }
- constexpr static checked_result<R>
- modulus(const R & t, const R & u) noexcept {
- return t % u;
- }
- constexpr static boost::logic::tribool
- less_than(const R & t, const R & u) noexcept {
- return t < u;
- }
- constexpr static boost::logic::tribool
- greater_than(const R & t, const R & u) noexcept {
- return t > u;
- }
- constexpr static boost::logic::tribool
- equal(const R & t, const R & u) noexcept {
- return t < u;
- }
- constexpr static checked_result<R>
- left_shift(const R & t, const R & u) noexcept {
- return t << u;
- }
- constexpr static checked_result<R>
- right_shift(const R & t, const R & u) noexcept {
- return t >> u;
- }
- constexpr static checked_result<R>
- bitwise_or(const R & t, const R & u) noexcept {
- return t | u;
- }
- constexpr static checked_result<R>
- bitwise_xor(const R & t, const R & u) noexcept {
- return t ^ u;
- }
- constexpr static checked_result<R>
- bitwise_and(const R & t, const R & u) noexcept {
- return t & u;
- }
- constexpr static checked_result<R>
- bitwise_not(const R & t) noexcept {
- return ~t;
- }
- };
- namespace checked {
- // implement function call interface so that types other than
- // the result type R can be deduced from the function parameters.
- template<typename R, typename T>
- constexpr inline checked_result<R> cast(const T & t) /* noexcept */ {
- return heterogeneous_checked_operation<
- R,
- std::numeric_limits<R>::min(),
- std::numeric_limits<R>::max(),
- T
- >::cast(t);
- }
- template<typename R>
- constexpr inline checked_result<R> minus(const R & t) noexcept {
- return checked_operation<R>::minus(t);
- }
- template<typename R>
- constexpr inline checked_result<R> add(const R & t, const R & u) noexcept {
- return checked_operation<R>::add(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> subtract(const R & t, const R & u) noexcept {
- return checked_operation<R>::subtract(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> multiply(const R & t, const R & u) noexcept {
- return checked_operation<R>::multiply(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> divide(const R & t, const R & u) noexcept {
- return checked_operation<R>::divide(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> modulus(const R & t, const R & u) noexcept {
- return checked_operation<R>::modulus(t, u);
- }
- template<typename R>
- constexpr inline checked_result<bool> less_than(const R & t, const R & u) noexcept {
- return checked_operation<R>::less_than(t, u);
- }
- template<typename R>
- constexpr inline checked_result<bool> greater_than_equal(const R & t, const R & u) noexcept {
- return ! checked_operation<R>::less_than(t, u);
- }
- template<typename R>
- constexpr inline checked_result<bool> greater_than(const R & t, const R & u) noexcept {
- return checked_operation<R>::greater_than(t, u);
- }
- template<typename R>
- constexpr inline checked_result<bool> less_than_equal(const R & t, const R & u) noexcept {
- return ! checked_operation<R>::greater_than(t, u);
- }
- template<typename R>
- constexpr inline checked_result<bool> equal(const R & t, const R & u) noexcept {
- return checked_operation<R>::equal(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> left_shift(const R & t, const R & u) noexcept {
- return checked_operation<R>::left_shift(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> right_shift(const R & t, const R & u) noexcept {
- return checked_operation<R>::right_shift(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
- return checked_operation<R>::bitwise_or(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
- return checked_operation<R>::bitwise_xor(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
- return checked_operation<R>::bitwise_and(t, u);
- }
- template<typename R>
- constexpr inline checked_result<R> bitwise_not(const R & t) noexcept {
- return checked_operation<R>::bitwise_not(t);
- }
- } // checked
- } // safe_numerics
- } // boost
- #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP
|