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
operator general_storage_order<NumDims>() const {
boost::array ordering;
boost::array 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
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 sizes = { { 2,3,4 } };
IntArray a( sizes );
boost::cyclic_storage_order cyclic_storage(1);
boost::array 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::type::const_iterator iterator2;
typedef boost::subarray_gen::type::const_iterator iterator1;
for ( iterator3 it3 = a.begin(); it3 != a.end(); ++ it3 ) {
cout << "in first iterator:";
boost::detail::multi_array::const_sub_array & 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::type::const_iterator iterator2CRef;
typedef boost::subarray_gen::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 & 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