unfolds.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. #ifndef BOOST_HANA_TEST_AUTO_UNFOLDS_HPP
  5. #define BOOST_HANA_TEST_AUTO_UNFOLDS_HPP
  6. #include <boost/hana/assert.hpp>
  7. #include <boost/hana/equal.hpp>
  8. #include <boost/hana/fold_left.hpp>
  9. #include <boost/hana/fold_right.hpp>
  10. #include <boost/hana/if.hpp>
  11. #include <boost/hana/integral_constant.hpp>
  12. #include <boost/hana/optional.hpp>
  13. #include <boost/hana/plus.hpp>
  14. #include <boost/hana/unfold_left.hpp>
  15. #include <boost/hana/unfold_right.hpp>
  16. #include <laws/base.hpp>
  17. #include <support/minimal_product.hpp>
  18. #include "test_case.hpp"
  19. TestCase test_unfold_left{[]{
  20. namespace hana = boost::hana;
  21. hana::test::_injection<0> f{};
  22. auto stop_at = [=](auto stop) {
  23. return [=](auto x) {
  24. return hana::if_(hana::equal(stop, x),
  25. hana::nothing,
  26. hana::just(::minimal_product(x + hana::int_c<1>, f(x)))
  27. );
  28. };
  29. };
  30. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  31. hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<0>)),
  32. MAKE_TUPLE()
  33. ));
  34. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  35. hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<1>)),
  36. MAKE_TUPLE(f(hana::int_c<0>))
  37. ));
  38. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  39. hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<2>)),
  40. MAKE_TUPLE(f(hana::int_c<1>), f(hana::int_c<0>))
  41. ));
  42. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  43. hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<3>)),
  44. MAKE_TUPLE(f(hana::int_c<2>), f(hana::int_c<1>), f(hana::int_c<0>))
  45. ));
  46. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  47. hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<4>)),
  48. MAKE_TUPLE(f(hana::int_c<3>), f(hana::int_c<2>), f(hana::int_c<1>), f(hana::int_c<0>))
  49. ));
  50. }};
  51. TestCase test_unfold_right{[]{
  52. namespace hana = boost::hana;
  53. hana::test::_injection<0> f{};
  54. auto stop_at = [=](auto stop) {
  55. return [=](auto x) {
  56. return hana::if_(hana::equal(stop, x),
  57. hana::nothing,
  58. hana::just(::minimal_product(f(x), x + hana::int_c<1>))
  59. );
  60. };
  61. };
  62. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  63. hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<0>)),
  64. MAKE_TUPLE()
  65. ));
  66. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  67. hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<1>)),
  68. MAKE_TUPLE(f(hana::int_c<0>))
  69. ));
  70. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  71. hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<2>)),
  72. MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>))
  73. ));
  74. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  75. hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<3>)),
  76. MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>), f(hana::int_c<2>))
  77. ));
  78. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  79. hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<4>)),
  80. MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>), f(hana::int_c<2>), f(hana::int_c<3>))
  81. ));
  82. }};
  83. // Make sure unfolds can be reversed under certain conditions.
  84. TestCase test_unfold_undo{[]{
  85. namespace hana = boost::hana;
  86. using hana::test::ct_eq;
  87. auto z = ct_eq<999>{};
  88. auto f = ::minimal_product;
  89. auto g = [=](auto k) {
  90. return hana::if_(hana::equal(k, z),
  91. hana::nothing,
  92. hana::just(k)
  93. );
  94. };
  95. // Make sure the special conditions are met
  96. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  97. g(z),
  98. hana::nothing
  99. ));
  100. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  101. g(f(ct_eq<0>{}, z)),
  102. hana::just(::minimal_product(ct_eq<0>{}, z))
  103. ));
  104. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  105. g(f(z, ct_eq<0>{})),
  106. hana::just(::minimal_product(z, ct_eq<0>{}))
  107. ));
  108. // Make sure the reversing works
  109. {
  110. auto xs = MAKE_TUPLE();
  111. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  112. hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
  113. xs
  114. ));
  115. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  116. hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
  117. xs
  118. ));
  119. }
  120. {
  121. auto xs = MAKE_TUPLE(ct_eq<0>{});
  122. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  123. hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
  124. xs
  125. ));
  126. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  127. hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
  128. xs
  129. ));
  130. }
  131. {
  132. auto xs = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{});
  133. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  134. hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
  135. xs
  136. ));
  137. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  138. hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
  139. xs
  140. ));
  141. }
  142. {
  143. auto xs = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{});
  144. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  145. hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
  146. xs
  147. ));
  148. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  149. hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
  150. xs
  151. ));
  152. }
  153. }};
  154. #endif // !BOOST_HANA_TEST_AUTO_UNFOLDS_HPP