summaryrefslogtreecommitdiff
path: root/boost/safe_numerics
diff options
context:
space:
mode:
Diffstat (limited to 'boost/safe_numerics')
-rw-r--r--boost/safe_numerics/automatic.hpp134
-rw-r--r--boost/safe_numerics/checked_default.hpp31
-rw-r--r--boost/safe_numerics/checked_float.hpp9
-rw-r--r--boost/safe_numerics/checked_integer.hpp244
-rw-r--r--boost/safe_numerics/checked_result.hpp73
-rw-r--r--boost/safe_numerics/checked_result_operations.hpp115
-rw-r--r--boost/safe_numerics/concept/exception_policy.hpp5
-rw-r--r--boost/safe_numerics/concept/integer.hpp5
-rw-r--r--boost/safe_numerics/concept/numeric.hpp5
-rw-r--r--boost/safe_numerics/concept/promotion_policy.hpp5
-rw-r--r--boost/safe_numerics/concept/safe_numeric.hpp5
-rwxr-xr-xboost/safe_numerics/cpp.hpp5
-rw-r--r--boost/safe_numerics/exception.hpp27
-rw-r--r--boost/safe_numerics/exception_policies.hpp110
-rw-r--r--boost/safe_numerics/interval.hpp5
-rw-r--r--boost/safe_numerics/native.hpp5
-rw-r--r--boost/safe_numerics/range_value.hpp9
-rw-r--r--boost/safe_numerics/safe_base.hpp77
-rw-r--r--boost/safe_numerics/safe_base_operations.hpp485
-rw-r--r--boost/safe_numerics/safe_common.hpp5
-rw-r--r--boost/safe_numerics/safe_compare.hpp5
-rw-r--r--boost/safe_numerics/safe_integer.hpp5
-rw-r--r--boost/safe_numerics/safe_integer_literal.hpp5
-rw-r--r--boost/safe_numerics/safe_integer_range.hpp5
-rw-r--r--boost/safe_numerics/utility.hpp13
25 files changed, 751 insertions, 641 deletions
diff --git a/boost/safe_numerics/automatic.hpp b/boost/safe_numerics/automatic.hpp
index ee19c97e0a..df63bf8d90 100644
--- a/boost/safe_numerics/automatic.hpp
+++ b/boost/safe_numerics/automatic.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_AUTOMATIC_HPP
#define BOOST_NUMERIC_AUTOMATIC_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -83,14 +78,17 @@ public:
constexpr static const r_interval_type r_interval = t_interval + u_interval;
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -115,14 +113,17 @@ public:
constexpr static const r_interval_type r_interval = t_interval - u_interval;
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -154,14 +155,17 @@ public:
constexpr static const r_interval_type r_interval = t_interval * u_interval;
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -192,33 +196,36 @@ public:
};
constexpr static const r_interval_type rx(){
- if(u_interval.u < r_type(0)
- || u_interval.l > r_type(0))
- return t_interval / u_interval;
- return utility::minmax(
- std::initializer_list<r_type> {
- t_interval.l / u_interval.l,
- t_interval.l / r_type(-1),
- t_interval.l / r_type(1),
- t_interval.l / u_interval.u,
- t_interval.u / u_interval.l,
- t_interval.u / r_type(-1),
- t_interval.u / r_type(1),
- t_interval.u / u_interval.u,
- }
- );
+ if(u_interval.u < r_type(0)
+ || u_interval.l > r_type(0))
+ return t_interval / u_interval;
+ return utility::minmax(
+ std::initializer_list<r_type> {
+ t_interval.l / u_interval.l,
+ t_interval.l / r_type(-1),
+ t_interval.l / r_type(1),
+ t_interval.l / u_interval.u,
+ t_interval.u / u_interval.l,
+ t_interval.u / r_type(-1),
+ t_interval.u / r_type(1),
+ t_interval.u / u_interval.u,
+ }
+ );
}
constexpr static const r_interval_type r_interval = rx();
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -268,14 +275,17 @@ public:
constexpr static const r_interval_type r_interval = rx();
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -308,6 +318,8 @@ public:
checked::cast<temp_base_type>(base_value(std::numeric_limits<U>::max()))
};
+ // workaround some microsoft problem
+ #if 0
constexpr static r_type min(const r_type & t, const r_type & u){
// assert(! u.exception());
// assert(! t.exception());
@@ -319,6 +331,7 @@ public:
// assert(! t.exception());
return static_cast<bool>(t < u) ? u : t;
}
+ #endif
// union of two intervals
// note: we can't use t_interval | u_interval because it
@@ -328,22 +341,27 @@ public:
const r_interval_type & t,
const r_interval_type & u
){
- const r_type & rl = min(t.l, u.l);
- const r_type & ru = max(t.u, u.u);
- return r_interval_type(rl, ru);
+ //const r_type & rl = min(t.l, u.l);
+ const r_type & rmin = static_cast<bool>(t.l < u.l) ? t.l : u.l;
+ //const r_type & ru = max(t.u, u.u);
+ const r_type & rmax = static_cast<bool>(t.u < u.u) ? u.u : t.u;
+ return r_interval_type(rmin, rmax);
}
constexpr static const r_interval_type r_interval =
union_interval(t_interval, u_interval);
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -373,14 +391,17 @@ public:
constexpr static const r_interval_type r_interval =
t_interval << u_interval;
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
@@ -413,14 +434,17 @@ public:
constexpr static const r_interval_type r_interval = t_interval >> u_interval;
+ constexpr static auto rl = r_interval.l;
+ constexpr static auto ru = r_interval.u;
+
using type = typename result_type<
temp_base_type,
- r_interval.l.exception()
+ rl.exception()
? std::numeric_limits<temp_base_type>::min()
- : static_cast<temp_base_type>(r_interval.l),
- r_interval.u.exception()
+ : static_cast<temp_base_type>(rl),
+ ru.exception()
? std::numeric_limits<temp_base_type>::max()
- : static_cast<temp_base_type>(r_interval.u)
+ : static_cast<temp_base_type>(ru)
>::type;
};
diff --git a/boost/safe_numerics/checked_default.hpp b/boost/safe_numerics/checked_default.hpp
index 5a5bb44d24..07699c4fca 100644
--- a/boost/safe_numerics/checked_default.hpp
+++ b/boost/safe_numerics/checked_default.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP
#define BOOST_NUMERIC_CHECKED_DEFAULT_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2017 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -49,14 +44,27 @@ namespace safe_numerics {
// it should trap with a static_assert. This occurs at compile time while
// calculating result interval. This needs more investigation.
-template<typename R, typename T = void, class Default = void>
-struct checked_operation{
+template<
+ typename R,
+ 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);
}
- constexpr static checked_result<T>
- minus(const T & t) noexcept {
+};
+
+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>
@@ -124,7 +132,7 @@ namespace checked {
template<typename R, typename T>
constexpr checked_result<R> cast(const T & t) /* noexcept */ {
- return checked_operation<R, T>::cast(t);
+ return heterogeneous_checked_operation<R, T>::cast(t);
}
template<typename R>
constexpr checked_result<R> minus(const R & t) noexcept {
@@ -184,7 +192,7 @@ constexpr checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
}
template<typename R>
constexpr checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
- return checked_operation<R>::bitwise_or(t, u);
+ return checked_operation<R>::bitwise_xor(t, u);
}
template<typename R>
constexpr checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
@@ -200,4 +208,3 @@ constexpr checked_result<R> bitwise_not(const R & t) noexcept {
} // boost
#endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP
-
diff --git a/boost/safe_numerics/checked_float.hpp b/boost/safe_numerics/checked_float.hpp
index a382e9889e..696c14c52b 100644
--- a/boost/safe_numerics/checked_float.hpp
+++ b/boost/safe_numerics/checked_float.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CHECKED_FLOAT_HPP
#define BOOST_NUMERIC_CHECKED_FLOAT_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2017 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -27,7 +22,7 @@ namespace checked {
// layer 0 - implement safe operations for floating
template<typename R, typename T>
-struct checked_unary_operation<R, T,
+struct heterogeneous_checked_operation<R, T, F,
typename std::enable_if<
std::is_floating_point<R>::value
&& std::is_floating_point<T>::value
@@ -40,7 +35,7 @@ struct checked_unary_operation<R, T,
}; // checked_unary_operation
template<typename R, typename T, typename U>
-struct checked_binary_operation<R, T, U,
+struct checked_operation<R, T, U, F,
typename std::enable_if<
std::is_floating_point<R>::value
>::type
diff --git a/boost/safe_numerics/checked_integer.hpp b/boost/safe_numerics/checked_integer.hpp
index e86b3994dd..7e7bef357a 100644
--- a/boost/safe_numerics/checked_integer.hpp
+++ b/boost/safe_numerics/checked_integer.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CHECKED_INTEGER_HPP
#define BOOST_NUMERIC_CHECKED_INTEGER_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -38,8 +33,12 @@ using bool_type = typename std::conditional<tf, std::true_type, std::false_type>
// Note presumption of twos complement integer arithmetic
// convert an integral value to some other integral type
-template<typename R, typename T>
-struct checked_operation<R, T,
+template<
+ typename R,
+ typename T,
+ class F
+>
+struct heterogeneous_checked_operation<R, T, F,
typename std::enable_if<
std::is_integral<R>::value
&& std::is_integral<T>::value
@@ -54,7 +53,7 @@ struct checked_operation<R, T,
const T & t,
std::true_type, // R is signed
std::true_type // T is signed
- ) noexcept {
+ ){
// INT32-C Ensure that operations on signed
// integers do not overflow
return
@@ -62,8 +61,7 @@ struct checked_operation<R, T,
t,
std::numeric_limits<R>::max()
) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"converted signed value too large"
)
:
@@ -71,8 +69,7 @@ struct checked_operation<R, T,
t,
std::numeric_limits<R>::min()
) ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"converted signed value too small"
)
:
@@ -84,7 +81,7 @@ struct checked_operation<R, T,
const T & t,
std::true_type, // R is signed
std::false_type // T is unsigned
- ) noexcept {
+ ){
// INT30-C Ensure that unsigned integer operations
// do not wrap
return
@@ -92,8 +89,7 @@ struct checked_operation<R, T,
t,
std::numeric_limits<R>::max()
) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"converted unsigned value too large"
)
:
@@ -105,7 +101,7 @@ struct checked_operation<R, T,
const T & t,
std::false_type, // R is unsigned
std::false_type // T is unsigned
- ) noexcept {
+ ){
// INT32-C Ensure that operations on unsigned
// integers do not overflow
return
@@ -113,8 +109,7 @@ struct checked_operation<R, T,
t,
std::numeric_limits<R>::max()
) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"converted unsigned value too large"
)
:
@@ -126,11 +121,10 @@ struct checked_operation<R, T,
const T & t,
std::false_type, // R is unsigned
std::true_type // T is signed
- ) noexcept {
+ ){
return
boost::safe_numerics::safe_compare::less_than(t, 0) ?
- checked_result<R>(
- safe_numerics_error::domain_error,
+ F::template invoke<safe_numerics_error::domain_error>(
"converted negative value to unsigned"
)
:
@@ -138,8 +132,7 @@ struct checked_operation<R, T,
t,
std::numeric_limits<R>::max()
) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"converted signed value too large"
)
:
@@ -149,7 +142,7 @@ struct checked_operation<R, T,
}; // cast_impl_detail
constexpr static checked_result<R>
- cast(const T & t) noexcept {
+ cast(const T & t){
return
cast_impl_detail::cast_impl(
t,
@@ -160,15 +153,19 @@ struct checked_operation<R, T,
};
// converting floating point value to integral type
-template<typename R, typename T>
-struct checked_operation<R, T,
+template<
+ typename R,
+ typename T,
+ class F
+>
+struct heterogeneous_checked_operation<R, T, F,
typename std::enable_if<
std::is_integral<R>::value
&& std::is_floating_point<T>::value
>::type
>{
constexpr static checked_result<R>
- cast(const T & t) noexcept {
+ cast(const T & t){
return static_cast<R>(t);
}
};
@@ -176,29 +173,38 @@ struct checked_operation<R, T,
// converting integral value to floating point type
// INT35-C. Use correct integer precisions
-template<typename R, typename T>
-struct checked_operation<R, T,
+template<
+ typename R,
+ typename T,
+ class F
+>
+struct heterogeneous_checked_operation<R, T, F,
typename std::enable_if<
std::is_floating_point<R>::value
&& std::is_integral<T>::value
>::type
>{
constexpr static checked_result<R>
- cast(const T & t) noexcept {
+ cast(const T & t){
if(std::numeric_limits<R>::digits < std::numeric_limits<T>::digits){
if(utility::significant_bits(t) > std::numeric_limits<R>::digits){
- return {
+ return F::invoke(
safe_numerics_error::precision_overflow_error,
"keep precision"
- };
+ );
}
}
return t;
}
};
-template<typename R>
-struct checked_operation<R,
+// binary operations on primitive integer types
+
+template<
+ typename R,
+ class F
+>
+struct checked_operation<R, F,
typename std::enable_if<
std::is_integral<R>::value
>::type
@@ -212,12 +218,11 @@ struct checked_operation<R,
const R t,
const R u,
std::false_type // R unsigned
- ) noexcept {
+ ){
return
// INT30-C. Ensure that unsigned integer operations do not wrap
std::numeric_limits<R>::max() - u < t ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"addition result too large"
)
:
@@ -230,18 +235,17 @@ struct checked_operation<R,
const R t,
const R u,
std::true_type // R signed
- ) noexcept {
+ ){
+ // INT32-C. Ensure that operations on signed integers do not result in overflow
return
// INT32-C. Ensure that operations on signed integers do not result in overflow
((u > 0) && (t > (std::numeric_limits<R>::max() - u))) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"addition result too large"
)
:
((u < 0) && (t < (std::numeric_limits<R>::min() - u))) ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"addition result too low"
)
:
@@ -251,7 +255,7 @@ struct checked_operation<R,
}; // add_impl_detail
constexpr static checked_result<R>
- add(const R & t, const R & u) noexcept {
+ add(const R & t, const R & u){
return add_impl_detail::add(t, u, std::is_signed<R>());
}
@@ -264,12 +268,11 @@ struct checked_operation<R,
const R t,
const R u,
std::false_type // R is unsigned
- ) noexcept {
+ ){
// INT30-C. Ensure that unsigned integer operations do not wrap
return
t < u ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"subtraction result cannot be negative"
)
:
@@ -282,18 +285,16 @@ struct checked_operation<R,
const R t,
const R u,
std::true_type // R is signed
- ) noexcept { // INT32-C
+ ){ // INT32-C
return
// INT32-C. Ensure that operations on signed integers do not result in overflow
((u > 0) && (t < (std::numeric_limits<R>::min() + u))) ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"subtraction result overflows result type"
)
:
((u < 0) && (t > (std::numeric_limits<R>::max() + u))) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"subtraction result overflows result type"
)
:
@@ -303,7 +304,7 @@ struct checked_operation<R,
}; // subtract_impl_detail
- constexpr static checked_result<R> subtract(const R & t, const R & u) noexcept {
+ constexpr static checked_result<R> subtract(const R & t, const R & u){
return subtract_impl_detail::subtract(t, u, std::is_signed<R>());
}
@@ -315,10 +316,9 @@ struct checked_operation<R,
constexpr static checked_result<R> minus(
const R t,
std::false_type // R is unsigned
- ) noexcept {
+ ){
return t > 0 ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"minus unsigned would be negative"
)
:
@@ -331,10 +331,9 @@ struct checked_operation<R,
constexpr static checked_result<R> minus(
const R t,
std::true_type // R is signed
- ) noexcept { // INT32-C
+ ){ // INT32-C
return t == std::numeric_limits<R>::min() ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"subtraction result overflows result type"
)
:
@@ -344,7 +343,7 @@ struct checked_operation<R,
}; // minus_impl_detail
- constexpr static checked_result<R> minus(const R & t) noexcept {
+ constexpr static checked_result<R> minus(const R & t){
return minus_impl_detail::minus(t, std::is_signed<R>());
}
@@ -358,9 +357,9 @@ struct checked_operation<R,
const R t,
const R u,
std::false_type, // R is unsigned
- std::false_type // !(sizeof(R) > sizeof(std::uintmax_t) / 2)
+ std::false_type // !(sizeochecked_result<R>R) > sizeochecked_result<R>std::uintmax_t) / 2)
- ) noexcept {
+ ){
// INT30-C
// fast method using intermediate result guaranteed not to overflow
// todo - replace std::uintmax_t with a size double the size of R
@@ -368,8 +367,7 @@ struct checked_operation<R,
return
static_cast<i_type>(t) * static_cast<i_type>(u)
> std::numeric_limits<R>::max() ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"multiplication overflow"
)
:
@@ -380,14 +378,13 @@ struct checked_operation<R,
const R t,
const R u,
std::false_type, // R is unsigned
- std::true_type // (sizeof(R) > sizeof(std::uintmax_t) / 2)
+ std::true_type // (sizeochecked_result<R>R) > sizeochecked_result<R>std::uintmax_t) / 2)
- ) noexcept {
+ ){
// INT30-C
return
u > 0 && t > std::numeric_limits<R>::max() / u ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"multiplication overflow"
)
:
@@ -400,9 +397,9 @@ struct checked_operation<R,
const R t,
const R u,
std::true_type, // R is signed
- std::false_type // ! (sizeof(R) > (sizeof(std::intmax_t) / 2))
+ std::false_type // ! (sizeochecked_result<R>R) > (sizeochecked_result<R>std::intmax_t) / 2))
- ) noexcept {
+ ){
// INT30-C
// fast method using intermediate result guaranteed not to overflow
// todo - replace std::intmax_t with a size double the size of R
@@ -412,8 +409,7 @@ struct checked_operation<R,
static_cast<i_type>(t) * static_cast<i_type>(u)
> static_cast<i_type>(std::numeric_limits<R>::max())
) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"multiplication overflow"
)
:
@@ -421,8 +417,7 @@ struct checked_operation<R,
static_cast<i_type>(t) * static_cast<i_type>(u)
< static_cast<i_type>(std::numeric_limits<R>::min())
) ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"multiplication overflow"
)
:
@@ -433,21 +428,19 @@ struct checked_operation<R,
const R t,
const R u,
std::true_type, // R is signed
- std::true_type // (sizeof(R) > (sizeof(std::intmax_t) / 2))
- ) noexcept { // INT32-C
+ std::true_type // (sizeochecked_result<R>R) > (sizeochecked_result<R>std::intmax_t) / 2))
+ ){ // INT32-C
return t > 0 ?
u > 0 ?
t > std::numeric_limits<R>::max() / u ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"multiplication overflow"
)
:
checked_result<R>(t * u)
: // u <= 0
u < std::numeric_limits<R>::min() / t ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"multiplication overflow"
)
:
@@ -455,16 +448,14 @@ struct checked_operation<R,
: // t <= 0
u > 0 ?
t < std::numeric_limits<R>::min() / u ?
- checked_result<R>(
- safe_numerics_error::negative_overflow_error,
+ F::template invoke<safe_numerics_error::negative_overflow_error>(
"multiplication overflow"
)
:
checked_result<R>(t * u)
: // u <= 0
t != 0 && u < std::numeric_limits<R>::max() / t ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"multiplication overflow"
)
:
@@ -473,7 +464,7 @@ struct checked_operation<R,
}
}; // multiply_impl_detail
- constexpr static checked_result<R> multiply(const R & t, const R & u) noexcept {
+ constexpr static checked_result<R> multiply(const R & t, const R & u){
return multiply_impl_detail::multiply(
t,
u,
@@ -493,7 +484,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::false_type // R is unsigned
- ) noexcept {
+ ){
return t / u;
}
@@ -501,11 +492,10 @@ struct checked_operation<R,
const R & t,
const R & u,
std::true_type // R is signed
- ) noexcept {
+ ){
return
(u == -1 && t == std::numeric_limits<R>::min()) ?
- checked_result<R>(
- safe_numerics_error::positive_overflow_error,
+ F::template invoke<safe_numerics_error::positive_overflow_error>(
"result cannot be represented"
)
:
@@ -515,10 +505,9 @@ struct checked_operation<R,
}; // divide_impl_detail
// note that we presume that the size of R >= size of T
- constexpr static checked_result<R> divide(const R & t, const R & u) noexcept {
+ constexpr static checked_result<R> divide(const R & t, const R & u){
if(u == 0){
- return checked_result<R>(
- safe_numerics_error::domain_error,
+ return F::template invoke<safe_numerics_error::domain_error>(
"divide by zero"
);
}
@@ -533,7 +522,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::false_type // R is unsigned
- ) noexcept {
+ ){
return t % u;
}
@@ -541,7 +530,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::true_type // R is signed
- ) noexcept {
+ ){
if(u >= 0)
return t % u;
checked_result<R> ux = checked::minus(u);
@@ -551,10 +540,9 @@ struct checked_operation<R,
}
}; // modulus_impl_detail
- constexpr static checked_result<R> modulus(const R & t, const R & u) noexcept {
+ constexpr static checked_result<R> modulus(const R & t, const R & u){
if(0 == u)
- return checked_result<R>(
- safe_numerics_error::domain_error,
+ return F::template invoke<safe_numerics_error::domain_error>(
"denominator is zero"
);
@@ -605,7 +593,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::false_type // R is unsigned
- ) noexcept {
+ ){
// the value of the result is E1 x 2^E2, reduced modulo one more than
// the maximum value representable in the result type.
@@ -619,8 +607,7 @@ struct checked_operation<R,
)
){
// behavior is undefined
- return checked_result<R>(
- safe_numerics_error::shift_too_large,
+ return F::template invoke<safe_numerics_error::shift_too_large>(
"shifting left more bits than available is undefined behavior"
);
}
@@ -631,7 +618,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::true_type // R is signed
- ) noexcept {
+ ){
// and [E1] has a non-negative value
if(t >= 0){
// and E1 x 2^E2 is representable in the corresponding
@@ -647,8 +634,7 @@ struct checked_operation<R,
)
){
// behavior is undefined
- return checked_result<R>(
- safe_numerics_error::shift_too_large,
+ return F::template invoke<safe_numerics_error::shift_too_large>(
"shifting left more bits than available"
);
}
@@ -657,8 +643,7 @@ struct checked_operation<R,
}
}
// otherwise, the behavior is undefined.
- return checked_result<R>(
- safe_numerics_error::negative_shift,
+ return F::template invoke<safe_numerics_error::negative_shift>(
"shifting a negative value"
);
}
@@ -668,7 +653,7 @@ struct checked_operation<R,
constexpr static checked_result<R> left_shift(
const R & t,
const R & u
- ) noexcept {
+ ){
// INT34-C - Do not shift an expression by a negative number of bits
// standard paragraph 5.8 & 1
@@ -677,15 +662,13 @@ struct checked_operation<R,
return t;
}
if(u < 0){
- return checked_result<R>(
- safe_numerics_error::negative_shift,
+ return F::template invoke<safe_numerics_error::negative_shift>(
"shifting negative amount"
);
}
if(u > std::numeric_limits<R>::digits){
// behavior is undefined
- return checked_result<R>(
- safe_numerics_error::shift_too_large,
+ return F::template invoke<safe_numerics_error::shift_too_large>(
"shifting more bits than available"
);
}
@@ -705,7 +688,7 @@ struct checked_operation<R,
const R & t,
const R & u,
std::false_type // T is unsigned
- ) noexcept {
+ ){
// the value of the result is the integral part of the
// quotient of E1/2E2
return t >> u;
@@ -715,12 +698,11 @@ struct checked_operation<R,
const R & t,
const R & u,
std::true_type // T is signed;
- ) noexcept {
+ ){
if(t < 0){
// note that the C++ standard considers this case is "implemenation
// defined" rather than "undefined".
- return checked_result<R>(
- safe_numerics_error::negative_value_shift,
+ return F::template invoke<safe_numerics_error::negative_value_shift>(
"shifting a negative value"
);
}
@@ -733,21 +715,19 @@ struct checked_operation<R,
constexpr static checked_result<R> right_shift(
const R & t,
const R & u
-) noexcept {
+){
// INT34-C - Do not shift an expression by a negative number of bits
// standard paragraph 5.8 & 1
// if the right operand is negative
if(u < 0){
- return checked_result<R>(
- safe_numerics_error::negative_shift,
+ return F::template invoke<safe_numerics_error::negative_shift>(
"shifting negative amount"
);
}
if(u > std::numeric_limits<R>::digits){
// behavior is undefined
- return checked_result<R>(
- safe_numerics_error::shift_too_large,
+ return F::template invoke<safe_numerics_error::shift_too_large>(
"shifting more bits than available"
);
}
@@ -761,56 +741,52 @@ constexpr static checked_result<R> right_shift(
// as it would break too many programs. Specifically, we permit signed
// integer operands.
-constexpr static checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
+constexpr static checked_result<R> bitwise_or(const R & t, const R & u){
using namespace boost::safe_numerics::utility;
const unsigned int result_size
= std::max(significant_bits(t), significant_bits(u));
if(result_size > bits_type<R>::value){
- return checked_result<R>{
- safe_numerics_error::positive_overflow_error,
+ return F::template invoke<safe_numerics_error::positive_overflow_error>(
"result type too small to hold bitwise or"
- };
+ );
}
return t | u;
}
-constexpr static checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
+constexpr static checked_result<R> bitwise_xor(const R & t, const R & u){
using namespace boost::safe_numerics::utility;
const unsigned int result_size
= std::max(significant_bits(t), significant_bits(u));
if(result_size > bits_type<R>::value){
- return checked_result<R>{
- safe_numerics_error::positive_overflow_error,
+ return F::template invoke<safe_numerics_error::positive_overflow_error>(
"result type too small to hold bitwise or"
- };
+ );
}
return t ^ u;
}
-constexpr static checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
+constexpr static checked_result<R> bitwise_and(const R & t, const R & u){
using namespace boost::safe_numerics::utility;
const unsigned int result_size
= std::min(significant_bits(t), significant_bits(u));
if(result_size > bits_type<R>::value){
- return checked_result<R>{
- safe_numerics_error::positive_overflow_error,
+ return F::template invoke<safe_numerics_error::positive_overflow_error>(
"result type too small to hold bitwise and"
- };
+ );
}
return t & u;
}
-constexpr static checked_result<R> bitwise_not(const R & t) noexcept {
+constexpr static checked_result<R> bitwise_not(const R & t){
using namespace boost::safe_numerics::utility;
if(significant_bits(t) > bits_type<R>::value){
- return checked_result<R>{
- safe_numerics_error::positive_overflow_error,
+ return F::template invoke<safe_numerics_error::positive_overflow_error>(
"result type too small to hold bitwise inverse"
- };
+ );
}
return ~t;
}
diff --git a/boost/safe_numerics/checked_result.hpp b/boost/safe_numerics/checked_result.hpp
index 55efca082a..10bd7a65c8 100644
--- a/boost/safe_numerics/checked_result.hpp
+++ b/boost/safe_numerics/checked_result.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CHECKED_RESULT
#define BOOST_NUMERIC_CHECKED_RESULT
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -32,21 +27,54 @@ struct checked_result {
// don't permit construction without initial value;
checked_result() = delete;
+ // note: I implemented the following non-default copy and move
+ // constructors because I thought I needed to do this in order
+ // to make them constexpr. Turns out though that doing this creates
+ // a syntax error because the assignment results in error due
+ // to assignment "outside of object lifetime". I think this could
+ // be addressed by replacing the anonymous union above with a
+ // named union. This would create some syntax changes which would
+ // ripple through some parts of th program. So for now, we'll just
+ // rely on the default copy and move constructors.
+ #if 0
+ // copy constructor
+ constexpr /*explicit*/ checked_result(const checked_result & r) noexpect :
+ m_e(r.m_e)
+ {
+ if(safe_numerics_error::success == r.m_e)
+ m_r = r.m_r;
+ else
+ m_msg = r.m_msg;
+ }
+
+ // move constructor
+ constexpr /*explicit*/ checked_result(checked_result && r) noexcept :
+ m_e(r.m_e)
+ {
+ if(safe_numerics_error::success == r.m_e)
+ m_r = r.m_r;
+ else
+ m_msg = r.m_msg;
+ }
+ #endif
+ checked_result(const checked_result & r) = default;
+ checked_result(checked_result && r) = default;
+
constexpr /*explicit*/ checked_result(const R & r) :
m_e(safe_numerics_error::success),
m_r(r)
{}
#if 0
template<typename T>
- constexpr /*explicit*/ checked_result(const T & t) :
+ constexpr /*explicit*/ checked_result(const T & t) noexcept :
m_e(safe_numerics_error::success),
m_r(t)
{}
#endif
constexpr /*explicit*/ checked_result(
- safe_numerics_error e,
+ const safe_numerics_error & e,
const char * msg = ""
- ) :
+ ) noexcept :
m_e(e),
m_msg(msg)
{
@@ -54,7 +82,7 @@ struct checked_result {
}
// permit construct from another checked result type
template<typename T>
- constexpr /*explicit*/ checked_result(const checked_result<T> & t) :
+ constexpr /*explicit*/ checked_result(const checked_result<T> & t) noexcept :
m_e(t.m_e)
{
static_assert(
@@ -71,18 +99,18 @@ struct checked_result {
}
// accesors
- constexpr operator R() const {
+ constexpr operator R() const noexcept{
// don't assert here. Let the library catch these errors
assert(! exception());
return m_r;
}
- constexpr operator safe_numerics_error () const {
+ constexpr operator safe_numerics_error () const noexcept{
// note that this is a legitimate operation even when
// the operation was successful - it will return success
return m_e;
}
- constexpr operator const char *() const {
+ constexpr operator const char *() const noexcept{
assert(exception());
return m_msg;
}
@@ -91,6 +119,27 @@ struct checked_result {
checked_result & operator=(const checked_result &) = delete;
};
+#if 0
+template<typename R>
+constexpr checked_result<R> make_checked_result(
+ const safe_numerics_error & e,
+ char const * const & m
+) noexcept {
+ return checked_result<R>(e, m);
+}
+#endif
+
+template <class R>
+class make_checked_result {
+public:
+ template<safe_numerics_error E>
+ constexpr static checked_result<R> invoke(
+ char const * const & m
+ ) noexcept {
+ return checked_result<R>(E, m);
+ }
+};
+
} // safe_numerics
} // boost
diff --git a/boost/safe_numerics/checked_result_operations.hpp b/boost/safe_numerics/checked_result_operations.hpp
index c1af3167e5..0492cab432 100644
--- a/boost/safe_numerics/checked_result_operations.hpp
+++ b/boost/safe_numerics/checked_result_operations.hpp
@@ -1,11 +1,6 @@
- #ifndef BOOST_NUMERIC_CHECKED_RESULT_OPERATIONS
+#ifndef BOOST_NUMERIC_CHECKED_RESULT_OPERATIONS
#define BOOST_NUMERIC_CHECKED_RESULT_OPERATIONS
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -13,12 +8,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
// Implemenation of arithmetic on "extended" integers.
-// extended integers are
+// Extended integers are defined in terms of C++ primitive integers as
// a) an interger range
// b) extra elements +inf, -inf, indeterminate
//
-// arithmetic operations are closed on the set of extended integers
-// but operations are not associative when they result in the
+// Integer operations are closed on the set of extended integers
+// but operations are not necessarily associative when they result in the
// extensions +inf, -inf, and indeterminate
//
// in this code, the type "checked_result<T>" where T is some
@@ -38,6 +33,34 @@
namespace boost {
namespace safe_numerics {
+template<typename T>
+constexpr void display(const boost::safe_numerics::checked_result<T> & c){
+ switch(c.m_e){
+ case safe_numerics_error::success:
+ std::terminate();
+ case safe_numerics_error::positive_overflow_error: // result is above representational maximum
+ std::terminate();
+ case safe_numerics_error::negative_overflow_error: // result is below representational minimum
+ std::terminate();
+ case safe_numerics_error::domain_error: // one operand is out of valid range
+ std::terminate();
+ case safe_numerics_error::range_error: // result cannot be produced for this operation
+ std::terminate();
+ case safe_numerics_error::precision_overflow_error: // result lost precision
+ std::terminate();
+ case safe_numerics_error::underflow_error: // result is too small to be represented
+ std::terminate();
+ case safe_numerics_error::negative_value_shift: // negative value in shift operator
+ std::terminate();
+ case safe_numerics_error::negative_shift: // shift a negative value
+ std::terminate();
+ case safe_numerics_error::shift_too_large: // l/r shift exceeds variable size
+ std::terminate();
+ case safe_numerics_error::uninitialized_value: // creating of uninitialized value
+ std::terminate();
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// implement C++ operators for check_result<T>
@@ -85,13 +108,13 @@ constexpr inline operator+(
const checked_result<T> & u
){
using value_type = sum_value_type;
- constexpr const std::uint8_t order = static_cast<std::uint8_t>(value_type::count);
+ const std::uint8_t order = static_cast<std::uint8_t>(value_type::count);
// note major pain. Clang constexpr multi-dimensional array is fine.
// but gcc doesn't permit a multi-dimensional array to be be constexpr.
// so we need to some ugly gymnastics to make our system work for all
// all systems.
- constexpr const enum safe_numerics_error result[order * order] = {
+ const enum safe_numerics_error result[order * order] = {
// t == known_value
//{
// u == ...
@@ -135,6 +158,18 @@ constexpr inline operator+(
return checked_result<T>(e, "addition result");
}
+// unary +
+template<class T>
+typename std::enable_if<
+ std::is_integral<T>::value,
+ checked_result<T>
+>::type
+constexpr inline operator+(
+ const checked_result<T> & t
+){
+ return t;
+}
+
// integers subtraction
template<class T>
typename std::enable_if<
@@ -192,6 +227,19 @@ constexpr inline operator-(
return checked_result<T>(e, "subtraction result");
}
+// unary -
+template<class T>
+typename std::enable_if<
+ std::is_integral<T>::value,
+ checked_result<T>
+>::type
+constexpr inline operator-(
+ const checked_result<T> & t
+){
+// assert(false);
+ return checked_result<T>(0) - t;
+}
+
struct product_value_type {
// characterization of various values
const enum flag {
@@ -201,8 +249,12 @@ struct product_value_type {
greater_than_zero,
greater_than_max,
indeterminate,
+ // count of number of cases for values
count,
- t_value
+ // temporary values for special cases
+ t_value,
+ u_value,
+ z_value
} m_flag;
template<class T>
constexpr flag to_flag(const checked_result<T> & t) const {
@@ -440,20 +492,20 @@ constexpr inline operator%(
//{
// u == ...
value_type::indeterminate, // less_than_min,
- value_type::indeterminate, // less_than_zero,
+ value_type::z_value, // less_than_zero,
value_type::indeterminate, // zero,
- value_type::indeterminate, // greater_than_zero,
+ value_type::z_value, // greater_than_zero,
value_type::indeterminate, // greater than max,
value_type::indeterminate, // indeterminate,
//},
// t == less_than_zero,
//{
// u == ...
- value_type::t_value, // less_than_min,
+ value_type::t_value, // less_than_min,
value_type::greater_than_zero, // less_than_zero,
value_type::indeterminate, // zero,
value_type::less_than_zero, // greater_than_zero,
- value_type::t_value, // greater than max,
+ value_type::t_value, // greater than max,
value_type::indeterminate, // indeterminate,
//},
// t == zero,
@@ -479,9 +531,9 @@ constexpr inline operator%(
// t == greater_than_max
//{
value_type::indeterminate, // less_than_min,
- value_type::indeterminate, // less_than_zero,
+ value_type::u_value, // less_than_zero,
value_type::indeterminate, // zero,
- value_type::indeterminate, // greater_than_zero,
+ value_type::u_value, // greater_than_zero,
value_type::indeterminate, // greater than max,
value_type::indeterminate, // indeterminate,
//},
@@ -509,6 +561,10 @@ constexpr inline operator%(
return safe_numerics_error::range_error;
case value_type::t_value:
return t;
+ case value_type::u_value:
+ return checked::subtract<T>(u, 1);
+ case value_type::z_value:
+ return checked::subtract<T>(1, u);
case value_type::greater_than_max:
case value_type::less_than_min:
default:
@@ -536,9 +592,8 @@ constexpr boost::logic::tribool operator<(
//
// b) return false because the two values are "equal"
//
- // for our purposes, b) is the better interpretation as it better
- // models our view that the < operation referes to the place holders
- // rather than some underlying value.
+ // for our purposes, a) seems the better interpretation.
+
enum class result_type : std::uint8_t {
runtime,
false_value,
@@ -558,7 +613,7 @@ constexpr boost::logic::tribool operator<(
//{
// u == ...
result_type::true_value, // known_value,
- result_type::false_value, // less_than_min, see above argument
+ result_type::indeterminate, // less_than_min, see above argument
result_type::true_value, // greater_than_max,
result_type::indeterminate, // indeterminate,
//},
@@ -567,7 +622,7 @@ constexpr boost::logic::tribool operator<(
// u == ...
result_type::false_value, // known_value,
result_type::false_value, // less_than_min,
- result_type::false_value, // greater_than_max, see above argument
+ result_type::indeterminate, // greater_than_max, see above argument
result_type::indeterminate, // indeterminate,
//},
// t == indeterminate
@@ -719,18 +774,6 @@ typename std::enable_if<
std::is_integral<T>::value,
checked_result<T>
>::type
-constexpr inline operator-(
- const checked_result<T> & t
-){
-// assert(false);
- return checked_result<T>(0) - t;
-}
-
-template<class T>
-typename std::enable_if<
- std::is_integral<T>::value,
- checked_result<T>
->::type
constexpr inline operator~(
const checked_result<T> & t
){
@@ -750,7 +793,7 @@ constexpr inline operator<<(
using value_type = product_value_type;
const std::uint8_t order = static_cast<std::uint8_t>(value_type::count);
- const std::uint8_t result[order * order] = {
+ constexpr const std::uint8_t result[order * order] = {
// t == less_than_min
//{
// u == ...
diff --git a/boost/safe_numerics/concept/exception_policy.hpp b/boost/safe_numerics/concept/exception_policy.hpp
index f0b98fcea9..134ed25807 100644
--- a/boost/safe_numerics/concept/exception_policy.hpp
+++ b/boost/safe_numerics/concept/exception_policy.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CONCEPT_EXCEPTION_POLICY_HPP
#define BOOST_NUMERIC_CONCEPT_EXCEPTION_POLICY_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/concept/integer.hpp b/boost/safe_numerics/concept/integer.hpp
index 80defa4575..79d0791c7f 100644
--- a/boost/safe_numerics/concept/integer.hpp
+++ b/boost/safe_numerics/concept/integer.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CONCEPT_INTEGER_HPP
#define BOOST_NUMERIC_CONCEPT_INTEGER_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/concept/numeric.hpp b/boost/safe_numerics/concept/numeric.hpp
index 0885a5511f..d7f0f34709 100644
--- a/boost/safe_numerics/concept/numeric.hpp
+++ b/boost/safe_numerics/concept/numeric.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CONCEPT_NUMERIC_HPP
#define BOOST_NUMERIC_CONCEPT_NUMERIC_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/concept/promotion_policy.hpp b/boost/safe_numerics/concept/promotion_policy.hpp
index b71ed91192..14bbb3cb89 100644
--- a/boost/safe_numerics/concept/promotion_policy.hpp
+++ b/boost/safe_numerics/concept/promotion_policy.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CONCEPT_PROMOTION_POLICY_HPP
#define BOOST_NUMERIC_CONCEPT_PROMOTION_POLICY_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/concept/safe_numeric.hpp b/boost/safe_numerics/concept/safe_numeric.hpp
index 00481a02c6..0b6ac12803 100644
--- a/boost/safe_numerics/concept/safe_numeric.hpp
+++ b/boost/safe_numerics/concept/safe_numeric.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CONCEPT_SAFE_NUMERIC_HPP
#define BOOST_NUMERIC_CONCEPT_SAFE_NUMERIC_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/cpp.hpp b/boost/safe_numerics/cpp.hpp
index 9d42c2f981..456fae58b8 100755
--- a/boost/safe_numerics/cpp.hpp
+++ b/boost/safe_numerics/cpp.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_CPP_HPP
#define BOOST_NUMERIC_CPP_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/exception.hpp b/boost/safe_numerics/exception.hpp
index b67f74fb97..284b801d09 100644
--- a/boost/safe_numerics/exception.hpp
+++ b/boost/safe_numerics/exception.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_EXCEPTION
#define BOOST_NUMERIC_EXCEPTION
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -47,7 +42,7 @@ enum class safe_numerics_error : std::uint8_t {
negative_value_shift, // negative value in shift operator
negative_shift, // shift a negative value
shift_too_large, // l/r shift exceeds variable size
- uninitialized_value // l/r shift exceeds variable size
+ uninitialized_value // creating of uninitialized value
};
const std::uint8_t safe_numerics_casting_error_count =
@@ -63,7 +58,7 @@ namespace std {
template <>
struct is_error_code_enum<boost::safe_numerics::safe_numerics_error>
: public true_type {};
-};
+} // std
namespace boost {
namespace safe_numerics {
@@ -100,10 +95,10 @@ public:
}
return ""; // suppress bogus warning
}
-} safe_numerics_error_category ;
+} safe_numerics_error_category {};
// constexpr - damn, can't use constexpr due to std::error_code
-std::error_code make_error_code(safe_numerics_error e){
+std::error_code make_error_code(const safe_numerics_error & e){
return std::error_code(static_cast<int>(e), safe_numerics_error_category);
}
@@ -126,7 +121,7 @@ namespace std {
template <>
struct is_error_condition_enum<boost::safe_numerics::safe_numerics_actions>
: public true_type {};
-};
+} // std
namespace boost {
namespace safe_numerics {
@@ -172,14 +167,20 @@ public:
// suppress bogus warning
return false;
}
-} safe_numerics_actions_category ;
-
-std::error_condition make_error_condition(safe_numerics_error e) {
+} safe_numerics_actions_category {};
+
+// the following function is used to "finish" implementation of conversion
+// of safe_numerics_error to std::error_condition. At least for now, this
+// isn't being used and defining here it can lead duplicate symbol errors
+// depending on the compiler. So suppress it until further notice
+#if 0
+std::error_condition make_error_condition(const safe_numerics_error & e) {
return std::error_condition(
static_cast<int>(e),
safe_numerics_error_category
);
}
+#endif
} // safe_numerics
} // boost
diff --git a/boost/safe_numerics/exception_policies.hpp b/boost/safe_numerics/exception_policies.hpp
index efa4cbe055..8a106974e5 100644
--- a/boost/safe_numerics/exception_policies.hpp
+++ b/boost/safe_numerics/exception_policies.hpp
@@ -1,18 +1,13 @@
#ifndef BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
#define BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 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)
-#include <type_traits> // is_convertible
+#include <boost/mp11.hpp>
#include "exception.hpp"
@@ -57,7 +52,7 @@ struct exception_policy {
// ignore any error and just return.
struct ignore_exception {
- constexpr ignore_exception(const safe_numerics_error &, const char *){}
+ constexpr ignore_exception(const safe_numerics_error &, const char * ){}
};
// If an exceptional condition is detected at runtime throw the exception.
@@ -89,8 +84,8 @@ make_safe_numerics_action(const safe_numerics_error & e){
case safe_numerics_error::shift_too_large:
return safe_numerics_actions::implementation_defined_behavior;
-// case safe_numerics_error::uninitialized_value:
-// return safe_numerics_actions::uninitialized_value;
+ case safe_numerics_error::uninitialized_value:
+ return safe_numerics_actions::uninitialized_value;
case safe_numerics_error::success:
return safe_numerics_actions::no_action;
@@ -102,32 +97,69 @@ make_safe_numerics_action(const safe_numerics_error & e){
return safe_numerics_actions::no_action;
}
-template<class EP>
+////////////////////////////////////////////////////////////////////////////////
+// compile time error dispatcher
+
+// note slightly baroque implementation of a compile time switch statement
+// which instatiates oonly those cases which are actually invoked. This is
+// motivated to implement the "trap" functionality which will generate a syntax
+// error if and only a function which might fail is called.
+
+namespace dispatch_switch {
+
+ template<class EP, safe_numerics_actions>
+ struct dispatch_case {};
+
+ template<class EP>
+ struct dispatch_case<EP, safe_numerics_actions::uninitialized_value> {
+ constexpr static void invoke(const safe_numerics_error & e, const char * msg){
+ EP::on_uninitialized_value(e, msg);
+ }
+ };
+ template<class EP>
+ struct dispatch_case<EP, safe_numerics_actions::arithmetic_error> {
+ constexpr static void invoke(const safe_numerics_error & e, const char * msg){
+ EP::on_arithmetic_error(e, msg);
+ }
+ };
+ template<class EP>
+ struct dispatch_case<EP, safe_numerics_actions::implementation_defined_behavior> {
+ constexpr static void invoke(const safe_numerics_error & e, const char * msg){
+ EP::on_implementation_defined_behavior(e, msg);
+ }
+ };
+ template<class EP>
+ struct dispatch_case<EP, safe_numerics_actions::undefined_behavior> {
+ constexpr static void invoke(const safe_numerics_error & e, const char * msg){
+ EP::on_undefined_behavior(e, msg);
+ }
+ };
+
+} // dispatch_switch
+
+template<class EP, safe_numerics_error E>
constexpr void
-dispatch(const safe_numerics_error & e, char const * const & msg){
- const safe_numerics_actions a = make_safe_numerics_action(e);
- switch(a){
- case safe_numerics_actions::uninitialized_value:
- EP::on_uninitialized_value(e, msg);
- break;
- case safe_numerics_actions::arithmetic_error:
- EP::on_arithmetic_error(e, msg);
- break;
- case safe_numerics_actions::implementation_defined_behavior:
- EP::on_implementation_defined_behavior(e, msg);
- break;
- case safe_numerics_actions::undefined_behavior:
- EP::on_undefined_behavior(e, msg);
- break;
- default:
- assert(false);
- }
+dispatch(const char * msg){
+ constexpr safe_numerics_actions a = make_safe_numerics_action(E);
+ dispatch_switch::dispatch_case<EP, a>::invoke(E, msg);
}
+template<class EP, class R>
+class dispatch_and_return {
+public:
+ template<safe_numerics_error E>
+ constexpr static checked_result<R> invoke(
+ char const * const & msg
+ ) {
+ dispatch<EP, E>(msg);
+ return checked_result<R>(E, msg);
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
// pre-made error policy classes
-// loose policy
+// loose exception
// - throw on arithmetic errors
// - ignore other errors.
// Some applications ignore these issues and still work and we don't
@@ -136,7 +168,7 @@ using loose_exception_policy = exception_policy<
throw_exception, // arithmetic error
ignore_exception, // implementation defined behavior
ignore_exception, // undefined behavior
- ignore_exception // uninitialized value
+ ignore_exception // uninitialized value
>;
// loose trap
@@ -146,20 +178,12 @@ using loose_exception_policy = exception_policy<
// bit manipulation operations to work.
using loose_trap_policy = exception_policy<
trap_exception, // arithmetic error
- ignore_exception, // implementation defined behavior
- ignore_exception, // undefined behavior
- ignore_exception // uninitialized value
+ ignore_exception, // implementation defined behavior
+ ignore_exception, // undefined behavior
+ ignore_exception // uninitialized value
>;
-#if 0
-template<>
-constexpr void
-dispatch<loose_trap_policy>(const safe_numerics_error &, char const * const &){// strict exception policy
- static_assert(false, "trap");
-}
-#endif
-
-// - permit just about anything
+// strict exception
// - throw at runtime on any kind of error
// recommended for new code. Check everything at compile time
// if possible and runtime if necessary. Trap or Throw as
@@ -169,7 +193,7 @@ using strict_exception_policy = exception_policy<
throw_exception,
throw_exception,
throw_exception,
- throw_exception
+ ignore_exception
>;
// strict trap
diff --git a/boost/safe_numerics/interval.hpp b/boost/safe_numerics/interval.hpp
index 9292d7f4ac..2d85aee689 100644
--- a/boost/safe_numerics/interval.hpp
+++ b/boost/safe_numerics/interval.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_INTERVAL_HPP
#define BOOST_NUMERIC_INTERVAL_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/native.hpp b/boost/safe_numerics/native.hpp
index f948badd1a..78d34fd1ad 100644
--- a/boost/safe_numerics/native.hpp
+++ b/boost/safe_numerics/native.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_NATIVE_HPP
#define BOOST_NUMERIC_NATIVE_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/range_value.hpp b/boost/safe_numerics/range_value.hpp
index a441809d13..ceef19e898 100644
--- a/boost/safe_numerics/range_value.hpp
+++ b/boost/safe_numerics/range_value.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_RANGE_VALUE_HPP
#define BOOST_RANGE_VALUE_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -44,9 +39,9 @@ std::basic_ostream<CharT, Traits> & operator<<(
const range_value<T> & t
){
return os
- << boost::safe_numerics::make_interval(t.m_t)
+ << boost::safe_numerics::make_interval<T>()
<< t.m_t;
-};
+}
template<typename T>
struct result_display {
diff --git a/boost/safe_numerics/safe_base.hpp b/boost/safe_numerics/safe_base.hpp
index 7d56b8421f..55508d0d5e 100644
--- a/boost/safe_numerics/safe_base.hpp
+++ b/boost/safe_numerics/safe_base.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_BASE_HPP
#define BOOST_NUMERIC_SAFE_BASE_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -14,10 +9,7 @@
#include <limits>
#include <type_traits> // is_integral, enable_if, conditional
-
-#include <boost/mpl/eval_if.hpp>
-#include <boost/mpl/identity.hpp>
-
+#include <boost/config.hpp> // BOOST_CLANG
#include "concept/exception_policy.hpp"
#include "concept/promotion_policy.hpp"
@@ -106,6 +98,12 @@ template<
>
class safe_literal_impl;
+// works for both GCC and clang
+#if BOOST_CLANG==1
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmismatched-tags"
+#endif
+
/////////////////////////////////////////////////////////////////
// Main implementation
@@ -183,37 +181,9 @@ public:
struct skip_validation{};
- constexpr explicit safe_base(const Stored & rhs, skip_validation) :
- m_t(rhs)
- {}
-
- // default constructor
- /*
- constexpr explicit safe_base() {
- // this permits creating of invalid instances. This is inline
- // with C++ built-in but violates the premises of the whole library
- // choice are:
- // do nothing - violates premise of he library that all safe objects
- // are valid
- // initialize to valid value - violates C++ behavior of types.
- // add "initialized" flag. Preserves fixes the above, but doubles
- // "overhead"
- // still pending on this.
- }
- */
- constexpr safe_base() = default;
+ constexpr explicit safe_base(const Stored & rhs, skip_validation);
- // note: Rule of Five. Supply all or none of the following
- // a) user-defined destructor
- ~safe_base() = default;
- // b) copy-constructor
- constexpr safe_base(const safe_base &) = default;
- // c) copy-assignment
- constexpr safe_base & operator=(const safe_base &) = default;
- // d) move constructor
- constexpr safe_base(safe_base &&) = default;
- // e) move assignment operator
- constexpr safe_base & operator=(safe_base &&) = default;
+ constexpr safe_base();
// construct an instance of a safe type
// from an instance of a convertible underlying type.
@@ -225,9 +195,7 @@ public:
is_safe<T>::value,
bool
>::type = true
- ) :
- m_t(validated_cast(t))
- {}
+ );
template<class T>
constexpr /*explicit*/ safe_base(
@@ -236,9 +204,24 @@ public:
std::is_integral<T>::value,
bool
>::type = true
- ) :
- m_t(validated_cast(t))
- {}
+ );
+
+ template<class T, T value>
+ constexpr /*explicit*/ safe_base(
+ const std::integral_constant<T, value> &
+ );
+
+ // note: Rule of Five. Supply all or none of the following
+ // a) user-defined destructor
+ ~safe_base() = default;
+ // b) copy-constructor
+ constexpr safe_base(const safe_base &) = default;
+ // c) copy-assignment
+ constexpr safe_base & operator=(const safe_base &) = default;
+ // d) move constructor
+ constexpr safe_base(safe_base &&) = default;
+ // e) move assignment operator
+ constexpr safe_base & operator=(safe_base &&) = default;
/////////////////////////////////////////////////////////////////
// casting operators for intrinsic integers
@@ -359,4 +342,8 @@ public:
} // std
+#if BOOST_CLANG==1
+#pragma GCC diagnostic pop
+#endif
+
#endif // BOOST_NUMERIC_SAFE_BASE_HPP
diff --git a/boost/safe_numerics/safe_base_operations.hpp b/boost/safe_numerics/safe_base_operations.hpp
index ea69c95f76..982358208a 100644
--- a/boost/safe_numerics/safe_base_operations.hpp
+++ b/boost/safe_numerics/safe_base_operations.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_BASE_OPERATIONS_HPP
#define BOOST_NUMERIC_SAFE_BASE_OPERATIONS_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -18,7 +13,6 @@
#include <cassert>
#include <boost/config.hpp>
-#include <boost/mpl/eval_if.hpp>
#include <boost/core/enable_if.hpp> // lazy_enable_if
#include <boost/integer.hpp>
@@ -35,17 +29,6 @@
namespace boost {
namespace safe_numerics {
-// invoke error handling
-template<class EP, typename R>
-constexpr void
-dispatch(const checked_result<R> & cr){
- // if the result contains an error condition
- if(cr.exception())
- // dispatch to the appropriate function
- dispatch<EP>(cr.m_e, cr.m_msg);
- // otherwise just do a simple return
-}
-
/////////////////////////////////////////////////////////////////
// validation
@@ -58,11 +41,15 @@ struct validate_detail {
const T & t
){
// INT08-C
- const r_type r = checked::cast<R>(t);
- if(r.exception()){
- dispatch<E>(r);
- }
- return base_value(r);
+ const r_type rx = heterogeneous_checked_operation<
+ R,
+ typename base_type<T>::type,
+ dispatch_and_return<E, R>
+ >::cast(t);
+ const R r = rx.exception()
+ ? static_cast<R>(t)
+ : rx.m_r;
+ return r;
}
};
struct exception_not_possible {
@@ -116,6 +103,59 @@ validated_cast(const safe_literal_impl<T, N, P1, E1> &) const {
}
/////////////////////////////////////////////////////////////////
+// constructors
+
+template<class Stored, Stored Min, Stored Max, class P, class E>
+ constexpr /*explicit*/ safe_base<Stored, Min, Max, P, E>::safe_base(
+ const Stored & rhs,
+ skip_validation
+) :
+ m_t(rhs)
+{}
+
+template<class Stored, Stored Min, Stored Max, class P, class E>
+constexpr /*explicit*/ safe_base<Stored, Min, Max, P, E>::safe_base(){
+ dispatch<E, safe_numerics_error::uninitialized_value>(
+ "safe values must be initialized"
+ );
+}
+
+// construct an instance of a safe type
+// from an instance of a convertible underlying type.
+template<class Stored, Stored Min, Stored Max, class P, class E>
+template<class T>
+constexpr /*explicit*/ safe_base<Stored, Min, Max, P, E>::safe_base(
+ const T & t,
+ typename std::enable_if<
+ is_safe<T>::value,
+ bool
+ >::type
+) :
+ m_t(validated_cast(t))
+{}
+
+template<class Stored, Stored Min, Stored Max, class P, class E>
+template<class T>
+constexpr /*explicit*/ safe_base<Stored, Min, Max, P, E>::safe_base(
+ const T & t,
+ typename std::enable_if<
+ std::is_integral<T>::value,
+ bool
+ >::type
+) :
+ m_t(validated_cast(t))
+{}
+
+template<class Stored, Stored Min, Stored Max, class P, class E>
+template<class T, T value>
+constexpr /*explicit*/ safe_base<Stored, Min, Max, P, E>::safe_base(
+
+ const std::integral_constant<T, value> &
+) :
+ m_t(validated_cast(value))
+{}
+
+/////////////////////////////////////////////////////////////////
// casting operators
// cast to a builtin type from a safe type
@@ -242,6 +282,33 @@ struct common_promotion_policy {
// all other safe types including float and user defined ones.
//
+// helper - cast arguments to binary operators to a specified
+// result type
+
+template<class EP, class R, class T, class U>
+std::pair<R, R>
+constexpr static casting_helper(const T & t, const U & u){
+ using r_type = checked_result<R>;
+ const r_type tx = heterogeneous_checked_operation<
+ R,
+ typename base_type<T>::type,
+ dispatch_and_return<EP, R>
+ >::cast(base_value(t));
+ const R tr = tx.exception()
+ ? static_cast<R>(t)
+ : tx.m_r;
+
+ const r_type ux = heterogeneous_checked_operation<
+ R,
+ typename base_type<U>::type,
+ dispatch_and_return<EP, R>
+ >::cast(base_value(u));
+ const R ur = ux.exception()
+ ? static_cast<R>(u)
+ : ux.m_r;
+ return std::pair<R, R>(tr, ur);
+}
+
// Note: the following global operators will be found via
// argument dependent lookup.
@@ -266,32 +333,29 @@ private:
// if exception possible
using exception_policy = typename common_exception_policy<T, U>::type;
+ using r_type = checked_result<result_base_type>;
+
constexpr static result_base_type
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- // the following will use checked arithmetic
- const r_type r = (tx + ux);
- if(!r.exception()){
- return static_cast<result_base_type>(r);
- }
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ const r_type rx = checked_operation<
+ result_base_type,
+ dispatch_and_return<exception_policy, result_base_type>
+ >::add(r.first, r.second);
+
return
- static_cast<result_base_type>(tx)
- + static_cast<result_base_type>(ux);
+ rx.exception()
+ ? r.first + r.second
+ : rx.m_r;
}
- using r_type = checked_result<result_base_type>;
using r_type_interval_t = interval<r_type>;
- constexpr static r_type_interval_t get_r_type_interval(){
+ constexpr static const r_type_interval_t get_r_type_interval(){
constexpr const r_type_interval_t t_interval{
checked::cast<result_base_type>(base_value(std::numeric_limits<T>::min())),
checked::cast<result_base_type>(base_value(std::numeric_limits<T>::max()))
@@ -302,11 +366,9 @@ private:
};
return t_interval + u_interval;
}
+ constexpr static const r_type_interval_t r_type_interval = get_r_type_interval();
- static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
-
- using return_interval_t = interval<result_base_type>;
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -325,12 +387,15 @@ private:
return false;
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -391,27 +456,24 @@ private:
constexpr static result_base_type
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- // the following will use checked arithmetic
- r_type r = (tx - ux);
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ const r_type rx = checked_operation<
+ result_base_type,
+ dispatch_and_return<exception_policy, result_base_type>
+ >::subtract(r.first, r.second);
+
return
- static_cast<result_base_type>(tx)
- - static_cast<result_base_type>(ux);
+ rx.exception()
+ ? r.first + r.second
+ : rx.m_r;
}
using r_type_interval_t = interval<r_type>;
- constexpr static r_type_interval_t get_r_type_interval(){
+ constexpr static const r_type_interval_t get_r_type_interval(){
constexpr const r_type_interval_t t_interval{
checked::cast<result_base_type>(base_value(std::numeric_limits<T>::min())),
checked::cast<result_base_type>(base_value(std::numeric_limits<T>::max()))
@@ -424,11 +486,9 @@ private:
return t_interval - u_interval;
}
-
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -448,11 +508,14 @@ private:
}
public:
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -513,23 +576,22 @@ private:
constexpr static result_base_type
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- r_type r = (tx * ux);
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ const r_type rx = checked_operation<
+ result_base_type,
+ dispatch_and_return<exception_policy, result_base_type>
+ >::multiply(r.first, r.second);
+
return
- static_cast<result_base_type>(tx)
- * static_cast<result_base_type>(ux);
+ rx.exception()
+ ? r.first * r.second
+ : rx.m_r;
}
+
using r_type_interval_t = interval<r_type>;
constexpr static r_type_interval_t get_r_type_interval(){
@@ -548,8 +610,7 @@ private:
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -568,12 +629,15 @@ private:
return false;
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -652,23 +716,20 @@ private:
>::type;
using t_type = checked_result<temp_base>;
- const t_type tx = checked::cast<temp_base>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const t_type ux = checked::cast<temp_base>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- const t_type r = (tx / ux);
-
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
+ const std::pair<t_type, t_type> r = casting_helper<
+ exception_policy,
+ temp_base
+ >(t, u);
+
+ const t_type rx = checked_operation<
+ temp_base,
+ dispatch_and_return<exception_policy, temp_base>
+ >::divide(r.first, r.second);
+
return
- static_cast<result_base_type>(tx)
- / static_cast<result_base_type>(ux);
+ rx.exception()
+ ? r.first / r.second
+ : rx;
}
using r_type_interval_t = interval<r_type>;
@@ -708,9 +769,7 @@ private:
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
-
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -722,19 +781,21 @@ private:
constexpr static bool exception_possible(){
constexpr const r_type_interval_t ri = get_r_type_interval();
constexpr const r_type_interval_t ui = u_interval();
-
return
static_cast<bool>(ui.includes(r_type(0)))
|| ri.l.exception()
|| ri.u.exception();
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -810,23 +871,20 @@ private:
>::type;
using t_type = checked_result<temp_base>;
- const t_type tx = checked::cast<temp_base>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const t_type ux = checked::cast<temp_base>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- t_type r = (tx % ux);
-
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
+ const std::pair<t_type, t_type> r = casting_helper<
+ exception_policy,
+ temp_base
+ >(t, u);
+
+ const t_type rx = checked_operation<
+ temp_base,
+ dispatch_and_return<exception_policy, temp_base>
+ >::modulus(r.first, r.second);
+
return
- static_cast<result_base_type>(tx)
- % static_cast<result_base_type>(ux);
+ rx.exception()
+ ? r.first % r.second
+ : rx;
}
using r_type_interval_t = interval<r_type>;
@@ -868,8 +926,7 @@ private:
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -881,19 +938,21 @@ private:
constexpr static bool exception_possible(){
constexpr const r_type_interval_t ri = get_r_type_interval();
constexpr const r_type_interval_t ui = u_interval();
-
return
static_cast<bool>(ui.includes(r_type(0)))
|| ri.l.exception()
|| ri.u.exception();
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -958,19 +1017,12 @@ private:
// if exception possible
constexpr static bool
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- const boost::logic::tribool r = (tx < ux);
- if(r || !r) // answer is not indeterminate
- return static_cast<bool>(r);
- dispatch<exception_policy>(
- checked_result<bool>(safe_numerics_error::domain_error)
- );
- return safe_compare::less_than(base_value(t), base_value(u));
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ return safe_compare::less_than(r.first, r.second);
}
using r_type_interval_t = interval<r_type>;
@@ -1068,19 +1120,12 @@ private:
// exception possible
constexpr static bool
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- const boost::logic::tribool r = (tx == ux);
- if(! boost::logic::indeterminate(r))
- return static_cast<bool>(r);
- dispatch<exception_policy>(
- checked_result<bool>(safe_numerics_error::domain_error)
- );
- return safe_compare::equal(base_value(t), base_value(u));
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ return safe_compare::equal(r.first, r.second);
}
using r_type_interval = interval<r_type>;
@@ -1160,20 +1205,20 @@ private:
constexpr static result_base_type
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- const r_type r = checked::left_shift(tx.m_r, ux.m_r);
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
- return t << u;
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ const r_type rx = checked_operation<
+ result_base_type,
+ dispatch_and_return<exception_policy, result_base_type>
+ >::left_shift(r.first, r.second);
+
+ return
+ rx.exception()
+ ? r.first << r.second
+ : rx.m_r;
}
using r_type_interval_t = interval<r_type>;
@@ -1193,8 +1238,7 @@ private:
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -1213,12 +1257,15 @@ private:
return false;
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -1287,20 +1334,20 @@ struct right_shift_result {
constexpr static result_base_type
return_value(const T & t, const U & u, std::true_type){
- const r_type tx = checked::cast<result_base_type>(base_value(t));
- if(tx.exception())
- dispatch<exception_policy>(tx);
- const r_type ux = checked::cast<result_base_type>(base_value(u));
- if(ux.exception())
- dispatch<exception_policy>(ux);
- const r_type r = checked::right_shift(tx.m_r, ux.m_r);
- if(!r.exception())
- return static_cast<result_base_type>(r);
- // handle error condition
- dispatch<exception_policy>(r);
- // if we get here, the error has been ignored
- // just get the result the old fashioned way
- return t >> u;
+ const std::pair<result_base_type, result_base_type> r = casting_helper<
+ exception_policy,
+ result_base_type
+ >(t, u);
+
+ const r_type rx = checked_operation<
+ result_base_type,
+ dispatch_and_return<exception_policy, result_base_type>
+ >::right_shift(r.first, r.second);
+
+ return
+ rx.exception()
+ ? r.first >> r.second
+ : rx.m_r;
}
using r_type_interval_t = interval<r_type>;
@@ -1324,9 +1371,7 @@ struct right_shift_result {
static constexpr const r_type_interval_t r_type_interval = get_r_type_interval();
- using return_interval_t = interval<result_base_type>;
-
- constexpr static return_interval_t return_interval{
+ constexpr static const interval<result_base_type> return_interval{
r_type_interval.l.exception()
? std::numeric_limits<result_base_type>::min()
: static_cast<result_base_type>(r_type_interval.l),
@@ -1351,12 +1396,15 @@ struct right_shift_result {
);
}
+ constexpr static auto rl = return_interval.l;
+ constexpr static auto ru = return_interval.u;
+
public:
using type =
safe_base<
result_base_type,
- return_interval.l,
- return_interval.u,
+ rl,
+ ru,
promotion_policy,
exception_policy
>;
@@ -1418,6 +1466,8 @@ private:
using r_type = typename std::make_unsigned<result_base_type>::type;
using r_type_interval_t = interval<r_type>;
+ #if 0
+ // breaks compilation for earlier versions of clant
constexpr static const r_type_interval_t r_interval{
r_type(0),
utility::round_out(
@@ -1427,6 +1477,7 @@ private:
)
)
};
+ #endif
using exception_policy = typename common_exception_policy<T, U>::type;
@@ -1434,8 +1485,15 @@ public:
// lazy_enable_if_c depends on this
using type = safe_base<
result_base_type,
- r_interval.l,
- r_interval.u,
+ //r_interval.l,
+ r_type(0),
+ //r_interval.u,
+ utility::round_out(
+ std::max(
+ static_cast<r_type>(base_value(std::numeric_limits<T>::max())),
+ static_cast<r_type>(base_value(std::numeric_limits<U>::max()))
+ )
+ ),
promotion_policy,
exception_policy
>;
@@ -1483,6 +1541,8 @@ private:
using r_type = typename std::make_unsigned<result_base_type>::type;
using r_type_interval_t = interval<r_type>;
+ #if 0
+ // breaks compilation for earlier versions of clant
constexpr static const r_type_interval_t r_interval{
r_type(0),
utility::round_out(
@@ -1492,15 +1552,22 @@ private:
)
)
};
-
+ #endif
using exception_policy = typename common_exception_policy<T, U>::type;
public:
// lazy_enable_if_c depends on this
using type = safe_base<
result_base_type,
- r_interval.l,
- r_interval.u,
+ //r_interval.l,
+ r_type(0),
+ //r_interval.u,
+ utility::round_out(
+ std::min(
+ static_cast<r_type>(base_value(std::numeric_limits<T>::max())),
+ static_cast<r_type>(base_value(std::numeric_limits<U>::max()))
+ )
+ ),
promotion_policy,
exception_policy
>;
@@ -1547,6 +1614,8 @@ struct bitwise_xor_result {
using r_type = typename std::make_unsigned<result_base_type>::type;
using r_type_interval_t = interval<r_type>;
+ #if 0
+ // breaks compilation for earlier versions of clant
constexpr static const r_type_interval_t r_interval{
r_type(0),
utility::round_out(
@@ -1556,6 +1625,7 @@ struct bitwise_xor_result {
)
)
};
+ #endif
using exception_policy = typename common_exception_policy<T, U>::type;
@@ -1563,8 +1633,15 @@ public:
// lazy_enable_if_c depends on this
using type = safe_base<
result_base_type,
- r_interval.l,
- r_interval.u,
+ //r_interval.l,
+ r_type(0),
+ //r_interval.u,
+ utility::round_out(
+ std::max(
+ static_cast<r_type>(base_value(std::numeric_limits<T>::max())),
+ static_cast<r_type>(base_value(std::numeric_limits<U>::max()))
+ )
+ ),
promotion_policy,
exception_policy
>;
@@ -1652,8 +1729,10 @@ void safe_base<T, Min, Max, P, E>::input(
validated_cast(m_t);
}
if(is.fail()){
- boost::safe_numerics::dispatch<E>(
- boost::safe_numerics::safe_numerics_error::domain_error,
+ boost::safe_numerics::dispatch<
+ E,
+ boost::safe_numerics::safe_numerics_error::domain_error
+ >(
"error in file input"
);
}
diff --git a/boost/safe_numerics/safe_common.hpp b/boost/safe_numerics/safe_common.hpp
index 3e53e36e16..71a00ade7a 100644
--- a/boost/safe_numerics/safe_common.hpp
+++ b/boost/safe_numerics/safe_common.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_COMMON_HPP
#define BOOST_NUMERIC_SAFE_COMMON_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/safe_compare.hpp b/boost/safe_numerics/safe_compare.hpp
index 0c53c82245..2b52c2dfe5 100644
--- a/boost/safe_numerics/safe_compare.hpp
+++ b/boost/safe_numerics/safe_compare.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP
#define BOOST_NUMERIC_SAFE_COMPARE_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/safe_integer.hpp b/boost/safe_numerics/safe_integer.hpp
index 0daa84d154..56281f36cf 100644
--- a/boost/safe_numerics/safe_integer.hpp
+++ b/boost/safe_numerics/safe_integer.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_INTEGER_HPP
#define BOOST_NUMERIC_SAFE_INTEGER_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/safe_integer_literal.hpp b/boost/safe_numerics/safe_integer_literal.hpp
index 2e6c1099e4..8def6d1ee6 100644
--- a/boost/safe_numerics/safe_integer_literal.hpp
+++ b/boost/safe_numerics/safe_integer_literal.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
#define BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/safe_integer_range.hpp b/boost/safe_numerics/safe_integer_range.hpp
index 7c059cbfbc..e9fce8447c 100644
--- a/boost/safe_numerics/safe_integer_range.hpp
+++ b/boost/safe_numerics/safe_integer_range.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_SAFE_INTEGER_RANGE_HPP
#define BOOST_NUMERIC_SAFE_INTEGER_RANGE_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2012 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/safe_numerics/utility.hpp b/boost/safe_numerics/utility.hpp
index 02dfdf99c2..79a439acc9 100644
--- a/boost/safe_numerics/utility.hpp
+++ b/boost/safe_numerics/utility.hpp
@@ -1,11 +1,6 @@
#ifndef BOOST_NUMERIC_UTILITY_HPP
#define BOOST_NUMERIC_UTILITY_HPP
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
@@ -103,7 +98,7 @@ namespace ilog2_detail {
constexpr static unsigned int ilog2(const boost::uint_t<8>::exact & t){
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
const char LogTable256[256] = {
- -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ static_cast<const char>(-1), 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
@@ -128,7 +123,7 @@ namespace ilog2_detail {
: 32 + ilog2(upper_half);
}
-}; // ilog2_detail
+} // ilog2_detail
template<typename T>
constexpr unsigned int ilog2(const T & t){
@@ -241,13 +236,13 @@ constexpr T round_out(const T & t){
if(t >= 0){
const std::uint8_t sb = utility::significant_bits(t);
return (sb < sizeof(T) * 8)
- ? (1ul << sb) - 1
+ ? ((T)1 << sb) - 1
: std::numeric_limits<T>::max();
}
else{
const std::uint8_t sb = utility::significant_bits(~t);
return (sb < sizeof(T) * 8)
- ? ~((1ul << sb) - 1)
+ ? ~(((T)1 << sb) - 1)
: std::numeric_limits<T>::min();
}
}