generative_tests.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #ifndef GENERATIVE_TESTS_RG072001_HPP
  2. #define GENERATIVE_TESTS_RG072001_HPP
  3. // Copyright 2002 The Trustees of Indiana University.
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // Boost.MultiArray Library
  8. // Authors: Ronald Garcia
  9. // Jeremy Siek
  10. // Andrew Lumsdaine
  11. // See http://www.boost.org/libs/multi_array for documentation.
  12. //
  13. // generative-tests.hpp - Framework for running tests on all the types
  14. // of multi_array
  15. //
  16. // In order to create a set of tests, you must define the following two
  17. // function signatures:
  18. // template <typename Array>
  19. // void access(Array& A, const mutable_array_tag&);
  20. //
  21. // template <typename Array>
  22. // void access(Array& A, const const_array_tag&);
  23. //
  24. // The framework will always pass 2x3x4 arrays into these functions.
  25. // The const_array_tag version of access must NOT attempt to modify
  26. // the array. Assume that the passed array has constness in this case.
  27. //
  28. // The mutable_array_tag version of access should pass the array to the
  29. // assign() function in order to set its values before running tests.
  30. //
  31. // If you wish to write your own code to assign data to the array
  32. // (ie. test the iterators by assigning data with them), you must
  33. // #define MULTIARRAY_TEST_ASSIGN before including this file.
  34. // assign() will call this function.
  35. //
  36. // If you wish to know how many tests were run, you must increment
  37. // the global variable 'tests_run' somewhere in your test code.
  38. //
  39. // Since generative-tests uses the Boost.Test framework, you must
  40. // define at least the following:
  41. //
  42. // int test_main(int,char*[]) { return run_generative_tests(); }
  43. //
  44. #include <boost/multi_array.hpp>
  45. #include <boost/core/lightweight_test.hpp>
  46. #include <boost/config.hpp> /* BOOST_NO_SFINAE */
  47. #include <algorithm>
  48. #include <iostream>
  49. #include <vector>
  50. namespace {
  51. unsigned int tests_run = 0;
  52. } // empty namespace
  53. struct mutable_array_tag { };
  54. struct const_array_tag { };
  55. template <typename Array>
  56. void assign_if_not_const(Array&, const const_array_tag&) {
  57. // do nothing
  58. }
  59. template <typename Array>
  60. void assign_if_not_const(Array& A, const mutable_array_tag&);
  61. #ifndef MULTIARRAY_TEST_ASSIGN
  62. template <typename Array>
  63. void assign_if_not_const(Array& A, const mutable_array_tag&) {
  64. typedef typename Array::index index;
  65. const index idx0 = A.index_bases()[0];
  66. const index idx1 = A.index_bases()[1];
  67. const index idx2 = A.index_bases()[2];
  68. int num = 0;
  69. for (index i = idx0; i != idx0 + 2; ++i)
  70. for (index j = idx1; j != idx1 + 3; ++j)
  71. for (index k = idx2; k != idx2 + 4; ++k)
  72. A[i][j][k] = num++;
  73. }
  74. #endif // MULTIARRAY_TEST_ASSIGN
  75. template <typename Array>
  76. void assign(Array& A) {
  77. assign_if_not_const(A,mutable_array_tag());
  78. }
  79. template <typename Array>
  80. void access(Array& A, const mutable_array_tag&);
  81. template <typename Array>
  82. void access(Array& A, const const_array_tag&);
  83. template <typename StorageOrder3,typename StorageOrder4,typename Modifier>
  84. void run_configuration(const StorageOrder3& so3,
  85. const StorageOrder4& so4,
  86. const Modifier& modifier) {
  87. // multi_array
  88. {
  89. typedef boost::multi_array<int,3> array;
  90. typename array::extent_gen extents;
  91. {
  92. array A(extents[2][3][4],so3);
  93. modifier.modify(A);
  94. access(A,mutable_array_tag());
  95. }
  96. }
  97. // multi_array_ref
  98. {
  99. typedef boost::multi_array_ref<int,3> array_ref;
  100. typename array_ref::extent_gen extents;
  101. {
  102. int local[24];
  103. array_ref A(local,extents[2][3][4],so3);
  104. modifier.modify(A);
  105. access(A,mutable_array_tag());
  106. }
  107. }
  108. // const_multi_array_ref
  109. {
  110. typedef boost::multi_array_ref<int,3> array_ref;
  111. typedef boost::const_multi_array_ref<int,3> const_array_ref;
  112. typename array_ref::extent_gen extents;
  113. {
  114. int local[24];
  115. array_ref A(local,extents[2][3][4],so3);
  116. modifier.modify(A);
  117. assign(A);
  118. const_array_ref B = A;
  119. access(B,const_array_tag());
  120. }
  121. }
  122. // sub_array
  123. {
  124. typedef boost::multi_array<int,4> array;
  125. typename array::extent_gen extents;
  126. {
  127. array A(extents[2][2][3][4],so4);
  128. modifier.modify(A);
  129. typename array::template subarray<3>::type B = A[1];
  130. access(B,mutable_array_tag());
  131. }
  132. }
  133. // const_sub_array
  134. {
  135. typedef boost::multi_array<int,4> array;
  136. typename array::extent_gen extents;
  137. {
  138. array A(extents[2][2][3][4],so4);
  139. modifier.modify(A);
  140. typename array::template subarray<3>::type B = A[1];
  141. assign(B);
  142. typename array::template const_subarray<3>::type C = B;
  143. access(C,const_array_tag());
  144. }
  145. }
  146. // array_view
  147. {
  148. typedef boost::multi_array<int,3> array;
  149. typedef typename array::index_range range;
  150. typename array::index_gen indices;
  151. typename array::extent_gen extents;
  152. {
  153. typedef typename array::index index;
  154. array A(extents[4][5][6],so3);
  155. modifier.modify(A);
  156. const index idx0 = A.index_bases()[0];
  157. const index idx1 = A.index_bases()[1];
  158. const index idx2 = A.index_bases()[2];
  159. typename array::template array_view<3>::type B =A[
  160. indices[range(idx0+1,idx0+3)]
  161. [range(idx1+1,idx1+4)]
  162. [range(idx2+1,idx2+5)]
  163. ];
  164. access(B,mutable_array_tag());
  165. }
  166. }
  167. // const_array_view
  168. {
  169. typedef boost::multi_array<int,3> array;
  170. typedef typename array::index_range range;
  171. typename array::index_gen indices;
  172. typename array::extent_gen extents;
  173. {
  174. typedef typename array::index index;
  175. array A(extents[4][5][6],so3);
  176. modifier.modify(A);
  177. const index idx0 = A.index_bases()[0];
  178. const index idx1 = A.index_bases()[1];
  179. const index idx2 = A.index_bases()[2];
  180. typename array::template array_view<3>::type B =A[
  181. indices[range(idx0+1,idx0+3)]
  182. [range(idx1+1,idx1+4)]
  183. [range(idx2+1,idx2+5)]
  184. ];
  185. assign(B);
  186. typename array::template const_array_view<3>::type C = B;
  187. access(C,const_array_tag());
  188. }
  189. }
  190. }
  191. template <typename ArrayModifier>
  192. void run_storage_tests(const ArrayModifier& modifier) {
  193. run_configuration(boost::c_storage_order(),
  194. boost::c_storage_order(),modifier);
  195. run_configuration(boost::fortran_storage_order(),
  196. boost::fortran_storage_order(),modifier);
  197. std::size_t ordering[] = {2,0,1,3};
  198. bool ascending[] = {false,true,true,true};
  199. run_configuration(boost::general_storage_order<3>(ordering,ascending),
  200. boost::general_storage_order<4>(ordering,ascending),
  201. modifier);
  202. }
  203. struct null_modifier {
  204. template <typename Array>
  205. void modify(Array&) const { }
  206. };
  207. struct set_index_base_modifier {
  208. template <typename Array>
  209. void modify(Array& A) const {
  210. #ifdef BOOST_NO_SFINAE
  211. typedef boost::multi_array_types::index index;
  212. A.reindex(index(1));
  213. #else
  214. A.reindex(1);
  215. #endif
  216. }
  217. };
  218. struct reindex_modifier {
  219. template <typename Array>
  220. void modify(Array& A) const {
  221. boost::array<int,4> bases = {{1,2,3,4}};
  222. A.reindex(bases);
  223. }
  224. };
  225. struct reshape_modifier {
  226. template <typename Array>
  227. void modify(Array& A) const {
  228. typedef typename Array::size_type size_type;
  229. std::vector<size_type> old_shape(A.num_dimensions());
  230. std::vector<size_type> new_shape(A.num_dimensions());
  231. std::copy(A.shape(),A.shape()+A.num_dimensions(),old_shape.begin());
  232. std::copy(old_shape.rbegin(),old_shape.rend(),new_shape.begin());
  233. A.reshape(new_shape);
  234. A.reshape(old_shape);
  235. }
  236. };
  237. int run_generative_tests() {
  238. run_storage_tests(null_modifier());
  239. run_storage_tests(set_index_base_modifier());
  240. run_storage_tests(reindex_modifier());
  241. run_storage_tests(reshape_modifier());
  242. std::cout << "Total Tests Run: " << tests_run << '\n';
  243. return boost::report_errors();
  244. }
  245. #endif // GENERATIVE_TESTS_RG072001_HPP