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