Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
660 khor 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
7
#if !defined(MATRIX_H_HAA_AGUST_2001)
8
#define MATRIX_H_HAA_AGUST_2001
9
 
10
#include <cassert>
11
#include <iostream>
12
#include <cmath>
13
#include "Vector.h"
14
#include "../CGLA/ArithMatFloat.h"
15
 
16
namespace LinAlg
17
{
18
 
19
	/*!
20
		\file Matrix.h
21
		\brief The Matrix type
22
	*/
23
 
24
 
25
	/*!
26
		\brief The Matrix type.
27
 
28
		This matrix teplate is one of the basic linear algebra types. In 
29
		principle it an overloaded Array of type T. The typedef Matrix with 
30
		T set to double
31
 
32
		typedef CMatrixType<double> CMatrix;
33
 
34
		is the delclaration intended to be used as the matrix type outside 
35
		the this and related files. The reson for making a template is 
36
		twofold, first it allows for an esay change of precision in this
37
		linear algebre package. Secondly it allows for other MAtrix types 
38
		in special cases.
39
 
40
		The data structure consists of the array of type T, T* Data, 
41
		with the Ilife vector, T** Ilife, refering to the begining 
42
		of each of the columns. Hereby a coherent data area is avalable and 
43
		the concept of 2-dimensionality is acheived by the Ilife vector. The 
44
		pointer to the data area can be obtained by operator [] (int i) 
45
		with i=0, e.g. 
46
 
47
		Matrix A;
48
 
49
		T* pData=A[0];  
50
 
51
		will  make pData point to the data.
52
 
53
		It should be noted that much of the functionality associated with this
54
		Matrix type and the associated Vector type is located in the 
55
		LapackFunc.h file.
56
 
57
		\see LapackFunc.h
58
		\see CVectorType  
59
		\see Additional matrix operators (Located in this file Matrix.h).
60
		\see CMatrix
61
		\see CVector
62
		\see CVec2Type
63
		\see CVec3Type
64
		\see CVec2
65
		\see CVec3
66
 
67
		\author Henrik Aanęs
68
		\version Aug 2001
69
	*/
70
	template <class T>
71
	class CMatrixType 
72
	{
73
		friend class CVectorType<T>;
74
 
75
	private:
76
		///The number of rows in the matrix
77
		int nRows;
78
		///The number of columns in the matrix
79
		int nCols;
80
		/// The number of elements in the matrix, i.e. nElems=nRows*nCols.
81
		int nElems;
82
		///The pointer to the data containing the elements of the matrix.
83
		T* Data;
84
		///The Ilife vector containing pointers to the start of the columns. That is pointers to elements in Data.
85
		T** Ilife;
86
 
87
		///Sets all the elements in the matrix to Scalar.
88
		void SetScalar(const T& Scalar) 
89
		{
90
			T* Itt=Data;
91
			T* Stop=&(Data[nElems]);
92
			while(Itt!=Stop)
93
				{
94
					*Itt=Scalar;
95
					++Itt;
96
				}
97
		} 
98
 
99
		///Clears the allocated memory.
100
		void CleanUp(void)
101
		{
102
			if(Data!=NULL) 
103
				delete [] Data; 
104
			if(Ilife!=NULL) 
105
				delete [] Ilife;
106
		};
107
 
108
		///Allocates memory. Note that nRows,nCols and nElems should be set first.
109
		void Allocate(void)
110
		{ 
111
			Data= new T[nElems]; 
112
			Ilife=new T*[nRows];	
113
			for(int cRow=0;cRow<nRows;cRow++) 
114
				Ilife[cRow]=&Data[cRow*nCols];
115
		};
116
 
117
	public:
118
		///	\name The Constructors and Destructors of the CMatrixType class.
119
		//@{
120
		CMatrixType<T>() : nRows(0),nCols(0),nElems(0),Data(NULL),Ilife(NULL) {};
121
 
122
		CMatrixType<T>(const int Row,const int Col) : nRows(Row),nCols(Col),nElems(Row*Col) {Allocate();}
123
 
124
		CMatrixType<T>(const int Row,const int Col,const T& Scalar) : nRows(Row),nCols(Col),nElems(Row*Col) {Allocate(); SetScalar(Scalar);};
125
 
126
		CMatrixType<T>(const CMatrixType<T>& Rhs) : nRows(Rhs.nRows),nCols(Rhs.nCols),nElems(Rhs.nRows*Rhs.nCols) 
127
		{ 
128
			Allocate();
129
			memcpy(Data,Rhs.Data,nElems*sizeof(T));
130
		}
131
 
132
		template <class VVT, class HVT, class MT, unsigned int ROWS>
133
		CMatrixType<T>(const CGLA::ArithMatFloat<VVT,HVT,MT,ROWS>& Rhs): 
134
			nRows(Rhs.get_v_dim()),nCols(Rhs.get_h_dim()),
135
			nElems(nRows*nCols) 
136
		{ 
137
			Allocate();
138
			for(int i=0;i<nElems;++i)
139
				Data[i] = Rhs.get()[i];
140
		}
141
 
142
		CMatrixType<T>(const CVectorType<T>& Rhs) : nRows(Rhs.Length()),nCols(1),nElems(Rhs.Length()) 
143
		{ 
144
			Allocate();
145
			memcpy(Data,Rhs.Data,nElems*sizeof(T));
146
		}
147
		virtual ~CMatrixType<T>(){CleanUp();};
148
		//@}
149
 
150
		/*!
151
			\name	Asignment opertors.
152
			The assignment operators of the CMatrixType class.
153
			Note that the matrix is resized if it does not have the correct size.
154
		*/
155
		//@{
156
		CMatrixType<T>& operator=(const T& Rhs){ SetScalar(Rhs);return *this;}
157
 
158
    CMatrixType<T>& operator=(const CMatrixType<T>& Rhs)
159
		{ 
160
			Resize(Rhs.nRows,Rhs.nCols); 
161
			memcpy(Data,Rhs.Data,nElems*sizeof(T));
162
			return *this;
163
		}
164
 
165
		template <class VVT, class HVT, class MT, unsigned int ROWS>
166
		CMatrixType<T>& operator=(const CGLA::ArithMatFloat<VVT,HVT,MT,ROWS>& Rhs)
167
		{ 
168
			Resize(Rhs.get_v_dim(),Rhs.get_h_dim()); 
169
			for(int i=0;i<nElems;++i)
170
				Data[i] = Rhs.get()[i];
171
			return *this;
172
		}
173
 
174
		CMatrixType<T>& operator=(const CVectorType<T>&Rhs)
175
		{
176
			Resize(Rhs.Lenght(),1);
177
			memcpy(Data,Rhs.Dat,nElems*sizeof(T));
178
			return *this;
179
		}
180
		//@}
181
 
182
 
183
		/*!
184
			\name Dimension functions.
185
			Functions dealing with the dimension of the matrix.
186
		*/
187
		//@{
188
		/// Returns the number of rows in the matrix
189
		const int Rows(void) const {return nRows;};
190
		///Retruns the number of columns in the matrix. 
191
		const int Cols(void) const {return nCols;};
192
		/// Resizes the matrix IF it does not already have the desired dimensions.
193
		void Resize(const int Row,const int Col)
194
		{
195
			if(Row!=nRows || Col!=nCols)
196
				{
197
					CleanUp();
198
					nRows=Row;
199
					nCols=Col;
200
					nElems=Row*Col;
201
					Data= new T[nElems];
202
					Ilife=new T*[nRows];
203
					for(int cRow=0;cRow<nRows;cRow++)
204
						{
205
							Ilife[cRow]=&Data[cRow*nCols];
206
						}
207
				}
208
		}
209
		//@}
210
 
211
		/*!
212
			\name Acces functions and operators.
213
			The [] operators are the ones intaended for usual use. The get 
214
			and set functions are added to allow for genral Matrix function 
215
			templates.
216
		*/
217
		//@{
218
		T* operator[](const int Row) 
219
		{
220
			assert(Row>=0);
221
			assert(Row<nRows);
222
 
223
			return Ilife[Row];
224
		}
225
 
226
		const T* operator[](const int Row) const 
227
		{
228
			assert(Row>=0);
229
			assert(Row<nRows);
230
 
231
			return Ilife[Row];
232
		}
233
 
234
		const T& get(const int Row,const int Col) const
235
		{
236
			assert(Row>=0 && Row<nRows);
237
			assert(Col>=0 && Col<nCols);
238
			return Ilife[Row][Col];
239
		}
240
 
241
		void set(const int Row,const int Col,const T val) 
242
		{
243
			assert(Row>=0 && Row<nRows);
244
			assert(Col>=0 && Col<nCols);
245
			Ilife[Row][Col]=val;
246
		}
247
		//@}
248
 
249
		/*! 
250
			\name Arithmetic operators.
251
			The aritmic operators of the CMatrixType class.
252
		*/
253
		//@{
254
		CMatrixType<T> operator+(const T& Rhs) const {CMatrixType<T>Ret(*this); return Ret+=Rhs;};
255
		CMatrixType<T> operator-(const T& Rhs) const {CMatrixType<T>Ret(*this); return Ret-=Rhs;};
256
		CMatrixType<T> operator*(const T& Rhs) const {CMatrixType<T>Ret(*this); return Ret*=Rhs;};
257
		CMatrixType<T> operator/(const T& Rhs) const {CMatrixType<T>Ret(*this); return Ret/=Rhs;};
258
		CMatrixType<T>& operator+=(const T& Rhs)
259
		{
260
 
261
			T* Itt=Data;
262
			T* Stop=&(Data[nElems]);
263
			while(Itt!=Stop)
264
				{
265
					(*Itt)+=Rhs;
266
					++Itt;
267
				}
268
 
269
			return *this; 
270
		}
271
 
272
		CMatrixType<T>& operator-=(const T& Rhs)
273
		{
274
			T* Itt=Data;
275
			T* Stop=&(Data[nElems]);
276
			while(Itt!=Stop)
277
				{
278
					(*Itt)-=Rhs;
279
					++Itt;
280
				}
281
 
282
			return *this; 
283
		}
284
 
285
		CMatrixType<T>& operator*=(const T& Rhs)
286
		{
287
			T* Itt=Data;
288
			T* Stop=&(Data[nElems]);
289
			while(Itt!=Stop)
290
				{
291
					(*Itt)*=Rhs;
292
					++Itt;
293
				}
294
 
295
			return *this; 
296
		}
297
 
298
		CMatrixType<T>& operator/=(const T& Rhs)
299
		{
300
			T* Itt=Data;
301
			T* Stop=&(Data[nElems]);
302
			while(Itt!=Stop)
303
				{
304
					(*Itt)/=Rhs;
305
					++Itt;
306
				}
307
 
308
			return *this; 
309
		}
310
 
311
		CMatrixType<T> operator+(const CMatrixType<T>& Rhs) const {CMatrixType<T>Ret(*this); return Ret+=Rhs;};
312
		CMatrixType<T> operator-(const CMatrixType<T>& Rhs) const {CMatrixType<T>Ret(*this); return Ret-=Rhs;};
313
 
314
		CMatrixType<T>& operator+=(const CMatrixType<T>& Rhs)
315
		{
316
			assert(nRows==Rhs.nRows);
317
			assert(nCols==Rhs.nCols);
318
 
319
			T* IttRhs=Rhs.Data;
320
			T* Itt=Data;
321
			T* Stop=&(Data[nElems]);
322
			while(Itt!=Stop)
323
				{
324
					(*Itt)+=(*IttRhs);
325
					++Itt;
326
					++IttRhs;
327
				}
328
 
329
			return *this; 
330
		}
331
 
332
		CMatrixType<T>& operator-=(const CMatrixType<T>& Rhs)
333
		{
334
			assert(nRows==Rhs.nRows);
335
			assert(nCols==Rhs.nCols);
336
			T* IttRhs=Rhs.Data;
337
			T* Itt=Data;
338
			T* Stop=&(Data[nElems]);
339
			while(Itt!=Stop)
340
				{
341
					(*Itt)-=(*IttRhs);
342
					++Itt;
343
					++IttRhs;
344
				}
345
			return *this; 
346
		}
347
 
348
		CMatrixType<T> operator* (const CMatrixType<T>& Rhs) const
349
		{
350
			assert(nCols==Rhs.nRows);
351
			CMatrixType<T> Ret(nRows,Rhs.nCols);
352
 
353
			for(int cRow=0;cRow<nRows;cRow++)
354
				{
355
					for(int cCol=0;cCol<Rhs.nCols;cCol++)
356
						{
357
							T* Ret_ij=&(Ret[cRow][cCol]);
358
							*Ret_ij=0;
359
							for(int cI=0;cI<nCols;cI++)
360
								{
361
									(*Ret_ij)+=(Ilife[cRow])[cI]*Rhs[cI][cCol];
362
								}
363
						}
364
				}
365
			return Ret;
366
		}
367
 
368
		CVectorType<T> operator* (const CVectorType<T>& Rhs) const 
369
		{
370
			assert(nCols==Rhs.nElems);
371
			CVectorType<T> Ret(nRows,0);
372
 
373
			T* ThisItt=Data;
374
			T* Stop=&(Data[nElems]);
375
			T* RhsItt;
376
			T* RetItt=Ret.Data;
377
			while(ThisItt!=Stop)
378
				{
379
					RhsItt=Rhs.Data;
380
					for(int cCol=nCols;cCol>0;--cCol)
381
						{
382
							(*RetItt)+=(*RhsItt)*(*ThisItt);
383
							++ThisItt;
384
							++RhsItt;
385
						}
386
					++RetItt;
387
				}
388
			return Ret;
389
		}
390
		//@}
391
 
392
		/*!
393
			\name Matrix Transpose.
394
			Functions to transpose the matrix
395
		*/
396
		//@{
397
		///Transposes the matrix itself.
398
		CMatrixType<T>& Transpose(void)
399
		{
400
			T* NewData =new T[nElems];
401
			T*RowP;
402
			int cRow;
403
			for(cRow=0;cRow<nRows;cRow++)
404
				{
405
					RowP=Ilife[cRow];
406
					for(int cCol=0;cCol<nCols;cCol++)
407
						{
408
							NewData[cCol*nRows+cRow]=RowP[cCol];
409
						}
410
				}
411
 
412
			CleanUp();
413
 
414
			Data=NewData;
415
			int temp=nRows;
416
			nRows=nCols;
417
			nCols=temp;
418
			Ilife=new T*[nRows];	
419
			for(cRow=0;cRow<nRows;cRow++) 
420
				{
421
					Ilife[cRow]=&Data[cRow*nCols];
422
				}
423
 
424
			return *this;
425
		}
426
 
427
		///Returns the Transpose of the matrix is returned in AT.
428
		void Transposed(CMatrixType<T>& AT) const
429
		{
430
			AT.Resize(nCols,nRows);
431
			for(int cRow=nRows-1;cRow>=0;--cRow)
432
				{
433
					for(int cCol=nCols-1;cCol>=0;--cCol)
434
						{
435
							AT[cCol][cRow]=Ilife[cRow][cCol];
436
						}
437
				}
438
		}
439
 
440
		///Returns the Transpose of the matrix is returned.
441
		CMatrixType<T> Transposed(void) const
442
		{
443
			CMatrixType<T> Ret(nCols,nRows);
444
			Transposed(Ret);
445
			return Ret;
446
		}
447
		//@}
448
 
449
 
450
		/*!
451
			\name Elementwise functions.
452
			Functions the perform some elementary operation on each 
453
			of the elements of the matrix.
454
		*/
455
		//@{
456
		///Pairwise multipling the elemtns of the two matrices. Equvivalent to MatLAb's .*
457
		void ElemMult(const CMatrixType<T>& Rhs)
458
		{
459
			T*Itt=Data;
460
			T*Stop=&(Data[nElems]);
461
			T*RhsItt=Rhs.Data;
462
			while(Itt!=Stop)
463
				{
464
					(*Itt)*=(*RhsItt);
465
					++Itt;
466
					++RhsItt;
467
				}
468
		}
469
 
470
		///Pairwise dividnig the the elemtns of the two matrices. Equvivalent to MatLAb's ./
471
		void ElemDiv(const CMatrixType<T>& Rhs)
472
		{
473
			T*Itt=Data;
474
			T*Stop=&(Data[nElems]);
475
			T*RhsItt=Rhs.Data;
476
			while(Itt!=Stop)
477
				{
478
					(*Itt)/=(*RhsItt);
479
					++Itt;
480
					++RhsItt;
481
				}
482
		}
483
 
484
		///The elements of the matrix squared. Equvivalent to MatLAb's .^2
485
		void ElemSqr(void)
486
		{
487
			T*Itt=Data;
488
			T*Stop=&(Data[nElems]);
489
			while(Itt!=Stop)
490
				{
491
					(*Itt)*=(*Itt);
492
					++Itt;
493
				}
494
		}
495
 
496
		///The square root of the elements. Equvivalent to MatLAb's .^0.5
497
		void ElemSqrt(void)
498
		{
499
			T*Itt=Data;
500
			T*Stop=&(Data[nElems]);
501
			while(Itt!=Stop)
502
				{
503
					(*Itt)=sqrt(*Itt);
504
					++Itt;
505
				}
506
		}
507
		//@}
508
 
509
		/*!
510
			\name Norms.
511
			Computes various norms of the matrix.
512
		*/
513
		//@{
514
		///The Max norm returns the maximum absolute value
515
		const T NormMax(void) const
516
		{
517
			T Ret=0;
518
			T Abs;
519
			const T*Itt=Data;
520
			const T*Stop=&(Data[nElems]);
521
			while(Itt!=Stop)
522
				{
523
					Abs=(*Itt)>0?(*Itt):-(*Itt);
524
					if(Ret<Abs)
525
						Ret=Abs;
526
 
527
					++Itt;
528
				}
529
			return Ret;
530
		}
531
 
532
		/// The Frobenius norm returns the square root of the element sum of squares.
533
		const T NormFrobenius(void) const
534
		{
535
			T Ret=0;
536
			const T*Itt=Data;
537
			const T*Stop=&(Data[nElems]);
538
			while(Itt!=Stop)
539
				{
540
					Ret+=(*Itt)*(*Itt);
541
					++Itt;
542
				}
543
			return sqrt(Ret);
544
		}
545
		//@}
546
 
547
 
548
		/*!
549
			\name Sub-part acces functions
550
			These functions are used to acces sub parts of the matrix.
551
		*/
552
		//@{
553
		///Get the cRow'th row and set it equal to Row. Equvivalent to Row=this(cRow,:) in Matlab.
554
		void GetRow(CVectorType<T>& Row,const int cRow) const
555
		{
556
			Row.Resize(nCols);
557
			memcpy(Row.Data,Ilife[cRow],nCols*sizeof(T));
558
		}
559
 
560
		///Sets the cRow'th row of the matrix equal to Row. Equvivalent to this(cRow,:)=Row in Matlab.
561
		void SetRow(CVectorType<T>& Row,const int cRow)
562
		{
563
			assert(Row.Length()==nCols);
564
			memcpy(Ilife[cRow],Row.Data,nCols*sizeof(T));
565
		}
566
 
567
		///Copies row 'from' of this matrix to row 'to' of matrix A. Equvivalent to A(to,:)=this(from,:) in Matlab.
568
		void RowTransfere(CMatrixType<T>& A, const int from,const int to) const
569
		{
570
			assert(A.Cols()==nCols);
571
			memcpy(A.Ilife[to],Ilife[from],nCols*sizeof(T));
572
		}
573
 
574
		void GetCol(CVectorType<T>&Col, const int nCol) const
575
		{
576
			Col.Resize(nRows);
577
			const T* Itt=&Data[nCol];
578
			T* VecItt=&Col[0];
579
			for(int cRow=0;cRow<nRows;cRow++)
580
				{
581
					*VecItt=*Itt;
582
					++VecItt;
583
					Itt+=nCols;
584
				}
585
		}
586
 
587
		void SetCol(CVectorType<T>&Col, const int nCol)
588
		{
589
			assert(nRows==Col.Length());
590
			assert(nCol<nCols);
591
 
592
			T* Itt=&Data[nCol];
593
			T* VecItt=&Col[0];
594
			for(int cRow=0;cRow<nRows;cRow++)
595
				{
596
					*Itt=*VecItt;
597
					++VecItt;
598
					Itt+=nCols;
599
				}
600
		}
601
 
602
		void GetSubMatrix(CMatrixType<T>& A, const int StartRow, const int StartCol, const int RowDim, const int ColDim) const
603
		{
604
			assert(StartRow+RowDim<=nRows);
605
			assert(StartCol+ColDim<=nCols);
606
			A.Resize(RowDim,ColDim);
607
			const T* Itt=&(Ilife[StartRow][StartCol]);
608
 
609
			for(int cRow=0;cRow<A.Rows();cRow++)
610
				{
611
					memcpy(A[cRow],Itt,A.Cols()*sizeof(T));
612
					Itt+=nCols;
613
				}
614
		}
615
 
616
		void SetSubMatrix(CMatrixType<T>& A, const int StartRow, const int StartCol)
617
		{
618
			assert(A.Rows()+StartRow<=nRows);
619
			assert(A.Cols()+StartCol<=nCols);
620
			T* Itt=&(Ilife[StartRow][StartCol]);
621
 
622
			for(int cRow=0;cRow<A.Rows();cRow++)
623
				{
624
					memcpy(Itt,A[cRow],A.Cols()*sizeof(T));
625
					Itt+=nCols;
626
				}
627
		}
628
 
629
		//@}
630
 
631
 
632
 
633
	};
634
 
635
	/*!
636
		\name Additional matrix operators
637
		These are operators heavily associated with CMAtrixType, but not included
638
		in the class definition it self.
639
	*/
640
	//@{
641
	template<class T>
642
	inline CMatrixType<T> operator+(const T& Lhs,const CMatrixType<T>&Rhs ) 
643
	{
644
		return Rhs+Lhs;
645
	}
646
 
647
	template<class T>
648
	inline CMatrixType<T> operator*(const T& Lhs,const CMatrixType<T>&Rhs ) 
649
	{
650
		return Rhs*Lhs;
651
	}
652
 
653
	template <class T>
654
	std::ostream& operator<<(std::ostream &s, const CMatrixType<T> &A)
655
	{
656
    int nRows=A.Rows();
657
    int nCols=A.Cols();
658
 
659
    for (int cRow=0; cRow<nRows; cRow++)
660
			{
661
        for (int cCol=0; cCol<nCols; cCol++)
662
					{
663
            s << A[cRow][cCol] << " ";
664
					}
665
        s << "\n";
666
			}
667
    return s;
668
	}
669
 
670
	template <class T>
671
	std::istream& operator>>(std::istream &s, CMatrixType<T> &A)
672
	{
673
    int nRows;
674
		int nCols;
675
 
676
    s >> nRows >> nCols;
677
 
678
    if ( nRows!=A.Rows() || nCols!=A.Cols() )
679
			A.Resize(nRows,nCols);
680
 
681
		T* RowP;
682
 
683
 
684
    for (int cRow=0; cRow<nRows;cRow++)
685
			{
686
				RowP=A[cRow];
687
        for (int cCol=0;cCol<nCols;cCol++)
688
					{
689
            s >>  RowP[cCol];
690
					}
691
			}
692
 
693
    return s;
694
	}
695
	//@}
696
 
697
	/// The Matrix annotation intended for use.
698
	typedef CMatrixType<double> CMatrix;
699
}
700
#endif // !defined(MATRIX_H_HAA_AGUST_2001)
701