Я работаю над проектом, который требует от меня написать собственную реализацию класса матрицы. Я решил реализовать матричный класс как шаблон, чтобы обеспечить проверку ошибок во время компиляции следующим образом:
template<size_t N, size_t M> // N × M matrix
class Matrix
{
// implementation...
};
Мне удалось реализовать основные операции, такие как сложение / вычитание, транспонирование и умножение. Однако у меня возникли проблемы с реализацией детерминанта. Я думал о его рекурсивной реализации с использованием Расширение Лапласа, поэтому я должен сначала реализовать способ вычисления i, j минора матрицы. Проблема в том, что минор матрицы N × N представляет собой матрицу (N-1) × (N-1). Следующее не компилируется: (сообщение об ошибке Error C2059 syntax error: '<'
, указывая на первую строку в функции)
template<size_t N>
Matrix<N-1, N-1> Minor(const Matrix<N, N>& mat, size_t i, size_t j)
{
Matrix<N-1, N-1> minor;
// calculate i,j minor
return minor
}
Как я могу обойти это и вычислить несовершеннолетнего, сохраняя при этом шаблонную форму класса?
РЕДАКТИРОВАТЬ: меня попросили привести рабочий пример. Вот соответствующая часть моего кода, я старался сделать его как можно более минимальным. Мой класс Matrix использует класс Vector, который я также написал сам. Я удалил любой несвязанный код, а также изменил все проверки ошибок на asserts
, поскольку реальный код выдает класс исключения, который снова был написан мной.
Здесь Vector.h
файл:
#pragma once
#include <vector>
#include <cassert>
template<size_t S>
class Vector
{
public:
Vector(double fInitialValue = 0.0);
Vector(std::initializer_list<double> il);
// indexing range is 0...S-1
double operator[](size_t i) const;
double& operator[](size_t i);
private:
std::vector<double> m_vec;
};
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
template<size_t S>
Vector<S>::Vector(double fInitialValue) : m_vec(S, fInitialValue)
{
}
template<size_t S>
Vector<S>::Vector(std::initializer_list<double> il) : m_vec(il)
{
assert(il.size() == S);
}
template<size_t S>
double Vector<S>::operator[](size_t i) const
{
return m_vec[i];
}
template<size_t S>
double& Vector<S>::operator[](size_t i)
{
return m_vec[i];
}
А вот и Matrix.h
файл:
#pragma once
#include "Vector.h"
template<size_t N, size_t M>
class Matrix
{
public:
Matrix(double fInitialValue = 0.0);
Matrix(std::initializer_list<Vector<M>> il);
// indexing range is 0...N-1, 0...M-1
Vector<M> operator[](int i) const;
Vector<M>& operator[](int i);
double Determinant() const;
private:
std::vector<Vector<M>> m_mat; // a collection of row vectors
template <size_t N>
friend Matrix<N - 1, N - 1> Minor(const Matrix<N, N>& mat, size_t i, size_t j);
};
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
template<size_t N, size_t M>
Matrix<N, M>::Matrix(double fInitialValue)
: m_mat(N, Vector<M>(fInitialValue)) {}
template<size_t N, size_t M>
Matrix<N, M>::Matrix(std::initializer_list<Vector<M>> il) : m_mat(il)
{
assert(il.size() == N);
}
template<size_t N, size_t M>
Vector<M> Matrix<N, M>::operator[](int i) const
{
return m_mat[i];
}
template<size_t N, size_t M>
Vector<M>& Matrix<N, M>::operator[](int i)
{
return m_mat[i];
}
template<size_t N, size_t M>
double Matrix<N, M>::Determinant() const
{
assert(N == M);
if (N == 2) {
return m_mat[0][0] * m_mat[1][1] - m_mat[0][1] * m_mat[1][0];
}
double det = 0;
for (size_t j = 0; j < N; j++) {
if (j % 2) {
det += m_mat[0][j] * Minor((*this), 0, j).Determinant();
}
else {
det -= m_mat[0][j] * Minor((*this), 0, j).Determinant();
}
}
return det;
}
template <size_t N>
Matrix<N - 1, N - 1> Minor(const Matrix<N, N>& mat, size_t i, size_t j)
{
Matrix<N - 1, N - 1> minor;
for (size_t n = 0; n < i; n++) {
for (size_t m = 0; m < j; m++) {
minor[n][m] = mat[n][m];
}
}
for (size_t n = i + 1; n < N; n++) {
for (size_t m = 0; m < j; m++) {
minor[n - 1][m] = mat[n][m];
}
}
for (size_t n = 0; n < i; n++) {
for (size_t m = j + 1; m < N; m++) {
minor[n][m - 1] = mat[n][m];
}
}
for (size_t n = i + 1; n < N; n++) {
for (size_t m = j + 1; m < N; m++) {
minor[n - 1][m - 1] = mat[n][m];
}
}
return minor;
}
Компилируя их вместе с простым main.cpp
файл:
#include "Matrix.h"#include <iostream>
int main() {
Matrix<3, 3> mat = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
std::cout << mat.Determinant();
}
производит — Error C2760 syntax error: unexpected token '<', expected 'declaration' ...\matrix.h 67
РЕДАКТИРОВАТЬ 2: Очевидно, я написал аргументы шаблона как <N - 1><N - 1>
вместо <N -1, N-1>
в реализации второстепенной функции. Изменение, которое исправило ошибку, но ввело новую — зависание компиляции, и через минуту или около того я получаю Error C1060 compiler is out of heap space ...\matrix.h 65
Задача ещё не решена.
Других решений пока нет …