2010-03-19 10 views
6

J'ai un tableau 1d contenant des données Nd, que je souhaite parcourir efficacement avec std :: transform ou std :: for_each.C++/STL: std :: transforme avec la foulée donnée?

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?? 
+0

Que voulez-vous que 'strMover' (ou l'ensemble' transform') fasse? – jpalecek

+0

Salut, j'ai besoin d'une transformation complète. Le strMover que j'ai écrit juste à titre d'illustration ... – Arman

Répondre

1

Eh bien, je l'ai décidé d'utiliser for_each au lieu de transformer toutes les autres décisions sont les bienvenus:

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)); 

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>); 
      } 
    }; 

De ce premier coup d'oeil est une solution sûre fil.

3

La réponse est de ne pas changer strMover, mais pour changer votre iterator. Définir une nouvelle classe d'itérateur qui enveloppe un float * mais avance de 3 places lorsque operator++ est appelée. .

Vous pouvez utiliser l'amplification de Permutation Iterator et utiliser une permutation non stricte qui ne comprend que la plage que vous êtes intéressé par

Si vous essayez de rouler votre propre iterator, il y a quelques précautions: rester stricte à la norme, vous Il est nécessaire de réfléchir soigneusement à ce que sera l'itérateur «final» correct pour un itérateur de foulée, étant donné que la mise en œuvre naïve ira joyeusement au-delà de la limite permise de la zone obscure, bien après la fin du tableau que les pointeurs ne devraient jamais entrer, par crainte de nasal demons.

Mais je dois demander: pourquoi vous stockez un tableau de points 3d en tant que tableau de float s en premier lieu? Définissez simplement un type de données Point3D et créez-en un tableau à la place. Beaucoup plus simple.

+0

J'aurais +1 mais je suis sorti, mais c'est ce que j'allais dire. S'il y a un besoin, je suis prêt à essayer d'écrire les itérateurs la prochaine fois que j'aurai du temps libre. – GManNickG

+0

Je suppose que je devrais noter que parce qu'un permutateur Iterator stocke sa permutation comme une liste, l'itérateur de permutation ne sera pas un itérateur d'accès aléatoire. Je ne sais pas si ce sera un problème pour paralléliser 'std :: transform' –

1

C'est terrible, les gens vous ont dit d'utiliser plutôt des itérateurs de foulée. Mis à part le fait de ne pas pouvoir utiliser les objets fonctionnels de la bibliothèque standard avec cette approche, il est très, très compliqué pour le compilateur de produire une optimisation multicore ou sse en utilisant des béquilles comme celle-ci. Rechercher "stride itérateur" pour la solution appropriée, par exemple dans C++ cookbook.

Et retour à la question originale ... utilisez Valarray et Stride pour simuler des tableaux multidimensionnels.

0

utilisez des adaptateurs boost. vous pouvez en obtenir des itérateurs. le seul inconvénient est le temps de compilation.

vector<float> pp = vector_load(pP); 
boost::for_each(pp|stride(3)|transformed(dosmtn()));