vector_alloc_test.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright (C) 2016-2018 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/yap/yap.hpp>
  7. #include <vector>
  8. #include <iostream>
  9. #include <boost/test/minimal.hpp>
  10. int allocations = 0;
  11. void * operator new(std::size_t size)
  12. {
  13. ++allocations;
  14. void * retval = malloc(size);
  15. if (!retval)
  16. throw std::bad_alloc();
  17. return retval;
  18. }
  19. void operator delete(void * ptr) noexcept { free(ptr); }
  20. struct take_nth
  21. {
  22. template<typename T>
  23. auto operator()(
  24. boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
  25. std::vector<T> const & vec)
  26. {
  27. return boost::yap::make_terminal(vec[n]);
  28. }
  29. std::size_t n;
  30. };
  31. struct equal_sizes_impl
  32. {
  33. template<typename T>
  34. auto operator()(
  35. boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
  36. std::vector<T> const & vec)
  37. {
  38. auto const expr_size = vec.size();
  39. if (expr_size != size)
  40. value = false;
  41. return 0;
  42. }
  43. std::size_t const size;
  44. bool value;
  45. };
  46. template<typename Expr>
  47. bool equal_sizes(std::size_t size, Expr const & expr)
  48. {
  49. equal_sizes_impl impl{size, true};
  50. boost::yap::transform(boost::yap::as_expr(expr), impl);
  51. return impl.value;
  52. }
  53. template<typename T, typename Expr>
  54. std::vector<T> & assign(std::vector<T> & vec, Expr const & e)
  55. {
  56. decltype(auto) expr = boost::yap::as_expr(e);
  57. assert(equal_sizes(vec.size(), expr));
  58. for (std::size_t i = 0, size = vec.size(); i < size; ++i) {
  59. vec[i] = boost::yap::evaluate(
  60. boost::yap::transform(boost::yap::as_expr(expr), take_nth{i}));
  61. }
  62. return vec;
  63. }
  64. template<typename T, typename Expr>
  65. std::vector<T> & operator+=(std::vector<T> & vec, Expr const & e)
  66. {
  67. decltype(auto) expr = boost::yap::as_expr(e);
  68. assert(equal_sizes(vec.size(), expr));
  69. for (std::size_t i = 0, size = vec.size(); i < size; ++i) {
  70. vec[i] += boost::yap::evaluate(
  71. boost::yap::transform(boost::yap::as_expr(expr), take_nth{i}));
  72. }
  73. return vec;
  74. }
  75. template<typename T>
  76. struct is_vector : std::false_type
  77. {
  78. };
  79. template<typename T, typename A>
  80. struct is_vector<std::vector<T, A>> : std::true_type
  81. {
  82. };
  83. BOOST_YAP_USER_UDT_UNARY_OPERATOR(
  84. negate, boost::yap::expression, is_vector); // -
  85. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  86. multiplies, boost::yap::expression, is_vector); // *
  87. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  88. divides, boost::yap::expression, is_vector); // /
  89. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  90. modulus, boost::yap::expression, is_vector); // %
  91. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  92. plus, boost::yap::expression, is_vector); // +
  93. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  94. minus, boost::yap::expression, is_vector); // -
  95. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  96. less, boost::yap::expression, is_vector); // <
  97. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  98. greater, boost::yap::expression, is_vector); // >
  99. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  100. less_equal, boost::yap::expression, is_vector); // <=
  101. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  102. greater_equal, boost::yap::expression, is_vector); // >=
  103. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  104. equal_to, boost::yap::expression, is_vector); // ==
  105. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  106. not_equal_to, boost::yap::expression, is_vector); // !=
  107. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  108. logical_or, boost::yap::expression, is_vector); // ||
  109. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  110. logical_and, boost::yap::expression, is_vector); // &&
  111. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  112. bitwise_and, boost::yap::expression, is_vector); // &
  113. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  114. bitwise_or, boost::yap::expression, is_vector); // |
  115. BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
  116. bitwise_xor, boost::yap::expression, is_vector); // ^
  117. int test_main(int, char * [])
  118. {
  119. int i;
  120. int const n = 10;
  121. std::vector<int> a(n), b(n), c(n), d(n);
  122. std::vector<double> e(n);
  123. // Reset allocation count. There should be none from this point on.
  124. allocations = 0;
  125. for (i = 0; i < n; ++i) {
  126. a[i] = i;
  127. b[i] = 2 * i;
  128. c[i] = 3 * i;
  129. d[i] = i;
  130. }
  131. assign(b, 2);
  132. assign(d, a + b * c);
  133. if_else(d < 30, b, c);
  134. a += if_else(d < 30, b, c);
  135. assign(e, c);
  136. e += e - 4 / (c + 1);
  137. for (i = 0; i < n; ++i) {
  138. std::cout << " a(" << i << ") = " << a[i] << " b(" << i
  139. << ") = " << b[i] << " c(" << i << ") = " << c[i] << " d("
  140. << i << ") = " << d[i] << " e(" << i << ") = " << e[i]
  141. << std::endl;
  142. }
  143. BOOST_CHECK(allocations == 0);
  144. return 0;
  145. }