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     // sanity check on test matrix - should be symetrical
107     check_symmetry(signed_multiplication_results);
108     check_symmetry(unsigned_multiplication_results);
109 
110     using namespace boost::mp11;
111     bool rval = true;
112 
113     mp_for_each<
114         mp_product<
115             test_signed_pair,
116             signed_test_types,
117             signed_value_indices,
118             signed_value_indices
119         >
120     >([&](auto I){
121         rval &= I();
122     });
123 
124     std::cout << "*** testing unsigned values\n";
125 
126     mp_for_each<
127         mp_product<
128             test_unsigned_pair,
129             unsigned_test_types,
130             unsigned_value_indices, unsigned_value_indices
131         >
132     >([&](auto I){
133         rval &= I();
134     });
135 
136     std::cout << (rval ? "success!" : "failure") << std::endl;
137     return rval ? 0 : 1;
138 }
139