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_LOGICAL_HPP
6 #define BOOST_HANA_TEST_LAWS_LOGICAL_HPP
7 
8 #include <boost/hana/assert.hpp>
9 #include <boost/hana/bool.hpp>
10 #include <boost/hana/concept/comparable.hpp>
11 #include <boost/hana/core/when.hpp>
12 #include <boost/hana/functional/capture.hpp>
13 #include <boost/hana/lazy.hpp>
14 #include <boost/hana/concept/logical.hpp>
15 
16 #include <laws/base.hpp>
17 
18 
19 namespace boost { namespace hana { namespace test {
20     template <typename L, typename = when<true>>
21     struct TestLogical : TestLogical<L, laws> {
22         using TestLogical<L, laws>::TestLogical;
23     };
24 
25     template <typename L>
26     struct TestLogical<L, laws> {
27         template <typename Xs, typename Pred, typename F>
for_each_such_thatboost::hana::test::TestLogical28         static void for_each_such_that(Xs xs, Pred pred, F f) {
29             hana::for_each(xs, [&pred, &f](auto x) {
30                 hana::eval_if(pred(x),
31                     hana::make_lazy(f)(x),
32                     [](auto) { }
33                 );
34             });
35         }
36 
37         template <typename Xs>
TestLogicalboost::hana::test::TestLogical38         TestLogical(Xs xs) {
39             hana::for_each(xs, [](auto x) {
40                 static_assert(Logical<decltype(x)>{}, "");
41             });
42 
43             foreach3(xs, hana::capture(xs)([](auto xs, auto a, auto b, auto c) {
44                 auto true_valued = [](auto x) {
45                     return hana::if_(x, true_c, false_c);
46                 };
47                 auto false_valued = [](auto x) {
48                     return hana::if_(x, false_c, true_c);
49                 };
50 
51                 // associativity
52                 BOOST_HANA_CHECK(hana::equal(
53                     hana::or_(a, hana::or_(b, c)),
54                     hana::or_(hana::or_(a, b), c)
55                 ));
56                 BOOST_HANA_CHECK(hana::equal(
57                     hana::and_(a, hana::and_(b, c)),
58                     hana::and_(hana::and_(a, b), c)
59                 ));
60 
61                 // equivalence through commutativity
62                 BOOST_HANA_CHECK(
63                     hana::or_(a, b) ^iff^ hana::or_(b, a)
64                 );
65                 BOOST_HANA_CHECK(
66                     hana::and_(a, b) ^iff^ hana::and_(b, a)
67                 );
68 
69                 // absorption
70                 BOOST_HANA_CHECK(hana::equal(
71                     hana::or_(a, hana::and_(a, b)), a
72                 ));
73                 BOOST_HANA_CHECK(hana::equal(
74                     hana::and_(a, hana::or_(a, b)), a
75                 ));
76 
77                 // left identity
78                 TestLogical::for_each_such_that(xs, true_valued,
79                 hana::capture(a)([](auto a, auto t) {
80                     BOOST_HANA_CHECK(hana::equal(
81                         hana::and_(t, a), a
82                     ));
83                 }));
84                 TestLogical::for_each_such_that(xs, false_valued,
85                 hana::capture(a)([](auto a, auto f) {
86                     BOOST_HANA_CHECK(hana::equal(
87                         hana::or_(f, a), a
88                     ));
89                 }));
90 
91                 // distributivity
92                 BOOST_HANA_CHECK(hana::equal(
93                     hana::or_(a, hana::and_(b, c)),
94                     hana::and_(hana::or_(a, b), hana::or_(a, c))
95                 ));
96                 BOOST_HANA_CHECK(hana::equal(
97                     hana::and_(a, hana::or_(b, c)),
98                     hana::or_(hana::and_(a, b), hana::and_(a, c))
99                 ));
100 
101                 // complements
102                 BOOST_HANA_CHECK(true_valued(hana::or_(a, hana::not_(a))));
103                 BOOST_HANA_CHECK(false_valued(hana::and_(a, hana::not_(a))));
104 
105             }));
106         }
107     };
108 
109     template <typename C>
110     struct TestLogical<C, when<Constant<C>::value>>
111         : TestLogical<C, laws>
112     {
113         template <typename Xs>
TestLogicalboost::hana::test::TestLogical114         TestLogical(Xs xs) : TestLogical<C, laws>{xs} {
__anone3b8abfa0902boost::hana::test::TestLogical115             foreach2(xs, [](auto x, auto y) {
116 
117                 BOOST_HANA_CHECK(hana::equal(
118                     hana::value(hana::not_(x)),
119                     hana::not_(hana::value(x))
120                 ));
121 
122                 BOOST_HANA_CHECK(hana::equal(
123                     hana::value(hana::and_(x, y)),
124                     hana::and_(hana::value(x), hana::value(y))
125                 ));
126 
127                 BOOST_HANA_CHECK(hana::equal(
128                     hana::value(hana::or_(x, y)),
129                     hana::or_(hana::value(x), hana::value(y))
130                 ));
131 
132             });
133         }
134     };
135 }}} // end namespace boost::hana::test
136 
137 #endif // !BOOST_HANA_TEST_LAWS_LOGICAL_HPP
138