// matrix transpose, using for_each
// line

#include <stdio.h>

#include <thrust/device_vector.h>
#include <thrust/sequence.h>

typedef thrust::device_vector<int> dvec;
typedef thrust::device_vector<int>::iterator dveciter;

// functor
struct reflectit {
   const int nrow,ncol;
   const dveciter oldm, newm;  
   reflectit(dveciter _oldm, dveciter _newm, int _nrow, int _ncol): 
      oldm(_oldm), newm(_newm), nrow(_nrow), ncol(_ncol) {}
   __device__
   void operator()(const int ij)  
   {  int oldrow = ij / ncol;
      int oldcol = ij % ncol;
      newm[oldcol*nrow+oldrow] = oldm[oldrow*ncol+oldcol]; 
   }
};

dvec transp(dvec oldmat, int nrow, int ncol)
{  int n = nrow * ncol;
   thrust::device_vector<int> newmat(n);
   thrust::device_vector<int> seq(n);
   thrust::sequence (seq.begin(),seq.end());
   thrust::for_each(seq.begin(),seq.end(),
      reflectit(oldmat.begin(),newmat.begin(),nrow,ncol));
   return newmat;

}

int main()
{  int mat[6] = {  // test data
      5, 12, 13,
      3, 4, 5};
   int nrow=2,ncol=3,n=nrow*ncol;
   thrust::device_vector<int> dmat(mat,mat+n);
   dvec newmat = transp(dmat,nrow,ncol);
   // newmat should now hold the transposed matrix, 5,3,12,4,13,5; check it:
   thrust::copy(newmat.begin(), newmat.end(), std::ostream_iterator<int>(std::cout, " "));
   std::cout << "\n";
}

