1 #ifndef BOOST_MULTI_ARRAY_GENERATIVE_TESTS_HPP
2 #define BOOST_MULTI_ARRAY_GENERATIVE_TESTS_HPP
4 // Copyright 2002 The Trustees of Indiana University.
6 // Use, modification and distribution is subject to the Boost Software
7 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 // Boost.MultiArray Library
11 // Authors: Ronald Garcia
14 // See http://www.boost.org/libs/multi_array for documentation.
17 // generative-tests.hpp - Framework for running tests on all the types
20 // In order to create a set of tests, you must define the following two
21 // function signatures:
22 // template <typename Array>
23 // void access(Array& A, const mutable_array_tag&);
25 // template <typename Array>
26 // void access(Array& A, const const_array_tag&);
28 // The framework will always pass 2x3x4 arrays into these functions.
29 // The const_array_tag version of access must NOT attempt to modify
30 // the array. Assume that the passed array has constness in this case.
32 // The mutable_array_tag version of access should pass the array to the
33 // assign() function in order to set its values before running tests.
35 // If you wish to write your own code to assign data to the array
36 // (ie. test the iterators by assigning data with them), you must
37 // #define MULTIARRAY_TEST_ASSIGN before including this file.
38 // assign() will call this function.
40 // If you wish to know how many tests were run, you must increment
41 // the global variable 'tests_run' somewhere in your test code.
43 // Since generative-tests uses the Boost.Test framework, you must
44 // define at least the following:
46 // int test_main(int,char*[]) { return run_generative_tests(); }
48 #include <boost/multi_array.hpp>
50 #include <boost/core/lightweight_test.hpp>
52 #include <boost/config.hpp> /* BOOST_NO_SFINAE */
58 unsigned int tests_run = 0;
61 struct mutable_array_tag { };
62 struct const_array_tag { };
64 template <typename Array>
65 void assign_if_not_const(Array&, const const_array_tag&) {
69 template <typename Array>
70 void assign_if_not_const(Array& A, const mutable_array_tag&);
72 #ifndef MULTIARRAY_TEST_ASSIGN
73 template <typename Array>
74 void assign_if_not_const(Array& A, const mutable_array_tag&) {
76 typedef typename Array::index index;
78 const index idx0 = A.index_bases()[0];
79 const index idx1 = A.index_bases()[1];
80 const index idx2 = A.index_bases()[2];
84 for (index i = idx0; i != idx0 + 2; ++i)
85 for (index j = idx1; j != idx1 + 3; ++j)
86 for (index k = idx2; k != idx2 + 4; ++k)
89 #endif // MULTIARRAY_TEST_ASSIGN
91 template <typename Array>
92 void assign(Array& A) {
93 assign_if_not_const(A,mutable_array_tag());
96 template <typename Array>
97 void access(Array& A, const mutable_array_tag&);
99 template <typename Array>
100 void access(Array& A, const const_array_tag&);
102 template <typename StorageOrder3,typename StorageOrder4,typename Modifier>
103 void run_configuration(const StorageOrder3& so3,
104 const StorageOrder4& so4,
105 const Modifier& modifier) {
108 typedef boost::multi_array<int,3> array;
109 typename array::extent_gen extents;
111 array A(extents[2][3][4],so3);
113 access(A,mutable_array_tag());
118 typedef boost::multi_array_ref<int,3> array_ref;
119 typename array_ref::extent_gen extents;
122 array_ref A(local,extents[2][3][4],so3);
124 access(A,mutable_array_tag());
127 // const_multi_array_ref
129 typedef boost::multi_array_ref<int,3> array_ref;
130 typedef boost::const_multi_array_ref<int,3> const_array_ref;
131 typename array_ref::extent_gen extents;
134 array_ref A(local,extents[2][3][4],so3);
138 const_array_ref B = A;
139 access(B,const_array_tag());
144 typedef boost::multi_array<int,4> array;
145 typename array::extent_gen extents;
147 array A(extents[2][2][3][4],so4);
149 typename array::template subarray<3>::type B = A[1];
150 access(B,mutable_array_tag());
155 typedef boost::multi_array<int,4> array;
156 typename array::extent_gen extents;
158 array A(extents[2][2][3][4],so4);
160 typename array::template subarray<3>::type B = A[1];
163 typename array::template const_subarray<3>::type C = B;
164 access(C,const_array_tag());
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;
174 typedef typename array::index index;
176 array A(extents[4][5][6],so3);
178 const index idx0 = A.index_bases()[0];
179 const index idx1 = A.index_bases()[1];
180 const index idx2 = A.index_bases()[2];
182 typename array::template array_view<3>::type B =A[
183 indices[range(idx0+1,idx0+3)]
184 [range(idx1+1,idx1+4)]
185 [range(idx2+1,idx2+5)]
187 access(B,mutable_array_tag());
192 typedef boost::multi_array<int,3> array;
193 typedef typename array::index_range range;
194 typename array::index_gen indices;
195 typename array::extent_gen extents;
197 typedef typename array::index index;
199 array A(extents[4][5][6],so3);
201 const index idx0 = A.index_bases()[0];
202 const index idx1 = A.index_bases()[1];
203 const index idx2 = A.index_bases()[2];
205 typename array::template array_view<3>::type B =A[
206 indices[range(idx0+1,idx0+3)]
207 [range(idx1+1,idx1+4)]
208 [range(idx2+1,idx2+5)]
212 typename array::template const_array_view<3>::type C = B;
213 access(C,const_array_tag());
218 template <typename ArrayModifier>
219 void run_storage_tests(const ArrayModifier& modifier) {
220 run_configuration(boost::c_storage_order(),
221 boost::c_storage_order(),modifier);
222 run_configuration(boost::fortran_storage_order(),
223 boost::fortran_storage_order(),modifier);
225 std::size_t ordering[] = {2,0,1,3};
226 bool ascending[] = {false,true,true,true};
227 run_configuration(boost::general_storage_order<3>(ordering,ascending),
228 boost::general_storage_order<4>(ordering,ascending),
232 struct null_modifier {
233 template <typename Array>
234 void modify(Array&) const { }
237 struct set_index_base_modifier {
238 template <typename Array>
239 void modify(Array& A) const {
240 #ifdef BOOST_NO_SFINAE
241 typedef boost::multi_array_types::index index;
249 struct reindex_modifier {
250 template <typename Array>
251 void modify(Array& A) const {
252 boost::array<int,4> bases = {{1,2,3,4}};
257 struct reshape_modifier {
258 template <typename Array>
259 void modify(Array& A) const {
260 typedef typename Array::size_type size_type;
261 std::vector<size_type> old_shape(A.num_dimensions());
262 std::vector<size_type> new_shape(A.num_dimensions());
264 std::copy(A.shape(),A.shape()+A.num_dimensions(),old_shape.begin());
265 std::copy(old_shape.rbegin(),old_shape.rend(),new_shape.begin());
267 A.reshape(new_shape);
268 A.reshape(old_shape);
272 int run_generative_tests() {
274 run_storage_tests(null_modifier());
275 run_storage_tests(set_index_base_modifier());
276 run_storage_tests(reindex_modifier());
277 run_storage_tests(reshape_modifier());
278 std::cout << "Total Tests Run: " << tests_run << '\n';
279 return boost::report_errors();