www.pudn.com > Face3DModel.zip > matrix.h


// Matrix.h: interface for the CMatrix class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#if !defined(AFX_MATRIX_H__D58D0A47_68B4_11D6_AD90_00B0D0652E95__INCLUDED_) 
#define AFX_MATRIX_H__D58D0A47_68B4_11D6_AD90_00B0D0652E95__INCLUDED_ 
 
#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
 
//  
// Class : CMatrix 
// Written by : R.I.Allen 
//  
// This is an encapsulation of a matrix class that allows all standard operations to be 
// performed on it. It also includes some odd procedures for importing and exporting matrices. 
//  
// Data is stored for the matrix in a flat allocation with 1 additional entry at the end which is 
// used as a reference counter for how many objects are using that data section. When one matrix 
// differs from another when referencing the same memory, a copy is made at that point, and they 
// go their separate ways. This is very useful when returing CMatrix objects which then need to be 
// assigned as it avoid additional memory allocation/deallocation calls. 
// 
#define UNUSED_PARAMETER(x) x 
#include  
 
class CMatrix : public CObject   
{ 
public: 
	DECLARE_SERIAL(CMatrix) ; 
public: 
	friend class	CMatrixHelper ;						// used for operator[][] 
	// construction and destruction 
					CMatrix() ;							// default constructor 
					CMatrix(const CMatrix &other) ;		// copy constructor 
					CMatrix(int nCols, int nRows) ;		// constructs an empty matrix of this size 
					CMatrix(int size, bool set_diagonal = true) ;	// creates a square matrix 
					CMatrix(VARIANT& var) ;				// from a SAFEARRAY variant 
	virtual			~CMatrix();							// destructor 
	void			Serialize(CArchive& archive) ;		// serialization 
     
	// matrix mathematical operations 
	CMatrix&		operator=(const CMatrix &other) ; 
	CMatrix			operator+(const CMatrix &other) const ; 
	CMatrix			operator-(const CMatrix &other) const ; 
	CMatrix			operator*(const CMatrix &other) const ; 
	void			operator+=(const CMatrix &other) ; 
	void			operator-=(const CMatrix &other) ; 
	void			operator*=(const CMatrix &other) ; 
	void			operator*=(double value) ; 
	friend CMatrix	operator*(const CMatrix &other, double value) ; 
	bool			operator==(const CMatrix &other) const ; 
	const CMatrixHelper	operator[](int nCol) const ;			// reading version 
	CMatrixHelper	operator[](int nCol) ;					// writing version 
 
	// element access 
	bool			SetElement(int nCol, int nRow, double value) ; 
#ifdef _DEBUG 
	double			GetElement(int nCol, int nRow) const ; 
#else 
	inline double	GetElement(int nCol, int nRow) const { return m_pData[nCol + nRow * m_NumColumns] ; } ; 
#endif 
	inline int		GetNumColumns() const { return m_NumColumns ; } ; 
	inline int		GetNumRows() const { return m_NumRows ; } ; 
	double			SumColumn(int col) const ; 
	double			SumRow(int row) const ; 
	double			SumColumnSquared(int col) const ; 
	double			SumRowSquared(int row) const ; 
	double			GetRowMin(int row) const ; 
	double			GetRowMax(int row) const ; 
	double			GetColumnMin(int col) const ; 
	double			GetColumnMax(int col) const ; 
	// matrix transposition 
	CMatrix			GetTransposed() const ; 
	void			Transpose() ; 
	// matrix inversion 
	CMatrix			GetInverted() const ; 
	bool			Invert() ; 
	// covariant (A' * A) 
	CMatrix			Covariant() const ; 
	// normalisation 
	CMatrix			GetNormalised(double min, double max) const ; 
	void			Normalise(double min, double max) ; 
	// ranges functions 
	void			GetNumericRange(double &min, double &max) const ; 
	// matrix concatenation 
	CMatrix			GetConcatinatedColumns(const CMatrix& other) const ; 
	void			ConcatinateColumns(const CMatrix &other) ; 
	CMatrix			GetConcatinatedRows(const CMatrix& other) const ; 
	void			ConcatinateRows(const CMatrix &other) ; 
	// adds an new row / column to the matrix 
	void			AddColumn(const double *pData) ; 
	void			AddRow(const double *pData) ; 
	// sub matrix extraction, setting 
	CMatrix			ExtractSubMatrix(int col_start, int row_start, int col_size, int row_size) const ; 
	void			SetSubMatrix(int col_start, int row_start, const CMatrix &other) ; 
	CMatrix			ExtractDiagonal() const ; 
	// squaring the matrix functions 
	CMatrix			GetSquareMatrix() const ; 
	void			MakeSquare() ; 
	// export functions/import 
	VARIANT			GetSafeArray() const ; 
	void			CopyToClipboard() const ; 
	void			WriteAsCSVFile(const CString& filename) const ; 
	static CMatrix	ReadFromCSVFile(const CString& filename) ; 
/* 
	// virtual functions 
#ifdef _DEBUG 
	virtual void	Dump(CDumpContext& dc) const ; 
	virtual void	AssertValid() const ; 
#endif 
*/ 
private: 
	// internal variables 
	int				m_NumColumns ;			// number of columns in matrix 
	int				m_NumRows ;				// number of rows in matrix 
	double*			m_pData ;				// pointer to data, may be shared among objects 
#ifdef _DEBUG 
	// variables used in debug for obejct counting 
	static int		m_NextObjectNumber ; 
	int				m_ObjectNumber ; 
#endif 
private: 
	// private internal functions 
	double*			AllocateMemory(int nCols, int nROws) ; 
	// reference counting functions 
	void			IncrementReferenceCount() ;	// increments the m_pData reference count 
	void			DecrementReferenceCount() ;	// decrements the m_pData reference count 
	void			DecrementAndRelease() ;		// decrements the count and releases the memory if required 
	int				GetReferenceCount() const ;	// returns the m_pData's reference count 
	// helper functions 
	CString			GetRowAsText(int row) const ; 
	static CString	ReadLine(CFile &file) ;		// reads a \r\n delimited line of text from a file 
	static int		GetStringToken(CString source, CString &destination, int start, char ch) ; 
}; 
 
// this class is used to help the operator[][] on a matrix object work correctly 
// it only provides the operator[] 
class CMatrixHelper 
{ 
public: 
	friend class	CMatrix ; 
protected: 
	// protected constructor so only friend class can construct 
	// a CMatrixHelper object 
					CMatrixHelper(CMatrix* pMatrix, int col) : m_pMatrix(pMatrix), m_pMatrixConst(NULL) 
						{ 
						m_Col = col ; 
						} ; 
					CMatrixHelper(const CMatrix* const pMatrix, int col) : m_pMatrixConst(pMatrix), m_pMatrix(NULL) 
						{ 
						m_Col = col ; 
						} ; 
					CMatrixHelper(CMatrixHelper& other) : m_pMatrix(other.m_pMatrix), m_pMatrixConst(other.m_pMatrixConst) 
						{ 
						m_Col = other.m_Col ; 
						} ; 
public: 
					~CMatrixHelper() 
						{ 
						} ; 
	double			operator[](int row) const 
						{ 
						ASSERT(row >= 0) ;									// array bounds error 
						ASSERT(row < m_pMatrixConst->m_NumRows) ;				// array bounds error 
						return m_pMatrixConst->m_pData[row * m_pMatrixConst->m_NumColumns + m_Col] ; 
						} ; 
	double&			operator[](int row) 
						{ 
						// first check the reference count on our data object to see whether we need to create a copy 
						if (m_pMatrix->GetReferenceCount() > 1) 
							{ 
							// we need to make a copy 
							double	*pData = m_pMatrix->m_pData ;			// take a copy of the pointer 
							m_pMatrix->DecrementReferenceCount() ;			// decrement the current reference count 
							m_pMatrix->m_pData = m_pMatrix->AllocateMemory(m_pMatrix->m_NumColumns, m_pMatrix->m_NumRows) ; 
							memcpy(m_pMatrix->m_pData, pData, sizeof(double) * m_pMatrix->m_NumColumns * m_pMatrix->m_NumRows) ; 
							m_pMatrix->IncrementReferenceCount() ;			// increment the new data's reference count 
							} 
						ASSERT(row >= 0) ;									// array bounds error 
						ASSERT(row < m_pMatrix->m_NumRows) ;					// array bounds error 
						ASSERT(m_pMatrix->m_pData) ; 
						return m_pMatrix->m_pData[m_Col + row * m_pMatrix->m_NumColumns] ; 
						} ; 
private: 
	// operator= is private to stop nefarious programmers! 
	void			operator=(CMatrixHelper& other) 
						{ 
						m_pMatrix = other.m_pMatrix ; 
//						m_pMatrixConst = other.m_Col ; 
						m_Col = other.m_Col ; 
						} ; 
	CMatrix*		m_pMatrix ; 
	const CMatrix*	m_pMatrixConst ; 
	int				m_Col ;						// column index for operator[][] 
} ; 
 
#endif // !defined(AFX_MATRIX_H__D58D0A47_68B4_11D6_AD90_00B0D0652E95__INCLUDED_)