summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/safe_numerics/test/test_interval.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/safe_numerics/test/test_interval.cpp')
-rw-r--r--src/boost/libs/safe_numerics/test/test_interval.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/boost/libs/safe_numerics/test/test_interval.cpp b/src/boost/libs/safe_numerics/test/test_interval.cpp
new file mode 100644
index 00000000..115f4abd
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_interval.cpp
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 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 <iostream>
+#include <limits>
+#include <functional>
+#include <array>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/interval.hpp>
+
+template<typename T>
+using fptr = T (*)(const T &, const T &);
+template<typename T>
+using fptr_interval = fptr<boost::safe_numerics::interval<T>>;
+
+template<typename T>
+struct op {
+ const fptr<T> m_f;
+ const fptr_interval<T> m_finterval;
+ const char * m_symbol;
+ const bool skip_zeros;
+};
+
+template<
+ typename T,
+ unsigned int N
+>
+bool test_type_operator(
+ const T (&value)[N],
+ const op<T> & opi
+){
+ using namespace boost::safe_numerics;
+
+ // for each pair of values p1, p2 (100)
+ for(const T & l1 : value)
+ for(const T & u1 : value){
+ if(l1 > u1) continue; // skip reverse range
+ const interval<T> p1(l1, u1);
+ for(const T & l2 : value)
+ for(const T & u2 : value){
+ if(l2 > u2) continue; // skip reverse range
+ const interval<T> p2(l2, u2);
+
+ // maybe skip intervals which include zero
+ if(opi.skip_zeros){
+ if(l2 == safe_numerics_error::range_error
+ || l2 == safe_numerics_error::domain_error
+ || u2 == safe_numerics_error::range_error
+ || u2 == safe_numerics_error::domain_error
+ || p2.includes(T(0))
+ )
+ continue;
+ }
+
+ // create a new interval from the operation
+ const interval<T> result_interval = opi.m_finterval(p1, p2);
+ std::cout
+ << p1 << opi.m_symbol << p2 << " -> " << result_interval << std::endl;
+
+ // if resulting interval is null
+ if(result_interval.u < result_interval.l)
+ continue;
+
+ // for each pair test values
+ for(const T r1 : value)
+ for(const T r2 : value){
+ // calculate result of operation
+ const T result = opi.m_f(r1, r2);
+ if(result != safe_numerics_error::range_error
+ && result != safe_numerics_error::domain_error ){
+ // note usage of tribool logic here !!!
+ // includes returns indeterminate the conditional
+ // returns false in both cases and this is what we want.
+ // This is very subtle, don't skim over this.
+ // if both r1 and r2 are within they're respective bounds
+ if(p1.includes(r1) && p2.includes(r2)
+ && ! result_interval.includes(result)){
+ #if 0
+ const boost::logic::tribool b1 = p1.includes(r1);
+ const boost::logic::tribool b2 = p2.includes(r2);
+ const boost::logic::tribool b3 = result_interval.includes(result);
+ const interval<T> result_intervalx = opi.m_finterval(p1, p2);
+ const T resultx = opi.m_f(r1, r2);
+ #endif
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// values
+// note: need to explicitly specify number of elements to avoid msvc failure
+template<typename T>
+const boost::safe_numerics::checked_result<T> value[8] = {
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+ std::numeric_limits<T>::lowest(),
+ T(-1),
+ T(0),
+ T(1),
+ std::numeric_limits<T>::max(),
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ boost::safe_numerics::safe_numerics_error::domain_error
+};
+
+// note: need to explicitly specify number of elements to avoid msvc failure
+template<typename T>
+const boost::safe_numerics::checked_result<T> unsigned_value[6] = {
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+ T(0),
+ T(1),
+ std::numeric_limits<T>::max(),
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ boost::safe_numerics::safe_numerics_error::domain_error
+};
+
+// invoke for each type
+struct test_type {
+ unsigned int m_error_count;
+ test_type() :
+ m_error_count(0)
+ {}
+ template<typename T>
+ bool operator()(const T &){
+ using namespace boost::safe_numerics;
+ std::cout
+ << "** testing "
+ << boost::core::demangle(typeid(T).name())
+ << std::endl;
+
+ using R = checked_result<T>;
+ // pointers to operands for types T
+ static const std::array<op<R>, 5> op_table{{
+ {operator+, operator+, "+", false},
+ {operator-, operator-, "-", false},
+ {operator*, operator*, "*", false},
+ {operator<<, operator<<, "<<", false},
+ {operator>>, operator>>, ">>", false},
+ }};
+
+ //for(unsigned int i = 0; i < sizeof(op_table)/sizeof(op) / sizeof(fptr<R>); ++i){
+ for(const op<R> & o : op_table){
+ if(std::is_signed<T>::value){
+ if(! test_type_operator(value<T>, o)){
+ ++m_error_count;
+ return false;
+ }
+ }
+ else{
+ if(! test_type_operator(unsigned_value<T>, o)){
+ ++m_error_count;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(int, char *[]){
+ using namespace boost::mp11;
+ // list of signed types
+ using signed_types = mp_list<std::int8_t, std::int16_t, std::int32_t, std::int64_t>;
+ // list of unsigned types
+ using unsigned_types = mp_list<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>;
+
+ test_type t;
+ mp_for_each<unsigned_types>(t);
+ mp_for_each<signed_types>(t);
+
+ std::cout << (t.m_error_count == 0 ? "success!" : "failure") << std::endl;
+ return t.m_error_count ;
+}