2010-02-02 10 views
7

¿Cómo puedo usar un std::valarray para almacenar/manipular una matriz 2D?¿Cómo puedo usar una std :: valarray para almacenar/manipular una matriz 2D contigua?

Me gustaría ver un ejemplo de una matriz 2D con elementos accedidos por índices de filas/columnas. Algo como este pseudo código:

matrix(i,j) = 42; 

Un ejemplo de cómo inicializar una matriz también sería bueno.

Ya conozco Boost.MultiArray, Boost.uBlas y Blitz ++.

Siéntase libre de responder por qué no debo usar valarray para mi caso de uso. Sin embargo, quiero que la memoria de la matriz multidimensional sea un bloque contiguo (columnas x filas). No hay matrices anidadas al estilo Java.

+0

¿Por qué le gustaría usar valarray? No lo he visto en uso en ningún lado y solo conozco los argumentos en contra de su uso. –

+1

@gf: Estoy bastante contento con el impulso para las matrices multidimensionales "dinámicas". Pero me topé con Valarray en otro lugar en SO, y tenía curiosidad sobre cómo podría usarse para arreglos multidimensionales. Los ejemplos en línea sobre el uso de valarray (particularmente para mi caso de uso) parecen escasos. –

+2

@GeorgFritzsche ¿cuáles son los argumentos en contra de usarlo? – johnbakers

Respuesta

11

De la parte superior de mi cabeza:

template <class element_type> 
class matrix 
{ 
public: 
    matrix(size_t width, size_t height): m_stride(width), m_height(height), m_storage(width*height) { } 

    element_type &operator()(size_t row, size_t column) 
    { 
     // column major 
     return m_storage[std::slice(column, m_height, m_stride)][row]; 

     // row major 
     return m_storage[std::slice(row, m_stride, m_height)][column]; 
    } 

private: 
    std::valarray<element_type> m_storage; 
    size_t m_stride; 
    size_t m_height; 
}; 

std::valarray proporciona muchas maneras interesantes para tener acceso a los elementos, a través de rodajas, las máscaras, las rebanadas multidimensionales, o una tabla de direccionamiento indirecto. Consulte std::slice_array, std::gslice_array, std::mask_array y std::indirect_array para obtener más información.

+0

Ah sí, gracias. Eso es lo que estaba buscando. Me gusta especialmente que hayas mostrado acceso principal de fila/columna. –

+0

¿Se garantiza que los datos de valarray sean contiguos, como vector? –

+0

de MSDN: la clase de plantilla describe un objeto que controla una secuencia de elementos de tipo Tipo que se almacenan como una matriz, diseñada para realizar operaciones matemáticas de alta velocidad y optimizada para el rendimiento computacional. Entonces, supongo que sí. – MSN

0

Here's un ejemplo que incluye un poco de manipulación de matrices

+1

¿Podría al menos incluir un breve ejemplo que aborde la pregunta? Los sitios externos pueden estar caídos en algún momento. –

+1

No parece ser capaz de encontrar una parte 2D 'valarray' en ese ejemplo, pero una matriz 2D aplanada. Creo que el OP quiere una cosa 'valarray >'. – dirkgently

+0

@dirkgently: Quiero que la memoria de la matriz sea contigua, por lo que no valarray >. Pregunta editada –

5
#include <iostream> 
#include <valarray> 

using namespace std; 

typedef valarray<valarray<int> > va2d; 

int main() 
{ 
    int data[][3] = { {1, 2, 3}, {4, 5, 6} }; 
    va2d mat(valarray<int>(3), 2); 
    for (int i = 0; i < 2; ++i) 
    { 
     for (int j = 0; j < 3; ++j) 
      mat[ i ][ j ] = data[ i ][ j ]; 
    } 
    for (int i = 0; i < 2; ++i) 
     for (int j = 0; j < 3; ++j) 
      cout << mat[ i ][ j ] << endl; 
} 

Más en valarray:

  • Está optimizado para el cálculo numérico.
  • Es un contenedor similar al vector con funciones especiales para cortar y cortar en cubitos.
  • No iteradores
  • Diseñado para máquinas de vectores y un mal desempeño en los actuales: vector de acceso puede ser más rápido
  • no fue apoyada por todos los compiladores (consulte la documentación)/mal implementado
  • Ver 26.1 para los tipos que se puede utilizar como un parámetro para valarray<T>: Ej:

3 Además, muchos miembros y relacionados funciones de valarray pueden ser correctamente instanciado y mostrará comportamiento bien definido si y solo si T cumple con los requisitos adicionales especificados para cada miembro o función relacionada.

4 [ Ejemplo: Es válido para instanciar valarray, pero el operador>() no se instanciado con éxito para operandos valarray, ya complejo no tiene ningún operadores de pedidos. -finalizar el ejemplo]

Edición n. ° 2: Las garantías estándar que vector, como las matrices, siempre usan memoria contigua. Además, tenemos: valarray plantilla

26.5.2 Clase

1 El valarray plantilla de clase es una matriz inteligente unidimensional, con elementos numerados secuencialmente de cero. Es una representación del concepto matemático de un conjunto ordenado de valores.La ilusión de mayor dimensionalidad puede ser producida por el idioma familiar de índices computados, junto con las potentes capacidades de subconjunto proporcionadas por operadores de subíndices generalizados.

y además:

26.5.2.3 acceso elemento valarray

4 Del mismo modo, la expresión & a [i] = & b [j] evalúa como cierto para cualquier! dos matrices a y b y para cualquier tamaño_t i y size_t j tal que i es menor que la longitud de ay j es menor que le ngth de b. Esta propiedad indica una ausencia de aliasing y se puede usar para optimizar los compiladores.

+0

Vaya. Lo siento. No aclaré mi pregunta lo suficientemente rápido. +1 de todos modos. –

+0

'valarray' está destinado a contener matrices multidimensionales sin anidar. 'valarray >' solo debería ser necesario para una matriz de matrices/matrices de diferentes tamaños. – Potatoswatter

+0

¡Guau, gracias por las cotizaciones estándar! :-) –

0

Si desea probar que la matriz multidimensional sea un bloque contiguo (columnas x filas). Puede ver este ejemplo con valarray.

template<class T> 
class Array: public std::valarray<T> { 
    size_t row,col; 
public: 
    Array(){} 
    Array(size_t nx) : std::valarray<T>(nx){row=nx,col=1;} 
    Array(size_t nx, size_t ny) : std::valarray<T>(nx*ny){row=nx,col=ny;} 
    virtual ~Array(){} 
    T& operator()(size_t i,size_t j) { return (*this)[i*col+j];} 
    size_t Size(size_t n) const { return (n<2) ? col: row;} 
}; 
Cuestiones relacionadas