mirror of
https://github.com/boostorg/safe_numerics.git
synced 2026-02-10 23:52:27 +00:00
added in binary operations |, &, and ^
This commit is contained in:
@@ -838,6 +838,78 @@ SAFE_NUMERIC_CONSTEXPR checked_result<R> right_shift(
|
||||
;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// bitwise operations
|
||||
|
||||
template<class R, class T, class U>
|
||||
SAFE_NUMERIC_CONSTEXPR checked_result<R> bitwise_or(
|
||||
const T & t,
|
||||
const U & u
|
||||
) {
|
||||
static_assert(
|
||||
std::is_integral<T>::value && std::is_signed<T>::value
|
||||
&& std::is_integral<U>::value && std::is_signed<T>::value,
|
||||
"only intrinsic unsigned integers permitted"
|
||||
);
|
||||
const checked_result<R> ru = cast<R>(u);
|
||||
const checked_result<R> rt = cast<R>(t);
|
||||
return
|
||||
rt != checked_result<R>::exception_type::no_exception ?
|
||||
rt
|
||||
:
|
||||
ru != checked_result<R>::exception_type::no_exception ?
|
||||
ru
|
||||
:
|
||||
static_cast<R>(ru) | static_cast<R>(rt)
|
||||
;
|
||||
}
|
||||
|
||||
template<class R, class T, class U>
|
||||
SAFE_NUMERIC_CONSTEXPR checked_result<R> bitwise_and(
|
||||
const T & t,
|
||||
const U & u
|
||||
) {
|
||||
static_assert(
|
||||
std::is_integral<T>::value && std::is_signed<T>::value
|
||||
&& std::is_integral<U>::value && std::is_signed<T>::value,
|
||||
"only intrinsic unsigned integers permitted"
|
||||
);
|
||||
const checked_result<R> ru = cast<R>(u);
|
||||
const checked_result<R> rt = cast<R>(t);
|
||||
return
|
||||
rt != checked_result<R>::exception_type::no_exception ?
|
||||
rt
|
||||
:
|
||||
ru != checked_result<R>::exception_type::no_exception ?
|
||||
ru
|
||||
:
|
||||
static_cast<R>(ru) & static_cast<R>(rt)
|
||||
;
|
||||
}
|
||||
|
||||
template<class R, class T, class U>
|
||||
SAFE_NUMERIC_CONSTEXPR checked_result<R> bitwise_xor(
|
||||
const T & t,
|
||||
const U & u
|
||||
) {
|
||||
static_assert(
|
||||
std::is_integral<T>::value && std::is_signed<T>::value
|
||||
&& std::is_integral<U>::value && std::is_signed<T>::value,
|
||||
"only intrinsic unsigned integers permitted"
|
||||
);
|
||||
const checked_result<R> ru = cast<R>(u);
|
||||
const checked_result<R> rt = cast<R>(t);
|
||||
return
|
||||
rt != checked_result<R>::exception_type::no_exception ?
|
||||
rt
|
||||
:
|
||||
ru != checked_result<R>::exception_type::no_exception ?
|
||||
ru
|
||||
:
|
||||
static_cast<R>(ru) ^ static_cast<R>(rt)
|
||||
;
|
||||
}
|
||||
|
||||
} // checked
|
||||
} // numeric
|
||||
} // boost
|
||||
|
||||
@@ -163,6 +163,7 @@ class safe_base {
|
||||
|
||||
template<class T>
|
||||
SAFE_NUMERIC_CONSTEXPR bool validate(const T & t) const {
|
||||
// INT08-C
|
||||
return ! (
|
||||
boost::numeric::checked::greater_than(
|
||||
base_value(t),
|
||||
@@ -340,44 +341,6 @@ public:
|
||||
);
|
||||
return *this = ~(m_t);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// logical operators
|
||||
|
||||
template<class U>
|
||||
Stored inline operator>>(const U & rhs) const {
|
||||
// verify that U is an integer type
|
||||
static_assert(
|
||||
std::numeric_limits<U>::is_integer,
|
||||
"right hand side is not an integer type"
|
||||
);
|
||||
if(m_t < 0)
|
||||
boost::numeric::overflow("right shift of negative number undefined");
|
||||
typedef decltype(Stored() >> U()) result_type;
|
||||
if(rhs > boost::numeric::bits<Stored>::value)
|
||||
boost::numeric::overflow("conversion of negative value to unsigned");
|
||||
|
||||
return m_t >> rhs;
|
||||
}
|
||||
template<class U>
|
||||
Stored inline operator<<(const U & rhs) const {
|
||||
// verify that U is an integer type
|
||||
static_assert(
|
||||
std::numeric_limits<U>::is_integer,
|
||||
"right hand side is not an integer type"
|
||||
);
|
||||
if(m_t < 0)
|
||||
boost::numeric::overflow("right shift of negative number undefined");
|
||||
typedef decltype(Stored() >> U()) result_type;
|
||||
if(rhs > boost::numeric::bits<Stored>::value)
|
||||
boost::numeric::overflow("conversion of negative value to unsigned");
|
||||
return m_t << rhs;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -642,7 +642,7 @@ SAFE_NUMERIC_CONSTEXPR inline operator>>(const T & t, const U & u){
|
||||
// note: it's possible to trap some sitations at compile and skip
|
||||
// the error checking. May later - for now check all the time.
|
||||
|
||||
SAFE_NUMERIC_CONSTEXPR const checked_result<result_base_type> r = {
|
||||
const checked_result<result_base_type> r = {
|
||||
checked::right_shift<result_base_type>(base_value(t), base_value(u))
|
||||
};
|
||||
r.template dispatch<exception_policy>();
|
||||
@@ -650,42 +650,150 @@ SAFE_NUMERIC_CONSTEXPR inline operator>>(const T & t, const U & u){
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// logical operators
|
||||
/*
|
||||
template<class T, class Stored, class Derived, class Policies>
|
||||
typename boost::enable_if<
|
||||
boost::is_integral<T>,
|
||||
typename multiply_result_type<T, Stored>::type
|
||||
// bitwise operators
|
||||
|
||||
// operator |
|
||||
template<class T, class U>
|
||||
struct or_result {
|
||||
typedef common_policies<T, U> P;
|
||||
typedef typename P::promotion_policy::template or_result<
|
||||
T,
|
||||
U,
|
||||
typename P::promotion_policy,
|
||||
typename P::exception_policy
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
typename boost::lazy_enable_if<
|
||||
boost::mpl::or_<
|
||||
boost::numeric::is_safe<T>,
|
||||
boost::numeric::is_safe<U>
|
||||
>,
|
||||
or_result<T, U>
|
||||
>::type
|
||||
inline operator|(const T & lhs, const safe_base<Stored, Derived, Policies> & rhs) {
|
||||
return rhs | lhs;
|
||||
}
|
||||
template<class T, class Stored, class Derived, class Policies>
|
||||
typename boost::enable_if<
|
||||
boost::is_integral<T>,
|
||||
typename multiply_result_type<T, Stored>::type
|
||||
>::type
|
||||
inline operator|(const T & lhs, const safe_base<Stored, Derived, Policies> & rhs) {
|
||||
return rhs | lhs;
|
||||
SAFE_NUMERIC_CONSTEXPR inline operator|(const T & t, const U & u){
|
||||
// argument dependent lookup should guarentee that we only get here
|
||||
// only if one of the types is a safe type. Verify this here
|
||||
typedef or_result<T, U> or_;
|
||||
typedef typename or_::P::exception_policy exception_policy;
|
||||
typedef typename or_::type result_type;
|
||||
static_assert(
|
||||
boost::numeric::is_safe<result_type>::value,
|
||||
"Promotion failed to return safe type"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<T>::is_integer
|
||||
&& (! std::numeric_limits<T>::is_signed)
|
||||
&& std::numeric_limits<U>::is_integer
|
||||
&& (! std::numeric_limits<U>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations are only applicable to unsigned integers"
|
||||
);
|
||||
|
||||
typedef typename base_type<result_type>::type result_base_type;
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<result_base_type>::is_integer
|
||||
&& (! std::numeric_limits<result_base_type>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations should return unsigned integers"
|
||||
);
|
||||
|
||||
checked_result<result_base_type> r = checked::bitwise_or<result_base_type>(t, u);
|
||||
r.template dispatch<exception_policy>();
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class T, class Stored, class Derived, class Policies>
|
||||
typename boost::enable_if<
|
||||
boost::is_integral<T>,
|
||||
decltype(T() & Stored())
|
||||
// operator &
|
||||
template<class T, class U>
|
||||
typename boost::lazy_enable_if<
|
||||
boost::mpl::or_<
|
||||
boost::numeric::is_safe<T>,
|
||||
boost::numeric::is_safe<U>
|
||||
>,
|
||||
or_result<T, U>
|
||||
>::type
|
||||
inline operator&(const T & lhs, const safe_base<Stored, Derived, Policies> & rhs) {
|
||||
return rhs & lhs;
|
||||
SAFE_NUMERIC_CONSTEXPR inline operator&(const T & t, const U & u){
|
||||
// argument dependent lookup should guarentee that we only get here
|
||||
// only if one of the types is a safe type. Verify this here
|
||||
typedef or_result<T, U> and_;
|
||||
typedef typename and_::P::exception_policy exception_policy;
|
||||
typedef typename and_::type result_type;
|
||||
static_assert(
|
||||
boost::numeric::is_safe<result_type>::value,
|
||||
"Promotion failed to return safe type"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<T>::is_integer
|
||||
&& (! std::numeric_limits<T>::is_signed)
|
||||
&& std::numeric_limits<U>::is_integer
|
||||
&& (! std::numeric_limits<U>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations are only applicable to unsigned integers"
|
||||
);
|
||||
|
||||
typedef typename base_type<result_type>::type result_base_type;
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<result_base_type>::is_integer
|
||||
&& (! std::numeric_limits<result_base_type>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations should return unsigned integers"
|
||||
);
|
||||
|
||||
checked_result<result_base_type> r = checked::bitwise_and<result_base_type>(t, u);
|
||||
r.template dispatch<exception_policy>();
|
||||
return r;
|
||||
}
|
||||
template<class T, class Stored, class Derived, class Policies>
|
||||
typename boost::enable_if<
|
||||
boost::is_integral<T>,
|
||||
decltype(T() ^ Stored())
|
||||
|
||||
// operator ^
|
||||
template<class T, class U>
|
||||
typename boost::lazy_enable_if<
|
||||
boost::mpl::or_<
|
||||
boost::numeric::is_safe<T>,
|
||||
boost::numeric::is_safe<U>
|
||||
>,
|
||||
or_result<T, U>
|
||||
>::type
|
||||
inline operator^(const T & lhs, const safe_base<Stored, Derived, Policies> & rhs) {
|
||||
return rhs ^ lhs;
|
||||
SAFE_NUMERIC_CONSTEXPR inline operator^(const T & t, const U & u){
|
||||
// argument dependent lookup should guarentee that we only get here
|
||||
// only if one of the types is a safe type. Verify this here
|
||||
typedef or_result<T, U> xor_;
|
||||
typedef typename xor_::P::exception_policy exception_policy;
|
||||
typedef typename xor_::type result_type;
|
||||
static_assert(
|
||||
boost::numeric::is_safe<result_type>::value,
|
||||
"Promotion failed to return safe type"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<T>::is_integer
|
||||
&& (! std::numeric_limits<T>::is_signed)
|
||||
&& std::numeric_limits<U>::is_integer
|
||||
&& (! std::numeric_limits<U>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations are only applicable to unsigned integers"
|
||||
);
|
||||
|
||||
typedef typename base_type<result_type>::type result_base_type;
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<result_base_type>::is_integer
|
||||
&& (! std::numeric_limits<result_base_type>::is_signed),
|
||||
// INT13-C
|
||||
"bitwise operations should return unsigned integers"
|
||||
);
|
||||
|
||||
checked_result<result_base_type> r = checked::bitwise_xor<result_base_type>(t, u);
|
||||
r.template dispatch<exception_policy>();
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// stream operators
|
||||
|
||||
template<
|
||||
class T,
|
||||
|
||||
Reference in New Issue
Block a user