2010-02-02 4 views
7

Comment puis-je utiliser un std::valarray pour stocker/manipuler un tableau 2D?Comment utiliser std :: valarray pour stocker/manipuler un tableau 2D contigu?

Je voudrais voir un exemple de tableau 2D avec des éléments accédés par des index de ligne/colonne. Quelque chose comme ce pseudo code:

matrix(i,j) = 42; 

Un exemple de la façon d'initialiser un tel tableau serait également agréable.

Je connais déjà Boost.MultiArray, Boost.uBlas et Blitz ++.

N'hésitez pas à répondre pourquoi je ne devrais pas utiliser valarray pour mon cas d'utilisation. Cependant, je souhaite que la mémoire du tableau multidimensionnel soit un bloc contigu (colonnes x lignes). Pas de tableaux imbriqués de style Java.

+0

Pourquoi voudriez-vous utiliser valarray? Je ne l'ai jamais vu utilisé et je ne connais que des arguments contre son utilisation. –

+1

@gf: Je suis assez satisfait de boost pour les tableaux multidimensionnels "dynamiques". Mais je suis tombé sur Valarray ailleurs dans SO, et était curieux de savoir comment il pourrait être utilisé pour les tableaux multidimensionnels. Les exemples en ligne sur l'utilisation de Valarray (en particulier pour mon cas d'utilisation) semblent rares. –

+2

@GeorgFritzsche quels sont les arguments contre l'utilisation? – johnbakers

Répondre

11

Du haut de ma tête:

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 offre de nombreuses possibilités intéressantes d'accéder à des éléments, par tranches, des masques, des tranches ou multidimentionnelle une table indirection. Voir std::slice_array, std::gslice_array, std::mask_array et std::indirect_array pour plus de détails.

+0

Ah oui, merci. C'est ce que je cherchais. J'apprécie particulièrement que vous ayez montré un accès majeur à la ligne/colonne. –

+0

Les données de Valarray sont-elles garanties contiguës, comme les vecteurs? –

+0

De MSDN: La classe de modèle décrit un objet qui contrôle une séquence d'éléments de type qui sont stockés en tant que tableau, conçu pour effectuer des opérations mathématiques à grande vitesse et optimisé pour les performances de calcul. Donc, je suppose que oui. – MSN

0

Here's un exemple qui comprend un peu de manipulation de la matrice

+1

Pourriez-vous au moins inclure un court exemple qui répond à la question? Les sites externes peuvent être en panne à un moment donné. –

+1

Je ne semble pas être capable de trouver une partie 2D 'valarray' dans cet exemple mais une matrice 2D aplatie. Je pense que l'OP veut une chose 'valarray >'. – dirkgently

+0

@dirkgently: Je veux que la mémoire du tableau soit contiguë, donc pas de valarray >. Question éditée –

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

Plus sur valarray:

  • Il est optimisé pour le calcul numérique.
  • Il s'agit d'un conteneur de type vector avec des fonctions membres spéciales pour trancher et découper en dés.
  • Pas itérateurs
  • Conçu pour les machines de vecteur et de mauvais résultats sur les actuels: vector l'accès peut être plus rapide
  • n'a pas été soutenu par tous les compilateurs (consultez la documentation)/mal mis en œuvre
  • Voir 26,1 pour les types qui peut être utilisé comme un paramètre à valarray<T>: par exemple:

3 En outre, de nombreux membres et associés fonctions de valarray peuvent être Instancé avec succès et présentera un comportement bien défini si et seulement si T satisfait exigences supplémentaires spécifiées pour chaque membre ou une fonction connexe.

4 [ Exemple: Il est valable pour instancier valarray, mais l'opérateur>() ne sera pas instancié avec succès pour opérandes valarray, car complexe n'a pas de opérateurs commande. -end example]

Édition 2: Les garanties standard que vector, comme les tableaux, utilisent toujours la mémoire contiguë. De plus, nous avons:

26.5.2 modèle Classe valarray

1 Le modèle de classe valarray est un tableau intelligent unidimensionnel, avec éléments numérotés de manière séquentielle à partir zéro. C'est une représentation du concept mathématique d'un ensemble ordonné de valeurs.L' dimension plus élevée peut être produite par l'idiome familier des indices calculés, ainsi que les puissantes capacités de sous-ensembles fournies par les opérateurs d'indice généralisés.

et en outre:

26.5.2.3 accès d'élément de valarray

4 De la même manière, l'expression & a [i] = & b [j] évalue aussi vrai pour tout! deux tableaux a et b et pour toute taille_t i et size_t j tels que i est inférieur à la longueur de a et j est inférieure à le ng de b. Cette propriété indique une absence d'aliasing et peut être utilisée pour optimiser les compilateurs.

+0

Oups. Pardon. Je n'ai pas clarifié ma question assez rapidement. +1 de toute façon. –

+0

'valarray' est destiné à contenir des tableaux multidimensionnels sans imbrication. 'valarray >' ne devrait être nécessaire que pour un tableau de matrices/tableaux de tailles différentes. – Potatoswatter

+0

Wow, merci pour les citations standard! :-) –

0

Si vous voulez tester le tableau multidimensionnel pour qu'il soit un bloc contigu (colonnes x lignes). Vous pouvez voir cet exemple avec 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;} 
}; 
Questions connexes