• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 
5 #ifndef BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
6 #define BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
7 
8 #include <boost/hana/and.hpp>
9 #include <boost/hana/assert.hpp>
10 #include <boost/hana/bool.hpp>
11 #include <boost/hana/concept/constant.hpp>
12 #include <boost/hana/concept/orderable.hpp>
13 #include <boost/hana/concept/product.hpp>
14 #include <boost/hana/concept/sequence.hpp>
15 #include <boost/hana/core/when.hpp>
16 #include <boost/hana/first.hpp>
17 #include <boost/hana/greater.hpp>
18 #include <boost/hana/greater_equal.hpp>
19 #include <boost/hana/lazy.hpp>
20 #include <boost/hana/less.hpp>
21 #include <boost/hana/less_equal.hpp>
22 #include <boost/hana/not.hpp>
23 #include <boost/hana/or.hpp>
24 #include <boost/hana/ordering.hpp>
25 #include <boost/hana/second.hpp>
26 #include <boost/hana/value.hpp>
27 
28 #include <laws/base.hpp>
29 
30 
31 namespace boost { namespace hana { namespace test {
32     template <typename T, typename = when<true>>
33     struct TestOrderable : TestOrderable<T, laws> {
34         using TestOrderable<T, laws>::TestOrderable;
35     };
36 
37     template <typename T>
38     struct TestOrderable<T, laws> {
39         template <typename Xs>
TestOrderableboost::hana::test::TestOrderable40         TestOrderable(Xs xs) {
41             hana::for_each(xs, [](auto x) {
42                 static_assert(Orderable<decltype(x)>{}, "");
43             });
44 
45             foreach2(xs, [](auto a, auto b) {
46 
47                 // antisymmetry
48                 BOOST_HANA_CHECK(
49                     hana::and_(hana::less_equal(a, b), hana::less_equal(b, a))
50                         ^implies^ hana::equal(a, b)
51                 );
52 
53                 // totality
54                 BOOST_HANA_CHECK(
55                     hana::or_(hana::less_equal(a, b), hana::less_equal(b, a))
56                 );
57 
58                 // other methods in terms of `less_equal`
59                 BOOST_HANA_CHECK(
60                     hana::less(a, b) ^iff^ hana::not_(hana::less_equal(b, a))
61                 );
62 
63                 BOOST_HANA_CHECK(
64                     hana::greater(a, b) ^iff^ hana::less(b, a)
65                 );
66 
67                 BOOST_HANA_CHECK(
68                     hana::greater_equal(a, b) ^iff^ hana::not_(hana::less(a, b))
69                 );
70 
71                 // less.than & al.
72                 BOOST_HANA_CHECK(hana::less.than(a)(b) ^iff^ hana::less(b, a));
73                 BOOST_HANA_CHECK(hana::greater.than(a)(b) ^iff^ hana::greater(b, a));
74                 BOOST_HANA_CHECK(hana::less_equal.than(a)(b) ^iff^ hana::less_equal(b, a));
75                 BOOST_HANA_CHECK(hana::greater_equal.than(a)(b) ^iff^ hana::greater_equal(b, a));
76 
77                 // ordering
78                 _injection<0> f{}; // test::_injection is also monotonic
79                 BOOST_HANA_CHECK(
80                     hana::ordering(f)(a, b) ^iff^ hana::less(f(a), f(b))
81                 );
82             });
83 
84             // transitivity
85             foreach3(xs, [](auto a, auto b, auto c) {
86                 BOOST_HANA_CHECK(
87                     hana::and_(hana::less_equal(a, b), hana::less_equal(b, c))
88                         ^implies^ hana::less_equal(a, c)
89                 );
90             });
91         }
92     };
93 
94     template <typename C>
95     struct TestOrderable<C, when<Constant<C>::value>>
96         : TestOrderable<C, laws>
97     {
98         template <typename Xs>
TestOrderableboost::hana::test::TestOrderable99         TestOrderable(Xs xs) : TestOrderable<C, laws>{xs} {
__anondb8711260402boost::hana::test::TestOrderable100             foreach2(xs, [](auto a, auto b) {
101 
102                 BOOST_HANA_CHECK(
103                     hana::value(hana::less(a, b)) ^iff^
104                         hana::less(hana::value(a), hana::value(b))
105                 );
106 
107             });
108         }
109     };
110 
111     template <typename P>
112     struct TestOrderable<P, when<Product<P>::value>>
113         : TestOrderable<P, laws>
114     {
115         template <typename Products>
TestOrderableboost::hana::test::TestOrderable116         TestOrderable(Products products)
117             : TestOrderable<P, laws>{products}
118         {
__anondb8711260502boost::hana::test::TestOrderable119             foreach2(products, [](auto x, auto y) {
120                 BOOST_HANA_CHECK(
121                     hana::less(x, y) ^iff^
122                     hana::or_(
123                         hana::less(hana::first(x), hana::first(y)),
124                         hana::and_(
125                             hana::equal(hana::first(x), hana::first(y)),
126                             hana::less(hana::second(x), hana::second(y))
127                         )
128                     )
129                 );
130             });
131         }
132     };
133 
134     template <typename S>
135     struct TestOrderable<S, when<Sequence<S>::value>>
136         : TestOrderable<S, laws>
137     {
138         struct invalid { };
139 
140         template <typename Xs>
TestOrderableboost::hana::test::TestOrderable141         TestOrderable(Xs xs) : TestOrderable<S, laws>{xs} {
142             constexpr auto list = make<S>;
143 
144             //////////////////////////////////////////////////////////////////
145             // less
146             //////////////////////////////////////////////////////////////////
147             BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
148                 list(),
149                 list()
150             )));
151 
152             BOOST_HANA_CONSTANT_CHECK(hana::less(
153                 list(),
154                 list(invalid{})
155             ));
156             BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
157                 list(invalid{}),
158                 list()
159             )));
160             BOOST_HANA_CONSTANT_CHECK(hana::less(
161                 list(ct_ord<0>{}),
162                 list(ct_ord<7>{})
163             ));
164             BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
165                 list(ct_ord<1>{}),
166                 list(ct_ord<0>{})
167             )));
168 
169             BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
170                 list(ct_ord<0>{}, ct_ord<1>{}, ct_ord<8>{}),
171                 list(ct_ord<0>{}, ct_ord<1>{})
172             )));
173 
174             BOOST_HANA_CONSTANT_CHECK(hana::less(
175                 list(ct_ord<0>{}, ct_ord<0>{}, ct_ord<8>{}),
176                 list(ct_ord<0>{}, ct_ord<1>{})
177             ));
178         }
179     };
180 }}} // end namespace boost::hana::test
181 
182 #endif // !BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
183