1 //  Copyright (c) 2012 Robert Ramey
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <iostream>
8 
9 #include <boost/core/demangle.hpp>
10 #include <boost/safe_numerics/checked_result_operations.hpp>
11 #include <boost/safe_numerics/checked_integer.hpp>
12 
13 // note: T should be of tyme checked_result<R> for some integer type R
14 template<class T>
test_checked_subtract(T v1,T v2,char expected_result)15 bool test_checked_subtract(
16     T v1,
17     T v2,
18     char expected_result
19 ){
20     using namespace boost::safe_numerics;
21     const T result = v1 - v2;
22     std::cout
23         << v1 << " - " << v2 << " -> " << result
24         << std::endl;
25 
26     switch(expected_result){
27     case '.':
28         if(result.exception()){
29             std::cout
30                 << "erroneously detected error in subtraction "
31                 << std::endl;
32             v1 - v2;
33             return false;
34         }
35         return true;
36     case '-':
37         if(safe_numerics_error::negative_overflow_error == result.m_e)
38             return true;
39     case '+':
40         if(safe_numerics_error::positive_overflow_error == result.m_e)
41             return true;
42     case '!':
43         if(safe_numerics_error::range_error == result.m_e)
44             return true;
45     }
46     std::cout
47         << "failed to detect error in ition "
48         << std::hex << result << "(" << std::dec << result << ")"
49         << " != "<< v1 << " - " << v2
50         << std::endl;
51     v1 - v2;
52     return false;
53 }
54 
55 #include "test_checked_subtract.hpp"
56 
57 template<typename T, typename First, typename Second>
58 struct test_signed_pair {
operator ()test_signed_pair59     bool operator()() const {
60         std::size_t i = First();
61         std::size_t j = Second();
62         std::cout << std::dec << i << ',' << j << ','
63             << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
64         return test_checked_subtract(
65             signed_values<T>[i],
66             signed_values<T>[j],
67             signed_subtraction_results[i][j]
68         );
69     };
70 };
71 
72 template<typename T, typename First, typename Second>
73 struct test_unsigned_pair {
operator ()test_unsigned_pair74     bool operator()() const {
75         std::size_t i = First();
76         std::size_t j = Second();
77         std::cout << std::dec << i << ',' << j << ','
78             << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
79         return test_checked_subtract(
80             unsigned_values<T>[i],
81             unsigned_values<T>[j],
82             unsigned_subtraction_results[i][j]
83         );
84     };
85 };
86 
87 #include <boost/mp11/algorithm.hpp>
88 
main()89 int main(){
90     using namespace boost::mp11;
91 
92     bool rval = true;
93 
94     std::cout << "*** testing signed values\n";
95 
96     mp_for_each<
97         mp_product<
98             test_signed_pair,
99             signed_test_types,
100             signed_value_indices,
101             signed_value_indices
102         >
103     >([&](auto I){
104         rval &= I();
105     });
106 
107     std::cout << "*** testing unsigned values\n";
108 
109     mp_for_each<
110         mp_product<
111             test_unsigned_pair,
112             unsigned_test_types,
113             unsigned_value_indices, unsigned_value_indices
114         >
115     >([&](auto I){
116         rval &= I();
117     });
118 
119     std::cout << (rval ? "success!" : "failure") << std::endl;
120     return rval ? 0 : 1;
121 }
122