1 //  Copyright (c) 2018 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_or(T v1,T v2,char expected_result)15 bool test_checked_or(
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 bitwise or "
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 bitwise or "
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_or.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_or(
65             signed_values<T>[i],
66             signed_values<T>[j],
67             signed_or_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_or(
80             unsigned_values<T>[i],
81             unsigned_values<T>[j],
82             unsigned_or_results[i][j]
83         );
84     };
85 };
86 
87 #include "check_symmetry.hpp"
88 
89 #include <boost/mp11/algorithm.hpp>
90 
main()91 int main(){
92     using namespace boost::mp11;
93     // sanity check on test matrix - should be symetrical
94     check_symmetry(signed_or_results);
95     check_symmetry(unsigned_or_results);
96 
97     bool rval = true;
98 
99     std::cout << "*** testing signed values\n";
100     mp_for_each<
101         mp_product<
102             test_signed_pair,
103             signed_test_types,
104             signed_value_indices,
105             signed_value_indices
106         >
107     >([&](auto I){
108         rval &= I();
109     });
110 
111     std::cout << "*** testing unsigned values\n";
112 
113     mp_for_each<
114         mp_product<
115             test_unsigned_pair,
116             unsigned_test_types,
117             unsigned_value_indices, unsigned_value_indices
118         >
119     >([&](auto I){
120         rval &= I();
121     });
122 
123     std::cout << (rval ? "success!" : "failure") << std::endl;
124     return rval ? 0 : 1;
125 }
126