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