Boost logo

Boost Users :

Subject: [Boost-users] Multi_array and rotated views
From: petros (pmamales_at_[hidden])
Date: 2011-06-27 21:38:13


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






Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net