Реализация определителя матрицы в шаблонном классе матрицы - PullRequest
0 голосов
/ 19 ноября 2018

Я работаю над проектом, который требует от меня написания собственной реализации класса матрицы.Я решил реализовать матричный класс как шаблон, чтобы обеспечить проверку ошибок во время компиляции следующим образом:

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

EDIT2: по-видимому, я написал аргументы шаблона как <N - 1><N - 1> вместо <N -1, N-1> в реализации функции Minor.Изменение, которое исправило ошибку, но ввело новое - зависание компиляции, и через минуту или около того я получаю Error C1060 compiler is out of heap space ...\matrix.h 65

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...