00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00022 class mdp_matrix {
00023 private:
00025 #ifdef MATRIXOPTIMIZE
00026 map<int,deque<mdp_complex*> > stored;
00027 #endif
00028 enum {FREE, HARD} flag;
00029 uint irows,icols,imax;
00030 mdp_complex *m;
00031
00032 uint& rows();
00033 uint& cols();
00034
00035 public:
00036 void allocate();
00037 void reallocate();
00038 void deallocate();
00039 void dimension(const uint, const uint);
00040 mdp_matrix();
00041 mdp_matrix(const mdp_matrix& a);
00042 mdp_matrix(const uint r, const uint c);
00043 mdp_matrix(mdp_complex* z, const uint r, const uint c);
00044 virtual ~mdp_matrix();
00045
00046 const mdp_matrix& operator=(const mdp_matrix& a);
00047 mdp_complex& operator[] (const uint i);
00048 const mdp_complex& operator[] (const uint i) const;
00049
00050 mdp_complex& operator() (const uint i, const uint j);
00051 const mdp_complex& operator() (const uint i, const uint j) const;
00052 mdp_matrix operator() (const uint i);
00053
00054 friend void prepare(mdp_matrix&);
00055
00056 mdp_complex* address();
00057 const uint rows() const;
00058 const uint cols() const;
00059 const uint size() const;
00060 uint rowmax() const;
00061 uint colmax() const;
00062
00063 friend mdp_matrix operator+ (const mdp_matrix& a);
00064 friend mdp_matrix operator- (const mdp_matrix& a);
00065
00066 friend mdp_matrix operator+ (const mdp_matrix& a, const mdp_matrix& b);
00067 friend mdp_matrix operator- (const mdp_matrix& a, const mdp_matrix& b);
00068 friend mdp_matrix operator* (const mdp_matrix& a, const mdp_matrix& b);
00069 friend mdp_matrix operator/ (const mdp_matrix& a, const mdp_matrix& b);
00070
00071 friend mdp_matrix operator+ (const mdp_matrix& a, mdp_complex b);
00072 friend mdp_matrix operator- (const mdp_matrix& a, mdp_complex b);
00073 friend mdp_matrix operator* (const mdp_matrix& a, mdp_complex b);
00074 friend mdp_matrix operator/ (const mdp_matrix& a, mdp_complex b);
00075
00076 friend mdp_matrix operator+ (mdp_complex a, const mdp_matrix& b);
00077 friend mdp_matrix operator- (mdp_complex a, const mdp_matrix& b);
00078 friend mdp_matrix operator* (mdp_complex a, const mdp_matrix& b);
00079 friend mdp_matrix operator/ (mdp_complex a, const mdp_matrix& b);
00080
00081 friend mdp_matrix operator+ (const mdp_matrix& a, mdp_real b);
00082 friend mdp_matrix operator- (const mdp_matrix& a, mdp_real b);
00083 friend mdp_matrix operator* (const mdp_matrix& a, mdp_real b);
00084 friend mdp_matrix operator/ (const mdp_matrix& a, mdp_real b);
00085
00086 friend mdp_matrix operator+ (mdp_real a, const mdp_matrix& b);
00087 friend mdp_matrix operator- (mdp_real a, const mdp_matrix& b);
00088 friend mdp_matrix operator* (mdp_real a, const mdp_matrix& b);
00089 friend mdp_matrix operator/ (mdp_real a, const mdp_matrix& b);
00090
00091 mdp_matrix operator+=(const mdp_matrix& a);
00092 mdp_matrix operator-=(const mdp_matrix& a);
00093 mdp_matrix operator*=(const mdp_matrix& a);
00094 mdp_matrix operator/=(const mdp_matrix& a);
00095
00096 mdp_matrix operator+=(mdp_complex a);
00097 mdp_matrix operator-=(mdp_complex a);
00098 mdp_matrix operator*=(mdp_complex a);
00099 mdp_matrix operator/=(mdp_complex a);
00100
00101 mdp_matrix operator+=(mdp_real a);
00102 mdp_matrix operator-=(mdp_real a);
00103 mdp_matrix operator*=(mdp_real a);
00104 mdp_matrix operator/=(mdp_real a);
00105
00106 void operator=(mdp_complex a);
00107 void operator=(mdp_real a);
00108
00109 friend mdp_matrix inv(const mdp_matrix& a);
00110 friend mdp_matrix pow(const mdp_matrix& a, uint b);
00111 friend mdp_matrix exp(const mdp_matrix& a);
00112 friend mdp_matrix log(const mdp_matrix& a);
00113 friend mdp_matrix sin(const mdp_matrix& a);
00114 friend mdp_matrix cos(const mdp_matrix& a);
00115
00116 friend mdp_matrix mdp_identity();
00117 friend mdp_matrix mdp_zero();
00118
00119 friend mdp_real max(const mdp_matrix& a);
00120 friend mdp_matrix submatrix(const mdp_matrix& a, uint i, uint j);
00121 friend mdp_complex det(const mdp_matrix& a);
00122 friend mdp_complex trace(const mdp_matrix& a);
00123 friend mdp_matrix hermitian(const mdp_matrix& a);
00124 friend mdp_matrix transpose(const mdp_matrix& a);
00125 friend mdp_matrix conj(const mdp_matrix& a);
00126
00127 };
00128
00129 ostream& operator<< (ostream& os, const mdp_matrix& a) {
00130 uint i,j;
00131 for(i=0; i<a.rows(); i++) {
00132 if(i==0) os << "[[";
00133 else os << " [";
00134 for(j=0; j<a.cols(); j++)
00135 if(j==0) os << " " << a(i,j);
00136 else os << ", " << a(i,j) << " ";
00137 if(i==(a.rows()-1)) os << "]]\n";
00138 else os << "], \n";
00139 }
00140 return os;
00141 }
00142
00143
00144 void print(const mdp_matrix& a) {
00145 cout << a;
00146 }
00147
00148 void mdp_matrix::dimension(const uint a, const uint b) {
00149 flag=FREE;
00150 rows()=a;
00151 cols()=b;
00152 imax=a*b;
00153 reallocate();
00154 }
00155
00156 mdp_matrix::mdp_matrix() {
00157 flag=FREE;
00158 rows()=0;
00159 cols()=0;
00160 imax=0;
00161 allocate();
00162 }
00163
00164 mdp_matrix::mdp_matrix(const mdp_matrix& a) {
00165 flag=FREE;
00166 rows()=a.rows();
00167 cols()=a.cols();
00168 imax=a.imax;
00169 allocate();
00170 for(uint i=0; i<imax; i++) m[i]=a[i];
00171 }
00172
00173 mdp_matrix::mdp_matrix(const uint a, const uint b) {
00174 flag=FREE;
00175 rows()=a;
00176 cols()=b;
00177 imax=a*b;
00178 allocate();
00179 }
00180
00181 mdp_matrix::mdp_matrix(mdp_complex* z, const uint a, const uint b) {
00182 flag=HARD;
00183 rows()=a;
00184 cols()=b;
00185 imax=a*b;
00186 m=z;
00187 #if defined(USE_DOUBLE_PRECISION) && defined(MATRIX_SSE2)
00188 _sse_check_alignment((void*) m, 0xf);
00189 #endif
00190 }
00191
00192 mdp_matrix::~mdp_matrix() {
00193 if(flag!=HARD) deallocate();
00194 }
00195
00196 inline void mdp_matrix::allocate() {
00197 if(flag==HARD) error("mdp_matrix::allocate()\nCannot allocate a HARD object");
00198 #ifdef MATRIXOPTIMIZE
00199 deque<mdp_complex*> &q=stored[imax];
00200 if(q.size()) {
00201 m=q[0];
00202 q.pop_front();
00203 } else
00204 #endif
00205 m=new mdp_complex[imax];
00206 if(imax!=0 && m==0) error("mdp_matrix::allocate()\nOut of memory");
00207 memset(m,0,imax*sizeof(mdp_complex));
00208 }
00209
00210 inline void mdp_matrix::deallocate() {
00211 if(flag==HARD) error("mdp_matrix::deallocate()\nCannot allocate a HARD object");
00212 #ifdef MATRIXOPTIMIZE
00213 stored[imax].push_front(m);
00214 #else
00215 delete[] m;
00216 #endif
00217 m=0;
00218 }
00219
00220 inline void mdp_matrix::reallocate() {
00221 if(flag==HARD) error("mdp_matrix::reallocate()\nCannot allocate a HARD object");
00222 deallocate();
00223 allocate();
00224 }
00225
00226 inline const mdp_matrix& mdp_matrix::operator=(const mdp_matrix& x) {
00227 uint i=0;
00228 if(rows()!=x.rows() || cols()!=x.cols()) {
00229 rows()=x.rows(); cols()=x.cols(); imax=x.imax;
00230 reallocate();
00231 }
00232 for(; i<imax; i++) m[i]=x[i];
00233 return *this;
00234 }
00235
00236 inline mdp_complex& mdp_matrix::operator[] (uint i) {
00237 return m[i];
00238 }
00239
00240 inline const mdp_complex& mdp_matrix::operator[] (uint i) const {
00241 return m[i];
00242 }
00243
00244
00245 inline mdp_complex& mdp_matrix::operator() (uint i, uint j) {
00246 return m[i*cols()+j];
00247 }
00248
00249 inline const mdp_complex& mdp_matrix::operator() (uint i, uint j) const {
00250 return m[i*cols()+j];
00251 }
00252
00253 inline mdp_matrix mdp_matrix::operator() (const uint i) {
00254 return mdp_matrix(m+i*cols(), cols(),1);
00255 }
00256
00257 inline void prepare(mdp_matrix& a) {
00258 }
00259
00260 inline mdp_complex* mdp_matrix::address() {
00261 return m;
00262 }
00263
00264 inline uint& mdp_matrix::rows() {
00265 return irows;
00266 }
00267
00268 inline uint& mdp_matrix::cols() {
00269 return icols;
00270 }
00271
00272 inline const uint mdp_matrix::rows() const {
00273 return irows;
00274 }
00275
00276 inline const uint mdp_matrix::cols() const {
00277 return icols;
00278 }
00279
00280 inline const uint mdp_matrix::size() const {
00281 return imax;
00282 }
00283
00284 inline uint mdp_matrix::rowmax() const {
00285 return irows;
00286 }
00287
00288 inline uint mdp_matrix::colmax() const {
00289 return icols;
00290 }
00291
00292 inline mdp_matrix operator+ (const mdp_matrix& a) {
00293 return a;
00294 }
00295
00296
00297 inline mdp_matrix operator- (const mdp_matrix& a) {
00298 mdp_matrix tmp(a.rows(), a.cols());
00299 uint i,j;
00300 for(i=0; i<a.rows(); i++)
00301 for(j=0; j<a.cols(); j++)
00302 tmp(i,j)=-a(i,j);
00303 return tmp;
00304 }
00305
00306
00307
00308 inline mdp_matrix operator+ (const mdp_matrix& x,
00309 const mdp_matrix& y) {
00310 mdp_matrix z(x.rows(),x.cols());
00311 #if defined(CHECK_ALL)
00312 if(x.rows()!=y.rows() || x.cols()!=y.cols())
00313 error("mdp_matrix::operator+()\nWrong argument size");
00314 #endif
00315 for(register uint i=0; i<z.imax; i++) z[i]=x[i]+y[i];
00316 return z;
00317 }
00318
00319 inline mdp_matrix operator- (const mdp_matrix& x, const mdp_matrix& y) {
00320 if(x.rows()!=y.rows() || x.cols()!=y.cols())
00321 error("mdp_matrix::operator-()\nwrong argument size");
00322 mdp_matrix z(x.rows(),x.cols());
00323 for(register uint i=0; i<z.imax; i++) z[i]=x[i]-y[i];
00324 return z;
00325 }
00326
00327 inline mdp_matrix operator* (const mdp_matrix& x, const mdp_matrix& y) {
00328 register uint i, j, k;
00329 if(x.cols()!=y.rows())
00330 error("mdp_matrix::operator*()\nwrong argument size");
00331 mdp_matrix z(x.rows(),y.cols());
00332 #if defined(MATRIX_SSE2) && defined(USE_DOUBLE_PRECISION)
00333 if(x.rows()==x.cols() && y.rows()==3) {
00334 register int i, cols()=y.cols(), cols()2=2*cols();
00335 _sse_su3 *u =(_sse_su3*) x.m;
00336 _sse_double *in =(_sse_double*) y.m;
00337 _sse_double *out=(_sse_double*) z.m;
00338 for(i=0; i<cols(); i++, in++, out++) {
00339 _sse_double_load_123(*in, *(in+cols()), *(in+cols()2));
00340 _sse_double_su3_multiply(*u);
00341 _sse_double_store_up_123(*out, *(out+cols()), *(out+cols()2));
00342 }
00343 return z;
00344 }
00345 #endif
00346 #if defined(MATRIX_SSE2) && !defined(USE_DOUBLE_PRECISION)
00347 if(x.rows()==x.cols() && y.imax==3) {
00348 _sse_su3 *u =(_sse_su3*) x.m;
00349 _sse_su3_vector *in =(_sse_su3_vector*) y.m;
00350 _sse_su3_vector *out=(_sse_su3_vector*) z.m;
00351 _sse_float_pair_load(*in, *in);
00352 _sse_float_su3_multiply(*u);
00353 _sse_float_pair_store_up(*out, *out);
00354 return z;
00355 }
00356 #endif
00357 for(i=0; i<x.rows(); i++)
00358 for(j=0; j<y.cols(); j++) {
00359 z(i,j)=x(i,0)*y(0,j);
00360 for(k=1; k<x.cols(); k++) z(i,j)+=x(i,k)*y(k,j);
00361 }
00362 return z;
00363 }
00364
00365 inline mdp_matrix operator/ (const mdp_matrix& a,
00366 const mdp_matrix& b) {
00367 return a*inv(b);
00368 }
00369
00370 inline mdp_matrix operator+ (const mdp_matrix& a, mdp_complex b) {
00371 if(a.cols()!=a.rows()) error("mdp_matrix::operator+(...)\nmdp_matrix is not squared");
00372 mdp_matrix tmp;
00373 register uint i;
00374 tmp=a;
00375 for(i=0; i<a.cols(); i++) tmp(i,i)+=b;
00376 return tmp;
00377 }
00378
00379 inline mdp_matrix operator- (const mdp_matrix& a, mdp_complex b) {
00380 if(a.cols()!=a.rows()) error("mdp_matrix::operator-(...)\nmdp_matrix is not squared");
00381 mdp_matrix tmp;
00382 register uint i;
00383 tmp=a;
00384 for(i=0; i<a.cols(); i++) tmp(i,i)-=b;
00385 return tmp;
00386 }
00387
00388 inline mdp_matrix operator* (const mdp_matrix& y, mdp_complex x) {
00389 register uint i;
00390 mdp_matrix z(y.rows(),y.cols());
00391 #if defined(MATRIX_SSE2)
00392 if(y.rows()==3) {
00393 static _sse_float factor1 ALIGN16;
00394 static _sse_float factor2 ALIGN16;
00395 static _sse_double factor3 ALIGN16;
00396 static _sse_double factor4 ALIGN16;
00397 _sse_su3_vector *in =(_sse_su3_vector*) y.m;
00398 _sse_su3_vector *out=(_sse_su3_vector*) z.m;
00399 #if defined(USE_DOUBLE_PRECISION)
00400 factor3.c1=factor3.c2=x.imag();
00401 factor4.c1=factor4.c2=x.real()/x.imag();
00402 for(i=0; i<y.cols(); i++, in++, out++) {
00403 _sse_double_load(*in);
00404 _sse_double_vector_mulc(factor3,factor4);
00405 _sse_double_store(*out);
00406 }
00407 #else
00408 factor1.c1=factor1.c2=factor1.c3=factor1.c4=x.imag();
00409 factor2.c1=factor2.c2=factor2.c3=factor2.c4=x.real()/x.imag();
00410 for(i=0; i<y.cols()-1; i+=2, in+=2, out+=2) {
00411 _sse_float_pair_load(*in, *(in+1));
00412 _sse_float_vector_mulc(factor1,factor2);
00413 _sse_float_pair_store(*out, *(out+1));
00414
00415 }
00416 if(i==y.cols()-1) {
00417 _sse_float_pair_load(*in, *in);
00418 _sse_float_vector_mulc(factor1,factor2);
00419 _sse_float_pair_store(*out, *out);
00420 }
00421 #endif
00422 return z;
00423 }
00424 #endif
00425 for(i=0; i<y.imax; i++) z[i]=x*y[i];
00426 return z;
00427 }
00428
00429 inline mdp_matrix operator/ (const mdp_matrix& a, mdp_complex b) {
00430 return a*(1.0/b);
00431 }
00432 ;
00433 inline mdp_matrix operator+ (mdp_complex b, const mdp_matrix& a) {
00434 return a+b;
00435 }
00436
00437 inline mdp_matrix operator- (mdp_complex b, const mdp_matrix& a) {
00438 if(a.cols()!=a.rows()) error("mdp_matrix::operator-(...)\nmdp_matrix is not squared");
00439 mdp_matrix tmp(a.rows(), a.cols());
00440 uint i,j;
00441 for(i=0; i<a.rows(); i++) {
00442 for(j=0; j<a.cols(); j++) tmp(i,j)=-a(i,j);
00443 tmp(i,i)+=b;
00444 }
00445 return tmp;
00446 }
00447
00448 inline mdp_matrix operator* (mdp_complex x, const mdp_matrix& y) {
00449 return y*x;
00450 }
00451
00452 inline mdp_matrix operator/ (mdp_complex b, const mdp_matrix& a) {
00453 return b*inv(a);
00454 }
00455
00456 inline mdp_matrix operator+ (const mdp_matrix& a, mdp_real b) {
00457 if(a.cols()!=a.rows()) error("mdp_matrix::operator+(...)\nmdp_matrix is not squared");
00458 mdp_matrix tmp;
00459 uint i;
00460 tmp=a;
00461 for(i=0; i<a.cols(); i++) tmp(i,i).real()+=b;
00462 return tmp;
00463 }
00464
00465 inline mdp_matrix operator- (const mdp_matrix& a, mdp_real b) {
00466 if(a.cols()!=a.rows()) error("mdp_matrix::operator-(...)\nmdp_matrix is not squared");
00467 mdp_matrix tmp;
00468 uint i;
00469 tmp=a;
00470 for(i=0; i<a.cols(); i++) tmp(i,i).real()-=b;
00471 return tmp;
00472 }
00473
00474 inline mdp_matrix operator* (const mdp_matrix& y, mdp_real x) {
00475 register uint i;
00476 mdp_matrix z(y.rows(),y.cols());
00477 #if defined(MATRIX_SSE2)
00478 if(y.rows()==3) {
00479 static _sse_float factor1 ALIGN16;
00480 static _sse_double factor2 ALIGN16;
00481
00482 _sse_su3_vector *in =(_sse_su3_vector*) y.m;
00483 _sse_su3_vector *out=(_sse_su3_vector*) z.m;
00484 #if defined(USE_DOUBLE_PRECISION)
00485 factor2.c1=factor2.c2=x;
00486 for(i=0; i<y.cols(); i++, in++, out++) {
00487 _sse_double_load(*in);
00488 _sse_double_vector_mul(factor2);
00489 _sse_double_store(*out);
00490 }
00491 #else
00492 factor1.c1=factor1.c2=factor1.c3=factor1.c4=x;
00493 for(i=0; i<y.cols()-1; i+=2, in+=2, out+=2) {
00494 _sse_float_pair_load(*in, *(in+1));
00495 _sse_float_vector_mul(factor1);
00496 _sse_float_pair_store(*out, *(out+1));
00497 }
00498 if(i==y.cols()-1) {
00499 _sse_float_pair_load(*in, *in);
00500 _sse_float_vector_mul(factor1);
00501 _sse_float_pair_store(*out, *out);
00502 }
00503 #endif
00504 return z;
00505 }
00506 #endif
00507 for(i=0; i<y.imax; i++) z[i]=x*y[i];
00508 return z;
00509 }
00510
00511 inline mdp_matrix operator/ (const mdp_matrix& a, mdp_real b) {
00512 return a*(1.0/b);
00513 }
00514
00515 inline mdp_matrix operator+ (mdp_real b, const mdp_matrix& a) {
00516 return a+b;
00517 }
00518
00519 inline mdp_matrix operator- (mdp_real b, const mdp_matrix& a) {
00520 if(a.cols()!=a.rows()) error("mdp_matrix::operator-(...)\nmdp_matrix is not squared");
00521 mdp_matrix tmp(a.rows(), a.cols());
00522 uint i,j;
00523 for(i=0; i<a.rows(); i++) {
00524 for(j=0; j<a.cols(); j++) tmp(i,j)=-a(i,j);
00525 tmp(i,i)+=b;
00526 }
00527 return tmp;
00528 }
00529
00530 inline mdp_matrix operator* (mdp_real a, const mdp_matrix& b) {
00531 return b*a;
00532 }
00533
00534 inline mdp_matrix mdp_identity(uint i) {
00535 mdp_matrix tmp(i,i);
00536 register uint r,c;
00537 for(r=0; r<i; r++)
00538 for(c=0; c<i; c++)
00539 tmp(r,c)=(r==c)?mdp_complex(1,0):mdp_complex(0,0);
00540 return tmp;
00541 }
00542
00543 inline mdp_matrix mdp_zero(uint i) {
00544 mdp_matrix tmp(i,i);
00545 register uint r,c;
00546 for(r=0; r<i; r++)
00547 for(c=0; c<i; c++)
00548 tmp(r,c)=(mdp_complex) 0;
00549 return tmp;
00550 }
00551
00552 inline mdp_real max(const mdp_matrix& a) {
00553 register uint i;
00554 register double x=0,y=0;
00555 for(i=0; i<a.imax; i++) if ((y=abs(a[i]))>x) x=y;
00556 return x;
00557 }
00558
00559 inline mdp_matrix submatrix (const mdp_matrix& a, uint i, uint j) {
00560 #ifdef CHECK_ALL
00561 if (((a.rows()<2) || (a.cols()<2)) ||
00562 ((a.rows()-1<i) || (a.cols()-1<j))) error("submatrix(...)\nWrong dimensions in submatrix");
00563 #endif
00564 mdp_matrix tmp(a.rows()-1,a.cols()-1);
00565 register uint r,c;
00566 for(r=0; r<i; r++)
00567 for(c=0; c<j; c++) tmp(r,c) =a(r,c);
00568 for(r=i+1; r<a.rows(); r++)
00569 for(c=0; c<j; c++) tmp(r-1,c)=a(r,c);
00570 for(r=0; r<i; r++)
00571 for(c=j+1; c<a.cols(); c++) tmp(r,c-1)=a(r,c);
00572 for(r=i+1; r<a.rows(); r++)
00573 for(c=j+1; c<a.cols(); c++) tmp(r-1,c-1)=a(r,c);
00574 return tmp;
00575 }
00576
00577 inline mdp_complex det(const mdp_matrix& a) {
00578 #ifdef CHECK_ALL
00579 if (a.rows()!=a.cols()) error("det(...)\nmdp_matrix is not squared");
00580 #endif
00581 if (a.rows()==0) return 0;
00582 if (a.rows()==1) return a(0,0);
00583 register uint i,j,k,l;
00584 mdp_matrix A;
00585 A=a;
00586 mdp_complex tmp, pivot, x=mdp_complex(1,0);
00587 for(i=0; i<A.cols(); i++) {
00588 for(j=i; (A(i,j)==mdp_complex(0,0)) && (j<A.cols()); j++);
00589 if (j==A.cols()) return 0;
00590 if (i!=j) {
00591 for(k=0; k<A.rows(); k++) {
00592 tmp=A(k,j);
00593 A(k,j)=A(k,i);
00594 A(k,i)=tmp;
00595 }
00596 x*=-A(i,i);
00597 } else x*=A(i,i);
00598 for(k=i+1; k<A.rows(); k++) {
00599 pivot=A(k,i)/A(i,i);
00600 for(l=i; l<A.cols(); l++) A(k,l)-=pivot*A(i,l);
00601 }
00602 }
00603 return x;
00604 }
00605
00606 inline mdp_matrix inv(const mdp_matrix& a) {
00607 #ifdef CHECK_ALL
00608 if ((a.rows()!=a.cols()) || (a.rows()==0)) error("inv(...)\nmdp_matrix is not squared");
00609 #endif
00610 mdp_matrix tma, tmp;
00611 mdp_complex x,pivot;
00612 register uint r,c,i,rmax;
00613 tma=a;
00614 tmp=mdp_identity(a.rows());
00615 for(c=0; c<a.cols(); c++) {
00616 rmax=c;
00617 pivot=tma(c,c);
00618 for(r=c+1; r<a.rows(); r++)
00619 if(abs(tma(r,c))>abs(pivot)) {
00620 rmax=r;
00621 pivot=tma(r,c);
00622 }
00623 for(i=0; i<a.cols(); i++) {
00624 x=tma(rmax,i);
00625 tma(rmax,i)=tma(c,i);
00626 tma(c,i)=x/pivot;
00627 x=tmp(rmax,i);
00628 tmp(rmax,i)=tmp(c,i);
00629 tmp(c,i)=x/pivot;
00630 }
00631 for(r=0; r<a.rows(); r++)
00632 if(r!=c) {
00633 pivot=tma(r,c);
00634 for(i=0; i<a.cols(); i++) {
00635 tma(r,i)-=pivot*tma(c,i);
00636 tmp(r,i)-=pivot*tmp(c,i);
00637 }
00638 }
00639 }
00640 return tmp;
00641 }
00642
00643 inline mdp_matrix pow(const mdp_matrix& a, int i) {
00644 #ifdef CHECK_ALL
00645 if (a.rows()!=a.cols()) error("pow(...)\nmdp_matrix is not squared");
00646 #endif
00647 mdp_matrix tmp;
00648 tmp=mdp_identity(a.cols());
00649 uint j=(i<0)?-i:i;
00650 for(;j>0; j--) tmp=tmp*a;
00651 if (i<0) tmp=inv(tmp);
00652 return tmp;
00653 }
00654
00655 inline mdp_matrix exp(const mdp_matrix& a) {
00656 #ifdef CHECK_ALL
00657 if (a.rows()!=a.cols()) error("exp(...)\nmdp_matrix is not squared");
00658 #endif
00659 mdp_matrix tmp;
00660 mdp_matrix term;
00661 register uint i=1;
00662 term=a;
00663 tmp=mdp_identity(a.rows());
00664 tmp+=a;
00665 do {
00666 term=(1./++i)*term*a;
00667 tmp+=term;
00668 } while (max(term)>mdp_precision);
00669 return tmp;
00670 }
00671
00672
00673 inline mdp_matrix mdp_matrix::operator+=(const mdp_matrix& a) {
00674 (*this)=(*this)+a;
00675 return *this;
00676 }
00677
00678 inline mdp_matrix mdp_matrix::operator-=(const mdp_matrix& a) {
00679 (*this)=(*this)-a;
00680 return *this;
00681 }
00682
00683 inline mdp_matrix mdp_matrix::operator*=(const mdp_matrix& a) {
00684 (*this)=(*this)*a;
00685 return *this;
00686 }
00687
00688 inline mdp_matrix mdp_matrix::operator/=(const mdp_matrix& a) {
00689 (*this)=(*this)/a;
00690 return *this;
00691 }
00692
00693
00694 inline mdp_matrix mdp_matrix::operator+=(mdp_complex a) {
00695 (*this)=(*this)+a;
00696 return *this;
00697 }
00698
00699 inline mdp_matrix mdp_matrix::operator-=(mdp_complex a) {
00700 (*this)=(*this)-a;
00701 return *this;
00702 }
00703
00704 inline mdp_matrix mdp_matrix::operator*=(mdp_complex a) {
00705 (*this)=(*this)*a;
00706 return *this;
00707 }
00708
00709 inline mdp_matrix mdp_matrix::operator/=(mdp_complex a) {
00710 (*this)=(*this)/a;
00711 return *this;
00712 }
00713
00714 inline mdp_matrix mdp_matrix::operator+=(mdp_real a) {
00715 (*this)=(*this)+a;
00716 return *this;
00717 }
00718
00719 inline mdp_matrix mdp_matrix::operator-=(mdp_real a) {
00720 (*this)=(*this)-a;
00721 return *this;
00722 }
00723
00724 inline mdp_matrix mdp_matrix::operator*=(mdp_real a) {
00725 (*this)=(*this)*a;
00726 return *this;
00727 }
00728
00729 inline mdp_matrix mdp_matrix::operator/=(mdp_real a) {
00730 (*this)=(*this)/a;
00731 return *this;
00732 }
00733
00734 inline void mdp_matrix::operator=(mdp_complex a) {
00735 uint i,j;
00736 for(i=0; i<rows(); i++)
00737 for(j=0; j<cols(); j++)
00738 (*this)(i,j)=(i==j)?a:0;
00739 }
00740
00741 inline void mdp_matrix::operator=(mdp_real a) {
00742 uint i,j;
00743 for(i=0; i<rows(); i++)
00744 for(j=0; j<cols(); j++)
00745 (*this)(i,j)=(i==j)?mdp_complex(a,0):0;
00746 }
00747
00748
00749 mdp_matrix log(const mdp_matrix& a) {
00750 #ifdef CHECK_ALL
00751 if (a.rows()!=a.cols()) error("log(...)\nmdp_matrix is not squared");
00752 #endif
00753 mdp_matrix tmp,b,c,t1;
00754 register uint i=1, j=1;
00755 b=mdp_identity(a.cols());
00756 b=a-b;
00757 c=b;
00758 tmp=b;
00759 do {
00760 c=c*b;
00761 t1=((mdp_real)(i=-i)/(j+=1))*c;
00762 tmp+=t1;
00763 } while (max(t1)>mdp_precision);
00764 return tmp;
00765 }
00766
00767 mdp_matrix sin(const mdp_matrix& a) {
00768 #ifdef CHECK_ALL
00769 if (a.rows()!=a.cols()) error("sin(...)\nmdp_matrix is not squared");
00770 #endif
00771 mdp_matrix tmp, t1;
00772 register uint i=1;
00773 t1=a;
00774 tmp=t1;
00775
00776 do {
00777 t1=((mdp_real) -1.0/(++i)/(++i))*t1*a*a;
00778 tmp+=t1;
00779 } while (max(t1)>mdp_precision);
00780 return tmp;
00781 }
00782
00783 mdp_matrix cos(const mdp_matrix& a) {
00784 #ifdef CHECK_ALL
00785 if (a.rows()!=a.cols()) error("cos(...)\nmdp_matrix is not squared");
00786 #endif
00787 mdp_matrix tmp,t1;
00788 register uint i=0;
00789 t1=mdp_identity(a.rows());
00790 tmp=t1;
00791 do {
00792 t1=((mdp_real) -1.0/(++i)/(++i))*t1*a*a;
00793 tmp+=t1;
00794 } while (max(t1)>mdp_precision);
00795 return tmp;
00796 }
00797
00798 inline mdp_complex trace(const mdp_matrix& a) {
00799 #ifdef CHECK_ALL
00800 if (a.rows()!=a.cols()) error("trace(...)\nmdp_matrix is not squared");
00801 #endif
00802 register uint c;
00803 mdp_complex x;
00804 for(c=0; c<a.cols(); c++) x+=a(c,c);
00805 return x;
00806 }
00807
00808 inline mdp_matrix transpose(const mdp_matrix& a) {
00809 mdp_matrix tmp(a.cols(), a.rows());
00810 register uint r,c;
00811 for(r=0; r<a.rows(); r++)
00812 for(c=0; c<a.cols(); c++)
00813 tmp(c,r)=a(r,c);
00814 return tmp;
00815 }
00816
00817 inline mdp_matrix hermitian(const mdp_matrix& a) {
00818 mdp_matrix tmp(a.cols(), a.rows());
00819
00820 #if defined(MATRIX_SSE2) && defined(USE_DOUBLE_PRECISION)
00821 if(a.cols()==3 && a.rows()==3) {
00822 _sse_double_hermitian_su3((_sse_double*) tmp.address(),
00823 (_sse_double*) a.address());
00824 return tmp;
00825 }
00826 #endif
00827 register uint r,c;
00828 for(r=0; r<a.rows(); r++)
00829 for(c=0; c<a.cols(); c++)
00830 tmp(c,r)=conj(a(r,c));
00831 return tmp;
00832 }
00833
00834
00835 inline mdp_matrix conj(const mdp_matrix& a) {
00836 mdp_matrix tmp(a.rows(), a.cols());
00837 register uint r,c;
00838 for(r=0; r<a.rows(); r++)
00839 for(c=0; c<a.cols(); c++)
00840 tmp(r,c)=conj(a(r,c));
00841 return tmp;
00842 }
00843
00844