// Matrix_BASE.h Copyright (C) 2009 adolfo@di-mare.com #ifdef Spanish_dox /** \file Matrix_BASE.h \brief Declaraciones y definiciones para la clase abstracta no polimórfica \c Matrix_BASE<>. \author Adolfo Di Mare \date 2009 - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04 */ #endif #ifdef English_dox /** \file Matrix_BASE.h \brief Declarations and definitiones for the non polymorphic abstract class \c Matrix_BASE<>. \author Adolfo Di Mare \date 2009 - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04 */ #endif #ifndef Matrix_BASE_h #define Matrix_BASE_h // Evita la inclusión múltiple /// Escuela de Ciencias de la Computación e Informática. /// \see http://www.ecci.ucr.ac.cr namespace ECCI {} /// C++ STL /// \namespace std // Está acá para que Doxygen lo documente #include // throw out_of_range; #ifdef Spanish_dox /// Matriz chirrisquitica de adolfo@di-mare.com #endif #ifdef English_dox /// Chirrisquitica matrix by adolfo@di-mare.com #endif namespace Mx { // Clase base de la matriz chirrisquitica. template class Matrix_BASE { public: typedef E value_type; // nombres STL typedef value_type& reference; typedef const value_type& const_reference; protected: // "protected" evita que existan objetos de tipo Matrix_BASE<> Matrix_BASE(unsigned m = 1, unsigned n = 1) { } Matrix_BASE(const Matrix_BASE& M); Matrix_BASE(const E& val); ~Matrix_BASE() { } ///< Destructor. protected: unsigned rows() const; unsigned cols() const; unsigned size() const; unsigned count() const; unsigned capacity() const; protected: Matrix_BASE& operator= (const Matrix_BASE& M); Matrix_BASE& copy( const Matrix_BASE& M ); Matrix_BASE& move( Matrix_BASE& M ); Matrix_BASE& swap( Matrix_BASE& M ); void clear(); public: bool same( const Matrix_BASE & M ) const { return this == &M; } protected: bool equals( const Matrix_BASE & M ) const; ///< ¿¿¿ A == B ??? protected: E& operator()(unsigned i, unsigned j); const E& operator()(unsigned i, unsigned j) const; E& at(unsigned i, unsigned j); // throw (out_of_range); const E& at(unsigned i, unsigned j) const; void reShape(unsigned m, unsigned n); void reSize( unsigned m, unsigned n); void transpose(); void setDefault(const E& same); const E& getDefault(); public: template friend bool check_ok_Matrix( const MAT& M ); template friend class test_Matrix; ///< BUnit Test. public: // operadores con una parámetro marcado como Matrix_BASE<> template friend MAT operator+ (const Matrix_BASE& A, const MAT& B); template friend MAT operator- (const Matrix_BASE& A, const MAT& B); template friend MAT operator* (const Matrix_BASE& A, const MAT& B); template friend bool operator== ( const Matrix_BASE& A, const MAT& B ); template friend bool operator!= ( const Matrix_BASE& A, const MAT &B ); public: // funciones amigas para implementar métodos abstractos no polimórficos template friend bool check_ok_Matrix( const MAT& M ); template friend unsigned count_Matrix( const MAT& M ); template friend void clear_Matrix( MAT& M ); template friend bool equals_Matrix( const MAT& A, const MAT& B ); template friend void add_Matrix( MAT& Res, const MAT& M ); template friend void substract_Matrix( MAT& Res, const MAT& M ); template friend void multiply_Matrix( MAT& Res, const MAT& A, const MAT& B ); template friend typename MAT::reference at_Matrix( MAT& M, unsigned i, unsigned j ); template friend typename MAT::const_reference at_Matrix( const MAT& M, unsigned i, unsigned j ); }; // Matrix_BASE #ifdef Spanish_dox /** Verificación genérica de la invariante de la clase \c check_ok(). - http://www.di-mare.com/adolfo/binder/c03.htm#k1-Rep \remark Libera al programador de implementar el método \c Ok() - http://www.di-mare.com/adolfo/binder/c04.htm#sc11 */ #endif #ifdef English_dox /** Generic verification of the class invariant \c check_ok(). - http://www.di-mare.com/adolfo/binder/c03.htm#k1-Rep \remark Releaves the programner form implementing method \c Ok() - http://www.di-mare.com/adolfo/binder/c04.htm#sc11 */ #endif template bool check_ok_Matrix( const MAT& M ) { if ( ! (&M != 0 ) ) { return false; /// - check_ok(): &M != 0 . } if ( M.rows() == 0 || M.cols() == 0 ) { // si alguno es cero... if ( M.rows() != 0 || M.cols() != 0 ) { // ... los 2 deben serlo return false; /// - check_ok(): (M.rows() == 0) <==> (M.cols() == 0) } } for (unsigned i=0; icheck_ok( M(i,j) ) } } } return true; } #ifdef Spanish_dox /// Implementación por defecto para \c Matrix_BASE::count() #endif #ifdef English_dox /// Default implementation for \c Matrix_BASE::count() #endif template unsigned count_Matrix( const MAT& M ) { return M.size(); } #ifdef Spanish_dox /// Implementación por defecto para \c Matrix_BASE::clear() #endif #ifdef English_dox /// Default implementation for \c Matrix_BASE::clear() #endif template void clear_Matrix( MAT& M ) { M.reSize(1,1); M(0,0) = typename MAT::value_type(); } #ifdef Spanish_dox /// Implementación por defecto para \c Matrix_BASE::operator==() #endif #ifdef English_dox /// Default implementation for \c Matrix_BASE::operator==() #endif template bool equals_Matrix( const MAT& A, const MAT& B ) { if ( A.rows() != B.rows() || A.cols() != B.cols() ) { return false; } for (unsigned i=0; i #ifdef Spanish_dox /** Implementación por defecto para \c operator+( Matrix_BASE&, Matrix_BASE ) \pre - \c "*this" y \c "M" deben tener las mismas dimensiones. - rows() == M.rows() && cols() == M.cols() . \remarks - Esta es la implementación para Matrix_BASE operator+( Matrix_BASE&, Matrix_BASE ) . - El compilador tiene problemas en compilar un función amiga ("friend") definida con plantillas si esa función amiga no está definida (implementada) dentro de la declaración de la clase. Para solventar esta deficiencia existe esta función que realiza el trabajo, aunque es poco cómodo de usar. */ #endif #ifdef English_dox /** Default implementation for \c operator+( Matrix_BASE&, Matrix_BASE ) \pre - \c "*this" y \c "M" must have the same dimentions. - rows() == M.rows() && cols() == M.cols() . \remarks - This is the implementation for Matrix_BASE operator+( Matrix_BASE&, Matrix_BASE ) . - The compiler has problems compiling a friend function ("friend") defined with templates if that friend function is not defined (implemented) within the class declaration. To overcome this deficiency there exists this function that does the work, although it is not convenient to use. */ #endif template void add_Matrix( MAT& Res, const MAT& M ) { // verifica que las dos matrices sean del mismo tamaño assert( "Matrix_BASE::add()" && ( Res.rows() == M.rows() ) ); assert( "Matrix_BASE::add()" && ( Res.cols() == M.cols() ) ); // Como las matrices son del mismo tamaño basta sumarlas entrada por entrada. for ( unsigned i=0 ; i&, Matrix_BASE ) #endif #ifdef English_dox /// Default implementation for \c operator-( Matrix_BASE&, Matrix_BASE ) #endif template void substract_Matrix( MAT& Res, const MAT& M ) { // verifica que las dos matrices sean del mismo tamaño assert( "Matrix_BASE::substract()" && ( Res.rows() == M.rows() ) ); assert( "Matrix_BASE::substract()" && ( Res.cols() == M.cols() ) ); // Como las matrices son del mismo tamaño basta restarlas entrada por entrada. for ( unsigned i=0 ; i A * B y almacena el resultado en \c "Res". - Las dimensiones de \c "*this" se ajustan de manera que:
Res.rows() == A.rows() && Res.cols() == B.cols() - Esta es la implementación de Matrix_BASE operator*() . \pre - \c "A" y \c "B" deben tener dimensiones compatibles. - A.cols() == B.rows() . - La multiplicación se hace [Fila x Columna], lo que implica que la cantidad de valores en la filas de \c "A" debe ser igual a la cantidad de columnas de \c "B". \par Complejidad: O( A.cols() * B.cols() * A.cols() ) */ #endif #ifdef English_dox /** Calculates the multiplication A * B and stores the result in \c "Res". - The dimensions for \c "*this" get adjusted such that:
Res.rows() == A.rows() && Res.cols() == B.cols() - This is the implementation for Matrix_BASE operator*() . \pre - \c "A" y \c "B" must have compatible dimensions. - A.cols() == B.rows() . - The multiplication is carried out [Row x Column], which means that the number of valies in the rows for \c "A" must be equal to the number of columns of \c "B". \par Complexity: O( A.cols() * B.cols() * A.cols() ) */ #endif template void multiply_Matrix( MAT& Res, const MAT& A, const MAT& B ) { // Verifica que las matrices se puedan multiplicar assert( "Matrix_List::multiply()" && (A.cols() == B.rows()) ); Res.reSize( A.rows(), B.cols() ); typename MAT::value_type sum; for (unsigned i=0; i(i,j) = sum; // produce un error de compilación // this->operator()(i,j) = sum; // SI funciona // (*this)(i,j) = sum; // SI funciona Res(i,j) = sum; // SI funciona } } return; } #ifdef Spanish_dox /// Implementación por defecto para \c Matrix_BASE::at() #endif #ifdef English_dox /// Default implementation for \c Matrix_BASE::at() #endif template typename MAT::reference at_Matrix( MAT& M, unsigned i, unsigned j ) { if ( i>=M.rows() ) { throw std::out_of_range( "Mx::Matrix_BASE::at(i,j) [ i>=M.rows() ]" ); } else if ( j>=M.cols() ) { throw std::out_of_range( "Mx::Matrix_BASE::at(i,j) [ j>=M.cols() ]" ); } else { return M(i,j); } } #ifdef Spanish_dox /// Implementación por defecto para \c Matrix_BASE::at() const #endif #ifdef English_dox /// Default implementation for \c Matrix_BASE::at() const #endif template typename MAT::const_reference at_Matrix( const MAT& M, unsigned i, unsigned j ) { if ( i>=M.rows() ) { throw std::out_of_range( "Mx::Matrix_BASE::at(i,j) const [ i>=M.rows() ]" ); } else if ( j>=M.cols() ) { throw std::out_of_range( "Mx::Matrix_BASE::at(i,j) const [ j>=M.cols() ]" ); } else { return M(i,j); } } /// \c A+B template inline MAT operator+ (const Matrix_BASE& A, const MAT& B) { MAT Res = *( // MAT Res = *( (MAT*)(&A) ); reinterpret_cast( const_cast< Matrix_BASE* >(&A) ) ); add_Matrix(Res,B); // esta es la implementación por defecto return Res; /* NOTA La manera simple de implementar este operador es declararlo así: template MAT operator+( const MAT& , const MAT&); Desafortunadamente, cuando se usa la matriz junto con otras clases, como por ejemplo std::string<> u otra similar, esta definición produce un conflicto de ambigüedad, pues esta misma definición también calza como operador para la clase string<>. La forma de evitar este choque es declarar "A", el primer parámetro, de un tipo marcado por la matriz. Por eso "A" está declarado así: const Matrix_BASE& A; Con esta modificación, ya la plantilla de matrices no calza con parámetros de otro tipo y así queda eliminado el conflicto con la clase string<>. Sería más cómodo usar una plantilla de plantillas, como ésta: template MAT operator+( const MAT& , const MAT&); Este tipo de uso de plantillas es prohibo porque produce todavía más conflictos. Por eso, no queda más que forzar el uso del lenguaje usando punteros y cambios de tipo para lograr que esta versión del operator+() se use sólo para objetos derivados de la clase Matrix_BASE<>. El truco para transformar una referencia a la clase base en una referencia a la clase derivada requiere del uso de punteros. Para transformar el parámetro "A" en un objeto del tipo del segundo parámetro "B" se usa esta secuencia de transformaciones de tipos y punteros: 1) Hace falta usar (&A) para trabajar con punteros en lugar de del objeto de tipo Matrix_BASE<>. 2) Hace falta usar const_cast<> porque A es un parámetro "const" y la variable "Res" no está definida como objeto "const". 3) Hace falta usar reinterpret_cast<> para cambiar el tipo de la clase base a la clase derivada en un contexto es que la clase derivada no es una clase que contiene métodos virtuales. Matrix_BASE<> no tiene VMT y, en consecuencia, usar dynamic_cast<> es un error de compilación. 4) Hace falta usar punteros porque un objeto de tipo Matrix_BASE<> tiene un tamaño diferente al de cualquier de las clases derivadas de Matrix_BASE<>por lo que usar reinterpret_cast<> en esos objetos produce un error de compilación. 5) Como todos los punteros tienen el mismo tamaño, sí es posible usar reinterpret_cast<> para transformar un puntero a la clase Matrix_BASE<> en un puntero a la clase derivada. 6) Como lo que se hace al principio es tomar la dirección "&A", a fin de cuentas ese puntero debe ser dereferenciado usando el operador "*" para que lo utilice el constructor de copia. Es mucho más sencillo usar el código sin "XXX_cast<>": MAT Res = *( (MAT*)(&A) ); En las implementaciones de las otras operaciones esta es la notación que se usa, porque es más corta, pese a que es mucho más peligrosa de usar en un contexto general. Una vez que la matriz "Res" queda inicializada con una copia del valor del primer parámetro "A", se usa la plantilla genérica add_Matrix() para dejar en "Res" el resultado de la suma. Como el tipo de "Res" es el adecuado (no es Matrix_BASE<>), al retornar el compilador invoca el contructor de copia de la clase derivada. Esta función está declarada "inline" porque el cambio de tipos no ocupa tiempo de ejecución y porque así el compilador tiene la oportunidad de suprimir la segunda invocación al constructor de copia (que sería invocada para retornar "Res"). */ } /// \c A-B template inline MAT operator- (const Matrix_BASE& A, const MAT& B) { MAT Res = *( (MAT*)(&A) ); substract_Matrix(Res,B); return Res; } /// \c Res=A*B template inline MAT operator* (const Matrix_BASE& A, const MAT& B) { MAT Res; multiply_Matrix(Res, *( (MAT*)(&A) ), B); return Res; } /// ¿¿¿ (A == B) ??? template inline bool operator== ( const Matrix_BASE& A, const MAT& B ) { return equals_Matrix( (*(MAT*)(&A)),B ); } /// ¿¿¿ (A != B) ??? template inline bool operator!= ( const Matrix_BASE& A, const MAT &B ) { return !(A==B); } /***********\ ** ** ** DOXYGEN ** ** ** \***********/ #ifdef Spanish_dox /// \c "Doxygen: Documentación en español" #define Spanish_dox "Doxygen: Documentación en español" /// \def Matrix_BASE_h /// \brief Usada para evitar la inclusión múltiple. #endif #ifdef English_dox /// "Doxygen: English documentation" #define English_dox "Doxygen: English documentation" /// \def Matrix_BASE_h /// \brief Used to avoid multiple inclusion. #endif #ifdef Spanish_dox /** \class Matrix_BASE \brief Esta es la plantilla base para las implementacion de la clase matriz chirrisquitica. - La matriz tiene dimensiones \c rows() x \c cols(). - Se le puede cambia su dimensión dinámicamente con el método \c reSize(). - La clase \c E debe incluir un neutro para la adición, cuyo valor debe poderse obtener invocando \c Sparse_Matrix::value_type(). - Las operaciones aritméticas "+" "-" "*" deben estar definidas para \c Matrix_BASE::value_type y debe existir \c Matrix_BASE::value_type(1). \see http://www.oonumerics.org/oon/ */ #endif #ifdef English_dox /** \class Matrix_BASE \brief This is the base template for the implementaciones of the chirrisquitica matrix. - The matrix has dimensions \c rows() x \c cols(). - Its dimensions can change dinamically using \c reSize(). - Call \c E must have a neutral for addition. Its value should be obtained invoking \c Sparse_Matrix::value_type(). - The arithmetic operations "+" "-" "*" must be defined for \c Matrix_BASE::value_type and \c Matrix_BASE::value_type(1). \see http://www.oonumerics.org/oon/ */ #endif #ifdef Spanish_dox /// \typedef Matrix_BASE::value_type /// \brief Tipo del objeto almacenado, similar al nombre usado en STL /// \typedef Matrix_BASE::reference /// \brief Referencia al objeto almacenado, similar al nombre usado en STL /// \typedef Matrix_BASE::const_reference /// \brief Referencia constante al objeto almacenado, similar al nombre usado en STL #endif #ifdef English_dox /// \typedef Matrix_BASE::value_type /// \brief Type of the stored object, similar to the name used in the STL /// \typedef Matrix_BASE::reference /// \brief Reference to the stored object, similar to the name used in the STL /// \typedef Matrix_BASE::const_reference /// \brief Reference [const] to the stored object, similar to the name used in the STL #endif #ifdef Spanish_dox /** \fn Matrix_BASE::Matrix_BASE(unsigned m, unsigned n); \brief Constructor de vector. - Obtiene suficiente memoria dinámica para almacenas los n * m valores de la matriz. - Si \c "value_type" es uno de los tipos escalares básicos, como lo son \c int o \c float, los valores almacenados en la matriz no son inicializados en cero. - Si \c "m" o \c "n" es cero, la matriz queda vacía. \fn Matrix_BASE::Matrix_BASE(const E& val); \brief Constructor escalar. - La matriz es escalar de dimensiones 1x1 y valor \c "V". \fn Matrix_BASE::Matrix_BASE( const Matrix_BASE& ); \brief Constructor de copia. */ #endif #ifdef English_dox /** \fn Matrix_BASE::Matrix_BASE(unsigned m, unsigned n); \brief Vector constructor. - Allocates enough dynamic memory to store the n * m matrix values. - If \c "value_type" is one of the basic scalar types, as \c int or \c float, the stored values in the matrix will not be initialized to zero. - If \c "m" or \c "n" is zero, the matrix is empty. \fn Matrix_BASE::Matrix_BASE(const E& val); \brief Scalar constructor. - The matrix is scalar with dimension 1x1 and value \c "V". \fn Matrix_BASE::Matrix_BASE( const Matrix_BASE& ); \brief Copy constructor. */ #endif #ifdef Spanish_dox /** \fn unsigned Matrix_BASE::rows() const; \brief Cantidad de filas de la matriz. \fn unsigned Matrix_BASE::cols() const; \brief Cantidad de columnas de la matriz. \fn unsigned Matrix_BASE::size() const; \brief Cantidad de valores almacenados en la matriz. \fn unsigned Matrix_BASE::count() const; \brief Sinónimo de \c size(). \fn unsigned Matrix_BASE::capacity() const; \brief Cantidad máxima posible de valores diferentes que pueden ser almacenados en la matriz. */ #endif #ifdef English_dox /** \fn unsigned Matrix_BASE::rows() const; \brief Number of rows in the matrix. \fn unsigned Matrix_BASE::cols() const; \brief Number of columns in the matrix. \fn unsigned Matrix_BASE::size() const; \brief Number of values stored in the matrix. \fn unsigned Matrix_BASE::count() const; \brief Sinonim of \c size(). \fn unsigned Matrix_BASE::capacity() const; \brief Maximum number of values that can be stored in the matrix. */ #endif #ifdef Spanish_dox /** \fn Matrix_BASE& Matrix_BASE::operator=(const Matrix_BASE &M); \brief Sinónimo de \c this->copy(M). \fn Matrix_BASE& Matrix_BASE::copy(const Matrix_BASE &M); \brief Copia desde \c "M". - Copia todo el valor de \c "M" sobre \c "*this" de forma que el nuevo valor de \c "*this" sea un duplicado exacto del valor de \c "M". - El valor anterior de \c "*this" se pierde. - El objeto \c "M" mantiene su valor. - Luego de la copia, cuando el valor de \c "M" cambia, el de \c "*this" no cambiará, y viceversa, pues la copia es una copia profunda; no es superficial. - Si \c "*this" es \c "M" su valor no cambia. - Después de esta operación siempre es verdadero que *this == M . \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05 */ #endif #ifdef English_dox /** \fn Matrix_BASE& Matrix_BASE::operator=(const Matrix_BASE &M); \brief Sinonim of \c this->copy(M). \fn Matrix_BASE& Matrix_BASE::copy(const Matrix_BASE &M); \brief Copies from \c "M". - Copies the whole value from \c "M" into \c "*this" in such a way that the new valuer for \c "*this" is an exact duplicate of the value in \c "M". - The previous value stored in \c "*this" is lost. - Object \c "M" maintains its value. - After the copy, when the value for \c "M" changes, the value for \c "*this" will not change, and viceversa, because the copy is a deep copy; it is not supperficial. - If \c "*this" is \c "M" its value will not change. - After this operation it is always true that *this == M . \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05 */ #endif #ifdef Spanish_dox /** \fn Matrix_BASE& Matrix_BASE::move(Matrix_BASE &M); \brief Traslada el valor de \c "M" a \c "*this". - El valor anterior de \c "*this" se pierde - El nuevo valor de \c "*this" es el que \c "M" tuvo - \c "M" queda en el estado en que queda cualquier objeto cuando es inicializardo con el constructor de vector. - Si \c "*this" es \c "M" entonces su valor no cambia - En general, después de esta operación casi nunca ocurre que (*this == M) \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc07 */ #endif #ifdef English_dox /** \fn Matrix_BASE& Matrix_BASE::move(Matrix_BASE &M); \brief Moves the value from \c "M" into \c "*this". - The previous value stored in \c "*this" is lost. - The new value for \c "*this" is what was stored in \c "M". - \c "M" remains in the state an object will have after being initialized by the vector contructor. - If \c "*this" is \c "M" its value will not change. - In general, after this operation, it will almost never ocurr that (*this == M) . \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc07 */ #endif #ifdef Spanish_dox /** \fn Matrix_BASE& Matrix_BASE::swap(Matrix_BASE &M); \brief Intercambia los valores de \c "*this" y \c "M". - En muchas ocasiones toma menos tiempo esta operación que \c copy() o \c move(). \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08 */ #endif #ifdef English_dox /** \fn Matrix_BASE& Matrix_BASE::swap(Matrix_BASE &M); \brief Interchanges the values of \c "*this" and \c "M". - In many ocations this operation takes less time than \c copy() or \c move(). \returns \c "*this" \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08 */ #endif #ifdef Spanish_dox /** \fn Matrix_BASE& Matrix_BASE::clear(); \brief Deja el valor de \c "*this" en el valor en que lo inicializa el constructor de vector. */ #endif #ifdef English_dox /** \fn Matrix_BASE& Matrix_BASE::clear(); \brief Leaves \c "*this" with the value the vector constructor initializes it to. */ #endif #ifdef Spanish_dox /// \fn bool Matrix_BASE::same( const Matrix_BASE & M ) const; /// \brief Retorna \c true si \c "M" comparte su valor con \c "*this". #endif #ifdef English_dox /// \fn bool Matrix_BASE::same( const Matrix_BASE & M ) const; /// \brief Returns \c true if \c "M" shares its value with \c "*this". #endif #ifdef Spanish_dox /** \fn reference Matrix_BASE::operator()(unsigned,unsigned); \brief Retorna una referencia al elemento \c [i][j] de la matriz. - \c M(i,j) significa lo que en arreglos es \c M[i][j]. - Esta referencia permite cambiar el valor almacenado. - M(i,j) = val; // M(i,j) es un "lvalue" (modificable) */ /** \fn const_reference Matrix_BASE::operator()(unsigned,unsigned) const; \brief Retorna una referencia constante al elemento \c [i][j] de la matriz [CONST]. - \c M(i,j) significa lo que en arreglos es \c M[i][j]. - Esta referencia solo permite leer el valor almacenado. - val = M(i,j); // M(i,j) es un "rvalue" (const) */ /** \fn reference Matrix_BASE::at(unsigned, unsigned); \brief Retorna una referencia al elemento \c [i][j] de la matriz. - Vefica que en la matriz exista el valor de índices \c [i][j]. - Si \c [i][j] está fuera de rango levanta una excepción de tipo \c std::out_of_range. - Esta referencia permite cambiar el valor almacenado. - M.at(i,j) = val; // M.at(i,j) es un "lvalue" (modificable) */ /** \fn const_reference Matrix_BASE::at(unsigned, unsigned) const; \brief Retorna una referencia constante al elemento \c [i][j] de la matriz [CONST]. - Vefica que en la matriz exista el valor de índices \c [i][j]. - Si \c [i][j] está fuera de rango levanta una excepción de tipo \c std::out_of_range. - Esta referencia solo permite leer el valor almacenado. - val = M.at(i,j); // M.at(i,j) es un "rvalue" (const) */ #endif #ifdef English_dox /** \fn reference Matrix_BASE::operator()(unsigned, unsigned); \brief Returns a reference to element \c [i][j] in the matrix. - \c M(i,j) means what in arrays is \c M[i][j]. - This reference allows modifying the stored value. - M(i,j) = val; // M(i,j) is un "lvalue" (mutable) */ /** \fn const_reference Matrix_BASE::operator()(unsigned, unsigned) const; \brief Returns a const reference to element \c [i][j] in the matrix [CONST]. - \c M(i,j) means what in arrays is \c M[i][j]. - This reference only allows reading the stored value. - val = M(i,j); // M(i,j) is a "rvalue" (const) */ /** \fn reference Matrix_BASE::at(unsigned, unsigned); \brief Returns a reference to element \c [i][j] in the matrix. - Verifyes that a value with indexes \c [i][j] exists in the matrix. - If \c [i][j] is out of range throws exception \c std::out_of_range. - This reference allows modifying the stored value. - M.at(i,j) = val; // M.at(i,j) is un "lvalue" (mutable) */ /** \fn const_reference Matrix_BASE::at(unsigned, unsigned) const; \brief Returns a const reference to element \c [i][j] in the matrix [CONST]. - Verifyes that a value with indexes \c [i][j] exists in the matrix. - If \c [i][j] is out of range throws exception \c std::out_of_range. - This reference only allows reading the stored value. - val = M.at(i,j); // M.at(i,j) is a "rvalue" (const) */ #endif #ifdef Spanish_dox /** \fn void Matrix_BASE::reSize(unsigned m, unsigned n); \brief Le cambia las dimensiones a la matriz. - Si (m*n == 0) deja la matriz vacía. \fn void Matrix_BASE::reShape(unsigned m, unsigned n); \brief Le ajusta las dimensiones a la matriz. - Trata de cambiar las dimensiones de la matriz conservando los valores almacenados actuales. De esta forma, una matriz 4x12 puede ser transformada en 8x6 sin tener que adquirir nueva memoria dinámica, lo que hace que esta operación en algunas ocasiones sea más rápida que \c reSize(m,n). - En muchos casos no es posible reajustar las dimensiones de la matriz. \fn void Matrix_BASE::transpose(); \brief Transforma la matriz en su transpuesta. */ #endif #ifdef English_dox /** \fn void Matrix_BASE::reSize(unsigned m, unsigned n); \brief Changes the dimensions for the matrix. - If (m*n == 0) the matrix becomes empty. \fn void Matrix_BASE::reShape(unsigned m, unsigned n); \brief Reshapes the dimensions for the matrix. - Tries to change the dimensions fot the matrix while preserving current stored values. In this way, a 4x12 matrix can be transformed into a 8x6 without having to acquire new dynamic memory, which sometimes makes this operation faster than \c Resize(m,n). - In many cases it is not possible to reshape the dimensions of the matrix. \fn void Matrix_BASE::transpose(); \brief Transforms the matrix into its transpose. */ #endif #ifdef Spanish_dox /** \fn Matrix_BASE::setDefault(const E& same); \brief Define cuál es el valor almacenado en la mayor parte de la matriz. - En muchos casos reorganiza al matriz de manera que ocupe menos espacio usando como valor comodín a \c same. - Si same != getDefault() la matriz queda reducida como si hubiera sido invocado \c clear(). \fn Matrix_BASE::getDefault(); \brief Valor almacenado en la mayor parte de la matriz. */ #endif #ifdef English_dox /** \fn Matrix_BASE::setDefault(const E& same); \brief Defines which is the most common value stored in the matrix. - Oftentimes this method will reorganizce the matrix in such a way that less space is needed using \c same as the most common value. - If same != getDefault() the matrix becomes empty as if \c clear() had been invoked for it. \fn Matrix_BASE::getDefault(); \brief Gets the most common value stored in the matrix. */ #endif #ifdef Spanish_dox #endif #ifdef English_dox #endif } // namespace Mx #endif // Matrix_BASE_h // EOF: Matrix_BASE.h