• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
57 namespace {
58   unsigned int tests_run = 0;
59 } // empty namespace
60 
61 struct mutable_array_tag { };
62 struct const_array_tag { };
63 
64 template <typename Array>
assign_if_not_const(Array &,const const_array_tag &)65 void assign_if_not_const(Array&, const const_array_tag&) {
66   // do nothing
67 }
68 
69 template <typename Array>
70 void assign_if_not_const(Array& A, const mutable_array_tag&);
71 
72 #ifndef MULTIARRAY_TEST_ASSIGN
73 template <typename Array>
assign_if_not_const(Array & A,const mutable_array_tag &)74 void 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 
91 template <typename Array>
assign(Array & A)92 void assign(Array& A) {
93   assign_if_not_const(A,mutable_array_tag());
94 }
95 
96 template <typename Array>
97 void access(Array& A, const mutable_array_tag&);
98 
99 template <typename Array>
100 void access(Array& A, const const_array_tag&);
101 
102 template <typename StorageOrder3,typename StorageOrder4,typename Modifier>
run_configuration(const StorageOrder3 & so3,const StorageOrder4 & so4,const Modifier & modifier)103 void 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(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(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(B);
162 
163       typename array::template const_subarray<3>::type C = B;
164       access(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(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(B);
211 
212       typename array::template const_array_view<3>::type C = B;
213       access(C,const_array_tag());
214     }
215   }
216 }
217 
218 template <typename ArrayModifier>
run_storage_tests(const ArrayModifier & modifier)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);
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 
232 struct null_modifier {
233   template <typename Array>
modifynull_modifier234   void modify(Array&) const { }
235 };
236 
237 struct set_index_base_modifier {
238   template <typename Array>
modifyset_index_base_modifier239   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 
249 struct reindex_modifier {
250   template <typename Array>
modifyreindex_modifier251   void modify(Array& A) const {
252     boost::array<int,4> bases = {{1,2,3,4}};
253     A.reindex(bases);
254  }
255 };
256 
257 struct reshape_modifier {
258   template <typename Array>
modifyreshape_modifier259   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 
run_generative_tests()272 int run_generative_tests() {
273 
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();
280 }
281 
282 #endif
283