My Project
Loading...
Searching...
No Matches
tnt_matrix.h
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_MATRIX_H
25#define TNT_MATRIX_H
26
27#include "tnt_subscript.h"
28#include "tnt_vector.h"
29#include <cstdlib>
30#include <cassert>
31#include <iostream>
32#include <sstream>
33#include <fstream>
34
35namespace TNT
36{
37
38//namespace Linear_Algebra {
39
40
55template <class T>
56class Matrix
57{
58
59 private:
60 Subscript m_;
61 Subscript n_;
62 Subscript mn_; // total size
63 T* v_;
64 T** row_;
65 T* vm1_ ; // these point to the same data, but are 1-based
66 T** rowm1_;
67
68 // internal helper function to create the array
69 // of row pointers
70
71 void initialize(Subscript M, Subscript N)
72 {
73 mn_ = M*N;
74 m_ = M;
75 n_ = N;
76
77 v_ = new T[mn_];
78 row_ = new T*[M];
79 rowm1_ = new T*[M];
80
81 assert(v_ != NULL);
82 assert(row_ != NULL);
83 assert(rowm1_ != NULL);
84
85 T* p = v_;
86 vm1_ = v_ - 1;
87 for (Subscript i=0; i<M; i++)
88 {
89 row_[i] = p;
90 rowm1_[i] = p-1;
91 p += N ;
92
93 }
94
95 rowm1_ -- ; // compensate for 1-based offset
96 }
97
98 void copy(const T* v)
99 {
100 Subscript N = m_ * n_;
101 Subscript i;
102
103#ifdef TNT_UNROLL_LOOPS
104 Subscript Nmod4 = N & 3;
105 Subscript N4 = N - Nmod4;
106
107 for (i=0; i<N4; i+=4)
108 {
109 v_[i] = v[i];
110 v_[i+1] = v[i+1];
111 v_[i+2] = v[i+2];
112 v_[i+3] = v[i+3];
113 }
114
115 for (i=N4; i< N; i++)
116 v_[i] = v[i];
117#else
118
119 for (i=0; i< N; i++)
120 v_[i] = v[i];
121#endif
122 }
123
124 void set(const T& val)
125 {
126 Subscript N = m_ * n_;
127 Subscript i;
128
129#ifdef TNT_UNROLL_LOOPS
130 Subscript Nmod4 = N & 3;
131 Subscript N4 = N - Nmod4;
132
133 for (i=0; i<N4; i+=4)
134 {
135 v_[i] = val;
136 v_[i+1] = val;
137 v_[i+2] = val;
138 v_[i+3] = val;
139 }
140
141 for (i=N4; i< N; i++)
142 v_[i] = val;
143#else
144
145 for (i=0; i< N; i++)
146 v_[i] = val;
147
148#endif
149 }
150
151
152
153 void destroy()
154 {
155 /* do nothing, if no memory has been previously allocated */
156 if (v_ == NULL) return ;
157
158 /* if we are here, then matrix was previously allocated */
159 if (v_ != NULL) delete [] (v_);
160 if (row_ != NULL) delete [] (row_);
161
162 /* return rowm1_ back to original value */
163 rowm1_ ++;
164 if (rowm1_ != NULL ) delete [] (rowm1_);
165 }
166
167 public:
168
169 typedef Subscript size_type;
170 typedef T value_type;
171 typedef T element_type;
172 typedef T* pointer;
173 typedef T* iterator;
174 typedef T& reference;
175 typedef const T* const_iterator;
176 typedef const T& const_reference;
177
178 Subscript lbound() const { return 1;}
179
180
181
182
183 operator T**(){ return row_; }
184 operator const T**() const { return row_; }
185
186
190 Subscript size() const { return mn_; }
191
192 // constructors
193
194 Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
195
196 Matrix(const Matrix<T> &A)
197 {
198 initialize(A.m_, A.n_);
199 copy(A.v_);
200 }
201
210 Matrix(Subscript M, Subscript N, const T& value = T(0))
211 {
212 initialize(M,N);
213 set(value);
214 }
215
224 Matrix(Subscript M, Subscript N, const T* v)
225 {
226 initialize(M,N);
227 copy(v);
228 }
229
238 Matrix(Subscript M, Subscript N, const char *s)
239 {
240 initialize(M,N);
241 //std::istrstream ins(s);
242 std::istringstream ins(s);
243
244 Subscript i, j;
245
246 for (i=0; i<M; i++)
247 for (j=0; j<N; j++)
248 ins >> row_[i][j];
249 }
250
251 // destructor
252 //
253 ~Matrix()
254 {
255 destroy();
256 }
257
258
282 Matrix<T>& newsize(Subscript M, Subscript N)
283 {
284 if (num_rows() == M && num_cols() == N)
285 return *this;
286
287 destroy();
288 initialize(M,N);
289
290 return *this;
291 }
292
293
294
295
304 {
305 if (v_ == B.v_)
306 return *this;
307
308 if (m_ == B.m_ && n_ == B.n_) // no need to re-alloc
309 copy(B.v_);
310
311 else
312 {
313 destroy();
314 initialize(B.m_, B.n_);
315 copy(B.v_);
316 }
317
318 return *this;
319 }
320
321 Matrix<T>& operator=(const T& scalar)
322 {
323 set(scalar);
324 return *this;
325 }
326
327
328 Subscript dim(Subscript d) const
329 {
330#ifdef TNT_BOUNDS_CHECK
331 assert( d >= 1);
332 assert( d <= 2);
333#endif
334 return (d==1) ? m_ : ((d==2) ? n_ : 0);
335 }
336
337 Subscript num_rows() const { return m_; }
338 Subscript num_cols() const { return n_; }
339
340
341
342
343 inline T* operator[](Subscript i)
344 {
345#ifdef TNT_BOUNDS_CHECK
346 assert(0<=i);
347 assert(i < m_) ;
348#endif
349 return row_[i];
350 }
351
352 inline const T* operator[](Subscript i) const
353 {
354#ifdef TNT_BOUNDS_CHECK
355 assert(0<=i);
356 assert(i < m_) ;
357#endif
358 return row_[i];
359 }
360
361 inline reference operator()(Subscript i)
362 {
363#ifdef TNT_BOUNDS_CHECK
364 assert(1<=i);
365 assert(i <= mn_) ;
366#endif
367 return vm1_[i];
368 }
369
370 inline const_reference operator()(Subscript i) const
371 {
372#ifdef TNT_BOUNDS_CHECK
373 assert(1<=i);
374 assert(i <= mn_) ;
375#endif
376 return vm1_[i];
377 }
378
379
380
381 inline reference operator()(Subscript i, Subscript j)
382 {
383#ifdef TNT_BOUNDS_CHECK
384 assert(1<=i);
385 assert(i <= m_) ;
386 assert(1<=j);
387 assert(j <= n_);
388#endif
389 return rowm1_[i][j];
390 }
391
392
393
394 inline const_reference operator() (Subscript i, Subscript j) const
395 {
396#ifdef TNT_BOUNDS_CHECK
397 assert(1<=i);
398 assert(i <= m_) ;
399 assert(1<=j);
400 assert(j <= n_);
401#endif
402 return rowm1_[i][j];
403 }
404
405
406
407 Vector<T> diag() const
408 {
409 Subscript N = n_ < m_ ? n_ : m_;
410 Vector<T> d(N);
411
412 for (int i=0; i<N; i++)
413 d[i] = row_[i][i];
414
415 return d;
416 }
417
418 Matrix<T> upper_triangular() const;
419 Matrix<T> lower_triangular() const;
420
421 /* basic computations */
422
423};
424
425
426/* *************************** I/O ********************************/
427
428
429template <class T>
430std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
431{
432 Subscript M=A.num_rows();
433 Subscript N=A.num_cols();
434
435 s << M << " " << N << "\n";
436 for (Subscript i=0; i<M; i++)
437 {
438 for (Subscript j=0; j<N; j++)
439 {
440 s << A[i][j] << " ";
441 }
442 s << "\n";
443 }
444
445
446 return s;
447}
448
449
450template <class T>
451std::istream& operator>>(std::istream &s, Matrix<T> &A)
452{
453
454 Subscript M, N;
455
456 s >> M >> N;
457
458 if ( !(M == A.num_rows() && N == A.num_cols() ))
459 {
460 A.newsize(M,N);
461 }
462
463
464 for (Subscript i=0; i<M; i++)
465 for (Subscript j=0; j<N; j++)
466 {
467 s >> A[i][j];
468 }
469
470
471 return s;
472}
473
474
475
476// *******************[ basic matrix algorithms ]***************************
477
491template <class T>
492Matrix<T> & mult(Matrix<T>& C, const Matrix<T> &A, const Matrix<T> &B)
493{
494
495#ifdef TNT_BOUNDS_CHECK
496 assert(A.num_cols() == B.num_rows());
497#endif
498
499 Subscript M = A.num_rows();
500 Subscript N = A.num_cols();
501 Subscript K = B.num_cols();
502
503#ifdef TNT_BOUNDS_CHECK
504 assert(C.num_rows() == M);
505 assert(C.num_cols() == K);
506#endif
507
508 T sum;
509
510 const T* row_i;
511 const T* col_k;
512
513 for (Subscript i=0; i<M; i++)
514 for (Subscript k=0; k<K; k++)
515 {
516 row_i = &(A[i][0]);
517 col_k = &(B[0][k]);
518 sum = 0;
519 for (Subscript j=0; j<N; j++)
520 {
521 sum += *row_i * *col_k;
522 row_i++;
523 col_k += K;
524 }
525 C[i][k] = sum;
526 }
527
528 return C;
529}
530
531
540template <class T>
541inline Matrix<T> mult(const Matrix<T> &A, const Matrix<T> &B)
542{
543
544#ifdef TNT_BOUNDS_CHECK
545 assert(A.num_cols() == B.num_rows());
546#endif
547
548 Subscript M = A.num_rows();
549 Subscript N = A.num_cols();
550 Subscript K = B.num_cols();
551
552 Matrix<T> tmp(M,K);
553
554 // for (Subscript i=0; i<M; i++)
555 // {
556 // for (Subscript k=0; k<K; k++)
557 // {
558 // T sum = 0;
559 // for (Subscript j=0; j<N; j++)
560 // sum = sum + A[i][j] * B[j][k];
561 //
562 // tmp[i][k] = sum;
563 // }
564 // }
565
566 mult(tmp, A, B); // tmp = A*B
567
568 return tmp;
569}
570
579template <class T>
580inline Matrix<T> operator*(const Matrix<T> &A, const Matrix<T> &B)
581{
582 return mult(A,B);
583}
584
594template <class T>
595inline Vector<T> mult(const Matrix<T> &A, const Vector<T> &b)
596{
597
598#ifdef TNT_BOUNDS_CHECK
599 assert(A.num_cols() == b.dim());
600#endif
601
602 Subscript M = A.num_rows();
603 Subscript N = A.num_cols();
604
605 Vector<T> tmp(M);
606 T sum;
607
608 for (Subscript i=0; i<M; i++)
609 {
610 sum = 0;
611 for (Subscript j=0; j<N; j++)
612 sum = sum + A[i][j] * b[j];
613
614 tmp[i] = sum;
615 }
616
617 return tmp;
618}
619
629template <class T>
630inline Vector<T> operator*(const Matrix<T> &A, const Vector<T> &b)
631{
632 return mult(A,b);
633}
634
635
647template <class T>
648inline Matrix<T> mult(const T& s, const Matrix<T> &A)
649{
650 Subscript M = A.num_rows();
651 Subscript N = A.num_cols();
652
653 Matrix<T> R(M,N);
654 for (int i=0; i<M; i++)
655 for (int j=0; j<N; j++)
656 R[i][j] = s * A[i][j];
657
658 return R;
659}
660
675template <class T>
676inline Matrix<T> mult(const Matrix<T> &A, const T& s)
677{
678 return mult(s, A);
679}
680
681
694template <class T>
695inline Matrix<T> mult_eq(const T& s, Matrix<T> &A)
696{
697 Subscript M = A.num_rows();
698 Subscript N = A.num_cols();
699
700 for (int i=0; i<M; i++)
701 for (int j=0; j<N; j++)
702 A[i][j] *= s;
703}
704
705template <class T>
706inline Matrix<T> mult_eq(Matrix<T> &A, const T&a)
707{
708 return mult_eq(a, A);
709}
710
711
723template <class T>
724inline Matrix<T> transpose_mult(const Matrix<T> &A, const Matrix<T> &B)
725{
726
727#ifdef TNT_BOUNDS_CHECK
728 assert(A.num_rows() == B.num_rows());
729#endif
730
731 Subscript M = A.num_cols();
732 Subscript N = A.num_rows();
733 Subscript K = B.num_cols();
734
735 Matrix<T> tmp(M,K);
736 T sum;
737
738 for (Subscript i=0; i<N; i++)
739 for (Subscript k=0; k<K; k++)
740 {
741 sum = 0;
742 for (Subscript j=0; j<M; j++)
743 sum = sum + A[j][i] * B[j][k];
744
745 tmp[i][k] = sum;
746 }
747
748 return tmp;
749}
750
762template <class T>
763inline Vector<T> transpose_mult(const Matrix<T> &A, const Vector<T> &b)
764{
765
766#ifdef TNT_BOUNDS_CHECK
767 assert(A.num_rows() == b.dim());
768#endif
769
770 Subscript M = A.num_cols();
771 Subscript N = A.num_rows();
772
773 Vector<T> tmp(M);
774
775 for (Subscript i=0; i<M; i++)
776 {
777 T sum = 0;
778 for (Subscript j=0; j<N; j++)
779 sum = sum + A[j][i] * b[j];
780
781 tmp[i] = sum;
782 }
783
784 return tmp;
785}
786
787
796template <class T>
797Matrix<T> add(const Matrix<T> &A, const Matrix<T> &B)
798{
799 Subscript M = A.num_rows();
800 Subscript N = A.num_cols();
801
802 assert(M==B.num_rows());
803 assert(N==B.num_cols());
804
805 Matrix<T> tmp(M,N);
806 Subscript i,j;
807
808 for (i=0; i<M; i++)
809 for (j=0; j<N; j++)
810 tmp[i][j] = A[i][j] + B[i][j];
811
812 return tmp;
813}
814
826template <class T>
827inline Matrix<T> operator+(const Matrix<T> &A, const Matrix<T> &B)
828{
829 return add(A,B);
830}
831
832
833
843template <class T>
845{
846 Subscript M = A.num_rows();
847 Subscript N = A.num_cols();
848
849 assert(M==B.num_rows());
850 assert(N==B.num_cols());
851
852 Matrix<T> tmp(M,N);
853 Subscript i,j;
854
855 for (i=0; i<M; i++)
856 for (j=0; j<N; j++)
857 tmp[i][j] = A[i][j] + B[i][j];
858
859 return A += tmp;
860}
861
873template <class T>
874inline Matrix<T> operator+=(Matrix<T> &A, const Matrix<T> &B)
875{
876 return add_eq(A,B);
877}
878
888template <class T>
889Matrix<T> minus(const Matrix <T>& A, const Matrix<T> &B)
890{
891 Subscript M = A.num_rows();
892 Subscript N = A.num_cols();
893
894 assert(M==B.num_rows());
895 assert(N==B.num_cols());
896
897 Matrix<T> tmp(M,N);
898 Subscript i,j;
899
900 for (i=0; i<M; i++)
901 for (j=0; j<N; j++)
902 tmp[i][j] = A[i][j] - B[i][j];
903
904 return tmp;
905
906}
907
919template <class T>
920inline Matrix<T> operator-(const Matrix<T> &A,
921 const Matrix<T> &B)
922{
923 return minus(A,B);
924}
925
926
937template <class T>
939{
940 Subscript M = A.num_rows();
941 Subscript N = A.num_cols();
942
943 assert(M==B.num_rows());
944 assert(N==B.num_cols());
945
946 Matrix<T> tmp(M,N);
947 Subscript i,j;
948
949 for (i=0; i<M; i++)
950 for (j=0; j<N; j++)
951 tmp[i][j] = A[i][j] * B[i][j];
952
953 return tmp;
954}
955
966template <class T>
968{
969 Subscript M = A.num_rows();
970 Subscript N = A.num_cols();
971
972 assert(M==B.num_rows());
973 assert(N==B.num_cols());
974
975 Subscript i,j;
976
977 for (i=0; i<M; i++)
978 for (j=0; j<N; j++)
979 A[i][j] *= B[i][j];
980
981 return A;
982}
983
984
995template <class T>
996double norm(const Matrix<T> &A)
997{
998 Subscript M = A.num_rows();
999 Subscript N = A.num_cols();
1000
1001 T sum = 0.0;
1002 for (int i=1; i<=M; i++)
1003 for (int j=1; j<=N; j++)
1004 sum += A(i,j) * A(i,j);
1005 return sqrt(sum);
1006
1007}
1008
1018template <class T>
1020{
1021 Subscript M = A.num_rows();
1022 Subscript N = A.num_cols();
1023
1024 Matrix<T> S(N,M);
1025 Subscript i, j;
1026
1027 for (i=0; i<M; i++)
1028 for (j=0; j<N; j++)
1029 S[j][i] = A[i][j];
1030
1031 return S;
1032}
1033
1034
1035
1036
1037
1038
1039
1051template <class T>
1053{
1054 int n = A.num_rows() < A.num_cols() ? A.num_rows() : A.num_cols();
1055 Vector<T> x(b);
1056 for (int k=n; k >= 1; k--)
1057 {
1058 x(k) /= A(k,k);
1059 for (int i=1; i< k; i++ )
1060 x(i) -= x(k) * A(i,k);
1061 }
1062
1063 return x;
1064}
1065
1077template <class T>
1079{
1080 int n = A.num_rows() < A.num_cols() ? A.num_rows() : A.num_cols();
1081 Vector<T> x(b);
1082 for (int k=1; k <= n; k++)
1083 {
1084 x(k) /= A(k,k);
1085 for (int i=k+1; i<= n; i++ )
1086 x(i) -= x(k) * A(i,k);
1087 }
1088
1089 return x;
1090}
1091
1092
1093//} /* namespace TNT::Linear_Algebra; */
1094} /* namespace TNT */
1095
1096#endif
1097// TNT_MATRIX_H
Definition tnt_matrix.h:57
Subscript size() const
Definition tnt_matrix.h:190
Matrix(Subscript M, Subscript N, const char *s)
Definition tnt_matrix.h:238
Matrix< T > & operator=(const Matrix< T > &B)
Definition tnt_matrix.h:303
Matrix(Subscript M, Subscript N, const T &value=T(0))
Definition tnt_matrix.h:210
Matrix< T > & newsize(Subscript M, Subscript N)
Definition tnt_matrix.h:282
Matrix(Subscript M, Subscript N, const T *v)
Definition tnt_matrix.h:224
Definition tnt_vector.h:49
Definition tnt_array1d.h:36
Matrix< T > & mult_element_eq(Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:967
Matrix< T > minus(const Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:889
Matrix< T > transpose(const Matrix< T > &A)
Definition tnt_matrix.h:1019
Matrix< T > add(const Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:797
double norm(const Matrix< T > &A)
Definition tnt_matrix.h:996
Matrix< T > mult_element(const Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:938
Vector< T > lower_triangular_solve(const Matrix< T > &A, const Vector< T > &b)
Definition tnt_matrix.h:1078
Matrix< T > & add_eq(Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:844
Matrix< T > & mult(Matrix< T > &C, const Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:492
Vector< T > upper_triangular_solve(const Matrix< T > &A, const Vector< T > &b)
Definition tnt_matrix.h:1052
Matrix< T > transpose_mult(const Matrix< T > &A, const Matrix< T > &B)
Definition tnt_matrix.h:724
Matrix< T > mult_eq(const T &s, Matrix< T > &A)
Definition tnt_matrix.h:695