mirror of
https://github.com/yuzu-emu/ext-boost.git
synced 2024-12-22 19:15:28 +00:00
218 lines
7 KiB
C++
218 lines
7 KiB
C++
#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 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 checked_result<R> minus(const R & t) noexcept {
|
|
return checked_operation<R>::minus(t);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> add(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::add(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> subtract(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::subtract(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> multiply(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::multiply(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> divide(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::divide(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> modulus(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::modulus(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<bool> less_than(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::less_than(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr 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 checked_result<bool> greater_than(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::greater_than(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr 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 checked_result<bool> equal(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::equal(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> left_shift(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::left_shift(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> right_shift(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::right_shift(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::bitwise_or(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::bitwise_xor(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
|
|
return checked_operation<R>::bitwise_and(t, u);
|
|
}
|
|
template<typename R>
|
|
constexpr 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
|