2010-03-19 10 views
6

Ich habe ein 1d-Array mit Nd-Daten, ich würde gerne mit std :: transform oder std :: for_each darauf traverse gehen.C++/STL: Std :: transform mit gegebenem Schritt?

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

Was möchten Sie 'strMover' (oder die ganze' Transformation') tun? – jpalecek

+0

Hallo, ich brauche eine ganze Transformation. Der StrMover, den ich nur zur Illustration geschrieben habe ... – Arman

Antwort

1

Nun, ich habe zu verwenden for_each entschieden statt zu verwandeln alle anderen Entscheidungen sind willkommen:

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

wo

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

Von den ersten Blick ist dies ein Thread sichere Lösung.

3

Die Antwort ist nicht strMover zu ändern, aber Ihren Iterator zu ändern. Definieren Sie eine neue Iteratorklasse, die eine float * umschließt, aber um 3 Stellen vorrückt, wenn operator++ aufgerufen wird. .

Sie boost die verwenden können Permutation Iterator und eine nicht strikte Permutation verwendet werden, die nur den Bereich enthält, die Sie interessieren sich für

Wenn Sie versuchen, Ihren eigenen Iterator zu rollen, gibt es einige Fallstricke: auf dem Standard streng zu bleiben, Sie Ich muss genau darüber nachdenken, was der richtige "End" -Iterator für einen solchen Schritt-Iterator ist, da die naive Implementierung fröhlich über das erlaubte "eine-nach-dem-Ende" zu dem dunklen Bereich weit nach dem Ende des Array, dessen Zeiger nie eintreten sollten, aus Angst vor nasal demons.

Aber ich muss fragen: Warum speichern Sie ein Array von 3D-Punkten als ein Array von float s in erster Linie? Definieren Sie einfach einen Point3D Datentyp und erstellen Sie stattdessen ein Array von diesem. Viel einfacher.

+0

Ich würde +1 geben, aber ich bin raus, aber das würde ich sagen. Wenn es einen Bedarf gibt, bin ich bereit zu versuchen, die Iteratoren das nächste Mal zu schreiben, wenn ich etwas Freizeit habe. – GManNickG

+0

Ich nehme an, ich sollte beachten, dass, weil ein Permutations-Iterator seine Permutation als eine Liste speichert, der Permutations-Iterator kein Direktzugriffs-Iterator sein wird. Ich weiß nicht, ob das ein Problem für die Parallelisierung von 'std :: transform 'sein wird –

1

Das ist schrecklich, Leute haben Ihnen gesagt, dass Sie stattdessen Schritt-Iteratoren verwenden sollen. Abgesehen davon, dass Sie mit diesem Ansatz keine funktionalen Objekte aus der Standardbibliothek verwenden können, machen Sie es sehr, sehr kompliziert für den Compiler, mit solchen Krücken Multicore- oder SSE-Optimierung zu erzeugen. Suchen Sie nach "stride iterator" für die richtige Lösung, zum Beispiel in C++ Kochbuch.

Und zurück zur ursprünglichen Frage ... benutze valarray und stride, um mehrdimensionale Arrays zu simulieren.

0

Boost-Adapter verwenden. Sie können Iteratoren daraus erhalten. Der einzige Nachteil ist die Kompilierungszeit.

Verwandte Themen