Subversion Repositories gelsvn

Rev

Rev 39 | Rev 58 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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