>source

매트릭스 클래스의 메모리 사용량을 줄여야 하는 애플리케이션이 있습니다. 내 행렬의 대부분은 대칭이므로 N2대신 N(N+1)/2메모리만 필요합니다. 나는 단순히 가질 수 없다매트릭스심내 클래스에서 파생된 클래스행렬자식 클래스는 항상 기본 클래스보다 더 많은 메모리를 사용하기 때문입니다. 나는 정의했다MatrixAbstract두 클래스가 모두 상속하는 클래스이지만 두 클래스 모두에서 작동하는 행렬 곱셈 함수를 얻는 데 문제가 있습니다.

내 질문

어떻게 정의할 수 있습니까?C= 곱하기(A,B)둘 중 하나를 수락하는 함수행렬또는매트릭스심모든 입력/출력에 대한 개체? 내 최소한의 작업 예제는 네 가지 정의가 포함되어 있기 때문에 그렇게 최소가 아닙니다.곱하다모두 동일한 code를 사용하고 하나로 결합되어야 합니다.

요구사항

  • 정적 할당만
  • 반드시 사용표준::배열행렬 요소의 경우
  • 반복되는 code 최소화: 행렬 연산이 많이 있지만 다른 점은매트릭스심기본 요소에서 요소를 저장하고 액세스하는 방법입니다.매트 발배열.

#include #include templateclass MatrixAbstract
{
private:
    static constexpr unsigned int numel= NUMEL;
    std::array matVals;   //The array of matrix elements
public:
    MatrixSuperclass(){}
    virtual unsigned int index_from_rc(const unsigned int&
 row, const unsigned int&
 col) const= 0;
    //get the value at a given row and column
    double get_value(const int&
 row, const int&
 col) const
    {
        return this->matVals[this->index_from_rc(row,col)];
    }
    //set the value, given the row and column
    void set_value(const int&
 row, const int&
 col, double value)
    {
        this->matVals[this->index_from_rc(row,col)]= value;
    }
};
templateclass Matrix : public MatrixSuperclass{
public:
    Matrix(){}
    //get the linear index in matVals corresponding to a row,column input
    unsigned int index_from_rc(const unsigned int&
 row, const unsigned int&
 col) const {
        return row*COLS + col;
    }
};
templateclass MatrixSym : public MatrixSuperclass{
public:
    MatrixSym(){}
    //get the linear index in matVals corresponding to a row,column input (Symmetric matrix)
    unsigned int index_from_rc(const unsigned int&
 row, const unsigned int&
 col) const {
        unsigned int z;
        return ( ( z= ( row < col ? col : row ) ) * ( z + 1 ) >> 1 ) + ( col < row ? col : row ) ;
    }
};
//THE FOLLOWING FOUR FUNCTIONS ALL USE THE EXACT SAME CODE, ONLY INPUT/OUTPUT TYPES CHANGE
//Multiply a Matrix and Matrix and output a Matrix
templateMatrix multiply (Matrix&
 inMatrix1, Matrix&
 inMatrix2) {
    Matrix outMatrix;
    for (unsigned int r= 0; r < ROWS; r++) {
        for (unsigned int c= 0; c < COLS; c++) {
            double val= 0.0;
            for (unsigned int rc= 0; rc < INNER; rc++) {
                val += inMatrix1.get_value(r,rc)*inMatrix2.get_value(rc,c);
            }
            outMatrix.set_value(r,c,val);
        }
    }
    return outMatrix;
}
//Multiply a Matrix and MatrixSym and output a Matrix
templateMatrix multiply (Matrix&
 inMatrix1, MatrixSym&
 inMatrix2) {
    Matrix outMatrix;
    for (unsigned int r= 0; r < ROWS; r++) {
        for (unsigned int c= 0; c < COLS; c++) {
            double val= 0.0;
            for (unsigned int rc= 0; rc < INNER; rc++) {
                val += inMatrix1.get_value(r,rc)*inMatrix2.get_value(rc,c);
            }
            outMatrix.set_value(r,c,val);
        }
    }
    return outMatrix;
}
//Multiply a MatrixSym and Matrix and output a Matrix
templateMatrix multiply (MatrixSym&
 inMatrix1, Matrix&
 inMatrix2) {
    //MatrixSym outMatrixSym;
    Matrix outMatrix;
    for (unsigned int r= 0; r < ROWS; r++) {
        for (unsigned int c= 0; c < COLS; c++) {
            double val= 0.0;
            for (unsigned int rc= 0; rc < INNER; rc++) {
                val += inMatrix1.get_value(r,rc)*inMatrix2.get_value(rc,c);
            }
            outMatrix.set_value(r,c,val);
        }
    }
    return outMatrix;
}
//Multiply a MatrixSym and MatrixSym and output a MatrixSym
templateMatrixSym multiply (MatrixSym&
 inMatrix1, MatrixSym&
 inMatrix2) {
    //MatrixSym outMatrixSym;
    MatrixSym outMatrix;
    for (unsigned int r= 0; r < ROWS; r++) {
        for (unsigned int c= 0; c < COLS; c++) {
            double val= 0.0;
            for (unsigned int rc= 0; rc < INNER; rc++) {
                val += inMatrix1.get_value(r,rc)*inMatrix2.get_value(rc,c);
            }
            outMatrix.set_value(r,c,val);
        }
    }
    return outMatrix;
}
int main()
{
    Matrix<3,3> A;
    MatrixSym<3> S;
    Matrix<3,3> AtimesA= multiply(A,A);
    Matrix<3,3> AtimesS= multiply(A,S);
    Matrix<3,3> StimesA= multiply(S,A);
    MatrixSym<3> StimesS= multiply(S,S);
    //Make sure that symmetric matrix S is indeed smaller than A
    std::cout << "sizeof(A)/sizeof(double)= " << sizeof(A)/sizeof(double) << std::endl;
    std::cout << "sizeof(S)/sizeof(double)= " << sizeof(S)/sizeof(double) << std::endl;
    return 0;
}

출력:

sizeof(A)/sizeof(double)= 9
sizeof(S)/sizeof(double)= 15

내가 시도한 것

  • 함수를 사용하려고 하면MatrixAbstract인수로 템플릿 매개변수를 가지고 놀아야 합니다.숫자템플릿 매개변수로. 또한 인스턴스화할 수 없습니다.MatrixAbstract반환 값입니다.
  • 둘 중 하나에 대해 함수를 템플릿화하는 방법을 알 수 없습니다.행렬또는매트릭스심. 내 직감은 이것이 그것을 해결하는 방법이지만 템플릿화된 클래스 입력에 대한 함수를 템플릿화하는 방법을 이해하지 못하지만 여전히 사용할 수는 있습니다.그리고콜스템플릿 인수로.

template<class InMatrix1Type, class InMatrix2Type, class OutMatrixType, unsigned int ROWS, unsigned int COLS, unsigned int INNER>OutMatrixType<ROWS,COLS> multiply (InMatrix1Type<ROWS,INNER>&amp;
 inMatrix1, InMatrix2Type<INNER,COLS>&amp;
 inMatrix2)

다음으로 시작하는 컴파일러 오류가 발생합니다.

error: ‘OutMatrixType’ is not a template
 OutMatrixType<ROWS,COLS> multiply (InMatrix1Type<ROWS,INNER>&amp;
 inMatrix1, InMatrix2Type<INNER,COLS>&amp;
 inMatrix2)
 ^~~~~~~~~~~~~

부분 템플릿 전문화(en.wikipedia.org/wiki/Partial_template_specialization)를 사용하고 있습니까?

moi2021-09-28 19:15:12

상속은 여기서 잘못된 도구입니다. 곱하기 함수를 각 행렬에 대해 하나씩 두 개의 유형 인수를 사용하는 템플릿으로 작성하십시오. 해당 인덱스의 값에 대한 참조를 반환하는 get_value(unsigned, unsigned)를 제공하는 "일반" Matrix 클래스를 작성하세요. 해당 인덱스의 값에 대한 참조를 반환하는 get_value(unsigned, unsigned)를 제공하는 두 번째 SymmetricMatrix 클래스를 작성하십시오. 곱하기는 값이 전체 행렬에서 오는지 대칭(작은) 행렬에서 오는지 상관하지 않습니다.

Pete Becker2021-09-28 19:15:12

학습 목적이 아니라면 기존 매트릭스 라이브러리를 사용하는 것이 좋습니다.

Eugene2021-09-28 19:15:12

@PeteBecker, Matrix 및 SymmetricMatrix는 데이터를 저장하는 방식을 제외하고는 거의 동일합니다. 이런 상황에서 상속이 최선의 방법이 아닙니까? 내 code의 모든 행렬에는 다른 멤버 함수와 속성이 많이 있으며 저장 공간을 덜 사용하는 세 번째 특수 행렬 유형도 있습니다(SymmetricMatrix와 다릅니다. code를 복사하여 붙여넣고 싶지 않습니다. 각 매트릭스 유형.

MountainDrew2021-09-28 19:15:12

@Eugene 일반 행렬보다 대칭 행렬에 더 적은 메모리를 사용하는 행렬 라이브러리를 알지 못합니다. 아시는 분 계시면 알려주세요.

MountainDrew2021-09-28 19:15:12

나는 오래된 Matrix 라이브러리 Newmat11을 사용합니다. Matrix보다 SymmetricMatrix에 더 적은 메모리를 사용하지만 동적 메모리 할당을 사용합니다.

Eugene2021-09-28 19:15:12
  • 이전 python : 데이터 프레임의 일부 열 변경
  • 다음 여러 TypeScript 파일을 개별 JavaScript 파일로 변환