Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
2 bj 1
#ifndef __CGLA_ARITHMATFLOAT_H__
2
#define __CGLA_ARITHMATFLOAT_H__
3
 
4
#include <vector>
5
#include <iostream>
6
 
7
#include "CGLA.h"
8
 
9
 
10
namespace CGLA {
11
 
12
	/** Basic class template for matrices.
13
 
14
	In this template a matrix is defined as an array of vectors. This may
15
	not in all cases be the most efficient but it has the advantage that 
16
	it is possible to use the double subscripting notation:
17
 
18
	T x = m[i][j]
19
 
20
	This template should be used through inheritance just like the 
21
	vector template */
22
	template <class VVT, class HVT, class MT, int ROWS>
23
	class ArithMatFloat
24
	{ 
25
#define for_all_i(expr) for(int i=0;i<ROWS;i++) {expr;}
26
 
27
	public:
28
 
29
		/// Horizontal vector type
30
		typedef HVT HVectorType;
31
 
32
		/// Vertical vector type
33
		typedef VVT VVectorType;
34
 
35
		/// The type of a matrix element
36
		typedef typename HVT::ScalarType ScalarType;
37
 
38
	protected:
39
 
40
		/// The actual contents of the matrix.
41
		HVT data[ROWS];
42
 
43
	protected:
44
 
45
		/// Construct 0 matrix
46
		ArithMatFloat() 
47
		{
10 jab 48
#ifndef NDEBUG
49
			for_all_i(data[i]=HVT(CGLA_INIT_VALUE));
50
#endif
2 bj 51
		}
52
 
53
		/// Construct a matrix where all entries are the same.
54
		explicit ArithMatFloat(ScalarType x)
55
		{
56
			for_all_i(data[i] = HVT(x));
57
		}
58
 
59
		/// Construct a matrix where all rows are the same.
60
		explicit ArithMatFloat(HVT _a)
61
		{
62
			for_all_i(data[i] = _a);
63
		}
64
 
65
 
66
		/// Construct a matrix with two rows.
67
		ArithMatFloat(HVT _a, HVT _b)
68
		{
69
			data[0] = _a;
70
			data[1] = _b;
71
		}
72
 
73
		/// Construct a matrix with three rows.
74
		ArithMatFloat(HVT _a, HVT _b, HVT _c)
75
		{
76
			data[0] = _a;
77
			data[1] = _b;
78
			data[2] = _c;
79
		}
80
 
81
		/// Construct a matrix with four rows.
82
		ArithMatFloat(HVT _a, HVT _b, HVT _c, HVT _d)
83
		{
84
			data[0] = _a;
85
			data[1] = _b;
86
			data[2] = _c;
87
			data[3] = _d;
88
		}
89
 
90
	public:
91
 
92
		/// Get vertical dimension of matrix 
93
		static int get_v_dim() {return VVT::get_dim();}
94
 
95
		/// Get horizontal dimension of matrix
96
		static int get_h_dim() {return HVT::get_dim();}
97
 
98
 
99
		/** Get const pointer to data array.
100
				This function may be useful when interfacing with some other API 
101
				such as OpenGL (TM). */
102
		const ScalarType* get() const 
103
		{
104
			return data[0].get();
105
		}
106
 
107
		/** Get pointer to data array.
108
				This function may be useful when interfacing with some other API 
109
				such as OpenGL (TM). */
110
		ScalarType* get()
111
		{
112
			return data[0].get();
113
		}
114
 
115
		/** Set values by passing an array to the matrix.
116
				The values should be ordered like [[row][row]...[row]] */
117
		void set(const ScalarType* sa) 
118
		{
119
			memcpy(get(), sa, sizeof(ScalarType)*get_h_dim()*get_v_dim());
120
		}
121
 
122
		/// Construct a matrix from an array of scalar values.
123
		explicit ArithMatFloat(const ScalarType* sa) 
124
		{
125
			set(sa);
126
		}
127
 
128
		/// Assign the rows of a 2D matrix.
129
		void set(HVT _a, HVT _b)
130
		{
131
			assert(ROWS==2);
132
			data[0] = _a;
133
			data[1] = _b;
134
		}
135
 
136
		/// Assign the rows of a 3D matrix.
137
		void set(HVT _a, HVT _b, HVT _c)
138
		{
139
			assert(ROWS==3);
140
			data[0] = _a;
141
			data[1] = _b;
142
			data[2] = _c;
143
		}
144
 
145
		/// Assign the rows of a 4D matrix.
146
		void set(HVT _a, HVT _b, HVT _c, HVT _d)
147
		{
148
			assert(ROWS==4);
149
			data[0] = _a;
150
			data[1] = _b;
151
			data[2] = _c;
152
			data[3] = _d;
153
		}
154
 
155
 
156
		//----------------------------------------------------------------------
157
		// index operators
158
		//----------------------------------------------------------------------
159
 
160
		/// Const index operator. Returns i'th row of matrix.
161
		const HVT& operator [] ( int i ) const
162
		{
163
			assert(i<ROWS);
164
			return data[i];
165
		}
166
 
167
		/// Non-const index operator. Returns i'th row of matrix.
168
		HVT& operator [] ( int i ) 
169
		{
170
			assert(i<ROWS);
171
			return data[i];
172
		}
173
 
174
		//----------------------------------------------------------------------
175
 
176
		/// Equality operator. 
177
		bool operator==(const MT& v) const 
178
		{
179
			for_all_i(if (data[i] != v[i]) return false)
180
				return true;
181
		}
182
 
183
		/// Inequality operator.
184
		bool operator!=(const MT& v) const 
185
		{
186
			return !(*this==v);
187
		}
188
 
189
		//----------------------------------------------------------------------
190
 
191
		/// Multiply scalar onto matrix. All entries are multiplied by scalar.
192
		const MT operator * (ScalarType k) const
193
		{
194
			MT v_new;
195
			for_all_i(v_new[i] = data[i] * k);
196
			return v_new;
197
		}
198
 
199
		/// Divide all entries in matrix by scalar.
200
		const MT operator / (ScalarType k) const
201
		{
202
			MT v_new;
203
			for_all_i(v_new[i] = data[i] / k);
204
			return v_new;      
205
		}
206
 
207
		/// Assignment multiplication of matrix by scalar.
208
		const MT& operator *=(ScalarType k) 
209
			{
210
				for_all_i(data[i] *= k); 
211
				return static_cast<const MT&>(*this);
212
			}
213
 
214
		/// Assignment division of matrix by scalar.
215
		const MT& operator /=(ScalarType k) 
216
			{ 
217
				for_all_i(data[i] /= k); 
218
				return static_cast<const MT&>(*this);
219
			}
220
 
221
		//----------------------------------------------------------------------
222
 
223
		/// Add two matrices. 
224
		const MT operator + (const MT& m1) const
225
		{
226
			MT v_new;
227
			for_all_i(v_new[i] = data[i] + m1[i]);
228
			return v_new;
229
		}
230
 
231
		/// Subtract two matrices.
232
		const MT operator - (const MT& m1) const
233
		{
234
			MT v_new;
235
			for_all_i(v_new[i] = data[i] - m1[i]);
236
			return v_new;
237
		}
238
 
239
		/// Assigment addition of matrices.
240
		const MT& operator +=(const MT& v) 
241
			{
242
				for_all_i(data[i] += v[i]); 
243
				return static_cast<const MT&>(*this);
244
			}
245
 
246
		/// Assigment subtraction of matrices.
247
		const MT& operator -=(const MT& v) 
248
			{
249
				for_all_i(data[i] -= v[i]); 
250
				return static_cast<const MT&>(*this);
251
			}
252
 
253
		//----------------------------------------------------------------------
254
 
255
		/// Negate matrix.
256
		const MT operator - () const
257
		{
258
			MT v_new;
259
			for_all_i(v_new[i] = - data[i]);
260
			return v_new;
261
		}
262
 
263
#undef for_all_i  
264
 
265
	};
266
 
267
	/// Multiply scalar onto matrix
268
	template <class VVT, class HVT, class MT, int ROWS>
269
	inline const MT operator * (double k, const ArithMatFloat<VVT,HVT,MT,ROWS>& v) 
270
	{
271
		return v * k;
272
	}
273
 
274
	/// Multiply scalar onto matrix
275
	template <class VVT, class HVT, class MT, int ROWS>
276
	inline const MT operator * (float k, const ArithMatFloat<VVT,HVT,MT,ROWS>& v) 
277
	{
278
		return v * k;
279
	}
280
 
281
	/// Multiply scalar onto matrix
282
	template <class VVT, class HVT, class MT, int ROWS>
283
	inline const MT operator * (int k, const ArithMatFloat<VVT,HVT,MT,ROWS>& v) 
284
	{
285
		return v * k;
286
	}
287
 
288
	/// Multiply vector onto matrix 
289
	template <class VVT, class HVT, class MT, int ROWS>
290
	inline VVT operator*(const ArithMatFloat<VVT,HVT,MT,ROWS>& m,const HVT& v) 
291
	{
292
		VVT v2;
293
		for(int i=0;i<ROWS;i++) v2[i] = dot(m[i], v);
294
		return v2;
295
	}
296
 
297
 
298
#ifndef WIN32
299
	/** Multiply two arbitrary matrices. 
300
			In principle, this function could return a matrix, but in general
301
			the new matrix will be of a type that is different from either of
302
			the two matrices that are multiplied together. We do not want to 
303
			return an ArithMatFloat - so it seems best to let the return value be
304
			a reference arg.
305
 
306
			This template can only be instantiated if the dimensions of the
307
			matrices match -- i.e. if the multiplication can actually be
308
			carried out. This is more type safe than the win32 version below.
309
	*/
310
 
311
	template <class VVT, class HVT, 
312
						class HV1T, class VV2T,
313
						class MT1, class MT2, class MT,
314
						int ROWS1, int ROWS2>
315
	inline void mul(const ArithMatFloat<VVT,HV1T,MT1,ROWS1>& m1,
316
									const ArithMatFloat<VV2T,HVT,MT2,ROWS2>& m2,
317
									ArithMatFloat<VVT,HVT,MT,ROWS1>& m)
318
	{
319
		int cols = ArithMatFloat<VVT,HVT,MT,ROWS1>::get_h_dim();
320
		for(int i=0;i<ROWS1;i++)
321
			for(int j=0;j<cols;j++)
10 jab 322
				{
323
					m[i][j] = 0;
324
					for(int k=0;k<ROWS2;k++)
325
						m[i][j] += m1[i][k] * m2[k][j]; 
326
				}
2 bj 327
	}
328
 
329
 
330
	/** Transpose. See the discussion on mul if you are curious as to why
331
			I don't simply return the transpose. */
332
	template <class VVT, class HVT, class M1T, class M2T, int ROWS, int COLS>
333
	inline void transpose(const ArithMatFloat<VVT,HVT,M1T,ROWS>& m,
334
												ArithMatFloat<HVT,VVT,M2T,COLS>& m_new)
335
	{
336
		for(int i=0;i<M2T::get_v_dim();i++)
337
			for(int j=0;j<M2T::get_h_dim();j++)
338
				m_new[i][j] = m[j][i];
339
	}
340
 
341
#else
342
 
343
	//----------------- win32 -------------------------------
344
	// Visual studio is not good at deducing the args. to these template functions.
345
	// This means that you can call the two functions below with 
346
	// matrices of wrong dimension.
347
 
348
	template <class M1, class M2, class M>
349
	inline void mul(const M1& m1, const M2& m2, M& m)
350
	{
351
		int cols = M::get_h_dim();
352
		int rows1 = M1::get_v_dim();
353
		int rows2 = M2::get_v_dim();
354
 
355
		for(int i=0;i<rows1;i++)
356
			for(int j=0;j<cols;j++)
10 jab 357
				{
358
					m[i][j] = 0;
359
					for(int k=0;k<rows2;k++)
360
						m[i][j] += m1[i][k] * m2[k][j];
361
				}
2 bj 362
	}
363
 
364
 
365
	/** Transpose. See the discussion on mul if you are curious as to why
366
			I don't simply return the transpose. */
367
	template <class M1, class M2>
368
	inline void transpose(const M1& m1, M2& m2)
369
	{
370
		for(int i=0;i<M2::get_v_dim();i++)
371
			for(int j=0;j<M2::get_h_dim();j++)
372
				m2[i][j] = m1[j][i];
373
	}
374
 
375
#endif
376
 
377
	/** Compute the outer product of a and b: a * transpose(b). This is 
378
			a matrix with a::rows and b::columns. */
379
 	template <class VVT, class HVT, class MT, int ROWS>
380
	void outer_product(const VVT& a, const HVT& b, 
381
										 ArithMatFloat<VVT,HVT,MT,ROWS>& m)
382
	{
383
		int R = VVT::get_dim();
384
		int C = HVT::get_dim();
385
		for(int i=0;i<R;++i)
386
			for(int j=0;j<C;++j)
387
				{
388
					m[i][j] = a[i] * b[j];
389
				}
390
	}
391
 
392
	/** Copy a matrix to another matrix, cell by cell.
393
			This conversion that takes a const matrix as first argument
394
			(source) and a non-const matrix as second argument
395
			(destination). The contents of the first matrix is simply copied
396
			to the second matrix. 
397
 
398
			However, if the first matrix is	larger than the second,
399
			the cells outside the range of the destination are simply not
400
			copied. If the destination is larger, the cells outside the 
401
			range of the source matrix are not touched.
402
 
403
			An obvious use of this function is to copy a 3x3 rotation matrix
404
			into a 4x4 transformation matrix.
405
	*/
406
 
407
	template <class M1, class M2>
408
	void copy_matrix(const M1& inmat, M2& outmat)
409
		{
410
			const int R = s_min(inmat.get_v_dim(), outmat.get_v_dim());
411
			const int C = s_min(inmat.get_h_dim(), outmat.get_h_dim());
412
			for(int i=0;i<R;++i)
413
				for(int j=0;j<C;++j)
414
					outmat[i][j] = inmat[i][j];
415
		}
416
 
417
	/** Put to operator */
418
	template <class VVT, class HVT, class MT, int ROWS>
419
	inline std::ostream& 
420
	operator<<(std::ostream&os, const ArithMatFloat<VVT,HVT,MT,ROWS>& m)
421
	{
422
		os << "[\n";
423
		for(int i=0;i<ROWS;i++) os << "  " << m[i] << "\n";
424
		os << "]\n";
425
		return os;
426
	}
427
 
428
	/** Get from operator */
429
	template <class VVT, class HVT, class MT, int ROWS>
430
	inline std::istream& operator>>(std::istream&is, 
431
																	const ArithMatFloat<VVT,HVT,MT,ROWS>& m)
432
	{
433
		for(int i=0;i<ROWS;i++) is>>m[i];
434
		return is;
435
	}
436
 
437
 
438
 
439
 
440
}
441
#endif