Матричный класс С++

В C, если бы я хотел создать матричную структуру, я бы использовал:

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

Затем я могу выделить его с помощью

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

Теперь я делаю equiv в С++?

EDIT:

Я хочу знать канонический способ реализации матричного класса в С++.

Ответы

Ответ 1

nota bene.

В этом ответе есть 20 upvotes, но не предназначено для поддержки std::valarray.

По моему опыту, лучше потратить время на установку и обучение использованию полноценной математической библиотеки, такой как Eigen. Valarray имеет меньше возможностей, чем конкуренция, но он не эффективнее или особенно удобен в использовании.

Если вам нужна лишь небольшая линейная алгебра, и вы не можете добавить что-либо в свою инструментальную цепочку, то, возможно, valarray подойдет. Но, будучи застрявшим, неспособным выразить математически правильное решение вашей проблемы, очень плохое положение. Math неумолимо и неумолимо. Используйте правильный инструмент для задания.


Стандартная библиотека предоставляет std::valarray<double>. std::vector<>, предложенный несколькими другими здесь, предназначен как универсальный контейнер для объектов. valarray, менее известный, потому что он более специализирован (не использует "специализированный" как термин С++) имеет несколько преимуществ:

  • Он не выделяет лишнее пространство. A vector округляет до ближайшей мощности два при распределении, поэтому вы можете изменять размер без перераспределения каждый раз. (Вы все еще можете изменить размер valarray, он по-прежнему будет таким же дорогим, как realloc().)
  • Вы можете разрезать его для доступа к строкам и столбцам.
  • Арифметические операторы работают так, как вы ожидали.

Конечно, преимущество перед использованием C состоит в том, что вам не нужно управлять памятью. Размеры могут находиться в стеке или в объекте среза.

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

C++ - это в основном надмножество C. Вы можете продолжать делать то, что делали.

Тем не менее, в C++ вам нужно определить правильный класс Matrix, который управляет собственной памятью. Например, он может быть поддержан внутренним std::vector, и вы можете переопределить operator[] или operator() чтобы соответствующим образом индексировать вектор (например, см. Как создать оператор индекса для класса Matrix?) из C++ FAQ.

Для начала:

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

(Обратите внимание, что вышеприведенное не делает никакой проверки границ, и я оставляю это как упражнение, чтобы шаблонировать его так, чтобы он работал для вещей, отличных от double.)

Ответ 3

Есть много тонкостей в создании эффективного и качественного класса матрицы. К счастью, есть несколько хороших реализаций.

Тщательно продумайте, хотите ли вы иметь матричный класс фиксированного размера или класс переменного размера. т.е. вы можете сделать это:

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

или вам нужно быть в состоянии сделать это

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

Есть хорошие библиотеки, которые поддерживают оба стиля, а некоторые поддерживают оба. У них разные схемы распределения и разные характеристики.

Если вы хотите написать код самостоятельно, тогда версия шаблона требует некоторых знаний о шаблонах (да). А для динамического нужны некоторые хаки, чтобы обойти множество небольших выделений, если они используются внутри узких циклов.

Ответ 4

Вы могли бы сделать так. Единственное различие заключается в том, что вам нужно будет отличить результат от malloc.

Скорее, вы должны использовать vector, либо как 1D-массив с вычисленной индексацией, либо встроенный вектор. (Первый лучше соответствует вашему коду.)

Например:

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] = /* ... */;

Или:

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] = /* ... */;

Но это только примеры. Вы хотите создать полноценный класс; если вы хотите получить больше советов по этому вопросу, отредактируйте свой вопрос и уточните, что вы хотели бы знать канонический способ реализации матричных классов.

Существуют уже существующие классы матриц. Моим любимым является то, что от boost, UBLAS.

Ответ 5

Вы можете использовать шаблон, например:

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

* edit, исправлена ​​опечатка.

Ответ 6

Проводя несколько лет назад, есть новые возможности с тем, что нам предоставил С++ 11.

Здесь ранний проект, который включен в библиотеку opengl, которую я готовлю, должен дать кому-то еще, кто наткнулся на эту современную отправную точку:

(примечание - это еще предстоит проверить или пересмотреть)

/*(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

Ответ 7

вы можете сделать это с помощью шаблона, если размер матрицы известен во время компиляции:

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

Ответ 8

Для класса матрицы вы хотите избегать перегрузки оператора [].
См. С++ FAQ 13.10

Кроме того, найдите в Интернете несколько бесплатных классов Matrix. В худшем случае они могут дать вам руководство. Лучший случай, меньше программного обеспечения, которое вы должны писать и отлаживать.

Ответ 9

ссылка Github

//
//  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

Ответ 10

Нет никакого "канонического" способа сделать матрицу в С++, STL не предоставляет такие классы, как "matrix". Однако есть некоторые сторонние библиотеки, которые это делают. Вам рекомендуется использовать их или написать собственную реализацию.

Ответ 11

Я написал библиотеку Matrix, которая поддерживает так много функций.

Из его документации:

Эта библиотека поддерживает математические операторы, такие как умножение, определитель, минор, кофактор и т.д.

использование

его использование аналогично c++ массивам.

Matrix<int> A(1, 2);
Matrix<int> B(2, 3);
Matrix<int> result(1, 3);

A[0][0] = 7;
A[0][1] = 10;

B[0][0] = 1;
B[0][1] = 4;
B[0][2] = 2;
B[1][0] = 1;
B[1][1] = 2;
B[1][2] = 100;

result = A * B;

result.dump.matrix();

Результат:

Matrix view:
-            -
| 17 48 1014 |
-            -

Вот документация

Ответ 12

В С++ вы можете использовать вот так:

matrix *p = new matrix;

После этого

delete p;