2010-03-19 12 views
6

Tengo una matriz 1d que contiene datos Nd, me gustaría recorrer efectivamente con std :: transform o std :: for_each.C++/STL: std :: transformar con paso dado?

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

¿Qué quiere 'strMover' (o toda la 'transform') para hacer? – jpalecek

+0

Hola, necesito una transformación completa. El strMover que escribí solo para ilustración ... – Arman

Respuesta

1

Bueno, he decidido utilizar for_each en lugar de transformar cualquier otra decisión son bienvenidos:

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

donde

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 esta primera mirada es una solución segura hilo.

3

la respuesta es no cambiar strMover, pero para cambiar su iterador. Defina una nueva clase de iterador que envuelve float * pero avanza 3 lugares cuando se llama a operator++. .

Puede impulsar el uso de Permutation Iterator y utilizar una permutación no estricta, que sólo incluye el rango que está interesado en

Si intenta rodar su propia iterador, hay algunos aspectos críticos: permanezca estricta de la norma, se Necesitamos pensar cuidadosamente acerca de cuál es el iterador "final" correcto para un iterador de zancada de este tipo, ya que la implementación ingenua pasará alegremente más allá del "final pasado" permitido hasta el área oscura mucho más allá del final del array al que los punteros nunca deberían entrar, por temor a nasal demons.

Pero tengo que preguntar: ¿por qué está almacenando una matriz de puntos 3d como una matriz de float s en primer lugar? Simplemente defina un tipo de datos Point3D y cree una matriz de eso en su lugar. Mucho más simple

+0

Me gustaría +1 pero estoy fuera, pero esto es lo que iba a decir. Si hay una necesidad, estoy dispuesto a tratar de escribir los iteradores la próxima vez que tenga algo de tiempo libre. – GManNickG

+0

Supongo que debería tener en cuenta que, dado que un Iterador de permutación almacena su permutación como una lista, el iterador de permutación no será un iterador de acceso aleatorio. No sé si esto será un problema para la paralelización de 'std :: transform' –

1

Esto es terrible, las personas que dijeron usar iteradores en lugar de zancada. Además de no poder usar objetos funcionales de la biblioteca estándar con este enfoque, es muy, muy complicado para el compilador producir optimización multinúcleo o sse mediante el uso de muletas como esta. Busque "iterador de zancada" para obtener la solución adecuada, por ejemplo, en el libro de cocina C++.

Y volviendo a la pregunta original ... valarray uso y paso para simular matrices multidimensionales.

0

adaptadores uso Boost. puedes obtener iteradores de ellos. la única desventaja es el tiempo de compilación.

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