1 | #ifndef GENERATIVE_TESTS_RG072001_HPP |
---|
2 | #define GENERATIVE_TESTS_RG072001_HPP |
---|
3 | |
---|
4 | // Copyright 2002 The Trustees of Indiana University. |
---|
5 | |
---|
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) |
---|
9 | |
---|
10 | // Boost.MultiArray Library |
---|
11 | // Authors: Ronald Garcia |
---|
12 | // Jeremy Siek |
---|
13 | // Andrew Lumsdaine |
---|
14 | // See http://www.boost.org/libs/multi_array for documentation. |
---|
15 | |
---|
16 | // |
---|
17 | // generative-tests.hpp - Framework for running tests on all the types |
---|
18 | // of multi_array |
---|
19 | // |
---|
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&); |
---|
24 | // |
---|
25 | // template <typename Array> |
---|
26 | // void access(Array& A, const const_array_tag&); |
---|
27 | // |
---|
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. |
---|
31 | // |
---|
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. |
---|
34 | // |
---|
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. |
---|
39 | // |
---|
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. |
---|
42 | // |
---|
43 | // Since generative-tests uses the Boost.Test framework, you must |
---|
44 | // define at least the following: |
---|
45 | // |
---|
46 | // int test_main(int,char*[]) { return run_generative_tests(); } |
---|
47 | // |
---|
48 | #include "boost/multi_array.hpp" |
---|
49 | |
---|
50 | #include "boost/test/minimal.hpp" |
---|
51 | |
---|
52 | #include <algorithm> |
---|
53 | #include <iostream> |
---|
54 | #include <vector> |
---|
55 | |
---|
56 | namespace { |
---|
57 | unsigned int tests_run = 0; |
---|
58 | } // empty namespace |
---|
59 | |
---|
60 | struct mutable_array_tag { }; |
---|
61 | struct const_array_tag { }; |
---|
62 | |
---|
63 | template <typename Array> |
---|
64 | void assign_if_not_const(Array&, const const_array_tag&) { |
---|
65 | // do nothing |
---|
66 | } |
---|
67 | |
---|
68 | template <typename Array> |
---|
69 | void assign_if_not_const(Array& A, const mutable_array_tag&); |
---|
70 | |
---|
71 | #ifndef MULTIARRAY_TEST_ASSIGN |
---|
72 | template <typename Array> |
---|
73 | void assign_if_not_const(Array& A, const mutable_array_tag&) { |
---|
74 | |
---|
75 | typedef typename Array::index index; |
---|
76 | |
---|
77 | const index idx0 = A.index_bases()[0]; |
---|
78 | const index idx1 = A.index_bases()[1]; |
---|
79 | const index idx2 = A.index_bases()[2]; |
---|
80 | |
---|
81 | |
---|
82 | int num = 0; |
---|
83 | for (index i = idx0; i != idx0 + 2; ++i) |
---|
84 | for (index j = idx1; j != idx1 + 3; ++j) |
---|
85 | for (index k = idx2; k != idx2 + 4; ++k) |
---|
86 | A[i][j][k] = num++; |
---|
87 | } |
---|
88 | #endif // MULTIARRAY_TEST_ASSIGN |
---|
89 | |
---|
90 | template <typename Array> |
---|
91 | void assign(Array& A) { |
---|
92 | assign_if_not_const(A,mutable_array_tag()); |
---|
93 | } |
---|
94 | |
---|
95 | template <typename Array> |
---|
96 | void access(Array& A, const mutable_array_tag&); |
---|
97 | |
---|
98 | template <typename Array> |
---|
99 | void access(Array& A, const const_array_tag&); |
---|
100 | |
---|
101 | template <typename StorageOrder3,typename StorageOrder4,typename Modifier> |
---|
102 | int run_configuration(const StorageOrder3& so3, |
---|
103 | const StorageOrder4& so4, |
---|
104 | const Modifier& modifier) { |
---|
105 | // multi_array |
---|
106 | { |
---|
107 | typedef boost::multi_array<int,3> array; |
---|
108 | typename array::extent_gen extents; |
---|
109 | { |
---|
110 | array A(extents[2][3][4],so3); |
---|
111 | modifier.modify(A); |
---|
112 | access(A,mutable_array_tag()); |
---|
113 | } |
---|
114 | } |
---|
115 | // multi_array_ref |
---|
116 | { |
---|
117 | typedef boost::multi_array_ref<int,3> array_ref; |
---|
118 | typename array_ref::extent_gen extents; |
---|
119 | { |
---|
120 | int local[24]; |
---|
121 | array_ref A(local,extents[2][3][4],so3); |
---|
122 | modifier.modify(A); |
---|
123 | access(A,mutable_array_tag()); |
---|
124 | } |
---|
125 | } |
---|
126 | // const_multi_array_ref |
---|
127 | { |
---|
128 | typedef boost::multi_array_ref<int,3> array_ref; |
---|
129 | typedef boost::const_multi_array_ref<int,3> const_array_ref; |
---|
130 | typename array_ref::extent_gen extents; |
---|
131 | { |
---|
132 | int local[24]; |
---|
133 | array_ref A(local,extents[2][3][4],so3); |
---|
134 | modifier.modify(A); |
---|
135 | assign(A); |
---|
136 | |
---|
137 | const_array_ref B = A; |
---|
138 | access(B,const_array_tag()); |
---|
139 | } |
---|
140 | } |
---|
141 | // sub_array |
---|
142 | { |
---|
143 | typedef boost::multi_array<int,4> array; |
---|
144 | typename array::extent_gen extents; |
---|
145 | { |
---|
146 | array A(extents[2][2][3][4],so4); |
---|
147 | modifier.modify(A); |
---|
148 | typename array::template subarray<3>::type B = A[1]; |
---|
149 | access(B,mutable_array_tag()); |
---|
150 | } |
---|
151 | } |
---|
152 | // const_sub_array |
---|
153 | { |
---|
154 | typedef boost::multi_array<int,4> array; |
---|
155 | typename array::extent_gen extents; |
---|
156 | { |
---|
157 | array A(extents[2][2][3][4],so4); |
---|
158 | modifier.modify(A); |
---|
159 | typename array::template subarray<3>::type B = A[1]; |
---|
160 | assign(B); |
---|
161 | |
---|
162 | typename array::template const_subarray<3>::type C = B; |
---|
163 | access(C,const_array_tag()); |
---|
164 | } |
---|
165 | } |
---|
166 | // array_view |
---|
167 | { |
---|
168 | typedef boost::multi_array<int,3> array; |
---|
169 | typedef typename array::index_range range; |
---|
170 | typename array::index_gen indices; |
---|
171 | typename array::extent_gen extents; |
---|
172 | { |
---|
173 | typedef typename array::index index; |
---|
174 | |
---|
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 | |
---|
181 | typename array::template array_view<3>::type B =A[ |
---|
182 | indices[range(idx0+1,idx0+3)] |
---|
183 | [range(idx1+1,idx1+4)] |
---|
184 | [range(idx2+1,idx2+5)] |
---|
185 | ]; |
---|
186 | access(B,mutable_array_tag()); |
---|
187 | } |
---|
188 | } |
---|
189 | // const_array_view |
---|
190 | { |
---|
191 | typedef boost::multi_array<int,3> array; |
---|
192 | typedef typename array::index_range range; |
---|
193 | typename array::index_gen indices; |
---|
194 | typename array::extent_gen extents; |
---|
195 | { |
---|
196 | typedef typename array::index index; |
---|
197 | |
---|
198 | array A(extents[4][5][6],so3); |
---|
199 | modifier.modify(A); |
---|
200 | const index idx0 = A.index_bases()[0]; |
---|
201 | const index idx1 = A.index_bases()[1]; |
---|
202 | const index idx2 = A.index_bases()[2]; |
---|
203 | |
---|
204 | typename array::template array_view<3>::type B =A[ |
---|
205 | indices[range(idx0+1,idx0+3)] |
---|
206 | [range(idx1+1,idx1+4)] |
---|
207 | [range(idx2+1,idx2+5)] |
---|
208 | ]; |
---|
209 | assign(B); |
---|
210 | |
---|
211 | typename array::template const_array_view<3>::type C = B; |
---|
212 | access(C,const_array_tag()); |
---|
213 | } |
---|
214 | } |
---|
215 | return boost::exit_success; |
---|
216 | } |
---|
217 | |
---|
218 | template <typename ArrayModifier> |
---|
219 | int 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); |
---|
224 | |
---|
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), |
---|
229 | modifier); |
---|
230 | |
---|
231 | return boost::exit_success; |
---|
232 | } |
---|
233 | |
---|
234 | struct null_modifier { |
---|
235 | template <typename Array> |
---|
236 | void modify(Array&) const { } |
---|
237 | }; |
---|
238 | |
---|
239 | struct set_index_base_modifier { |
---|
240 | template <typename Array> |
---|
241 | void modify(Array& A) const { A.reindex(1); } |
---|
242 | }; |
---|
243 | |
---|
244 | struct reindex_modifier { |
---|
245 | template <typename Array> |
---|
246 | void modify(Array& A) const { |
---|
247 | boost::array<int,4> bases = {{1,2,3,4}}; |
---|
248 | A.reindex(bases); |
---|
249 | } |
---|
250 | }; |
---|
251 | |
---|
252 | struct reshape_modifier { |
---|
253 | template <typename Array> |
---|
254 | void modify(Array& A) const { |
---|
255 | typedef typename Array::size_type size_type; |
---|
256 | std::vector<size_type> old_shape(A.num_dimensions()); |
---|
257 | std::vector<size_type> new_shape(A.num_dimensions()); |
---|
258 | |
---|
259 | std::copy(A.shape(),A.shape()+A.num_dimensions(),old_shape.begin()); |
---|
260 | std::copy(old_shape.rbegin(),old_shape.rend(),new_shape.begin()); |
---|
261 | |
---|
262 | A.reshape(new_shape); |
---|
263 | A.reshape(old_shape); |
---|
264 | } |
---|
265 | }; |
---|
266 | |
---|
267 | int run_generative_tests() { |
---|
268 | |
---|
269 | run_storage_tests(null_modifier()); |
---|
270 | run_storage_tests(set_index_base_modifier()); |
---|
271 | run_storage_tests(reindex_modifier()); |
---|
272 | run_storage_tests(reshape_modifier()); |
---|
273 | std::cout << "Total Tests Run: " << tests_run << '\n'; |
---|
274 | return boost::exit_success; |
---|
275 | } |
---|
276 | |
---|
277 | #endif // GENERATIVE_TESTS_RG072001_HPP |
---|