added in binary operations |, &, and ^

This commit is contained in:
Robert Ramey
2015-07-03 15:30:54 -07:00
parent 54617a8cca
commit f185d014f2
3 changed files with 211 additions and 68 deletions

View File

@@ -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

View File

@@ -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;
}
*/
};

View File

@@ -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,