views:

232

answers:

2

Hello, I have a 1d array containing Nd data, I would like to effectively traverse on it with std::transform or std::for_each.

unigned int nelems;
unsigned int stride=3;// we are going to have 3D points
float *pP;// this will keep xyzxyzxyz...
Load(pP);
std::transform(pP, pP+nelems, strMover<float>(pP, stride));//How to define the strMover??

Kind Regards,
Arman.

+3  A: 

The answer is not to change strMover, but to change your iterator. Define a new iterator class which wraps a float * but moves forward 3 places when operator++ is called.

You can use boost's Permutation Iterator and use a nonstrict permutation which only includes the range you are interested in.

If you try to roll your own iterator, there are some gotchas: to remain strict to the standard, you need to think carefully about what the correct "end" iterator for such a stride iterator is, since the naive implementation will merrily stride over and beyond the allowed "one-past-the-end" to the murky area far past the end of the array which pointers should never enter, for fear of nasal demons.

But I have to ask: why are you storing an array of 3d points as an array of floats in the first place? Just define a Point3D datatype and create an array of that instead. Much simpler.

Philip Potter
I'd +1 but I'm out, but this is what I was going to say. If there is a need, I'm willing to try to write the iterators next time I have some free time.
GMan
I suppose I should note that because a Permutation Iterator stores its permutation as a list, the Permutation Iterator won't be a random access iterator. I don't know if this will be a problem for parallelising `std::transform`
Philip Potter
+1  A: 

Well, I have decided to use for_each instead of transform any other decisions are welcome:

generator<unsigned int> gen(0, 1);
            vector<unsigned int> idx(m_nelem);//make an index
            std::generate(idx.begin(), idx.end(),gen);
            std::for_each(idx.begin(), idx.end(), strMover<float>(&pPOS[0],&m_COM[0],stride));

where

template<class T> T op_sum (T i, T j) { return i+j; }
template<class T> 
class strMover
    {
    T *pP_;
    T *pMove_;
    unsigned int stride_;
    public:
        strMover(T *pP,T *pMove, unsigned int stride):pP_(pP), pMove_(pMove),stride_(stride)
            {}
        void operator() ( const unsigned int ip )
            {
            std::transform(&pP_[ip*stride_], &pP_[ip*stride_]+stride_, 
                pMove_, &pP_[ip*stride_], op_sum<T>);
            }
    };

From first look this is a thread safe solution.

Arman.

Arman