1 #ifndef BOOST_TEST_LEFT_SHIFT_HPP
2 #define BOOST_TEST_LEFT_SHIFT_HPP
3
4 // Copyright (c) 2015 Robert Ramey
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9
10 #include <iostream>
11
12 #include <boost/safe_numerics/safe_integer.hpp>
13 #include <boost/safe_numerics/range_value.hpp>
14
15 template<class T1, class T2>
test_left_shift(T1 v1,T2 v2,const char * av1,const char * av2,char expected_result)16 bool test_left_shift(
17 T1 v1,
18 T2 v2,
19 const char *av1,
20 const char *av2,
21 char expected_result
22 ){
23 std::cout
24 << "testing "
25 << av1 << " << " << av2
26 << std::endl;
27 {
28 safe_t<T1> t1 = v1;
29 using result_type = decltype(t1 << v2);
30 std::cout << "safe<" << av1 << "> << " << av2 << " -> ";
31 static_assert(
32 boost::safe_numerics::is_safe<result_type>::value,
33 "Expression failed to return safe type"
34 );
35 try{
36 // use auto to avoid checking assignment.
37 auto result = t1 << v2;
38 std::cout << make_result_display(result);
39 if(expected_result == 'x'){
40 std::cout
41 << " ! = "<< av1 << " << " << av2
42 << " failed to detect arithmetic error in left shift"
43 << std::endl;
44 t1 << v2;
45 return false;
46 }
47 std::cout << std::endl;
48 }
49 catch(const std::exception & e){
50 if(expected_result == '.'){
51 std::cout
52 << "erroneously detected arithmetic error in left shift"
53 << " == "<< av1 << " << " << av2
54 << ' ' << e.what()
55 << std::endl;
56 try{
57 t1 << v2;
58 }
59 catch(const std::exception &){}
60 return false;
61 }
62 std::cout << std::endl;
63 }
64 }
65 {
66 safe_t<T2> t2 = v2;
67 using result_type = decltype(v1 << t2);
68 std::cout << av1 << " << " << "safe<" << av2 << "> -> ";
69 static_assert(
70 boost::safe_numerics::is_safe<result_type>::value,
71 "Expression failed to return safe type"
72 );
73
74 try{
75 // use auto to avoid checking assignment.
76 auto result = v1 << t2;
77 std::cout << make_result_display(result);
78 if(expected_result == 'x'){
79 std::cout
80 << " ! = "<< av1 << " << " << av2
81 << " failed to detect error in left shift"
82 << std::hex << result << "(" << std::dec << result << ")"
83 << std::endl;
84 v1 << t2;
85 return false;
86 }
87 std::cout << std::endl;
88 }
89 catch(const std::exception & e){
90 if(expected_result == '.'){
91 std::cout
92 << " == "<< av1 << " << " << av2
93 << "erroneously detected error in left shift "
94 << ' ' << e.what()
95 << std::endl;
96 try{
97 v1 << t2;
98 }
99 catch(const std::exception &){}
100 return false;
101 }
102 std::cout << std::endl;
103 }
104 }
105 {
106 safe_t<T1> t1 = v1;
107 safe_t<T2> t2 = v2;
108 using result_type = decltype(t1 << t2);
109 std::cout << "safe<" << av1 << "> << " << "safe<" << av2 << "> -> ";
110 static_assert(
111 boost::safe_numerics::is_safe<result_type>::value,
112 "Expression failed to return safe type"
113 );
114
115 try{
116 // use auto to avoid checking assignment.
117 auto result = t1 << t2;
118 std::cout << make_result_display(result);
119 if(expected_result == 'x'){
120 std::cout
121 << " ! = "<< av1 << " << " << av2
122 << " failed to detect error in left shift"
123 << std::endl;
124 t1 << t2;
125 return false;
126 }
127 std::cout << std::endl;
128 }
129 catch(const std::exception & e){
130 if(expected_result == '.'){
131 std::cout
132 << " == "<< av1 << " << " << av2
133 << " erroneously detected error in left shift"
134 << ' ' << e.what()
135 << std::endl;
136 try{
137 t1 << t2;
138 }
139 catch(const std::exception &){}
140 return false;
141 }
142 std::cout << std::endl;
143 }
144 }
145 return true; // correct result
146 }
147
148 #endif // BOOST_TEST_DIVIDE
149