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_and(T v1,T v2,char expected_result)15 bool test_checked_and(
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 and operation "
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 and operation "
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_and.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_and(
65             signed_values<T>[i],
66             signed_values<T>[j],
67             signed_and_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_and(
80             unsigned_values<T>[i],
81             unsigned_values<T>[j],
82             unsigned_and_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_and_results);
95     check_symmetry(unsigned_and_results);
96 
97     bool rval = true;
98 
99     std::cout << "*** testing signed values\n";
100 
101     mp_for_each<
102         mp_product<
103             test_signed_pair,
104             signed_test_types,
105             signed_value_indices,
106             signed_value_indices
107         >
108     >([&](auto I){
109         rval &= I();
110     });
111 
112     std::cout << "*** testing unsigned values\n";
113 
114     mp_for_each<
115         mp_product<
116             test_unsigned_pair,
117             unsigned_test_types,
118             unsigned_value_indices, unsigned_value_indices
119         >
120     >([&](auto I){
121         rval &= I();
122     });
123 
124     std::cout << (rval ? "success!" : "failure") << std::endl;
125     return rval ? 0 : 1;
126 }
127