• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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