euclidean_ring.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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_LAWS_EUCLIDEAN_RING_HPP
  5. #define BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
  6. #include <boost/hana/assert.hpp>
  7. #include <boost/hana/bool.hpp>
  8. #include <boost/hana/concept/comparable.hpp>
  9. #include <boost/hana/concept/constant.hpp>
  10. #include <boost/hana/concept/euclidean_ring.hpp>
  11. #include <boost/hana/core/when.hpp>
  12. #include <boost/hana/div.hpp>
  13. #include <boost/hana/equal.hpp>
  14. #include <boost/hana/for_each.hpp>
  15. #include <boost/hana/lazy.hpp>
  16. #include <boost/hana/mod.hpp>
  17. #include <boost/hana/mult.hpp>
  18. #include <boost/hana/not_equal.hpp>
  19. #include <boost/hana/plus.hpp>
  20. #include <boost/hana/value.hpp>
  21. #include <boost/hana/zero.hpp>
  22. #include <laws/base.hpp>
  23. namespace boost { namespace hana { namespace test {
  24. template <typename D, typename = when<true>>
  25. struct TestEuclideanRing : TestEuclideanRing<D, laws> {
  26. using TestEuclideanRing<D, laws>::TestEuclideanRing;
  27. };
  28. template <typename D>
  29. struct TestEuclideanRing<D, laws> {
  30. template <typename Xs>
  31. TestEuclideanRing(Xs xs) {
  32. hana::for_each(xs, [](auto x) {
  33. static_assert(EuclideanRing<decltype(x)>{}, "");
  34. });
  35. #ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
  36. zero<D>(); // force adding zero<D>'s member function to pending temploid list
  37. #endif
  38. foreach2(xs, [](auto a, auto b) {
  39. // commutativity
  40. BOOST_HANA_CHECK(hana::equal(
  41. hana::mult(a, b),
  42. hana::mult(b, a)
  43. ));
  44. only_when_(hana::not_equal(b, zero<D>()),
  45. hana::make_lazy([](auto a, auto b) {
  46. BOOST_HANA_CHECK(hana::equal(
  47. hana::plus(
  48. hana::mult(hana::div(a, b), b),
  49. hana::mod(a, b)
  50. ),
  51. a
  52. ));
  53. BOOST_HANA_CHECK(hana::equal(
  54. hana::mod(zero<D>(), b),
  55. zero<D>()
  56. ));
  57. })(a, b));
  58. });
  59. }
  60. };
  61. template <typename C>
  62. struct TestEuclideanRing<C, when<Constant<C>::value>>
  63. : TestEuclideanRing<C, laws>
  64. {
  65. template <typename Xs>
  66. TestEuclideanRing(Xs xs) : TestEuclideanRing<C, laws>{xs} {
  67. foreach2(xs, [](auto x, auto y) {
  68. only_when_(hana::not_equal(zero<C>(), y),
  69. hana::make_lazy([](auto x, auto y) {
  70. BOOST_HANA_CHECK(hana::equal(
  71. hana::div(hana::value(x), hana::value(y)),
  72. hana::value(hana::div(x, y))
  73. ));
  74. BOOST_HANA_CHECK(hana::equal(
  75. hana::mod(hana::value(x), hana::value(y)),
  76. hana::value(hana::mod(x, y))
  77. ));
  78. })(x, y));
  79. });
  80. }
  81. };
  82. }}} // end namespace boost::hana::test
  83. #endif // !BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP