Subversion Repositories gelsvn

Rev

Rev 382 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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