2010-01-16 56 views
14

En C, si quería crear una estructura de matriz, yo usaría:C++ Matrix Class

struct matrix { 
    int col, row; 
    double data[1]; // I want the matrix entries stored 
        // right after this struct 
} 

entonces puedo asignarlo con

matrix* allocate_matrix(int row, int col) { 
    matrix* m = malloc(sizeof(matrix) + sizeof(double) * (row * col - 1)); 
    m->row = row; m->col = col; 
    return m; 
} 

Ahora puedo hacer lo equiv en C++ ?

EDIT:

Quiero saber la forma canónica para implementar una clase de matriz en C++.

+1

Debe completar el '...' para aclarar la confusión que están teniendo algunas de las respuestas. – GManNickG

+0

buena llamada; esto es suficiente? – anon

Respuesta

-2

En C++ se puede utilizar como esto:

matrix *p = new matrix; 

Después de eso,

delete p; 
+0

El OP no era explícito en la redacción original de la pregunta, pero la intención era claramente que el último miembro de la 'struct' fuera una matriz de tamaño variable/indeterminado, simplemente usando' new' en lugar de 'malloc' won no funciona – jamesdlin

12

C++ es sobre todo un superconjunto de C. Puede seguir haciendo lo que estaba haciendo.

Dicho esto, en C++, lo que debe hacer es definir una clase Matrix adecuada que administre su propia memoria. Podría, por ejemplo, estar respaldado por un std::vector interno, y podría anular operator[] o operator() para indexar en el vector apropiadamente (por ejemplo, ver: How do I create a subscript operator for a Matrix class?) de C++ FAQ.

Para empezar:

class Matrix 
{ 
public: 
    Matrix(size_t rows, size_t cols); 
    double& operator()(size_t i, size_t j); 
    double operator()(size_t i, size_t j) const; 

private: 
    size_t mRows; 
    size_t mCols; 
    std::vector<double> mData; 
}; 

Matrix::Matrix(size_t rows, size_t cols) 
: mRows(rows), 
    mCols(cols), 
    mData(rows * cols) 
{ 
} 

double& Matrix::operator()(size_t i, size_t j) 
{ 
    return mData[i * mCols + j]; 
} 

double Matrix::operator()(size_t i, size_t j) const 
{ 
    return mData[i * mCols + j]; 
} 

(Tenga en cuenta que lo anterior no hace ninguna límites de comprobación, y lo dejo como ejercicio a la plantilla de modo que funciona para otras cosas que double.)

3

Usted podría hacerlo de esa manera. La única diferencia es que deberías lanzar el resultado desde malloc.

En su lugar, utilizaría vector, ya sea como una matriz 1D con indexación calculada o un vector incrustado. (El primero coincide con el código mejor.)

Por ejemplo:

template <typename T> // often, they are templates 
struct matrix 
{ 
    // should probably be hidden away, and the class would 
    // provide `at` and `operator()` for access 
    int col, row; 
    std::vector<T> data; 

    matrix(int columns, int rows) : 
    col(columns), row(rows), 
    data(col * row) 
    {} 

} 

matrix m(4, 4); 
m.data[1 + 1 * 4] = /* ... */; 

O:

template <typename T> 
struct matrix 
{ 
    int col, row; 
    std::vector<std::vector<T> > data; 

    matrix(int columns, int rows) : 
    col(columns), row(rows), 
    data(col, std::vector(row)) 
    {} 
} 

matrix m(4, 4); 
m.data[1][1] = /* ... */; 

Pero estos son sólo ejemplos. Te gustaría hacer una clase completa; si desea obtener más consejos al respecto, edite su pregunta y aclare que desea conocer la forma canónica de implementar clases de matriz.

Existen clases de matriz preexistentes. Mi favorito es el de boost, UBLAS.

+0

Quiere decir 'datos [1] [1]', no 'datos [1, 1]'. (Y técnicamente, 'm.data [1] [1]'.) – jamesdlin

+0

Oops, derp'ed totalmente ese. – GManNickG

+0

No creo que un 'vector' de' vector' vaya a ser una implementación muy eficiente. – bobobobo

4

Hay muchas sutilezas en la configuración de una clase de matriz eficiente y de alta calidad, afortunadamente hay varias implementaciones buenas flotando.

Piense con firmeza si desea una clase de matriz de tamaño fijo o una de tamaño variable. es decirse puede hacer esto:

// These tend to be fast and allocated on the stack. 
matrix<3,3> M; 

o necesita ser capaz de hacer esto

// These are slower but more flexible and partially allocated on the heap 
matrix M(3,3); 

Hay buenas bibliotecas que soportan cualquier estilo, y algunos que apoyan ambos. Tienen diferentes patrones de asignación y diferentes actuaciones.

Si desea codificarlo usted mismo, entonces la versión de la plantilla requiere cierto conocimiento de las plantillas (duh). Y el dinámico necesita algunos ataques para sortear muchas asignaciones pequeñas si se usa dentro de bucles apretados.

1

que podría hacerlo con una plantilla, si el tamaño de la matriz es conocido en tiempo de compilación: bene

template <int width, int height> 
class Matrix{ 
    double data[height][width]; 
    //...member functions 
}; 
30

nota.

Esta respuesta tiene 20 votos positivos ahora, pero es no destinado como una aprobación de std::valarray.

Según mi experiencia, es mejor invertir tiempo instalando y aprendiendo a utilizar una biblioteca matemática hecha y derecha como Eigen. Valarray tiene menos funciones que la competencia, pero no es más eficiente o particularmente fácil de usar.

Si solo necesitas un poco de álgebra lineal, y estás en punto muerto para no agregar nada a tu cadena de herramientas, entonces quizás valarray encajaría. Pero, estar atrapado incapaz de expresar la solución matemáticamente correcta a su problema es una posición muy mala. Matemáticas es implacable e implacable. Use la herramienta correcta para el trabajo.


La biblioteca estándar proporciona std::valarray<double>. std::vector<>, sugerido por algunos otros aquí, está pensado como un contenedor de propósito general para objetos. valarray, menos conocidos, ya que es más especializado (no usar "especializado" como el C++ plazo), tiene varias ventajas:

  • no asigna espacio adicional. A vector redondea a la potencia de dos más cercana al asignar, por lo que puede cambiar el tamaño sin reasignar cada vez. (Todavía puede cambiar el tamaño de un valarray; sigue siendo tan caro como realloc().)
  • Puede cortarlo para acceder fácilmente a filas y columnas.
  • Los operadores aritméticos funcionan como cabría esperar.

Por supuesto, la ventaja sobre el uso de C es que no necesita administrar la memoria. Las dimensiones pueden residir en la pila o en un objeto de división.

std::valarray<double> matrix(row * col); // no more, no less, than a matrix 
matrix[ std::slice(2, col, row) ] = pi; // set third column to pi 
matrix[ std::slice(3*row, row, 1) ] = e; // set fourth row to e 
+2

+1 por señalarme una parte infrautilizada de la stl – Shep

+0

@Shep Tengo que admitir que nunca he usado 'valarray' ... las pocas veces que lo intenté, las clases de rodajas fueron un problema. Tal vez valga la pena echarle un vistazo, y mejor que hacer las tuyas propias, como sugieren las otras respuestas aquí, pero hay mejores bibliotecas por ahí. (Bueno, parece que al menos, realmente no he usado ninguno. Boost BLAS debería ser bueno, sin embargo). – Potatoswatter

+2

Sí, esto se dirige hacia 10 votos ascendentes. 'std :: valarray' es bastante difícil de usar, solo admite álgebra básica de miembros, y no es muy popular. Pruebe la [Biblioteca Eigen] (http://eigen.tuxfamily.org/) que es muy fácil de usar, potente y popular. – Potatoswatter

2

usted podría utilizar una plantilla como:

#include <iostream> 
using std::cerr; 
using std::endl; 

//qt4type 
typedef unsigned int quint32; 

template <typename T> 
void deletep(T &) {} 
template <typename T> 
void deletep(T* & ptr) { 
    delete ptr; 
    ptr = 0; 
} 
template<typename T> 
class Matrix { 
    public: 
     typedef T value_type; 
     Matrix() : _cols(0), _rows(0), _data(new T[0]), auto_delete(true) {}; 
     Matrix(quint32 rows, quint32 cols, bool auto_del = true); 

     bool exists(quint32 row, quint32 col) const; 
     T & operator()(quint32 row, quint32 col); 
     T operator()(quint32 row, quint32 col) const; 
     virtual ~Matrix(); 

     int size() const { return _rows * _cols; } 
     int rows() const { return _rows; } 
     int cols() const { return _cols; } 
    private: 
     Matrix(const Matrix &); 
     quint32 _rows, _cols; 
     mutable T * _data; 
     const bool auto_delete; 
}; 
template<typename T> 
Matrix<T>::Matrix(quint32 rows, quint32 cols, bool auto_del) : _rows(rows), _cols(cols), auto_delete(auto_del) { 
    _data = new T[rows * cols]; 
} 
template<typename T> 
inline T & Matrix<T>::operator()(quint32 row, quint32 col) { 
    return _data[_cols * row + col]; 
} 
template<typename T> 
inline T Matrix<T>::operator()(quint32 row, quint32 col) const { 
    return _data[_cols * row + col]; 
} 

template<typename T> 
bool Matrix<T>::exists(quint32 row, quint32 col) const { 
    return (row < _rows && col < _cols); 
} 

template<typename T> 
Matrix<T>::~Matrix() { 
    if(auto_delete){ 
     for(int i = 0, c = size(); i < c; ++i){ 
      //will do nothing if T isn't a pointer 
      deletep(_data[i]); 
     } 
    } 
    delete [] _data; 
} 

int main() { 
    Matrix<int> m(10,10); 
    quint32 i = 0; 
    for(int x = 0; x < 10; ++x) { 
     for(int y = 0; y < 10; ++y, ++i) { 
      m(x, y) = i; 
     } 
    } 
    for(int x = 0; x < 10; ++x) { 
     for(int y = 0; y < 10; ++y) { 
      cerr << "@(" << x << ", " << y << ") : " << m(x,y) << endl; 
     } 
    } 
} 

* edición, fija un error tipográfico.

2

Para una clase de matriz, desea evitar la sobrecarga del operador [].
Ver C++ FAQ 13.10

Además, busque en la web algunas clases de matriz de software gratuito. En el peor de los casos, pueden orientarte. En el mejor de los casos, menos software que tiene que escribir y depurar.

3

Publicando unos años en el camino, hay algunas nuevas posibilidades con lo que C++ 11 nos ha otorgado.

He aquí un primer borrador que se incluye en una biblioteca de OpenGL que estoy cocinando hasta que debe dar cualquier otra persona que se topa con esto un moderno punto de partida:

(nota - esto aún no se ha probado ni revisado)

/*(KILLGPL: Incompatible with Libraries Linked to the GPL) 
============================================================================ 

"Free software" should be just that - free. Extreme copy-left licenses 
such as the GPL, GPL2, GPL3, etc, and their users have twisted the 
term "free" to meet their own anti-business, anti-closed source agendas by 
forcing licensees to relicense their software under the same "viral" terms 
and by forcing licensees to distribute sources with binary distributions. 
This license stands in protest of such licenses in an attempt to protect 
the freedoms that extreme copy-left licenses have been taking away from 
software developers for far too long. 

Permission is hereby granted, free of charge, to any person obtaining 
a copy of this software and associated documentation files (the 
"Software"), to deal in the Software with only one restriction: no part of 
it may be included in software projects that are distributed under "viral" 
licensing schemes like those found in the GPL, GPL2, GPL3, etc. 

There are no further usage restrictions. Licensees are encouraged to use 
this software in both open and closed source applications, so long as no 
part of the combined work is licensed under extreme copy-left licenses. 

The above copyright notice and this permission notice shall be included 
in all copies or substantial portions of the Software. Note - this notice 
does not have to appear in YOUR code, but must remain intact in the parts 
licensed under the KILLGPL. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ 

#ifndef MATRIX_HPP 
#define MATRIX_HPP 

#include <array> 
#include <cstdint> 
#include <iterator> 
#include <initializer_list> 
#include <iosfwd> 

/// Forward Declarations Required for free-function friends 
template<typename T, std::size_t X, std::size_t Y> 
class Matrix; 

/** 
* Performs a component-wise comparison between the two provided matrices 
* 
* @param lhs the first matrix to compare 
* 
* @param rhs the second matrix to compare 
* 
* @return true if the two matrices are equal, otherwise false 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
bool operator==(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; 

/** 
* Performs a component-wise comparison between the two provided matrices 
* 
* @param lhs the first matrix to compare 
* 
* @param rhs the second matrix to compare 
* 
* @return true if the two matrices are not equal, otherwise false 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
bool operator!=(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; 

/** 
* Inserts the provided Matrix into the provided output stream 
* 
* @param stream the stream to insert the provided Matrix into 
* 
* @param matrix the Matrix to insert into the provided stream 
* 
* @return the provided stream 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
std::ostream& operator<<(std::ostream& stream, const Matrix<T, X, Y>& matrix); 

/** 
* Extracts a Matrix from the provided input stream 
* 
* @param stream the stream to extract from 
* 
* @param matrix the Matrix to extract into 
* 
* @return the provided input stream 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
std::istream& operator>>(std::istream& stream, Matrix<T, X, Y>& matrix); 

/** 
* A modern general-purpose object-oriented matrix class without any legacy hacks from C 
* 
* Several common matrix types are also defined in the following format: 
* 
* Matrix {number of rows} x {number of columns} {type abbreviation} 
* 
* where the predefined type abbreviations are: 
* type  - abbreviation 
* -------------------------- 
* double - D 
* float  - F 
* int64_t - L 
* uint64_t - UL 
* int32_t - I 
* uint32_t - UI 
* int16_t - S 
* uint16_t - US 
* int8_t - C 
* uint8_t - UC 
* 
* example: Matrix3x3F - A tuple that holds 3x3 float elements 
* 
* User-defined matrix types are expected to follow the aforementioned format. 
* 
* @tparam T the type of data stored in this matrix 
* 
* @tparam Rows the number of rows in this matrix 
* 
* @tparam Columns the number of columns in this matrix 
*/ 
template<typename T, std::size_t Rows, std::size_t Columns> 
class Matrix 
{ 
    static_assert(Rows > 0, "The number of rows in a Matrix must be greater than zero"); 
    static_assert(Columns > 0, "The number of columns in a Matrix must be greater than zero"); 

    /// Privileged free-functions 
    friend std::ostream& operator<<<>(std::ostream&, const Matrix<T, Rows, Columns>&); 
    friend std::istream& operator>><>(std::istream&, const Matrix<T, Rows, Columns>&); 
    friend bool operator!=<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&); 
    friend bool operator==<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&); 

    /// The actual container that holds the elements of this Matrix 
    std::array<T, Rows * Columns> values; 

    public: 

    /// A convenience field that provides the total number of elements in this Matrix 
    static constexpr std::size_t Length = Rows * Columns; 

    /** 
    * Retrieves the identity-matrix 
    * 
    * @return the identity-matrix 
    * 
    */ 
    static constexpr Matrix IDENTITY() noexcept; 

    /** 
    * Retrieves the zero-matrix 
    * 
    * @return the zero-matrix 
    * 
    */ 
    static constexpr Matrix ZERO() noexcept; 

    /** 
    * Constructs a Matrix with each element initialized to zero 
    * 
    */ 
    constexpr Matrix() noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized to the provided array 
    * 
    * @param elements the array to initialize this Matrix with 
    * 
    */ 
    explicit constexpr Matrix(const std::array<T, Rows * Columns>& elements) noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized to the provided array 
    * 
    * @param elements the array to initialize this Matrix with 
    * 
    */ 
    explicit constexpr Matrix(std::array<T, Rows * Columns>&& elements) noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized with the provided values 
    * 
    * @param element the first value 
    * 
    * @param elements all subsequent values 
    * 
    * <pre>Matrix<int, 3, 3> matrix(1, 2, 3, 1, 2, 3, 1,2 ,3);</pre> 
    * 
    */ 
    template<typename ...E> 
    explicit constexpr Matrix(T element, E&&... elements) noexcept; 

    /** 
    * Retrieves a const reference to the element at the provided row and column 
    * 
    * @param row the row to access 
    * 
    * @param column the column to access 
    * 
    * @return the element at the provided row and column 
    * 
    */ 
    /*constexpr*/const T& operator()(std::size_t row, std::size_t column) const noexcept; 

    /** 
    * Retrieves a reference to the element at the provided row and column 
    * 
    * @param row the row to access 
    * 
    * @param column the column to access 
    * 
    * @return the element at the provided row and column 
    * 
    */ 
    /*constexpr*/T& operator()(std::size_t row, std::size_t column) noexcept; 

    // TODO: Global Free Functions for performing transformations 
}; 

namespace detail 
{ 
    // thanks be to Cubbi @ cplusplus.com for enlightenment 
    template<int ...> struct sequence 
    { 

    }; 

    template<int N, int ...S> struct sequence_generator : sequence_generator<N - 1, N - 1, S...> 
    { 

    }; 

    template<int ...S> struct sequence_generator < 0, S...> 
    { 
     using type = sequence<S...>; 
    }; 

    template<std::size_t X, std::size_t Y> 
    constexpr int get_element(std::size_t pos) 
    { 
     return pos % Y == pos/Y; 
    } 

    template <typename T, std::size_t Rows, std::size_t Columns, int ...S> 
    constexpr std::array<T, Rows * Columns> get_identity_array(sequence<S...>) 
    { 
     return std::array<T, Rows * Columns> {{ get_element<Rows, Columns>(S)... }}; 
    } 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
bool operator==(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept 
{ 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     if(lhs[i] == rhs[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
bool operator!=(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept 
{ 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     if(lhs[i] != rhs[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
Matrix<T, Rows, Columns> operator-(const Matrix<T, Rows, Columns>& source) noexcept 
{ 
    Matrix<T, Rows, Columns> rv(source); 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     rv[i] *= -1; 
    } 
    return rv; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::IDENTITY() noexcept 
{ 
    return Matrix{detail::get_identity_array<T, Rows, Columns>(typename detail::sequence_generator<Rows * Columns>::type())}; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::ZERO() noexcept 
{ 
    return Matrix{}; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix() noexcept 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix(const std::array<T, Rows * Columns>& values) noexcept : values(values) 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix(std::array<T, Rows * Columns>&& array) noexcept : values(array) 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
template<typename ...E> 
constexpr Matrix<T, Rows, Columns>::Matrix(T first, E&&... elements) noexcept : values {{ first, std::forward<T>(static_cast<T>(elements))... }} 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
/*constexpr*/const T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) const noexcept 
{ 
    dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])"); 
    dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])"); 
    return values[column * Rows + row]; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
/*constexpr*/T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) noexcept 
{ 
    dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])"); 
    dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])"); 
    return values[column * Rows + row]; 
} 


/// Built-in library matrix types 
typedef Matrix<uint8_t, 2, 2> Matrix2x2UC; 
typedef Matrix<uint8_t, 3, 3> Matrix3x3UC; 
typedef Matrix<uint8_t, 4, 4> Matrix4x4UC; 

typedef Matrix<int8_t, 2, 2> Matrix2x2C; 
typedef Matrix<int8_t, 3, 3> Matrix3x3C; 
typedef Matrix<int8_t, 4, 4> Matrix4x4C; 

typedef Matrix<uint16_t, 2, 2> Matrix2x2US; 
typedef Matrix<uint16_t, 3, 3> Matrix3x3US; 
typedef Matrix<uint16_t, 4, 4> Matrix4x4US; 

typedef Matrix<int16_t, 2, 2> Matrix2x2S; 
typedef Matrix<int16_t, 3, 3> Matrix3x3S; 
typedef Matrix<int16_t, 4, 4> Matrix4x4S; 

typedef Matrix<uint32_t, 2, 2> Matrix2x2UI; 
typedef Matrix<uint32_t, 3, 3> Matrix3x3UI; 
typedef Matrix<uint32_t, 4, 4> Matrix4x4UI; 

typedef Matrix<int32_t, 2, 2> Matrix2x2I; 
typedef Matrix<int32_t, 3, 3> Matrix3x3I; 
typedef Matrix<int32_t, 4, 4> Matrix4x4I; 

typedef Matrix<uint64_t, 2, 2> Matrix2x2UL; 
typedef Matrix<uint64_t, 3, 3> Matrix3x3UL; 
typedef Matrix<uint64_t, 4, 4> Matrix4x4UL; 

typedef Matrix<int64_t, 2, 2> Matrix2x2L; 
typedef Matrix<int64_t, 3, 3> Matrix3x3L; 
typedef Matrix<int64_t, 4, 4> Matrix4x4L; 

typedef Matrix<float, 2, 2> Matrix2x2F; 
typedef Matrix<float, 3, 3> Matrix3x3F; 
typedef Matrix<float, 4, 4> Matrix4x4F; 

typedef Matrix<double, 2, 2> Matrix2x2D; 
typedef Matrix<double, 3, 3> Matrix3x3D; 
typedef Matrix<double, 4, 4> Matrix4x4D; 
#endif 
+0

muy buen ejemplo. – Vincent

0

Github Link

// 
// iBS_Matrix.h 
// 
// 
// Created by nash on 11/29/15. 
// Copyright 2015 iBean Software. 
// All rights reserved. 
// current copy on Github: 
// 
#ifndef iBS_Matrix_h 
#define iBS_Matrix_h 

const int Matrix_MAJOR_VERSION = 1; 
const int Matrix_MINOR_VERSION = 0; 

#include <iostream> 
#include <vector> 
namespace iBS 
{ 
struct Matrix 
{ 
    std::vector<std::vector<int> > a; 

    Matrix& operator =(Matrix& o) 
    { 
     a.resize(o.a.size()); 
     for(int i=0;i<a.size();i++) 
      a[i].resize(o.a[i].size()); 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = o.a[i][j]; 
      } 
     return *this; 
    } 

    Matrix& operator +(Matrix& o) 
    { 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = a[i][j] + o.a[i][j]; 
      } 
     return *this; 
    } 
    Matrix& operator -(Matrix& o) 
    { 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = a[i][j] - o.a[i][j]; 
      } 
     return *this; 
    } 
    Matrix& operator *(Matrix& o) 
    { 
     if(a[0].size() != o.a.size()) return *this; 

     Matrix tm; 
     tm.a.resize(a.size()); 
     for(int i=0;i<tm.a.size();i++) 
      tm.a[i].resize(o.a[0].size()); 

     for(int i=0;i<tm.a.size();i++) 
      for(int j=0;j<tm.a[i].size();j++) 
      { 
       tm.a[i][j] = 0; 
       for (int c=0; c<a[i].size(); c++) 
       { 
        tm.a[i][j] += a[i][c] * o.a[c][j]; 
       } 

      } 
     *this = tm; 
     return *this; 
    } 
    Matrix& operator ^(int power) 
    { 
     Matrix tM2; 
     tM2 = *this; 

    // not <= below \/ because first time counts as 2 
     for(int i=1; i<power; ++i) 
      *this = (*this) * (tM2); 

     return *this; 
    } 

    void print() 
    { 
     for(int i=0;i<a.size();i++) 
     { 
      for(int j=0;j<a[i].size();j++) 
      { 
       std::cout << a[i][j] << ' '; 
      } 
      std::cout << std::endl; 
     } 
     std::cout << std::endl; 
    } 
}; 

}; // end of namespace iBS 

#endif // iBS_Matrix_h 
0

no hay manera "canónica" para hacer la matriz en C++, STL no proporciona clases como "matri X". Sin embargo, hay algunas bibliotecas de terceros que sí lo tienen. Le recomendamos que los use o escriba su propia implementación.