Hi,
I am coming back to the list with a question on multi_array views.
Some time ago, I asked if I could have a view that would offer a “rotated” multi_array.
That is, if I have a 3D MA (=multi_array)  of dimensions (shape) {L,M,N}), I would like to obtain a
reference to it which would look like {M,N,L} i.e. cyclically rotated (I would actually wish to be able to perform
this rotation many times). The operation should be performed at compile time (no need/wish to do it at run
time and pay the possible overhead in speed).
A couple of friends suggested that I used a storage structure something like this (files are attached for convenience of inspection).
 
namespace boost {
 
  class cyclic_storage_order
  {
    typedef detail::multi_array::size_type size_type;
  public:
      cyclic_storage_order( const std::size_t shift )
          :shift_(shift)
      {}
    template <std::size_t NumDims>
    operator general_storage_order<NumDims>() const {
      boost::array<size_type,NumDims> ordering;
      boost::array<bool,NumDims> ascending;
 
      for (size_type i=0; i != NumDims; ++i) {
        ordering[i] = (i+shift_)%NumDims;
        ascending[i] = true;
      }
      return general_storage_order<NumDims>(ordering.begin(),
                                            ascending.begin());
    }
  private:
      std::size_t shift_;
  };
}
 
Now, I am trying to use this is the following example (again the file is attached):
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
using std::cout;
using std::endl;
#include <boost/multi_array.hpp>
using boost::multi_array;
using boost::multi_array_ref;
using boost::const_multi_array_ref;
 
#include "MultiArrayRotation.h"
 
int main(){
    const unsigned short dimensionality = 3;
    typedef multi_array< int, dimensionality > IntArray;
    typedef IntArray::size_type size_type;
    typedef const_multi_array_ref< int, dimensionality > IntArrayCRef;
 
    boost::array<size_type,dimensionality> sizes = { { 2,3,4 } };
    IntArray a( sizes );
    boost::cyclic_storage_order cyclic_storage(1);
    boost::array<size_type,dimensionality> sizesRotated = { { 3, 4, 2 } };
    IntArrayCRef rotated( a.data(), sizesRotated, cyclic_storage );
 
//initialize:
    for ( size_t i = 0 ; i != sizes[0]; ++i )
        for ( size_t j = 0 ; j != sizes[1]; ++j )
            for ( size_t k = 0 ; k != sizes[2]; ++k )
                a[i][j][k] = (i+1) + 10 * (j+1) + 100*(k+1);
 
    typedef IntArray::const_iterator iterator3;
    typedef boost::subarray_gen<IntArray,2>::type::const_iterator  iterator2;
    typedef boost::subarray_gen<IntArray,1>::type::const_iterator    iterator1;
 
    for ( iterator3 it3 = a.begin(); it3 != a.end(); ++ it3 ) {
        cout << "in first iterator:";
        boost::detail::multi_array::const_sub_array<int,2>    & d2 = *it3;
        cout << (d2.shape())[0] << "x" << (d2.shape())[1] << endl;
        for ( iterator2 it2 = it3->begin(); it2 != it3->end(); ++ it2 ) {
//            cout << "\t" << it2->shape()[0] << endl;
            for ( iterator1 it1 = it2->begin(); it1 != it2->end(); ++ it1 )
                cout << "\t\t" << (*it1) << endl;
        }
    }
//for a rotated system:
    typedef IntArrayCRef::const_iterator iterator3CRef;
    typedef boost::subarray_gen<IntArrayCRef,2>::type::const_iterator  iterator2CRef;
    typedef boost::subarray_gen<IntArrayCRef,1>::type::const_iterator    iterator1CRef;
 
    cout  << endl << "In Rotated System" << endl;
    for ( iterator3CRef it3 = rotated.begin(); it3 != rotated.end(); ++ it3 ) {
        cout << "in first iterator:";
        //boost::const_multi_array_ref::const_sub_array<int,2>    & d2 = *it3;
        cout << (it3->shape())[0] << "x" << (it3->shape())[1] << endl;
        for ( iterator2CRef it2 = it3->begin(); it2 != it3->end(); ++ it2 ) {
//            cout << "\t" << it2->shape()[0] << endl;
            for ( iterator1CRef it1 = it2->begin(); it1 != it2->end(); ++ it1 )
                cout << "\t\t" << (*it1) << endl;
        }
    }
 
    return 1;
}
 
This gives me undesired results, though. What I have done here, is define a 2x3x4 main array with entries like abc (i.e. 3 digits).
From the value of abc I can infer the coordinates of the element in the main array.
Following the cascade of iterators to sub_arrays, I see that, in the end, I obtain for each value of the first coordinate, the corresponding slices.
Then I do a rotation (once) and descend down the iterators. I would expect now 3 slices (instead of 2, before), organized so that each one has the same middle digit (in the abc
“representation”. This, however, is not happenning!
I attach the code which I have built successfully w/msvc2010 on win7. I use boost1.45.
A friend (Larry Evans) , who had offered a lot of help in the past and whom I contacted for suggestion let me know that, the program did not compile in his environment
(gcc 4.6.0 and boost v1.46).
Any suggestion, help will be greatly appreciated.
Kind Regards,
Petros