PLaSK library
Loading...
Searching...
No Matches
tnt_cmat.h
Go to the documentation of this file.
1/*
2*
3* Template Numerical Toolkit (TNT)
4*
5* Mathematical and Computational Sciences Division
6* National Institute of Technology,
7* Gaithersburg, MD USA
8*
9*
10* This software was developed at the National Institute of Standards and
11* Technology (NIST) by employees of the Federal Government in the course
12* of their official duties. Pursuant to title 17 Section 105 of the
13* United States Code, this software is not subject to copyright protection
14* and is in the public domain. NIST assumes no responsibility whatsoever for
15* its use by other parties, and makes no guarantees, expressed or implied,
16* about its quality, reliability, or any other characteristic.
17*
18*/
19
20
21// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
22//
23
24#ifndef TNT_CMAT_H
25#define TNT_CMAT_H
26
27#include "tnt_subscript.h"
28#include "tnt_vec.h"
29#include <cstdlib>
30#include <cassert>
31#include <iostream>
32#include <sstream>
33
34namespace TNT
35{
36
37
38template <class T>
39class Matrix
40{
41
42
43 public:
44
46 typedef T value_type;
47 typedef T element_type;
48 typedef T* pointer;
49 typedef T* iterator;
50 typedef T& reference;
51 typedef const T* const_iterator;
52 typedef const T& const_reference;
53
54 Subscript lbound() const { return 1;}
55
56 protected:
59 Subscript mn_; // total size
60 T* v_;
61 T** row_;
62 T* vm1_ ; // these point to the same data, but are 1-based
63 T** rowm1_;
64
65 // internal helper function to create the array
66 // of row pointers
67
69 {
70 mn_ = M*N;
71 m_ = M;
72 n_ = N;
73
74 v_ = new T[mn_];
75 row_ = new T*[M];
76 rowm1_ = new T*[M];
77
78 assert(v_ != NULL);
79 assert(row_ != NULL);
80 assert(rowm1_ != NULL);
81
82 T* p = v_;
83 vm1_ = v_ - 1;
84 for (Subscript i=0; i<M; i++)
85 {
86 row_[i] = p;
87 rowm1_[i] = p-1;
88 p += N ;
89
90 }
91
92 rowm1_ -- ; // compensate for 1-based offset
93 }
94
95 void copy(const T* v)
96 {
97 Subscript N = m_ * n_;
98 Subscript i;
99
100#ifdef TNT_UNROLL_LOOPS
101 Subscript Nmod4 = N & 3;
102 Subscript N4 = N - Nmod4;
103
104 for (i=0; i<N4; i+=4)
105 {
106 v_[i] = v[i];
107 v_[i+1] = v[i+1];
108 v_[i+2] = v[i+2];
109 v_[i+3] = v[i+3];
110 }
111
112 for (i=N4; i< N; i++)
113 v_[i] = v[i];
114#else
115
116 for (i=0; i< N; i++)
117 v_[i] = v[i];
118#endif
119 }
120
121 void set(const T& val)
122 {
123 Subscript N = m_ * n_;
124 Subscript i;
125
126#ifdef TNT_UNROLL_LOOPS
127 Subscript Nmod4 = N & 3;
128 Subscript N4 = N - Nmod4;
129
130 for (i=0; i<N4; i+=4)
131 {
132 v_[i] = val;
133 v_[i+1] = val;
134 v_[i+2] = val;
135 v_[i+3] = val;
136 }
137
138 for (i=N4; i< N; i++)
139 v_[i] = val;
140#else
141
142 for (i=0; i< N; i++)
143 v_[i] = val;
144
145#endif
146 }
147
148
149
150 void destroy()
151 {
152 /* do nothing, if no memory has been previously allocated */
153 if (v_ == NULL) return ;
154
155 /* if we are here, then matrix was previously allocated */
156 if (v_ != NULL) delete [] (v_);
157 if (row_ != NULL) delete [] (row_);
158
159 /* return rowm1_ back to original value */
160 rowm1_ ++;
161 if (rowm1_ != NULL ) delete [] (rowm1_);
162 }
163
164
165 public:
166
167 operator T**(){ return row_; }
168 operator T**() const { return row_; }
169
170
171 Subscript size() const { return mn_; }
172
173 // constructors
174
175 Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
176
178 {
179 initialize(A.m_, A.n_);
180 copy(A.v_);
181 }
182
183 Matrix(Subscript M, Subscript N, const T& value = T())
184 {
185 initialize(M,N);
186 set(value);
187 }
188
189 Matrix(Subscript M, Subscript N, const T* v)
190 {
191 initialize(M,N);
192 copy(v);
193 }
194
195 Matrix(Subscript M, Subscript N, const char *s)
196 {
197 initialize(M,N);
198 //std::istrstream ins(s);
199 std::istringstream ins(s);
200
201 Subscript i, j;
202
203 for (i=0; i<M; i++)
204 for (j=0; j<N; j++)
205 ins >> row_[i][j];
206 }
207
208 // destructor
209 //
211 {
212 destroy();
213 }
214
215
216 // reallocating
217 //
219 {
220 if (num_rows() == M && num_cols() == N)
221 return *this;
222
223 destroy();
224 initialize(M,N);
225
226 return *this;
227 }
228
229
230
231
232 // assignments
233 //
235 {
236 if (v_ == A.v_)
237 return *this;
238
239 if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
240 copy(A.v_);
241
242 else
243 {
244 destroy();
245 initialize(A.m_, A.n_);
246 copy(A.v_);
247 }
248
249 return *this;
250 }
251
252 Matrix<T>& operator=(const T& scalar)
253 {
254 set(scalar);
255 return *this;
256 }
257
258
260 {
261#ifdef TNT_BOUNDS_CHECK
262 assert( d >= 1);
263 assert( d <= 2);
264#endif
265 return (d==1) ? m_ : ((d==2) ? n_ : 0);
266 }
267
268 Subscript num_rows() const { return m_; }
269 Subscript num_cols() const { return n_; }
270
271
272
273
275 {
276#ifdef TNT_BOUNDS_CHECK
277 assert(0<=i);
278 assert(i < m_) ;
279#endif
280 return row_[i];
281 }
282
283 inline const T* operator[](Subscript i) const
284 {
285#ifdef TNT_BOUNDS_CHECK
286 assert(0<=i);
287 assert(i < m_) ;
288#endif
289 return row_[i];
290 }
291
293 {
294#ifdef TNT_BOUNDS_CHECK
295 assert(1<=i);
296 assert(i <= mn_) ;
297#endif
298 return vm1_[i];
299 }
300
302 {
303#ifdef TNT_BOUNDS_CHECK
304 assert(1<=i);
305 assert(i <= mn_) ;
306#endif
307 return vm1_[i];
308 }
309
310
311
313 {
314#ifdef TNT_BOUNDS_CHECK
315 assert(1<=i);
316 assert(i <= m_) ;
317 assert(1<=j);
318 assert(j <= n_);
319#endif
320 return rowm1_[i][j];
321 }
322
323
324
326 {
327#ifdef TNT_BOUNDS_CHECK
328 assert(1<=i);
329 assert(i <= m_) ;
330 assert(1<=j);
331 assert(j <= n_);
332#endif
333 return rowm1_[i][j];
334 }
335
336
337
338
339};
340
341
342/* *************************** I/O ********************************/
343
344template <class T>
345std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
346{
347 Subscript M=A.num_rows();
348 Subscript N=A.num_cols();
349
350 s << M << " " << N << "\n";
351
352 for (Subscript i=0; i<M; i++)
353 {
354 for (Subscript j=0; j<N; j++)
355 {
356 s << A[i][j] << " ";
357 }
358 s << "\n";
359 }
360
361
362 return s;
363}
364
365template <class T>
366std::istream& operator>>(std::istream &s, Matrix<T> &A)
367{
368
369 Subscript M, N;
370
371 s >> M >> N;
372
373 if ( !(M == A.num_rows() && N == A.num_cols() ))
374 {
375 A.newsize(M,N);
376 }
377
378
379 for (Subscript i=0; i<M; i++)
380 for (Subscript j=0; j<N; j++)
381 {
382 s >> A[i][j];
383 }
384
385
386 return s;
387}
388
389// *******************[ basic matrix algorithms ]***************************
390
391
392template <class T>
394 const Matrix<T> &B)
395{
396 Subscript M = A.num_rows();
397 Subscript N = A.num_cols();
398
399 assert(M==B.num_rows());
400 assert(N==B.num_cols());
401
402 Matrix<T> tmp(M,N);
403 Subscript i,j;
404
405 for (i=0; i<M; i++)
406 for (j=0; j<N; j++)
407 tmp[i][j] = A[i][j] + B[i][j];
408
409 return tmp;
410}
411
412template <class T>
414 const Matrix<T> &B)
415{
416 Subscript M = A.num_rows();
417 Subscript N = A.num_cols();
418
419 assert(M==B.num_rows());
420 assert(N==B.num_cols());
421
422 Matrix<T> tmp(M,N);
423 Subscript i,j;
424
425 for (i=0; i<M; i++)
426 for (j=0; j<N; j++)
427 tmp[i][j] = A[i][j] - B[i][j];
428
429 return tmp;
430}
431
432template <class T>
434 const Matrix<T> &B)
435{
436 Subscript M = A.num_rows();
437 Subscript N = A.num_cols();
438
439 assert(M==B.num_rows());
440 assert(N==B.num_cols());
441
442 Matrix<T> tmp(M,N);
443 Subscript i,j;
444
445 for (i=0; i<M; i++)
446 for (j=0; j<N; j++)
447 tmp[i][j] = A[i][j] * B[i][j];
448
449 return tmp;
450}
451
452
453template <class T>
455{
456 Subscript M = A.num_rows();
457 Subscript N = A.num_cols();
458
459 Matrix<T> S(N,M);
460 Subscript i, j;
461
462 for (i=0; i<M; i++)
463 for (j=0; j<N; j++)
464 S[j][i] = A[i][j];
465
466 return S;
467}
468
469
470
471template <class T>
472inline Matrix<T> matmult(const Matrix<T> &A,
473 const Matrix<T> &B)
474{
475
476#ifdef TNT_BOUNDS_CHECK
477 assert(A.num_cols() == B.num_rows());
478#endif
479
480 Subscript M = A.num_rows();
481 Subscript N = A.num_cols();
482 Subscript K = B.num_cols();
483
484 Matrix<T> tmp(M,K);
485 T sum;
486
487 for (Subscript i=0; i<M; i++)
488 for (Subscript k=0; k<K; k++)
489 {
490 sum = 0;
491 for (Subscript j=0; j<N; j++)
492 sum = sum + A[i][j] * B[j][k];
493
494 tmp[i][k] = sum;
495 }
496
497 return tmp;
498}
499
500template <class T>
502 const Matrix<T> &B)
503{
504 return matmult(A,B);
505}
506
507template <class T>
508inline int matmult(Matrix<T>& C, const Matrix<T> &A,
509 const Matrix<T> &B)
510{
511
512 assert(A.num_cols() == B.num_rows());
513
514 Subscript M = A.num_rows();
515 Subscript N = A.num_cols();
516 Subscript K = B.num_cols();
517
518 C.newsize(M,K);
519
520 T sum;
521
522 const T* row_i;
523 const T* col_k;
524
525 for (Subscript i=0; i<M; i++)
526 for (Subscript k=0; k<K; k++)
527 {
528 row_i = &(A[i][0]);
529 col_k = &(B[0][k]);
530 sum = 0;
531 for (Subscript j=0; j<N; j++)
532 {
533 sum += *row_i * *col_k;
534 row_i++;
535 col_k += K;
536 }
537 C[i][k] = sum;
538 }
539
540 return 0;
541}
542
543
544template <class T>
546{
547
548#ifdef TNT_BOUNDS_CHECK
549 assert(A.num_cols() == x.dim());
550#endif
551
552 Subscript M = A.num_rows();
553 Subscript N = A.num_cols();
554
555 Vector<T> tmp(M);
556 T sum;
557
558 for (Subscript i=0; i<M; i++)
559 {
560 sum = 0;
561 const T* rowi = A[i];
562 for (Subscript j=0; j<N; j++)
563 sum = sum + rowi[j] * x[j];
564
565 tmp[i] = sum;
566 }
567
568 return tmp;
569}
570
571template <class T>
572inline Vector<T> operator*(const Matrix<T> &A, const Vector<T> &x)
573{
574 return matmult(A,x);
575}
576
577} // namespace TNT
578
579#endif
580// CMAT_H