text: #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 <typename Array>
  //   void access(Array& A, const mutable_array_tag&);
  //
  //   template <typename Array>
  //   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 "boost/multi_array.hpp"
  
  #include "boost/test/minimal.hpp"
  
  #include <boost/config.hpp> /* BOOST_NO_SFINAE */
  #include <algorithm>
  #include <iostream>
  #include <vector>
  
  namespace {
    unsigned int tests_run = 0;
  } // empty namespace 
  
  struct mutable_array_tag { };
  struct const_array_tag { };
  
  template <typename Array>
  void assign_if_not_const(Array&, const const_array_tag&) {
    // do nothing
  }
  
  template <typename Array>
  void assign_if_not_const(Array& A, const mutable_array_tag&);
  
  #ifndef MULTIARRAY_TEST_ASSIGN
  template <typename Array>
  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 <typename Array>
  void assign(Array& A) {
    assign_if_not_const(A,mutable_array_tag());
  }
  
  template <typename Array>
  void access(Array& A, const mutable_array_tag&);
  
  template <typename Array>
  void access(Array& A, const const_array_tag&);
  
  template <typename StorageOrder3,typename StorageOrder4,typename Modifier>
  int run_configuration(const StorageOrder3& so3,
                        const StorageOrder4& so4,
                        const Modifier& modifier) {
    // multi_array
    {
      typedef boost::multi_array<int,3> 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<int,3> 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<int,3> array_ref;
      typedef boost::const_multi_array_ref<int,3> 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<int,4> 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<int,4> 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<int,3> 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<int,3> 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());
      }
    }
    return boost::exit_success;
  }
  
  template <typename ArrayModifier>
  int 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); 
  
    return boost::exit_success;
  }
  
  struct null_modifier {
    template <typename Array>
    void modify(Array&) const { }
  };
  
  struct set_index_base_modifier {
    template <typename Array>
    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 <typename Array>
    void modify(Array& A) const {
      boost::array<int,4> bases = {{1,2,3,4}};
      A.reindex(bases);
   }
  };
  
  struct reshape_modifier {
    template <typename Array>
    void modify(Array& A) const {
      typedef typename Array::size_type size_type;
      std::vector<size_type> old_shape(A.num_dimensions());
      std::vector<size_type> 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::exit_success;
  }
  
  #endif // GENERATIVE_TESTS_RG072001_HPP
  