Uso de Mx::Matrix:
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Amigas 'defines'
Matrix_Map.h
Ir a la documentación de este archivo.
1 // Matrix_Map.h Copyright (C) 2004 adolfo@di-mare.com
2 
3 /** \file Matrix_Map.h
4  \brief Declaraciones y definiciones para la clase \c Matrix_Map.
5 
6  \author Adolfo Di Mare <adolfo@di-mare.com>
7  \date 2004
8 
9  - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
10 */
11 
12 #ifndef Matrix_Map_h
13 #define Matrix_Map_h
14 
15 #include <cassert> // assert()
16 #include <list>
17 #include <map>
18 #include <utility>
19 
20 
21 /// Definido por la biblioteca C++ estándar
22 namespace std {} // Está acá para que Doxygen lo documente
23 
24 /// Matriz chirrisquitica de adolfo@di-mare.com
25 namespace Mx {
26 
27 /** Esta es una clase matriz muy chirrisquitica almacenada como una matriz rala implementada con Map.
28  - La matriz tiene tamaño \c rows() x \c cols().
29  - Se le puede cambiar el tamaño dinámicamente con el método \c reSize().
30  - La clase \c E debe incluir un neutro para la adición, cuyo valor debe poderse
31  obtener invocando el convertidor \c Matrix_Map<E>::value_type().
32  - Las operaciones aritméticas "+" "-" "*" deben estar definidas para
33  \c Matrix_Map<E>::value_type y debe existir el valor \c Matrix_Map<E>::value_type().
34  \see http://www.oonumerics.org/oon/
35 */
36 template <class E>
37 class Matrix_Map {
38 public:
39  /// Tipo del objeto almacenado, similar al nombre usado en STL
40  typedef E value_type;
41  /// Tipo del objeto almacenado, similar al nombre usado en STL
43  /// Tipo del objeto almacenado, similar al nombre usado en STL
44  typedef const value_type& const_reference;
45  /// Tipo del tamaño de un objeto, similar al nombre usado en STL
46  typedef unsigned size_type;
47 public:
48  Matrix_Map(unsigned m = 1, unsigned n = 1);
49  Matrix_Map(const Matrix_Map& o); ///< Constructor de copia
50  /// Matriz escalar de valor \c V.
51  Matrix_Map(const value_type V) : m_same() { reSize(1,1); (*this)(0,0) = V; }
52  ~Matrix_Map();
53 public:
54  unsigned rows() const { return m_rows; } ///< Cantidad de filas de la matriz
55  unsigned cols() const { return m_cols; } ///< Cantidad de columnas de la Matriz
56  unsigned size() const { return rows() * m_cols; } ///< Cantidad de valores almacenados en la matriz
57  unsigned count() const { return size(); } ///< Cantidad de valores almacenados en la matriz
58  /// Cantidad máxima posible de valores diferentes que pueden ser almacenados en la matriz
59  size_type capacity() const { return size(); }
60 public:
61  Matrix_Map& operator = (const Matrix_Map &o) { return copy(o); } ///< Sinónimo de \c this->copy(o)
62  Matrix_Map& copy( const Matrix_Map &o );
63  Matrix_Map& move( Matrix_Map &o );
64  Matrix_Map& swap( Matrix_Map &o );
65 public:
66  /// ¿¿¿ (p == q) ???
67  friend bool operator == (const Matrix_Map &p, const Matrix_Map &q) { return p.equals(q); }
68  /// ¿¿¿ (p != q) ???
69  friend bool operator != (const Matrix_Map &p, const Matrix_Map &q) { return !(p==q); }
70  bool equals( const Matrix_Map & o ) const; ///< ¿¿¿ (*this==o) ???
71  /// Retorna \c true si \c "o" comparte sus valores con \c "*this"
72  bool same( const Matrix_Map & o ) const { return this == &o; }
73 private:
74  void add( const Matrix_Map & );
75  void substract( const Matrix_Map & );
76  void multiply( const Matrix_Map &, const Matrix_Map & );
77 public:
78  friend Matrix_Map operator + (const Matrix_Map& A, const Matrix_Map& B)
79  { Matrix_Map Res = A; Res.add(B); return Res; } ///< Retorna \c A+B
80  friend Matrix_Map operator - (const Matrix_Map& A, const Matrix_Map& B)
81  { Matrix_Map Res = A; Res.substract(B); return Res; } ///< Retorna \c A-B
82  friend Matrix_Map operator * (const Matrix_Map& A, const Matrix_Map& B)
83  { Matrix_Map Res; Res.multiply(A, B); return Res; } ///< Retorna \c A*B
84 public:
85  reference operator () (unsigned, unsigned);
86  const_reference operator () (unsigned, unsigned) const;
87 public:
88  void reSize( unsigned, unsigned);
89  void reShape(unsigned, unsigned);
90 public:
91  void setDefault(const E& same);
92  /// Valor almacenado en la mayor parte de la \c Matrix_Map
93  const E& getDefault() { return m_same; }
94  /// Ajusta la matriz para que pueda almacenar \c n valores diferentes a \c getDefault().
95  void reserve(size_type _Count);
96  void reSize(unsigned newsize);
97  void clear();
98 
99  template<class T> friend bool check_ok( const Matrix_Map<T>& M );
100  template<class T> friend class test_Matrix_Map; ///< Datos de prueba para la clase
101 private:
102  typedef
103  std::map<
104  std::pair<unsigned,unsigned>,
105  E
106  // ,std::less< std::pair<unsigned,unsigned> >
108  Diccionario m_dicc; ///< Vector que contiene los valores de la matiz.
109  unsigned m_rows; ///< Cantidad de filas de la matriz
110  unsigned m_cols; ///< Cantidad de columnas de la matriz
111  E m_same; ///< Valor almacenado en la mayor parte de la \c Matrix_Map
112 }; // Matrix_Map
113 
114 /** Verifica la invariante de la clase.
115  - El campo \c m_same indica cuál es el valor que se repite más en toda la matriz.
116  - Usualmente \c m_same es el neutro aditivo \c value_type().
117  - No existe un constructor explícito para darle a \c m_same su valor inicial, que
118  es siempre inicializado en \c value_type(). Para cambiarlo es necesario invocar
119  el método \c setgetDefault().
120  - El vector \c m_dicc contiene las listas de valores almacenados en la matriz.
121  Cualquiera de estas listas puede estar vacía; aún todas pueden ser listas vacías.
122  - La cantidad de columnas de la matriz es el valor fijo es \c m_cols.
123  - El largo de las listas de valores cambia cuando se hace referencia a un valor M(i,j)
124  mediante la versión que no es \c const del \c operator()(i,j). O sea, que es
125  ese método el encargado de agregar valores en \c m_dicc, pues el operador
126  homónimo \c const operator()(i,j) nunca agrega nada y, como es \c const, en
127  general retorna una referencia constante a \c m_same.
128  - Es posible que la matriz tenga dimensiones nulas, lo que implica que el vector
129  \c m_dicc está vacío.
130  - No hace falta alacenar la cantidad de valores de la matriz porque se siempre es
131  \c m_VL.size().
132  el valor \c 0 (cero) al campo \c m_capacity.
133 
134  \par <em>Rep</em> Modelo de la clase
135 \code
136 std::map<std::pair<unsigned,unsigned>, E , std::less<std::pair<unsigned,unsigned> > >
137 
138  m_dicc IT
139  /\
140  / \
141  / \
142  First second
143  _____________________
144  / \
145  | std::pair <0,1>, 'a' |
146  \_____________________/ 0 1 2 3 4 5 6
147  M(0,1)=='a' 0 / - a - - - - - \
148  1 | - - - - - - - |
149  _____________________ 2 | - - - - - - - |
150  / \ 3 | - - - - - b - |
151  | std::pair <3,5>, 'b' | 4 \ - - - - - - - /
152  \_____________________/
153  M(3,5)=='b'
154 
155  m_same == '-' m_rows == 5 m_cols == 7
156 \endcode
157 
158  - http://www.di-mare.com/adolfo/binder/c03.htm#k1-Rep
159  \remark
160  Libera al programador de implementar el método \c Ok()
161  - http://www.di-mare.com/adolfo/binder/c04.htm#sc11
162 */
163 template<class T>
164 bool check_ok( const Matrix_Map<T>& M ) {
165  if ( ! (&M != 0 ) ) {
166  /// - Invariante: ningún objeto puede estar almacenado en la posición nula.
167  return false;
168  }
169  if ( M.m_cols == 0 ) { // m_cols es el "marcador" que determina el valor de los demás
170  if ( ! ((M.m_dicc).empty()) ) {
171  return false; /// - Invariante: <code>(m_cols == 0) <==> (m_dicc.empty())</code>
172  }
173  }
174 
175  if ( ! check_ok( M.m_same ) ) {
176  return false; /// - Invariante: <code>check_ok( M.m_same )</code>
177  }
178  for (unsigned i=0; i<M.rows(); ++i) {
179  for (unsigned j=0; j<M.cols(); ++j) {
180  if ( ! check_ok( M(i,j) ) ) {
181  return false; /// - Invariante: <code>check_ok( M(i,j) )</code>
182  }
183  }
184  }
185  return true;
186 }
187 
188 /// Define el escalar que por defecto está en todas las entradas de la \c Matrix_Map.
189 /// - Si <code>same != getDefault()</code> la matriz queda vacía.
190 /// - De lo contrario, nada ocurre.
191 template<class E>
192 inline void Matrix_Map<E>::setDefault(const E& same) {
193  if ( m_same != same ) {
194  m_same = same;
195  }
196 }
197 /** \fn template <class E>inline Matrix_Map<E>::Matrix_Map(const value_type V);
198 
199  \brief Constructor a partir de \c Matrix_Map<E>::value_type(V).
200 
201  - La matriz resultante es una matriz escalar, de dimensiones 1x1,
202  y su valor es \c "V"
203 */
204 
205 /** Constructor de vector.
206  - Obtiene suficiente memoria dinámica para almacenas los
207  <code> n * m </code> valores de la matriz.
208  - Si \c "value_type" tiene un constructor de vector, lo
209  usar para inicializar cada uno de los valores de la matriz;
210  de lo contrario, los deja tal cual están en la memoria.
211  - Si \c "value_type" es uno de los tipos escalares básicos,
212  como lo son \c int o \c float, los valores almacenados
213  en la matriz quedan tal cual están y no son inicializados.
214  \pre
215  - <code> m * n > 0 </code>
216  - <code> (m > 0) && (n > 0) </code>
217 */
218 template <class E>
219 inline Matrix_Map<E>::Matrix_Map(unsigned m, unsigned n)
220  : m_dicc(), m_rows(m), m_cols(n), m_same()
221 {
222  if (m == 0 || n == 0) {
223  m_cols = 0;
224  m_rows = 0;
225  }
226 // m_same = E(); // Usa el número "cero" como neutro tipo "E"
227 }
228 /// constructor de copia
229 template <class E>
231  copy( o );
232  return;
233 }
234 
235 /// Destructor
236 template <class E>
238 
239 template <class E>
240 bool Matrix_Map<E>::equals( const Matrix_Map & o ) const {
241  if ( this == & o ) {
242  return true;
243  }
244  if (rows() != o.rows() || cols() != o.cols()) {
245  return false;
246  }
247 
248  for (unsigned i=0; i<rows(); i++) {
249  for (unsigned j=0; j<cols(); j++) {
250  if ( (*this)(i,j) != o(i,j) ) {
251  return false;
252  }
253  }
254  }
255  return true;
256 }
257 
258 /** Copia desde \c "o".
259  - Copia todo el valor de \c "o" sobre \c "*this", de forma que el nuevo valor de
260  \c "*this" sea un duplicado exacto del valor de \c "o".
261  - El valor anterior de \c "*this" se pierde.
262  - El objeto \c "o" mantiene su valor anterior.
263  - Luego de la copia, cuando el valor de \c "o" cambia, el de \c "*this" no cambiará,
264  y viceversa, pues la copia es una copia profunda; no es superficial.
265  - Si \c "*this" es \c "o" entonces su valor no cambia.
266  - Después de esta operación siempre ocurre que <code> *this == o </code>.
267 
268  \par Complejidad:
269  O( <code> rows() * cols() </code> )
270 
271  \returns *this
272  \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05
273 */
274 template <class E>
276  if (this == &o) { // evita auto-borrado
277  return *this;
278  }
279  this->m_dicc = o.m_dicc;
280  this->m_cols = o.cols();
281  this->m_rows = o.rows();
282  this->m_same = o.m_same;
283  return *this;
284 }
285 
286 /** Traslada el valor de \c "o" a \c "*this".
287  - El valor anterior de \c "*this" se pierde.
288  - El nuevo valor de \c "*this" es el que \c "o" tuvo.
289  - \c "o" queda en el estado en que lo dejaría \c Erase().
290  - Si \c "*this" es \c "o" entonces su valor no cambia.
291  - En general, después de esta operación casi
292  nunca ocurre que <code> (*this == o) </code>
293 
294  \par Complejidad:
295  O( <code> rows() * cols() </code> )
296 
297  \returns \c *this
298 
299  \see http://www.di-mare.com/adolfo/binder/c04.htm#sc07
300 */
301 template <class E>
303  if (this == &o) { // evita auto-borrado
304  return *this;
305  }
306  this->clear();
307 
308  for (
309  typename Diccionario::iterator it = o.m_dicc.begin();
310  it != o.m_dicc.end();
311  it++
312  ) {
313  this->m_dicc[ it->first ]= it->second;
314  this->m_dicc.insert( Diccionario::value_type( it->first , it->second ) );
315  }
316  this->m_cols = o.m_cols;
317  this->m_rows = o.m_rows;
318  this->m_same = o.m_same;
319  o.clear();
320  return *this;
321 }
322 
323 /** Intercambia los valores de \c "*this" y \c "o".
324  - Debido a que algunos métodos retornan copias del valor de \c "*this" en
325  lugar de una referencia, como ocurre con \c Matrix_Map::Child(), a veces
326  \c swap() no tiene el resultado esperado por el programador.
327  - Por ejemplo, si se invoca <code> T.Child(i). swap( T.Child(j) ) </code>
328  el resultado no es intercambiar los hijos, sino más bien intercambiar
329  los valores de los sub-árboles temporales \c T.Child(i) y \c T.Child(j).
330  La forma correcta de intercambiar hijos es usar \c Graft().
331 
332  \par Complejidad:
333  O( \c 1 )
334 
335  \returns *this
336 
337  \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08
338 */
339 template <class E>
341  std::swap( this->m_dicc , o.m_dicc );
342  std::swap( this->m_cols , o.m_cols );
343  std::swap( this->m_same , o.m_same );
344  std::swap( this->m_rows , o.m_rows );
345  return *this;
346 }
347 
348 /** Le cambia las dimensiones a la matriz.
349  - En algunos casos los valores almacenados en la matriz no quedan
350  todos iguales a \c Matrix_Map<E>::value_type().
351  \pre <code> (m > 0) && (n > 0) </code>
352 */
353 template <class E>
354 void Matrix_Map<E>::reSize(unsigned m, unsigned n) {
355  if ( m == 0 || n == 0) {
356  return;
357  }
358 
359  m_rows = m;
360  m_cols = n;
361  m_dicc.clear();
362  return;
363 
364 /* NOTA
365  Esta es la antigua especificación de reSize(). Es incorrecta
366  porque presume que el Rep de la matriz es un vector denso en
367  donde están almacenados todos los valores de la matriz:
368 
369  +----------------------------------------------------------+
370  | reSize(): Le cambia las dimensiones a la matriz. |
371  | ======== |
372  | - Si ocurre que (m*n) == rows() * cols() los valores de |
373  | la matriz se mantienen, aunque cambian sus dimensiones.|
374  | - Si (m*n) != rows() * cols() los valores de la matriz |
375  | quedarán inicializados de la misma forma en que los |
376  | inicializaría CERO == Matrix_Map<E>::value_type(). |
377  | |
378  | \pre (m > 0) && (n > 0) |
379  +----------------------------------------------------------+
380 
381  En la actual especificación, que ya está corregida, no queda
382  implícita la presunción sobre cómo está organizada internamente
383  la matriz. Por eso, esta nueva especificación sí sirve para una
384  matriz implementada con un vector denso de valores, o para la
385  matriz implementada como una matriz rala.
386 
387  Estos pequeños detalles en algunas ocasiones surgen cuando el
388  programador de una clase introduce mejoras o modificaciones, pues
389  muchas veces es muy difícil o prácticamente imposible predecir
390  todos los pormenores y detalles de una especificación o de una
391  implementación.
392 */
393 }
394 
395 /** Le ajusta las dimensiones a la matriz.
396  - Si ocurre que <code> (m*n) == rows()*cols() </code> hace
397  lo mismo que haría \c reSize(m,n).
398  - En caso contrario, no hace nada.
399 */
400 template <class E>
401 inline void Matrix_Map<E>::reShape(unsigned m, unsigned n) {
402  if ( m * n == m_rows * m_cols ) {
403  reSize(n,m);
404  }
405 }
406 
407 /// Deja el valor de \c *this en el valor en que lo
408 /// inicializa el constructor de vector.
409 template <class E>
411  m_dicc.clear();
412  m_same = value_type();
413  m_rows = m_cols = 1;
414 }
415 
416 /// Retorna una referencia al elemento [i,j] de la matriz ( \c const ).
417 /// - \c M(i,j) significa lo que en arreglos se denota con \c M[i][j].
418 /// - <code>val = M(i,j); // M(i,j) es un "rvalue" (const)</code>
419 template <class E>
420 const E& Matrix_Map<E>::operator () (unsigned i, unsigned j) const {
421  assert( "Matrix_Map<E>::operator()()" && (i < rows()) );
422  assert( "Matrix_Map<E>::operator()()" && (j < cols()) );
423 
424  typename Diccionario::const_iterator it;
425  std::pair<unsigned,unsigned> i_j (i,j);
426  it = m_dicc.find(i_j);
427  if ( it == m_dicc.end() ) {
428  return m_same;
429  }
430  else {
431  return it->second;
432  }
433 
434 /* NOTA
435  Como este método es "const", de antemano se sabe que el programador no puede
436  usarlo para modificar el valor de la matriz. Por eso, aunque el valor
437  retornado sea una referencia a valor común por defecto m_same, de antemano
438  el compilador asegura que ese valor no será modificado.
439 
440  Sin embargo, cuando el programador usa el método homónimo operator()(i,j)
441  que no es "const", es posible que el valor retornado sí sea modificado.
442  En ese caso, ya no es correcto retornar una referencia al valor común "m_same".
443  - Por eso, cuando se usa el hace referencia en el otro operator()(i,j) es
444  necesario agregar una entrada en los vectores paralelos en aquellos casos
445  en que no existe un valor diferente a "m_same" para (i,j).
446  - Esto quiere decir que sí es posible que al utilizar la versión modificable
447  de operator()(i,j) quede en el vector "m_dicc" un valor que es igual a
448  "m_same". En el caso peor, podría ocurrir que todos los valores almacenados
449  en el vector "m_dicc" sean todos iguales a "m_same".
450  - Una forma de corregir esta anomalía es "revisar después" si existe un valor
451  en el vector "m_dicc" que es igual a "m_same". Una forma eficiente de
452  hacerlo es mantener el el Rep un puntero "m_last_change" que apunte al
453  último valor "m_dicc" que la versión modificable de operator()(i,j) retornó.
454  En la siguiente invocación a operator()(i,j), se puede verificar si hubo un
455  ese valor anterior fue cambiado de manera que tiene almacenado "m_same".
456 */
457 }
458 
459 /// Retorna una referencia al elemento [i,j] de la matriz.
460 /// - \c M(i,j) significa lo que en arreglos se denota con \c M[i][j].
461 /// - <code>M(i,j) = val; // M(i,j) es un "lvalue" (modificable)</code>
462 template <class E>
463 inline E& Matrix_Map<E>::operator() (unsigned i, unsigned j) {
464  assert( "Matrix_Map<E>::operator()()" && (i < rows()) );
465  assert( "Matrix_Map<E>::operator()()" && (j < cols()) );
466 
467  // Busca al elemento M(i,j)
468  typename Diccionario::iterator it;
469  std::pair<unsigned,unsigned> i_j (i,j);
470  it = m_dicc.find(i_j);
471  if ( it == this->m_dicc.end() ) {
472  std::pair<typename Diccionario::iterator,bool> IT;
473  IT = this->m_dicc.insert (
474  typename Diccionario::value_type (
475  std::pair<unsigned,unsigned>(i,j),
476  m_same
477  )
478  );
479  it = IT.first;
480  // m_dicc[i_j] = m_same;
481  }
482 
483  return it->second; // m_dicc[i_j];
484 }
485 
486 /// Le cambia el tamaño máximo posible a la matriz.
487 /// - Le aumenta la cantidad de valores diferentes a \c getDefault().
488 /// - No hace nada cuando <code>size() < newsize</code>.
489 template <class E>
490 inline void Matrix_Map<E>::reSize(unsigned newsize) {
491 }
492 
493 /** Le suma a \c "*this" la matriz \c "O".
494  \pre
495  - \c "*this" y \c "O" deben tener las mismas dimensiones
496  - <code> rows() == O.rows() && cols() == O.cols() </code>
497 
498  \par Complejidad:
499  O( <code> rows() * cols() </code> )
500 
501  \remarks
502  - Esta es la implementación de Matrix_Map<E> operator+( Matrix_Map<E>&, Matrix_Map<E> )
503  - El compilador tiene problemas en compilar un función amiga (<em>"friend"</em>)
504  definida con plantillas si esa función amiga no está definida (implementada)
505  dentro de la declaración de la clase. Para solventar esta deficiencia existe
506  este método que realiza el trabajo, aunque es poco cómodo de usar.
507 */
508 template <class E>
510  // verifica que las dos matrices sean del mismo tamaño
511  assert( "Matrix_Map<E>::add()" && (rows() == O.rows()) && (cols() == O.cols()) );
512 
513  // Como las matrices son del mismo tamaño basta sumarlas entrada por entrada.
514  for ( unsigned i=0 ; i<rows() ; ++i ) {
515  for ( unsigned j=0 ; j<cols() ; ++j ) {
516  this->operator()(i,j) += O(i,j);
517  }
518  }
519  return;
520 }
521 
522 /** Le resta a \c "*this" la matriz \c "O".
523  \pre
524  - \c "*this" y \c "O" deben tener las mismas dimensiones
525  - <code> rows() == O.rows() && cols() == O.cols() </code>
526 
527  \par Complejidad:
528  O( <code> rows() * cols() </code> )
529 
530  \remarks
531  - Esta es la implementación de Matrix_Map<E> operator-( Matrix_Map<E>&, Matrix_Map<E> )
532  - El compilador tiene problemas en compilar un función amiga (<em>"friend"</em>)
533  definida con plantillas si esa función amiga no está definida (implementada)
534  dentro de la declaración de la clase. Para solventar esta deficiencia existe
535  este método que realiza el trabajo, aunque es poco cómodo de usar.
536 */
537 template <class E>
539  // verifica que las dos matrices sean del mismo tamaño
540  assert( "Matrix_Map<E>::substract()" && (rows() == O.rows()) && (cols() == O.cols()) );
541 
542  for ( unsigned i=0 ; i<rows() ; ++i ) {
543  for ( unsigned j=0 ; j<cols() ; ++j ) {
544  this->operator()(i,j) -= O(i,j);
545  }
546  }
547  return;
548 }
549 
550 /** Calcula la multiplicación <code> A * B </code> y la almacena en \c "*this".
551  - Las dimensiones de \c "*this" se ajustan de manera que:
552  - <code> rows() == A.rows() && cols() == B.cols()</code>
553 
554  \pre
555  - \c "A" y \c "B" deben tener dimensiones compatibles
556  - <code> A.cols() == B.rows() </code>
557  - La multiplicación se hace [Fila x Columna], lo que implica que la cantidad
558  de valores en la filas de \c "A" debe ser igual a la cantidad de columnas de \c "B"
559 
560  \par Complejidad:
561  O( <code> A.cols() * B.cols() * A.cols() * A.capacity() * B.capacity() </code> )
562 
563  \remarks
564  - Esta es la implementación de Matrix_Map<E> operator*( Matrix_Map<E>&, Matrix_Map<E> )
565  - El compilador tiene problemas en compilar un función amiga (<em>"friend"</em>)
566  definida con plantillas si esa función amiga no está definida (implementada)
567  dentro de la declaración de la clase. Para solventar esta deficiencia existe
568  este método que realiza el trabajo, aunque es poco cómodo de usar.
569 */
570 template <class E>
572  // Verifica que las matrices se puedan multiplicar
573  assert( (A.cols() == B.rows()) && " => Matrix_Map<E>::multiply()" );
574 
575  reSize( A.rows(), B.cols() );
576  value_type sum;
577  for (unsigned i=0; i<rows(); i++) {
578  for (unsigned j=0; j<cols(); j++) {
579  sum = E();
580  for (unsigned k=0; k<A.cols(); k++) {
581  sum = sum + A(i,k) * B(k,j);
582  }
583  // this->(i,j) = sum; // produce un error de compilación
584  // this->operator()(i,j) = sum; // también funciona
585  (*this)(i,j) = sum; // también funciona
586  }
587  }
588  return;
589 }
590 
591 /// Graba en el flujo \c COUT el valor de \c M[][].
592 template <class E>
593 std::ostream& operator<<(std::ostream& COUT, const Matrix_Map<E>& M) {
594  COUT << '[' << M.rows() << 'x' << M.cols() << ']' << std::endl;
595  for (unsigned i=0; i < M.rows(); ++i) {
596  for (unsigned j=0; j < M.cols(); ++j) {
597  COUT << " " << M(i,j);
598  }
599  COUT << std::endl;
600  }
601  return COUT;
602 }
603 
604 /// Obtiene del flujo \c CIN el valor para \c M[][].
605 template <class E>
606 std::istream& operator>>(std::istream& CIN, Matrix_Map<E>& M) {
607  assert( "This code has not been tested" );
608  unsigned rows,cols;
609  CIN >> rows >> cols;
610  M.reSize(rows,cols);
611  for (unsigned i=0; i<rows; i++) {
612  for (unsigned j=0; j<cols; j++) {
613  CIN >> M(i,j);
614  }
615  }
616  return CIN;
617 }
618 
619 } // namespace Mx
620 
621 // Este [horrible] truco permite "compartir" el mismo archivo Matrix_Lib.h
622 // entre Matrix.h y Matrix_Map.h
623 // #define Matrix Matrix_Map
624 // #include "Matrix_Lib.h"
625 // #undef Matrix
626 
627 #include "Matrix_Lib.h"
628 
629 #endif // Matrix_Map_h
630 // EOF: Matrix_Map.h
friend Matrix_Map operator*(const Matrix_Map &A, const Matrix_Map &B)
Retorna A*B.
Definition: Matrix_Map.h:82
void substract(const Matrix_Map &)
Le resta a &quot;*this&quot; la matriz &quot;O&quot;.
Definition: Matrix_Map.h:538
unsigned m_rows
Cantidad de filas de la matriz.
Definition: Matrix_Map.h:109
size_type capacity() const
Cantidad máxima posible de valores diferentes que pueden ser almacenados en la matriz.
Definition: Matrix_Map.h:59
value_type & reference
Tipo del objeto almacenado, similar al nombre usado en STL.
Definition: Matrix_Map.h:42
unsigned m_cols
Cantidad de columnas de la matriz.
Definition: Matrix_Map.h:110
Matrix_Map(unsigned m=1, unsigned n=1)
Constructor de vector.
Definition: Matrix_Map.h:219
unsigned count() const
Cantidad de valores almacenados en la matriz.
Definition: Matrix_Map.h:57
Matrix_Map & swap(Matrix_Map &o)
Intercambia los valores de &quot;*this&quot; y &quot;o&quot;.
Definition: Matrix_Map.h:340
Funciones para manipular Matrix_BASE&lt;&gt;.
std::istream & operator>>(std::istream &CIN, Matrix< E > &M)
Obtiene del flujo CIN el valor para M[][].
Definition: Matrix.h:615
bool check_ok(const Matrix< T > &M)
Verifica la invariante de la clase.
Definition: Matrix.h:170
unsigned cols() const
Cantidad de columnas de la Matriz.
Definition: Matrix_Map.h:55
Matrix_Map & copy(const Matrix_Map &o)
Copia desde &quot;o&quot;.
Definition: Matrix_Map.h:275
void clear()
Deja el valor de *this en el valor en que lo inicializa el constructor de vector. ...
Definition: Matrix_Map.h:410
Matrix_Map(const value_type V)
Matriz escalar de valor V.
Definition: Matrix_Map.h:51
void reShape(unsigned, unsigned)
Le ajusta las dimensiones a la matriz.
Definition: Matrix_Map.h:401
bool equals(const Matrix_Map &o) const
¿¿¿ (*this==o) ???
Definition: Matrix_Map.h:240
friend bool operator!=(const Matrix_Map &p, const Matrix_Map &q)
¿¿¿ (p != q) ???
Definition: Matrix_Map.h:69
const E & getDefault()
Valor almacenado en la mayor parte de la Matrix_Map.
Definition: Matrix_Map.h:93
unsigned size() const
Cantidad de valores almacenados en la matriz.
Definition: Matrix_Map.h:56
std::map< std::pair< unsigned, unsigned >, E > Diccionario
Definition: Matrix_Map.h:107
friend Matrix_Map operator+(const Matrix_Map &A, const Matrix_Map &B)
Retorna A+B.
Definition: Matrix_Map.h:78
Diccionario m_dicc
Vector que contiene los valores de la matiz.
Definition: Matrix_Map.h:108
unsigned rows() const
Cantidad de filas de la matriz.
Definition: Matrix_Map.h:54
E value_type
Tipo del objeto almacenado, similar al nombre usado en STL.
Definition: Matrix_Map.h:40
void setDefault(const E &same)
Define el escalar que por defecto está en todas las entradas de la Matrix_Map.
Definition: Matrix_Map.h:192
unsigned size_type
Tipo del tamaño de un objeto, similar al nombre usado en STL.
Definition: Matrix_Map.h:46
~Matrix_Map()
Destructor.
Definition: Matrix_Map.h:237
Matrix_Map & move(Matrix_Map &o)
Traslada el valor de &quot;o&quot; a &quot;*this&quot;.
Definition: Matrix_Map.h:302
Matrix_Map & operator=(const Matrix_Map &o)
Sinónimo de this-&gt;copy(o)
Definition: Matrix_Map.h:61
Esta es una clase matriz muy chirrisquitica almacenada como una matriz rala implementada con Map...
Definition: Matrix_Map.h:37
friend bool check_ok(const Matrix_Map< T > &M)
Verifica la invariante de la clase.
Definition: Matrix_Map.h:164
void multiply(const Matrix_Map &, const Matrix_Map &)
Calcula la multiplicación A * B y la almacena en &quot;*this&quot;.
Definition: Matrix_Map.h:571
void add(const Matrix_Map &)
Le suma a &quot;*this&quot; la matriz &quot;O&quot;.
Definition: Matrix_Map.h:509
friend bool operator==(const Matrix_Map &p, const Matrix_Map &q)
¿¿¿ (p == q) ???
Definition: Matrix_Map.h:67
reference operator()(unsigned, unsigned)
Retorna una referencia al elemento [i,j] de la matriz.
Definition: Matrix_Map.h:463
friend Matrix_Map operator-(const Matrix_Map &A, const Matrix_Map &B)
Retorna A-B.
Definition: Matrix_Map.h:80
void reserve(size_type _Count)
Ajusta la matriz para que pueda almacenar n valores diferentes a getDefault().
void reSize(unsigned, unsigned)
Le cambia las dimensiones a la matriz.
Definition: Matrix_Map.h:354
friend class test_Matrix_Map
Datos de prueba para la clase.
Definition: Matrix_Map.h:100
E m_same
Valor almacenado en la mayor parte de la Matrix_Map.
Definition: Matrix_Map.h:111
const value_type & const_reference
Tipo del objeto almacenado, similar al nombre usado en STL.
Definition: Matrix_Map.h:44
bool same(const Matrix_Map &o) const
Retorna true si &quot;o&quot; comparte sus valores con &quot;*this&quot;.
Definition: Matrix_Map.h:72