Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:59:41

0001 #ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP
0002 #define BOOST_NUMERIC_CHECKED_DEFAULT_HPP
0003 
0004 //  Copyright (c) 2017 Robert Ramey
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 // contains operation implementation of arithmetic operators
0011 // on built-in types.  The default implementation is to just
0012 // invoke the operation with no checking.  These are overloaded
0013 // for specific types such as integer, etc.
0014 
0015 // implement the equivant of template partial specialization for functions
0016 
0017 // what we need is
0018 // a) a default implementation of add, subtract, etc which just
0019 // implements the standard operations and returns the result
0020 // b) specific implementations to be called from safe implementation
0021 // such as safe<int> ... and someday maybe money<T, D> ...
0022 //
0023 // What we need is partial function specialization - but this doesn't
0024 // exist in C++ (yet?).  But particial specialization of structures DOES
0025 // exist.  So put our functions into a class which can then be
0026 // partially specialized.  Finally. add a function interface to so that
0027 // data types can be deduced from the function call.  We now have
0028 // the equivalent of partial function template specialization.
0029 
0030 // usage example: checked<int>::add(t, u) ...
0031 
0032 #include <boost/logic/tribool.hpp>
0033 #include "checked_result.hpp"
0034 
0035 namespace boost {
0036 namespace safe_numerics {
0037 
0038 // main function object which contains functions which handle
0039 // primitives which haven't been overriden.  For now, these
0040 // implement the default operation.  But I see this as an indicator
0041 // that there is more work to be done.  For example float * int should
0042 // never be called because promotions on operands should occur before
0043 // the operation is invoked. So rather than returning the default operation
0044 // it should trap with a static_assert. This occurs at compile time while
0045 // calculating result interval.  This needs more investigation.
0046 
0047 template<
0048     typename R,
0049     R Min,
0050     R Max,
0051     typename T,
0052     class F = make_checked_result<R>,
0053     class Default = void
0054 >
0055 struct heterogeneous_checked_operation {
0056     constexpr static checked_result<R>
0057     cast(const T & t) /* noexcept */ {
0058         return static_cast<R>(t);
0059     }
0060 };
0061 
0062 template<
0063     typename R,
0064     class F = make_checked_result<R>,
0065     class Default = void
0066 >
0067 struct checked_operation{
0068     constexpr static checked_result<R>
0069     minus(const R & t) noexcept {
0070         return - t;
0071     }
0072     constexpr static checked_result<R>
0073     add(const R & t, const R & u) noexcept {
0074         return t + u;
0075     }
0076     constexpr static checked_result<R>
0077     subtract(const R & t, const R & u) noexcept {
0078         return t - u;
0079     }
0080     constexpr static checked_result<R>
0081     multiply(const R & t, const R & u) noexcept {
0082         return t * u;
0083     }
0084     constexpr static checked_result<R>
0085     divide(const R & t, const R & u) noexcept {
0086         return t / u;
0087     }
0088     constexpr static checked_result<R>
0089     modulus(const R & t, const R & u) noexcept {
0090         return t % u;
0091     }
0092     constexpr static boost::logic::tribool
0093     less_than(const R & t, const R & u) noexcept {
0094         return t < u;
0095     }
0096     constexpr static boost::logic::tribool
0097     greater_than(const R & t, const R & u) noexcept {
0098         return t > u;
0099     }
0100     constexpr static boost::logic::tribool
0101     equal(const R & t, const R & u) noexcept {
0102         return t < u;
0103     }
0104     constexpr static checked_result<R>
0105     left_shift(const R & t, const R & u) noexcept {
0106         return t << u;
0107     }
0108     constexpr static checked_result<R>
0109     right_shift(const R & t, const R & u) noexcept {
0110         return t >> u;
0111     }
0112     constexpr static checked_result<R>
0113     bitwise_or(const R & t, const R & u) noexcept {
0114         return t | u;
0115     }
0116     constexpr static checked_result<R>
0117     bitwise_xor(const R & t, const R & u) noexcept {
0118         return t ^ u;
0119     }
0120     constexpr static checked_result<R>
0121     bitwise_and(const R & t, const R & u) noexcept {
0122         return t & u;
0123     }
0124     constexpr static checked_result<R>
0125     bitwise_not(const R & t) noexcept {
0126         return ~t;
0127     }
0128 };
0129 
0130 namespace checked {
0131 
0132 // implement function call interface so that types other than
0133 // the result type R can be deduced from the function parameters.
0134 
0135 template<typename R, typename T>
0136 constexpr inline checked_result<R> cast(const T & t) /* noexcept */ {
0137     return heterogeneous_checked_operation<
0138         R,
0139         std::numeric_limits<R>::min(),
0140         std::numeric_limits<R>::max(),
0141         T
0142     >::cast(t);
0143 }
0144 template<typename R>
0145 constexpr inline checked_result<R> minus(const R & t) noexcept {
0146     return checked_operation<R>::minus(t);
0147 }
0148 template<typename R>
0149 constexpr inline checked_result<R> add(const R & t, const R & u) noexcept {
0150     return checked_operation<R>::add(t, u);
0151 }
0152 template<typename R>
0153 constexpr inline checked_result<R> subtract(const R & t, const R & u) noexcept {
0154     return checked_operation<R>::subtract(t, u);
0155 }
0156 template<typename R>
0157 constexpr inline checked_result<R> multiply(const R & t, const R & u) noexcept {
0158     return checked_operation<R>::multiply(t, u);
0159 }
0160 template<typename R>
0161 constexpr inline checked_result<R> divide(const R & t, const R & u) noexcept {
0162     return checked_operation<R>::divide(t, u);
0163 }
0164 template<typename R>
0165 constexpr inline checked_result<R> modulus(const R & t, const R & u) noexcept {
0166     return checked_operation<R>::modulus(t, u);
0167 }
0168 template<typename R>
0169 constexpr inline checked_result<bool> less_than(const R & t, const R & u) noexcept {
0170     return checked_operation<R>::less_than(t, u);
0171 }
0172 template<typename R>
0173 constexpr inline checked_result<bool> greater_than_equal(const R & t, const R & u) noexcept {
0174     return ! checked_operation<R>::less_than(t, u);
0175 }
0176 template<typename R>
0177 constexpr inline checked_result<bool> greater_than(const R & t, const R & u) noexcept {
0178     return checked_operation<R>::greater_than(t, u);
0179 }
0180 template<typename R>
0181 constexpr inline checked_result<bool> less_than_equal(const R & t, const R & u) noexcept {
0182     return ! checked_operation<R>::greater_than(t, u);
0183 }
0184 template<typename R>
0185 constexpr inline checked_result<bool> equal(const R & t, const R & u) noexcept {
0186     return checked_operation<R>::equal(t, u);
0187 }
0188 template<typename R>
0189 constexpr inline checked_result<R> left_shift(const R & t, const R & u) noexcept {
0190     return checked_operation<R>::left_shift(t, u);
0191 }
0192 template<typename R>
0193 constexpr inline checked_result<R> right_shift(const R & t, const R & u) noexcept {
0194     return checked_operation<R>::right_shift(t, u);
0195 }
0196 template<typename R>
0197 constexpr inline checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
0198     return checked_operation<R>::bitwise_or(t, u);
0199 }
0200 template<typename R>
0201 constexpr inline checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
0202     return checked_operation<R>::bitwise_xor(t, u);
0203 }
0204 template<typename R>
0205 constexpr inline checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
0206     return checked_operation<R>::bitwise_and(t, u);
0207 }
0208 template<typename R>
0209 constexpr inline checked_result<R> bitwise_not(const R & t) noexcept {
0210     return checked_operation<R>::bitwise_not(t);
0211 }
0212 
0213 } // checked
0214 } // safe_numerics
0215 } // boost
0216 
0217 #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP