1 // Copyright (c) 2014 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/safe_compare.hpp>
11 
12 template<class T1, class T2>
print_argument_types(T1 v1,T2 v2)13 void print_argument_types(
14     T1 v1,
15     T2 v2
16 ){
17     const std::type_info & ti1 = typeid(v1);
18     const std::type_info & ti2 = typeid(v2);
19 
20     std::cout
21         << boost::core::demangle(ti1.name()) << ','
22         << boost::core::demangle(ti2.name());
23 }
24 
25 #include <boost/mp11/algorithm.hpp>
26 
27 using namespace boost::safe_numerics;
28 
29 template<class T1, class T2>
test_safe_compare_impl(T1 v1,T2 v2,char expected_result)30 bool test_safe_compare_impl(
31     T1 v1,
32     T2 v2,
33     char expected_result
34 ){
35     switch(expected_result){
36     case '=': {
37         if(! safe_compare::equal(v1, v2))
38             return false;
39         if(safe_compare::less_than(v1, v2))
40             return false;
41         if(safe_compare::greater_than(v1, v2))
42             return false;
43         break;
44     }
45     case '<': {
46         if(! safe_compare::less_than(v1, v2))
47             return false;
48         if(safe_compare::greater_than(v1, v2))
49             return false;
50         if(safe_compare::equal(v1, v2))
51             return false;
52         break;
53     }
54     case '>':{
55         if(! safe_compare::greater_than(v1, v2))
56             return false;
57         if(safe_compare::less_than(v1, v2))
58             return false;
59         if(safe_compare::equal(v1, v2))
60             return false;
61         break;
62     }
63     }
64     return true;
65 }
66 
67 template<class T1, class T2>
test_safe_compare(T1 v1,T2 v2,char expected_result)68 bool test_safe_compare(
69     T1 v1,
70     T2 v2,
71     char expected_result
72 ){
73     print_argument_types(v1, v2);
74     const bool result = test_safe_compare_impl(v1, v2, expected_result);
75     if(! result)
76         std::cout << " failed";
77     std::cout << '\n';
78     return result;
79 }
80 
81 #include "test_values.hpp"
82 
83 const char *test_compare_result[boost::mp11::mp_size<test_values>::value] = {
84 //      0       0       0       0
85 //      012345670123456701234567012345670
86 //      012345678901234567890123456789012
87 /* 0*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
88 /* 1*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
89 /* 2*/ "<<=<<<><<<><<<><<<<<<<<<<<<<<<<<<",
90 /* 3*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
91 /* 4*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
92 /* 5*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
93 /* 6*/ "<<<<<<=<<<><<<><<<<<<<<<<<<<<<<<<",
94 /* 7*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
95 
96 /* 8*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
97 /* 9*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
98 /*10*/ "<<<<<<<<<<=<<<><<<<<<<<<<<<<<<<<<",
99 /*11*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
100 /*12*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
101 /*13*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
102 /*14*/ "<<<<<<<<<<<<<<=<<<<<<<<<<<<<<<<<<",
103 /*15*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<",
104 
105 //      0       0       0       0
106 //      012345670123456701234567012345670
107 //      012345678901234567890123456789012
108 /*16*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
109 /*17*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
110 /*18*/ ">>>>><>>><>>><>>>>=<><<<><<<><<<>",
111 /*19*/ ">>>>><>>><>>><>>>>>=><<<><<<><<<>",
112 /*20*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
113 /*21*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
114 /*22*/ ">>>>>>>>><>>><>>>>>>>>=<><<<><<<>",
115 /*23*/ ">>>>>>>>><>>><>>>>>>>>>=><<<><<<>",
116 
117 /*24*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
118 /*25*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
119 /*26*/ ">>>>>>>>>>>>><>>>>>>>>>>>>=<><<<>",
120 /*27*/ ">>>>>>>>>>>>><>>>>>>>>>>>>>=><<<>",
121 /*28*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
122 /*29*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
123 /*30*/ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=<>",
124 /*31*/ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>",
125 /*32*/ "<<>><<>><<>><<>><<<<<<<<<<<<<<<<="
126 };
127 
128 using namespace boost::mp11;
129 
130 template<typename L>
131 struct test {
132     static_assert(mp_is_list<L>(), "must be a list of integral constants");
133     bool m_error;
testtest134     test(bool b = true) : m_error(b) {}
operator booltest135     operator bool(){
136         return m_error;
137     }
138     template<typename T>
operator ()test139     void operator()(const T &){
140         static_assert(mp_is_list<T>(), "must be a list of two integral constants");
141         constexpr size_t i1 = mp_first<T>(); // index of first argument
142         constexpr size_t i2 = mp_second<T>();// index of second argument
143         std::cout << i1 << ',' << i2 << ',';
144         using T1 = typename boost::mp11::mp_at_c<L, i1>::value_type;
145         using T2 = typename boost::mp11::mp_at_c<L, i2>::value_type;
146         m_error &= test_safe_compare<T1, T2>(
147             boost::mp11::mp_at_c<L, i1>(), // value of first argument
148             boost::mp11::mp_at_c<L, i2>(), // value of second argument
149             test_compare_result[i1][i2]
150         );
151     }
152 };
153 
main()154 int main(){
155     //TEST_EACH_VALUE_PAIR
156     test<test_values> rval(true);
157 
158     using value_indices = mp_iota_c<mp_size<test_values>::value>;
159     mp_for_each<
160         mp_product<mp_list, value_indices, value_indices>
161     >(rval);
162 
163     std::cout << (rval ? "success!" : "failure") << std::endl;
164     return ! rval ;
165 }
166