1#ifndef BOOST_MULTI_ARRAY_GENERATIVE_TESTS_HPP
2#define BOOST_MULTI_ARRAY_GENERATIVE_TESTS_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/core/lightweight_test.hpp>
51
52#include <boost/config.hpp> /* BOOST_NO_SFINAE */
53#include <algorithm>
54#include <iostream>
55#include <vector>
56
57namespace {
58 unsigned int tests_run = 0;
59} // empty namespace
60
61struct mutable_array_tag { };
62struct const_array_tag { };
63
64template <typename Array>
65void assign_if_not_const(Array&, const const_array_tag&) {
66 // do nothing
67}
68
69template <typename Array>
70void assign_if_not_const(Array& A, const mutable_array_tag&);
71
72#ifndef MULTIARRAY_TEST_ASSIGN
73template <typename Array>
74void assign_if_not_const(Array& A, const mutable_array_tag&) {
75
76 typedef typename Array::index index;
77
78 const index idx0 = A.index_bases()[0];
79 const index idx1 = A.index_bases()[1];
80 const index idx2 = A.index_bases()[2];
81
82
83 int num = 0;
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)
87 A[i][j][k] = num++;
88}
89#endif // MULTIARRAY_TEST_ASSIGN
90
91template <typename Array>
92void assign(Array& A) {
93 assign_if_not_const(A,mutable_array_tag());
94}
95
96template <typename Array>
97void access(Array& A, const mutable_array_tag&);
98
99template <typename Array>
100void access(Array& A, const const_array_tag&);
101
102template <typename StorageOrder3,typename StorageOrder4,typename Modifier>
103void run_configuration(const StorageOrder3& so3,
104 const StorageOrder4& so4,
105 const Modifier& modifier) {
106 // multi_array
107 {
108 typedef boost::multi_array<int,3> array;
109 typename array::extent_gen extents;
110 {
111 array A(extents[2][3][4],so3);
112 modifier.modify(A);
113 access(A,mutable_array_tag());
114 }
115 }
116 // multi_array_ref
117 {
118 typedef boost::multi_array_ref<int,3> array_ref;
119 typename array_ref::extent_gen extents;
120 {
121 int local[24];
122 array_ref A(local,extents[2][3][4],so3);
123 modifier.modify(A);
124 access(A,mutable_array_tag());
125 }
126 }
127 // const_multi_array_ref
128 {
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;
132 {
133 int local[24];
134 array_ref A(local,extents[2][3][4],so3);
135 modifier.modify(A);
136 assign(A);
137
138 const_array_ref B = A;
139 access(A&: B,const_array_tag());
140 }
141 }
142 // sub_array
143 {
144 typedef boost::multi_array<int,4> array;
145 typename array::extent_gen extents;
146 {
147 array A(extents[2][2][3][4],so4);
148 modifier.modify(A);
149 typename array::template subarray<3>::type B = A[1];
150 access(A&: B,mutable_array_tag());
151 }
152 }
153 // const_sub_array
154 {
155 typedef boost::multi_array<int,4> array;
156 typename array::extent_gen extents;
157 {
158 array A(extents[2][2][3][4],so4);
159 modifier.modify(A);
160 typename array::template subarray<3>::type B = A[1];
161 assign(A&: B);
162
163 typename array::template const_subarray<3>::type C = B;
164 access(A&: C,const_array_tag());
165 }
166 }
167 // 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
176 array A(extents[4][5][6],so3);
177 modifier.modify(A);
178 const index idx0 = A.index_bases()[0];
179 const index idx1 = A.index_bases()[1];
180 const index idx2 = A.index_bases()[2];
181
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)]
186 ];
187 access(A&: B,mutable_array_tag());
188 }
189 }
190 // const_array_view
191 {
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;
196 {
197 typedef typename array::index index;
198
199 array A(extents[4][5][6],so3);
200 modifier.modify(A);
201 const index idx0 = A.index_bases()[0];
202 const index idx1 = A.index_bases()[1];
203 const index idx2 = A.index_bases()[2];
204
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)]
209 ];
210 assign(A&: B);
211
212 typename array::template const_array_view<3>::type C = B;
213 access(A&: C,const_array_tag());
214 }
215 }
216}
217
218template <typename ArrayModifier>
219void 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
232struct null_modifier {
233 template <typename Array>
234 void modify(Array&) const { }
235};
236
237struct 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;
242 A.reindex(index(1));
243#else
244 A.reindex(1);
245#endif
246 }
247};
248
249struct reindex_modifier {
250 template <typename Array>
251 void modify(Array& A) const {
252 boost::array<int,4> bases = {.elems: {1,2,3,4}};
253 A.reindex(bases);
254 }
255};
256
257struct 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());
263
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());
266
267 A.reshape(new_shape);
268 A.reshape(old_shape);
269 }
270};
271
272int run_generative_tests() {
273
274 run_storage_tests(modifier: null_modifier());
275 run_storage_tests(modifier: set_index_base_modifier());
276 run_storage_tests(modifier: reindex_modifier());
277 run_storage_tests(modifier: reshape_modifier());
278 std::cout << "Total Tests Run: " << tests_run << '\n';
279 return boost::report_errors();
280}
281
282#endif
283

source code of boost/libs/multi_array/test/generative_tests.hpp