Armenian Knowledge Base  

Go Back   Armenian Knowledge Base > Technical sections > Languages, Compilers, Interpreters > Algorithms
Register

Reply
 
LinkBack Thread Tools
Old 30.01.2014, 07:16   #1
The splendid
 
AvDav's Avatar
 
Join Date: 07 2004
Location: Universe
Age: 36
Posts: 3,413
Downloads: 22
Uploads: 0
Reputation: 222 | 3
Default 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;
}
Reply With Quote
Reply

Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
How fast can you type the alphabet? Hans Andersen General 18 08.12.2005 22:35
Type Of Girls PsilocybeLarvae English Only 6 21.04.2005 01:09
Java: abstract or Interface Tria Languages, Compilers, Interpreters 2 13.04.2005 19:55
Abstract Algebra ...ECC HereNow Software Security 2 20.06.2002 23:59
Matrix Reloaded aka Matrix 2003 acid Cinema 1 31.05.2002 06:13


На правах рекламы:
реклама

All times are GMT. The time now is 14:02.


Powered by vBulletin® Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.