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 template<class T>
test_checked_left_shift(T v1,T v2,char expected_result)14 bool test_checked_left_shift(
15 T v1,
16 T v2,
17 char expected_result
18 ){
19 using namespace boost::safe_numerics;
20
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 left shift "
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 break;
40 case '+':
41 if(safe_numerics_error::positive_overflow_error == result.m_e)
42 return true;
43 break;
44 case '!':
45 if(result.exception())
46 return true;
47 break;
48 case 'n': // n negative_shift
49 if(safe_numerics_error::negative_shift == result.m_e)
50 return true;
51 break;
52 case 's': // s negative_value_shift
53 if(safe_numerics_error::negative_value_shift == result.m_e)
54 return true;
55 break;
56 case 'l': // l shift_too_large
57 if(safe_numerics_error::shift_too_large == result.m_e)
58 return true;
59 break;
60 default:
61 assert(false);
62 }
63 std::cout
64 << "failed to detect error in left shift "
65 << std::hex << result << "(" << std::dec << result << ")"
66 << " != "<< v1 << " << " << v2
67 << std::endl;
68 v1 << v2;
69 return false;
70 }
71
72 #include "test_checked_left_shift.hpp"
73
74 template<typename T, typename First, typename Second>
75 struct test_signed_pair {
operator ()test_signed_pair76 bool operator()() const {
77 std::size_t i = First();
78 std::size_t j = Second();
79 std::cout << std::dec << i << ',' << j << ','
80 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
81 return test_checked_left_shift(
82 signed_values<T>[i],
83 signed_values<T>[j],
84 signed_left_shift_results[i][j]
85 );
86 };
87 };
88
89 template<typename T, typename First, typename Second>
90 struct test_unsigned_pair {
operator ()test_unsigned_pair91 bool operator()() const {
92 std::size_t i = First();
93 std::size_t j = Second();
94 std::cout << std::dec << i << ',' << j << ','
95 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
96 return test_checked_left_shift(
97 unsigned_values<T>[i],
98 unsigned_values<T>[j],
99 unsigned_left_shift_results[i][j]
100 );
101 };
102 };
103
104 #include <boost/mp11/algorithm.hpp>
105
main()106 int main(){
107 using namespace boost::mp11;
108
109 bool rval = true;
110
111 std::cout << "*** testing signed values\n";
112 mp_for_each<
113 mp_product<
114 test_signed_pair,
115 signed_test_types,
116 signed_value_indices,
117 signed_value_indices
118 >
119 >([&](auto I){
120 rval &= I();
121 });
122
123 std::cout << "*** testing unsigned values\n";
124 mp_for_each<
125 mp_product<
126 test_unsigned_pair,
127 unsigned_test_types,
128 unsigned_value_indices, unsigned_value_indices
129 >
130 >([&](auto I){
131 rval &= I();
132 });
133
134 std::cout << (rval ? "success!" : "failure") << std::endl;
135 return rval ? 0 : 1;
136 }
137