Ego coder
Join Date: 07 2004
Location: Yerevan, Armenia
Age: 44
Posts: 3,738
Rep Power: 5
|
The Matrix as an abstract data type :)
Когда я впервые начал изучать объектно-ориентированное программирование, решил набивать руку, реализовывая разные абстракции. Тем более что их повторное использование, особенно в инженерных расчётах, очень актуальная задача. Конечно, можно отметить что таких реализаций уйма, и что не стоит изобретать вылосипед и прочее. Но на мой взгляд, любой опыт в это плане имеет свои плюсы. Начинаете думать как программист, чувствуете себя Богом
Ниже приведён абстрактный тип данный "Матрица", класс-шаблон, расчитан для любых типов данных где есть поддержка арифметических операций. Ну и весь набор операций, присущи данной абстракции представлен в виде открытого интерфейса класса.
Matrix.h
Code:
#ifndef __MATRIX_H
#define __MATRIX_H
#ifdef TEMP
#undef TEMP
#endif
#define TEMP template<class AnyType>
TEMP class Matrix {
public:
//Default constructor.
Matrix(int nRows, int nCols, AnyType *val = NULL);
//Copy constructor.
Matrix(Matrix<AnyType> &objRef);
//Destructor.
virtual ~Matrix();
//Makes transposition on matrix (swaps around rows with columns).
void DoTransposition();
//Returns determinant of matrix.
AnyType GetDeterminant();
//Returns minor of matrix[i][j] element.
AnyType GetMinor(int i, int j);
//Fills the i-th row with vector.
bool SetRow(const AnyType *ar, int num, int i);
//Fills the j-th column with vector.
bool SetColumn(const AnyType *ar, int num, int j);
//Prints matrix.
void print() const;
AnyType& operator()(const int &i, const int &j);
Matrix<AnyType>& operator=(const Matrix<AnyType> &mat);
Matrix<AnyType>& operator=(const AnyType &val);
//operators with matrix and matrix
friend Matrix<AnyType> operator*(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2);
friend Matrix<AnyType> operator+(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2);
friend Matrix<AnyType> operator-(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2);
Matrix<AnyType>& operator*=(Matrix<AnyType> &mat);
Matrix<AnyType>& operator+=(Matrix<AnyType> &mat);
Matrix<AnyType>& operator-=(Matrix<AnyType> &mat);
//operators with matrix and value
friend Matrix<AnyType> operator*(Matrix<AnyType> &mat, const AnyType &val);
friend Matrix<AnyType> operator+(Matrix<AnyType> &mat, const AnyType &val);
friend Matrix<AnyType> operator-(Matrix<AnyType> &mat, const AnyType &val);
friend Matrix<AnyType> operator*(const AnyType &val, Matrix<AnyType> &mat);
friend Matrix<AnyType> operator+(const AnyType &val, Matrix<AnyType> &mat);
friend Matrix<AnyType> operator-(const AnyType &val, Matrix<AnyType> &mat);
Matrix<AnyType>& operator*=(const AnyType &val);
Matrix<AnyType>& operator+=(const AnyType &val);
Matrix<AnyType>& operator-=(const AnyType &val);
//Return number of rows.
int GetRowCount() const;
//Returns number of columns.
int GetColumnCount() const;
protected:
//Allocates memory for matrix and initialize it
void Alloc(int nRows, int nCols, AnyType *val = NULL);
//Deallocates memory of matrix
void Free();
private:
//Dynamic memory for matrix.
AnyType **m_mat;
//Number of columns
int m_nRows;
//Number of rows
int m_nCols;
//Function-utility (computes minor of matrix[i][j]).
AnyType __fastcall Minor(int i, int j);
//Function-utility (computes determinant of matrix).
AnyType __fastcall Det();
};
#endif
Matrix.cpp
Code:
#include <cassert>
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include "matrix.h"
TEMP Matrix<AnyType>::Matrix(int nRows, int nCols, AnyType *val) : m_mat(NULL) {
Alloc(nRows, nCols, val);
}
TEMP Matrix<AnyType>::Matrix(Matrix<AnyType>& objRef) : m_mat(NULL) {
(*this) = objRef;
}
TEMP Matrix<AnyType>::~Matrix() {
Free();
}
TEMP int Matrix<AnyType>::GetColumnCount() const {
return m_nCols;
}
TEMP int Matrix<AnyType>::GetRowCount() const {
return m_nRows;
}
TEMP void Matrix<AnyType>::Alloc(int nRows, int nCols, AnyType *val) {
if(nRows <= 0 || nCols <= 0) return;
m_nRows = nRows;
m_nCols = nCols;
bool doRealloc = false;
if(m_mat) doRealloc = true;
m_mat = doRealloc ? (AnyType**)realloc(m_mat, m_nRows*sizeof(AnyType*)) : (AnyType**)malloc(m_nRows*sizeof(AnyType*));
for(int i = 0; i < m_nRows; i++) {
m_mat[i] = doRealloc ? (AnyType*)realloc(m_mat, m_nCols*sizeof(AnyType)) : (AnyType*)malloc(m_nCols*sizeof(AnyType));
if(val) for(int j = 0; j < m_nCols; j++) m_mat[i][j] = *val;
}
}
TEMP void Matrix<AnyType>::Free() {
if(m_mat) {
for(int i = m_nRows - 1; i >= 0; i--) free(m_mat[i]);
free(m_mat);
m_mat = NULL;
}
}
TEMP AnyType& Matrix<AnyType>::operator()(const int &i, const int &j) {
assert(m_mat && i >= 0 && i < m_nRows && j >= 0 && j < m_nCols);
return m_mat[i][j];
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator=(const Matrix<AnyType>& mat) {
Alloc(mat.GetRowCount(), mat.GetColumnCount());
for(int i = 0; i < m_nRows; i++)
for(int j = 0; j < m_nCols; j++)
m_mat[i][j] = mat.m_mat[i][j];
return *this;
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator=(const AnyType &val) {
for(int i = 0; i < m_nRows; i++)
for(int j = 0; j < m_nCols; j++)
m_mat[i][j] = val;
return (*this);
}
TEMP Matrix<AnyType> operator*(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2) {
assert(mat1.m_nCols == mat2.m_nRows);
AnyType Sum;
Matrix<AnyType> hold(mat1.m_nRows, mat2.m_nCols);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++) {
Sum = 0;
for(int k = 0; k < mat1.m_nCols; k++)
Sum += mat1(i, k)*mat2(k, j);
hold(i, j) = Sum;
}
return hold;
}
TEMP Matrix<AnyType> operator*(Matrix<AnyType> &mat, const AnyType &val) {
Matrix<AnyType> hold(mat);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) *= val;
return hold;
}
TEMP Matrix<AnyType> operator*(const AnyType &val, Matrix<AnyType> &mat) {
return (mat * val);
}
TEMP Matrix<AnyType> operator+(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2) {
assert(mat1.m_nCols == mat2.m_nCols && mat1.m_nRows == mat2.m_nRows);
Matrix<AnyType> hold(mat1);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) = mat1(i, j) + mat2(i, j);
return hold;
}
TEMP Matrix<AnyType> operator+(Matrix<AnyType> &mat, const AnyType &val) {
Matrix<AnyType> hold(mat);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) += val;
return hold;
}
TEMP Matrix<AnyType> operator+(const AnyType &val, Matrix<AnyType> &mat) {
return (mat + val);
}
TEMP Matrix<AnyType> operator-(Matrix<AnyType> &mat1, Matrix<AnyType> &mat2) {
assert(mat1.m_nCols==mat2.m_nCols && mat1.m_nRows==mat2.m_nRows);
Matrix<AnyType> hold(mat1);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) = mat1(i, j) - mat2(i, j);
return hold;
}
TEMP Matrix<AnyType> operator-(Matrix<AnyType> &mat, const AnyType &val) {
Matrix<AnyType> hold(mat);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) -= val;
return hold;
}
TEMP Matrix<AnyType> operator-(const AnyType &val, Matrix<AnyType> &mat) {
Matrix<AnyType> hold(mat);
for(int i = 0; i < hold.m_nRows; i++)
for(int j = 0; j < hold.m_nCols; j++)
hold(i, j) = val - hold(i, j);
return hold;
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator*=(Matrix<AnyType> &mat) {
return ((*this) = (*this) * mat);
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator+=(Matrix<AnyType> &mat) {
return ((*this) = (*this) + mat);
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator-=(Matrix<AnyType> &mat) {
return ((*this) = (*this) - mat);
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator*=(const AnyType &val) {
return ((*this) = (*this) * val);
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator+=(const AnyType &val) {
return ((*this) = (*this) + val);
}
TEMP Matrix<AnyType>& Matrix<AnyType>::operator-=(const AnyType &val) {
return ((*this) = (*this) - val);
}
TEMP void Matrix<AnyType>::DoTransposition() {
if(m_nCols!=m_nRows) {
Matrix<AnyType> hold(*this);
Alloc(m_nCols, m_nRows);
for(int i = 0; i < m_nRows; i++)
for(int j = 0; j < m_nCols; j++)
m_mat[i][j] = hold(j, i);
return;
}
AnyType hold;
for(int i = 0; i < m_nRows; i++)
for(int j = 0; j < i; j++) {
hold = m_mat[i][j];
m_mat[i][j] = m_mat[j][i];
m_mat[j][i] = hold;
}
}
TEMP AnyType __fastcall Matrix<AnyType>::Minor(int i, int j) {
if(m_nRows==2) return m_mat[1 - i][1 - j];
Matrix<AnyType> newSmallMat(m_nRows - 1, m_nCols - 1);
int i1 = 0, j1 = 0;
for(int ii = 0; ii < m_nRows; ii++) {
if(ii==i) continue;
j1 = 0;
for(int jj = 0; jj < m_nCols; jj++) {
if(jj==j) continue;
newSmallMat(i1, j1++) = m_mat[ii][jj];
}
i1++;
}
return (newSmallMat.Det());
}
TEMP AnyType __fastcall Matrix<AnyType>::Det() {
switch(m_nCols) {
case 1: return m_mat[0][0];
case 2: return ( m_mat[0][0]*m_mat[1][1] - m_mat[1][0]*m_mat[0][1]);
case 3: return (m_mat[0][0]*m_mat[1][1]*m_mat[2][2] + m_mat[1][0]*m_mat[2][1]*m_mat[0][2] +
m_mat[0][1]*m_mat[1][2]*m_mat[2][0] - m_mat[2][0]*m_mat[1][1]*m_mat[0][2] -
m_mat[1][0]*m_mat[0][1]*m_mat[2][2] - m_mat[0][0]*m_mat[2][1]*m_mat[1][2]);
case 4: return ((m_mat[0][0]*m_mat[1][1] - m_mat[0][1]*m_mat[1][0])*
(m_mat[2][2]*m_mat[3][3] - m_mat[2][3]*m_mat[3][2])+
(m_mat[0][2]*m_mat[1][0] - m_mat[0][0]*m_mat[1][2])*
(m_mat[2][1]*m_mat[3][3] - m_mat[2][3]*m_mat[3][1])+
(m_mat[0][0]*m_mat[1][3] - m_mat[0][3]*m_mat[1][0])*
(m_mat[2][1]*m_mat[3][2] - m_mat[2][2]*m_mat[3][1])+
(m_mat[0][1]*m_mat[1][2] - m_mat[0][2]*m_mat[1][1])*
(m_mat[2][0]*m_mat[3][3] - m_mat[2][3]*m_mat[3][0])+
(m_mat[0][3]*m_mat[1][1] - m_mat[0][1]*m_mat[1][3])*
(m_mat[2][0]*m_mat[3][2] - m_mat[2][2]*m_mat[3][0])+
(m_mat[0][2]*m_mat[1][3] - m_mat[0][3]*m_mat[1][2])*
(m_mat[2][0]*m_mat[3][1] - m_mat[2][1]*m_mat[3][0]));
default : break;
}
AnyType det = 0;
short sign;
for(int j = 0; j < m_nCols; j++) {
sign = 1;
if(j%2) sign=-1;
det += sign*m_mat[0][j]*Minor(0, j);
}
return det;
}
TEMP AnyType Matrix<AnyType>::GetDeterminant() {
assert(m_nRows == m_nCols);
return Det();
}
TEMP AnyType Matrix<AnyType>::GetMinor(int i, int j) {
assert(m_nRows == m_nCols && i >= 0 && j >= 0 && i < m_nRows && j < m_nCols);
return Minor(i, j);
}
TEMP void Matrix<AnyType>::print() const {
for(int i = 0; i < m_nRows; i++)
for(int j = 0; j < m_nCols; j++)
printf("%.1lf%c", m_mat[i][j], (j == m_nCols - 1 ? '\n' : '\t'));
}
TEMP bool Matrix<AnyType>::SetRow(const AnyType *ar, int num, int i) {
if(num > m_nCols || i < 0 || i >= m_nRows) return false;
for(int jj = 0; jj < num; jj++) m_mat[i][jj] = ar[jj];
return true;
}
TEMP bool Matrix<AnyType>::SetColumn(const AnyType *ar, int num, int j) {
if(num > m_nRows || j < 0 || j >= m_nCols) return false;
for(int ii = 0; ii< num; ii++) m_mat[ii][j] = ar[ii];
return true;
}
int main() {
time_t tm;
srand((unsigned long)time(NULL));
int n = 10;
Matrix<double> mat(n, n, NULL);
int i, j;
int r = mat.GetRowCount();
int c = mat.GetColumnCount();
for(i = 0; i < r; i++)
for(j = 0; j < c; j++) {
short sign = rand()%2;
sign == 0 ? sign = 1 : sign = -1;
mat(i,j) = ((double)(rand()%(n*n))/(double)(rand()%(n*n) + 1))*sign;
}
mat.print();
printf("\n\n");
time(&tm);
printf("\nStart computing determinant at: %s", ctime(&tm));
printf("\nDet(mat) = %.10lf\n", mat.GetDeterminant());
time(&tm);
printf("\nComputing ends at: %s%s", ctime(&tm), "\n");
return 0;
}
__________________
Каждый сам кузнец своего счастья, и несчастья тоже.
|