#ifndef GENERATIVE_TESTS_RG072001_HPP #define GENERATIVE_TESTS_RG072001_HPP // Copyright 2002 The Trustees of Indiana University. // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Boost.MultiArray Library // Authors: Ronald Garcia // Jeremy Siek // Andrew Lumsdaine // See http://www.boost.org/libs/multi_array for documentation. // // generative-tests.hpp - Framework for running tests on all the types // of multi_array // // In order to create a set of tests, you must define the following two // function signatures: // template // void access(Array& A, const mutable_array_tag&); // // template // void access(Array& A, const const_array_tag&); // // The framework will always pass 2x3x4 arrays into these functions. // The const_array_tag version of access must NOT attempt to modify // the array. Assume that the passed array has constness in this case. // // The mutable_array_tag version of access should pass the array to the // assign() function in order to set its values before running tests. // // If you wish to write your own code to assign data to the array // (ie. test the iterators by assigning data with them), you must // #define MULTIARRAY_TEST_ASSIGN before including this file. // assign() will call this function. // // If you wish to know how many tests were run, you must increment // the global variable 'tests_run' somewhere in your test code. // // Since generative-tests uses the Boost.Test framework, you must // define at least the following: // // int test_main(int,char*[]) { return run_generative_tests(); } // #include #include #include /* BOOST_NO_SFINAE */ #include #include #include namespace { unsigned int tests_run = 0; } // empty namespace struct mutable_array_tag { }; struct const_array_tag { }; template void assign_if_not_const(Array&, const const_array_tag&) { // do nothing } template void assign_if_not_const(Array& A, const mutable_array_tag&); #ifndef MULTIARRAY_TEST_ASSIGN template void assign_if_not_const(Array& A, const mutable_array_tag&) { typedef typename Array::index index; const index idx0 = A.index_bases()[0]; const index idx1 = A.index_bases()[1]; const index idx2 = A.index_bases()[2]; int num = 0; for (index i = idx0; i != idx0 + 2; ++i) for (index j = idx1; j != idx1 + 3; ++j) for (index k = idx2; k != idx2 + 4; ++k) A[i][j][k] = num++; } #endif // MULTIARRAY_TEST_ASSIGN template void assign(Array& A) { assign_if_not_const(A,mutable_array_tag()); } template void access(Array& A, const mutable_array_tag&); template void access(Array& A, const const_array_tag&); template void run_configuration(const StorageOrder3& so3, const StorageOrder4& so4, const Modifier& modifier) { // multi_array { typedef boost::multi_array array; typename array::extent_gen extents; { array A(extents[2][3][4],so3); modifier.modify(A); access(A,mutable_array_tag()); } } // multi_array_ref { typedef boost::multi_array_ref array_ref; typename array_ref::extent_gen extents; { int local[24]; array_ref A(local,extents[2][3][4],so3); modifier.modify(A); access(A,mutable_array_tag()); } } // const_multi_array_ref { typedef boost::multi_array_ref array_ref; typedef boost::const_multi_array_ref const_array_ref; typename array_ref::extent_gen extents; { int local[24]; array_ref A(local,extents[2][3][4],so3); modifier.modify(A); assign(A); const_array_ref B = A; access(B,const_array_tag()); } } // sub_array { typedef boost::multi_array array; typename array::extent_gen extents; { array A(extents[2][2][3][4],so4); modifier.modify(A); typename array::template subarray<3>::type B = A[1]; access(B,mutable_array_tag()); } } // const_sub_array { typedef boost::multi_array array; typename array::extent_gen extents; { array A(extents[2][2][3][4],so4); modifier.modify(A); typename array::template subarray<3>::type B = A[1]; assign(B); typename array::template const_subarray<3>::type C = B; access(C,const_array_tag()); } } // array_view { typedef boost::multi_array array; typedef typename array::index_range range; typename array::index_gen indices; typename array::extent_gen extents; { typedef typename array::index index; array A(extents[4][5][6],so3); modifier.modify(A); const index idx0 = A.index_bases()[0]; const index idx1 = A.index_bases()[1]; const index idx2 = A.index_bases()[2]; typename array::template array_view<3>::type B =A[ indices[range(idx0+1,idx0+3)] [range(idx1+1,idx1+4)] [range(idx2+1,idx2+5)] ]; access(B,mutable_array_tag()); } } // const_array_view { typedef boost::multi_array array; typedef typename array::index_range range; typename array::index_gen indices; typename array::extent_gen extents; { typedef typename array::index index; array A(extents[4][5][6],so3); modifier.modify(A); const index idx0 = A.index_bases()[0]; const index idx1 = A.index_bases()[1]; const index idx2 = A.index_bases()[2]; typename array::template array_view<3>::type B =A[ indices[range(idx0+1,idx0+3)] [range(idx1+1,idx1+4)] [range(idx2+1,idx2+5)] ]; assign(B); typename array::template const_array_view<3>::type C = B; access(C,const_array_tag()); } } } template void run_storage_tests(const ArrayModifier& modifier) { run_configuration(boost::c_storage_order(), boost::c_storage_order(),modifier); run_configuration(boost::fortran_storage_order(), boost::fortran_storage_order(),modifier); std::size_t ordering[] = {2,0,1,3}; bool ascending[] = {false,true,true,true}; run_configuration(boost::general_storage_order<3>(ordering,ascending), boost::general_storage_order<4>(ordering,ascending), modifier); } struct null_modifier { template void modify(Array&) const { } }; struct set_index_base_modifier { template void modify(Array& A) const { #ifdef BOOST_NO_SFINAE typedef boost::multi_array_types::index index; A.reindex(index(1)); #else A.reindex(1); #endif } }; struct reindex_modifier { template void modify(Array& A) const { boost::array bases = {{1,2,3,4}}; A.reindex(bases); } }; struct reshape_modifier { template void modify(Array& A) const { typedef typename Array::size_type size_type; std::vector old_shape(A.num_dimensions()); std::vector new_shape(A.num_dimensions()); std::copy(A.shape(),A.shape()+A.num_dimensions(),old_shape.begin()); std::copy(old_shape.rbegin(),old_shape.rend(),new_shape.begin()); A.reshape(new_shape); A.reshape(old_shape); } }; int run_generative_tests() { run_storage_tests(null_modifier()); run_storage_tests(set_index_base_modifier()); run_storage_tests(reindex_modifier()); run_storage_tests(reshape_modifier()); std::cout << "Total Tests Run: " << tests_run << '\n'; return boost::report_errors(); } #endif // GENERATIVE_TESTS_RG072001_HPP