00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _MATRIX_
00034 #define _MATRIX_
00035 #include <complex>
00036 #include <iostream>
00037 #include <fstream>
00038 #include <cstdlib>
00039
00040 #define PI 3.1415926535897932384626
00041 #define SQRT2 1.41421356237309504880169
00042 #define EABS(a) (abs(a)<1e-15?0.0:abs(a))
00043 #define EVAL(a) (abs(a)<1e-14?0.0:a)
00044
00045
00046 template <typename Z> static Z gconj(const Z &other) { return other; }
00047 template <> static std::complex<double>
00048 gconj<std::complex<double> >(const std::complex<double> & other) {
00049 return std::conj(other);
00050 }
00051
00056 template <typename Z> class Matrix {
00057 public:
00058
00059 Z *A;
00060 unsigned int M;
00061 unsigned int N;
00062
00063 Z* scratch;
00064
00065 Matrix(void) : M(0), N(0), A(0), scratch(0) {}
00066
00068
00069 Matrix(unsigned int Rows, unsigned int Cols);
00070
00072
00075 Matrix(Z *elements ,unsigned int Rows, unsigned int Cols);
00076
00077 Matrix(const Matrix &A);
00078 Matrix& operator =(const Matrix &C);
00079
00080 ~Matrix();
00081
00083 inline Z& operator() (unsigned int i, unsigned int j);
00084 const Z& operator() (unsigned i, unsigned j) const { return A[j*M+i]; }
00085
00087
00090 Matrix& operator+=(const Matrix& M);
00091
00093 Matrix& operator-=(const Matrix& M);
00094
00096
00097
00098
00099 Matrix& operator*=(Matrix M);
00100
00102
00103
00104
00105
00106 #ifdef _MSC_VER
00107 template<typename S>
00108 Matrix& operator*=(const S &c) {
00109 for (unsigned i=0;i<M*N;i++)
00110 A[i] *= c;
00111 return *this;
00112 }
00113 #else
00114 template <typename S> Matrix& operator*=(const S& s);
00115 #endif
00116
00118 #ifdef _MSC_VER
00119 friend std::ostream& operator<<(std::ostream&, const Matrix<Z>&);
00120 #else
00121 friend std::ostream& operator<<<>(std::ostream&, const Matrix&);
00122 #endif
00123
00125 void dump(const char* filename);
00127 void read(const char* filename);
00128 };
00129
00141 template <typename Z>
00142 Matrix<Z> operator+(const Matrix<Z>&, const Matrix<Z>&);
00143
00144 template <typename Z>
00145 Matrix<Z> operator-(const Matrix<Z> &, const Matrix<Z> &);
00146
00147
00148 template <typename Z>
00149 Matrix<Z> operator*(const Z &, const Matrix<Z> &);
00150
00151 #ifndef _MSC_VER
00152 template <typename Z, typename S>
00153 Matrix<Z> operator*(const S&, const Matrix<Z> &);
00154 #else
00155 template <typename Z, typename S>
00156 Matrix<Z> operator*(const S &a, const Matrix<Z> &B) {
00157 Matrix<Z> R = B;
00158 return R*=a;
00159 }
00160 #endif
00161
00162 template <typename Z>
00163 Matrix<Z> operator*(const Matrix<Z> &, const Matrix<Z> &);
00165
00179
00181
00183 template <typename Z>
00184 Matrix<Z> Adjoint(const Matrix<Z>&);
00185
00187 template <typename Z>
00188 Z Trace(Matrix<Z>&);
00189
00198 template <typename Z>
00199 Matrix<Z> PTrace(Matrix<Z>& R, unsigned dA, unsigned dB);
00200
00202 template <typename Z>
00203 Matrix<Z> TensorProduct(Matrix<Z>& A, Matrix<Z>& B);
00204
00209 template <typename Z>
00210 Z Determinant(Matrix<Z>& M);
00211
00215 template <typename Z>
00216 void SubMatrix(Matrix<Z>& M, Matrix<Z>& S, unsigned i, unsigned j);
00218
00221
00222
00223
00225
00226
00227
00228
00229
00230
00231 template<typename Z>
00232 Matrix<Z>::Matrix(unsigned int m, unsigned int n) : M(m), N(n) {
00233 A = new Z[m*n];
00234 scratch = new Z[n];
00235 }
00236
00237 template<typename Z>
00238 Matrix<Z>::Matrix(Z *a,unsigned int m, unsigned int n) : M(m), N(n) {
00239 A = new Z[m*n];
00240 scratch = new Z[n];
00241 for (unsigned i=0;i<n;i++)
00242 for (unsigned j=0;j<m;j++)
00243 A[i*m+j] = a[n*j+i];
00244 }
00245
00246 template<typename Z>
00247 Matrix<Z>::Matrix(const Matrix<Z> &t) : M(t.M), N(t.N) {
00248 A = new Z[t.M*t.N];
00249 scratch = new Z[N];
00250 for (unsigned i=0;i<t.M*t.N;i++) A[i] = t.A[i];
00251 }
00252
00253 template<typename Z>
00254 Matrix<Z>& Matrix<Z>::operator =(const Matrix<Z> &t) {
00255 if (this != &t) {
00256 if (N != t.N || M != t.M) {
00257 delete[] A;
00258 delete[] scratch;
00259 A = new Z[t.M*t.N];
00260 scratch = new Z[t.N];
00261 M = t.M; N = t.N;
00262 }
00263 for (unsigned i=0;i<M*N;i++) A[i] = t.A[i];
00264 }
00265 return *this;
00266 }
00267
00268 template<typename Z>
00269 Matrix<Z>::~Matrix() {
00270 delete[] A;
00271 delete[] scratch;
00272 }
00273
00274 template<typename Z>
00275 inline Z& Matrix<Z>::operator() (unsigned int i, unsigned int j) {
00276 return A[j*M+i];
00277 }
00278
00279 template<typename Z>
00280 Matrix<Z>& Matrix<Z>::operator+=(const Matrix<Z> &B) {
00281 for (unsigned i=0;i<M*N;i++)
00282 A[i] += B.A[i];
00283 return *this;
00284 }
00285
00286 template<typename Z>
00287 Matrix<Z>& Matrix<Z>::operator-=(const Matrix<Z> &B) {
00288 for (unsigned i=0;i<M*N;i++)
00289 A[i] -= B.A[i];
00290 return *this;
00291 }
00292
00293 template<typename Z>
00294 Matrix<Z>& Matrix<Z>::operator*=(Matrix<Z> B) {
00295
00296
00297 if (N != B.M)
00298 std::cerr << "Incompatible matrices passed to Matrix *=\n";
00299
00300
00301 if (this == &B)
00302 {
00303 Matrix<Z> TMP = B;
00304 return operator*=(TMP);
00305 }
00306
00307
00308 if (B.N > N)
00309 {
00310 Z *tmp = new Z[M*B.N];
00311 memcpy(tmp,A,M*N*sizeof(Z));
00312 delete[] A;
00313 A = tmp;
00314
00315 delete[] scratch;
00316 scratch = new Z[B.N];
00317 }
00318
00319 for (unsigned i=0;i<M;i++)
00320 {
00321
00322 for (unsigned j=0;j<N;j++)
00323 scratch[j] = A[j*M+i];
00324
00325
00326 for (unsigned j=0;j<B.N;j++)
00327 {
00328
00329 A[i+M*j] = 0;
00330 for (unsigned k=0;k<N;k++)
00331 A[i+M*j] += (scratch[k] * B.A[k+j*B.M]);
00332 }
00333 }
00334
00335 N = B.N;
00336 return *this;
00337 }
00338
00339 #ifndef _MSC_VER
00340 template<typename Z> template<typename S>
00341 Matrix<Z>& Matrix<Z>::operator*=(const S &c)
00342 {
00343 for (unsigned i=0;i<M*N;i++)
00344 A[i] *= c;
00345 return *this;
00346 }
00347 #endif
00348
00349 template<typename Z> void Matrix<Z>::dump(const char *fn) {
00350 std::ofstream out_file;
00351
00352 out_file.open(fn, std::ios::out | std::ios::binary);
00353
00354 if (out_file.bad()) {
00355 std::cerr << "Unable to open matrix file for writing" << fn << std::endl;
00356 exit(0);
00357 }
00358
00359 out_file.write(static_cast<unsigned int *>(&M),sizeof(unsigned int));
00360 out_file.write(static_cast<unsigned int *>(&N),sizeof(unsigned int));
00361
00362 out_file.write(A,N*M*sizeof(Z));
00363
00364 if (out_file.bad()) {
00365 std::cerr << "Unable to write matrix file " << fn << std::endl;
00366 exit(0);
00367 }
00368
00369 out_file.close();
00370 }
00371
00372
00373 template<typename Z> void Matrix<Z>::read(const char *fn) {
00374 unsigned int m,n;
00375 std::ifstream in_file;
00376
00377 in_file.open(fn, std::ios::in | std::ios::binary);
00378
00379 if (in_file.bad()) {
00380 std::cerr << "Unable to open matrix file " << fn
00381 << " for reading\n";
00382 exit(0);
00383 }
00384
00385 in_file.read(static_cast<unsigned int *>(&m),sizeof(unsigned int));
00386 in_file.read(static_cast<unsigned int *>(&n),sizeof(unsigned int));
00387
00388
00389 if (n<N || m<M) {
00390 delete[] A;
00391 A = new Z[n*m];
00392 }
00393 N = n; M = m;
00394
00395 in_file.read(A,N*M*sizeof(Z));
00396
00397 if (in_file.bad()) {
00398 std::cerr << "Unable to read matrix file " << fn << std::endl;
00399 exit(0);
00400 }
00401
00402 in_file.close();
00403 }
00404
00405
00406
00407
00408
00409 template <typename Z>
00410 Matrix<Z> operator*(const Matrix<Z> &A, const Matrix<Z> &B)
00411 {
00412 Matrix<Z> R = A;
00413 return R*=B;
00414 }
00415
00416 template <typename Z>
00417 Matrix<Z> operator+(const Matrix<Z> &A, const Matrix<Z> &B) {
00418 Matrix<Z> R = A;
00419 return R+=B;
00420 }
00421
00422 template <typename Z>
00423 Matrix<Z> operator-(const Matrix<Z> &A, const Matrix<Z> &B) {
00424 Matrix<Z> R = A;
00425 return R-=B;
00426 }
00427
00428 template <typename Z>
00429 Matrix<Z> operator*(const Z &a, const Matrix<Z> &B) {
00430 Matrix<Z> R = B;
00431
00432 return R*=a;
00433 }
00434
00435 #ifndef _MSC_VER
00436 template <typename Z, typename S>
00437 Matrix<Z> operator*(const S &a, const Matrix<Z> &B) {
00438 Matrix<Z> R = B;
00439 return R*=a;
00440 }
00441 #endif
00442
00443 template <typename Z>
00444 Matrix<Z> Adjoint(const Matrix<Z>& U) {
00445 Matrix<Z> ADJ(U.N,U.M);
00446 for (unsigned i=0;i<U.M;i++)
00447 for(unsigned j=0;j<U.N;j++)
00448 ADJ(j,i) = gconj<Z>(U(i,j));
00449 return ADJ;
00450 }
00451
00452 template<typename Z>
00453 Z Trace(Matrix<Z>& A) {
00454 Z result = 0;
00455 for (unsigned i=0;i<A.M;i++)
00456 result += A(i,i);
00457
00458 return result;
00459 }
00460
00461 template <typename Z>
00462 std::ostream& operator<<(std::ostream& output, const Matrix<Z>& A) {
00463 output << "[\n";
00464 for (unsigned i=0;i<A.M;i++) {
00465 for (unsigned j=0;j<A.N;j++)
00466
00467 output << "\t" << A.A[j*A.M+i] << "\t";
00468 output << "\n";
00469 }
00470 output << "]";
00471
00472 return output;
00473 }
00474
00475 template <typename Z>
00476 void SubMatrix(Matrix<Z> &P, Matrix<Z> &C, unsigned r, unsigned c) {
00477
00478 for (unsigned i=0;i<r;i++) {
00479 for (unsigned j=0;j<c;j++)
00480 C(i,j) = P(i,j);
00481 for (unsigned j=c+1;j<P.N;j++)
00482 C(i,j-1) = P(i,j);
00483 }
00484
00485 for (unsigned i=r+1;i<P.M;i++) {
00486 for (unsigned j=0;j<c;j++)
00487 C(i-1,j) = P(i,j);
00488 for (unsigned j=c+1;j<P.N;j++)
00489 C(i-1,j-1) = P(i,j);
00490 }
00491 }
00492
00493 template<typename Z>
00494 Matrix<Z> TensorProduct(Matrix<Z>& A,Matrix<Z>& B) {
00495
00496 if (A.M == 1 && A.N == 1) {
00497 return B;
00498 }
00499
00500 if (B.M == 1 && B.N == 1)
00501 return A;
00502
00503 unsigned rows = A.M*B.M;
00504 unsigned cols = A.N*B.N;
00505
00506 Matrix<Z> M(rows,cols);
00507
00508 for (unsigned i=0;i<rows;i++)
00509 for (unsigned j=0;j<cols;j++)
00510 M(i,j) = A(i/B.M,j/B.N) * B(i%B.M,j%B.N);
00511
00512 return M;
00513 }
00514
00515
00516 template<typename Z>
00517 Matrix<Z> PTrace(Matrix<Z>& M, unsigned dA, unsigned dB) {
00518
00519
00520
00521
00522 unsigned D = M.M / dB;
00523 unsigned dC;
00524
00525
00526
00527 if (dA == 0)
00528 dA = 1;
00529
00530
00531 dC = D / dA;
00532
00533 Matrix<Z> R(D,D), IA(dA,dA), IC(dC,dC), B(1,dB);
00534
00535 Matrix<Z> T(D,M.M);
00536
00537 B(0,0) = 1;
00538 for (unsigned i=1;i<dB;i++)
00539 B(0,i) = 0;
00540
00541 for (unsigned i=0;i<dA;i++) {
00542 IA(i,i) = 1;
00543 for (unsigned j=0;j<i;j++)
00544 IA(i,j) = IA(j,i) = 0;
00545 }
00546
00547 for (unsigned i=0;i<dC;i++) {
00548 IC(i,i) = 1;
00549 for (unsigned j=0;j<i;j++)
00550 IC(i,j) = IC(j,i) = 0;
00551 }
00552
00553
00554 Matrix<Z> TMP = TensorProduct(B,IC);
00555 T = TensorProduct(IA,TMP);
00556 R = T*M*Adjoint(T);
00557
00558 for (unsigned i=1;i<dB;i++) {
00559 B(0,i-1) = 0; B(0,i) = 1;
00560 TMP = TensorProduct(B,IC);
00561 T = TensorProduct(IA,TMP);
00562 R += (T*M*Adjoint(T));
00563 }
00564
00565 return R;
00566 }
00567
00568 template <typename Z>
00569 Z Determinant(Matrix<Z>& M) {
00570 Z d; int s;
00571 if (M.M == 2)
00572 return M(0,0)*M(1,1)-M(1,0)*M(0,1);
00573
00574 d = (Z)0; s = 1;
00575
00576 Matrix<Z> S(M.M-1,M.N-1);
00577
00578 for (unsigned i=0;i<M.M;i++) {
00579 SubMatrix(M,S,0,i);
00580 d += static_cast<const Z&>(s)*M(0,i) * Determinant(S);
00581 s *= -1;
00582
00583 }
00584 return d;
00585 }
00586
00587 #endif