1 #ifndef BOOST_TEST_MULTIPLY_HPP
2 #define BOOST_TEST_MULTIPLY_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 #include <boost/core/demangle.hpp>
12 
13 #include <boost/safe_numerics/safe_integer.hpp>
14 #include <boost/safe_numerics/range_value.hpp>
15 
16 template<class T1, class T2>
test_multiply(T1 v1,T2 v2,const char * av1,const char * av2,char expected_result)17 bool test_multiply(
18     T1 v1,
19     T2 v2,
20     const char *av1,
21     const char *av2,
22     char expected_result
23 ){
24     std::cout << "testing"<< std::endl;
25     {
26         safe_t<T1> t1 = v1;
27 
28         using result_type = decltype(t1 * v2);
29         std::cout << "safe<" << av1 << "> * " << av2 << " -> ";
30         static_assert(
31             boost::safe_numerics::is_safe<safe_t<T1> >::value,
32             "safe_t not safe!"
33         );
34         static_assert(
35             boost::safe_numerics::is_safe<result_type>::value,
36             "Expression failed to return safe type"
37         );
38 
39         try{
40             // use auto to avoid checking assignment.
41             auto result = t1 * v2;
42             std::cout << make_result_display(result);
43             if(expected_result == 'x'){
44                 const std::type_info & ti = typeid(result);
45                 std::cout
46                     << " *** failed to detect error in multiplication"
47                     << boost::core::demangle(ti.name())
48                     << std::endl;
49                 t1 * v2;
50                 return false;
51             }
52             std::cout << std::endl;
53         }
54         catch(const std::exception &){
55             if(expected_result == '.'){
56                 std::cout
57                     << " *** erroneously detected error in multiplication"
58                     << std::endl;
59                 try{
60                     t1 * v2;
61                 }
62                 catch(const std::exception &){}
63                 return false;
64             }
65         }
66     }
67     {
68         safe_t<T2> t2 = v2;
69         using result_type = decltype(v1 * t2);
70         std::cout << av1 << " * " << "safe<" << av2 << "> -> ";
71         static_assert(
72             boost::safe_numerics::is_safe<safe_t<T2> >::value,
73             "safe_t not safe!"
74         );
75         static_assert(
76             boost::safe_numerics::is_safe<result_type>::value,
77             "Expression failed to return safe type"
78         );
79 
80         try{
81             // use auto to avoid checking assignment.
82             auto result = v1 * t2;
83             std::cout << make_result_display(result);
84             if(expected_result == 'x'){
85                 const std::type_info & ti = typeid(result);
86                 std::cout
87                     << " *** failed to detect error in multiplication"
88                     << boost::core::demangle(ti.name())
89                     << std::endl;
90                 v1 * t2;
91                 return false;
92             }
93             std::cout << std::endl;
94         }
95         catch(const std::exception &){
96             if(expected_result == '.'){
97                 std::cout
98                     << " *** erroneously detected error in multiplication"
99                     << std::endl;
100                 try{
101                     v1 * t2;
102                 }
103                 catch(const std::exception &){}
104                 return false;
105             }
106         }
107     }
108     {
109         safe_t<T1> t1 = v1;
110         safe_t<T2> t2 = v2;
111 
112         using result_type = decltype(t1 * t2);
113         std::cout << "safe<" << av1 << "> * " << "safe<" << av2 << "> -> ";
114         static_assert(
115             boost::safe_numerics::is_safe<result_type>::value,
116             "Expression failed to return safe type"
117         );
118 
119         try{
120             // use auto to avoid checking assignment.
121             auto result = t1 * t2;
122             std::cout << make_result_display(result);
123             if(expected_result == 'x'){
124                 const std::type_info & ti = typeid(result);
125                 std::cout
126                     << " *** failed to detect error in multiplication"
127                     << boost::core::demangle(ti.name())
128                     << std::endl;
129                 t1 * t2;
130                 return false;
131             }
132             std::cout << std::endl;
133         }
134         catch(const std::exception &){
135             if(expected_result == '.'){
136                 std::cout
137                     << " *** erroneously detected error in multiplication"
138                     << std::endl;
139                 try{
140                     t1 * t2;
141                 }
142                 catch(const std::exception &){}
143                 return false;
144             }
145         }
146     }
147     return true;
148 }
149 
150 
151 #endif // BOOST_TEST_MULTIPLY
152