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 #include <boost/core/demangle.hpp>
9
10 #include <boost/safe_numerics/checked_result.hpp>
11 #include <boost/safe_numerics/checked_result_operations.hpp>
12 #include <boost/safe_numerics/checked_integer.hpp>
13
14 // note: T should be of tyme checked_result<R> for some integer type R
15 template<class T>
test_checked_right_shift(T v1,T v2,char expected_result)16 bool test_checked_right_shift(
17 T v1,
18 T v2,
19 char expected_result
20 ){
21 using namespace boost::safe_numerics;
22 const T result = v1 >> v2;
23 std::cout
24 << v1 << " >> " << v2 << " -> " << result
25 << std::endl;
26
27 switch(expected_result){
28 case '.':
29 if(result.exception()){
30 std::cout
31 << "erroneously detected error in right shift "
32 << std::endl;
33 v1 >> v2;
34 return false;
35 }
36 return true;
37 case '-':
38 if(safe_numerics_error::negative_overflow_error == result.m_e)
39 return true;
40 break;
41 case '+':
42 if(safe_numerics_error::positive_overflow_error == result.m_e)
43 return true;
44 break;
45 case '!':
46 if(safe_numerics_error::range_error == result.m_e)
47 return true;
48 break;
49 case 'n': // n negative_shift
50 if(safe_numerics_error::negative_shift == result.m_e)
51 return true;
52 break;
53 case 's': // s negative_value_shift
54 if(safe_numerics_error::negative_value_shift == result.m_e)
55 return true;
56 break;
57 case 'l': // l shift_too_large
58 if(safe_numerics_error::shift_too_large == result.m_e)
59 return true;
60 break;
61 default:
62 assert(false);
63 }
64 std::cout
65 << "failed to detect error in right shift "
66 << std::hex << result << "(" << std::dec << result << ")"
67 << " != "<< v1 << " >> " << v2
68 << std::endl;
69 v1 >> v2;
70 return false;
71 }
72
73 #include "test_checked_right_shift.hpp"
74
75 template<typename T, typename First, typename Second>
76 struct test_signed_pair {
operator ()test_signed_pair77 bool operator()() const {
78 std::size_t i = First();
79 std::size_t j = Second();
80 std::cout << std::dec << i << ',' << j << ','
81 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
82 return test_checked_right_shift(
83 signed_values<T>[i],
84 signed_values<T>[j],
85 signed_right_shift_results[i][j]
86 );
87 };
88 };
89
90 template<typename T, typename First, typename Second>
91 struct test_unsigned_pair {
operator ()test_unsigned_pair92 bool operator()() const {
93 std::size_t i = First();
94 std::size_t j = Second();
95 std::cout << std::dec << i << ',' << j << ','
96 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
97 return test_checked_right_shift(
98 unsigned_values<T>[i],
99 unsigned_values<T>[j],
100 unsigned_right_shift_results[i][j]
101 );
102 };
103 };
104
105 #include <boost/mp11/algorithm.hpp>
106
main()107 int main(){
108 using namespace boost::mp11;
109
110 bool rval = true;
111
112 std::cout << "*** testing signed values\n";
113
114 mp_for_each<
115 mp_product<
116 test_signed_pair,
117 signed_test_types,
118 signed_value_indices,
119 signed_value_indices
120 >
121 >([&](auto I){
122 rval &= I();
123 });
124
125 std::cout << "*** testing unsigned values\n";
126
127 mp_for_each<
128 mp_product<
129 test_unsigned_pair,
130 unsigned_test_types,
131 unsigned_value_indices, unsigned_value_indices
132 >
133 >([&](auto I){
134 rval &= I();
135 });
136
137 std::cout << (rval ? "success!" : "failure") << std::endl;
138 return rval ? 0 : 1;
139 }
140