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 type checked_result<R> for some integer type R
14 template<class T>
test_checked_multiply(T v1,T v2,char expected_result)15 bool test_checked_multiply(
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 << "testing "
24 << v1 << " * " << v2 << " -> " << result
25 << std::endl;
26
27 switch(expected_result){
28 case '0':
29 case '.':
30 if(result.exception()){
31 std::cout
32 << "erroneously detected error in multiplication "
33 << std::endl;
34 v1 * v2;
35 return false;
36 }
37 if(expected_result == '0'
38 && result != T(0)
39 ){
40 std::cout
41 << "failed to get expected zero result "
42 << std::endl;
43 v1 * v2;
44 return false;
45 }
46 return true;
47 case '-':
48 if(safe_numerics_error::negative_overflow_error == result.m_e)
49 return true;
50 break;
51 case '+':
52 if(safe_numerics_error::positive_overflow_error == result.m_e)
53 return true;
54 break;
55 case '!':
56 if(safe_numerics_error::range_error == result.m_e)
57 return true;
58 break;
59 }
60 std::cout
61 << "failed to detect error in multiplication "
62 << std::hex << result << "(" << std::dec << result << ")"
63 << " != "<< v1 << " * " << v2
64 << std::endl;
65 v1 * v2;
66 return false;
67 }
68
69 #include "test_checked_multiply.hpp"
70
71 template<typename T, typename First, typename Second>
72 struct test_signed_pair {
operator ()test_signed_pair73 bool operator()() const {
74 std::size_t i = First();
75 std::size_t j = Second();
76 std::cout << std::dec << i << ',' << j << ','
77 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
78 return test_checked_multiply(
79 signed_values<T>[i],
80 signed_values<T>[j],
81 signed_multiplication_results[i][j]
82 );
83 };
84 };
85
86 template<typename T, typename First, typename Second>
87 struct test_unsigned_pair {
operator ()test_unsigned_pair88 bool operator()() const {
89 std::size_t i = First();
90 std::size_t j = Second();
91 std::cout << std::dec << i << ',' << j << ','
92 << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
93 return test_checked_multiply(
94 unsigned_values<T>[i],
95 unsigned_values<T>[j],
96 unsigned_multiplication_results[i][j]
97 );
98 };
99 };
100
101 #include "check_symmetry.hpp"
102
103 #include <boost/mp11/algorithm.hpp>
104
main(int,char * [])105 int main(int , char *[]){
106 static_assert(
107 check_symmetry(signed_multiplication_results),
108 "sanity check on test matrix - should be symmetrical"
109 );
110 static_assert(
111 check_symmetry(unsigned_multiplication_results),
112 "sanity check on test matrix - should be symmetrical"
113 );
114
115 using namespace boost::mp11;
116 bool rval = true;
117
118 mp_for_each<
119 mp_product<
120 test_signed_pair,
121 signed_test_types,
122 signed_value_indices,
123 signed_value_indices
124 >
125 >([&](auto I){
126 rval &= I();
127 });
128
129 std::cout << "*** testing unsigned values\n";
130
131 mp_for_each<
132 mp_product<
133 test_unsigned_pair,
134 unsigned_test_types,
135 unsigned_value_indices, unsigned_value_indices
136 >
137 >([&](auto I){
138 rval &= I();
139 });
140
141 std::cout << (rval ? "success!" : "failure") << std::endl;
142 return rval ? 0 : 1;
143 }
144