CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // -*- C++ -*- 00002 // --------------------------------------------------------------------------- 00003 // 00004 #ifdef GNUPRAGMA 00005 #pragma implementation 00006 #endif 00007 00008 #include <string.h> 00009 00010 #include "CLHEP/Matrix/defs.h" 00011 #include "CLHEP/Random/Random.h" 00012 #include "CLHEP/Vector/ThreeVector.h" 00013 #include "CLHEP/Matrix/Vector.h" 00014 #include "CLHEP/Matrix/Matrix.h" 00015 00016 #ifdef HEP_DEBUG_INLINE 00017 #include "CLHEP/Matrix/Vector.icc" 00018 #endif 00019 00020 namespace CLHEP { 00021 00022 // Simple operation for all elements 00023 00024 #define SIMPLE_UOP(OPER) \ 00025 HepGenMatrix::mIter a=m.begin(); \ 00026 HepGenMatrix::mIter e=m.begin()+num_size(); \ 00027 for(;a<e; a++) (*a) OPER t; 00028 00029 #define SIMPLE_BOP(OPER) \ 00030 mIter a=m.begin(); \ 00031 mcIter b=m2.m.begin(); \ 00032 mcIter e=m.begin()+num_size(); \ 00033 for(;a<e; a++, b++) (*a) OPER (*b); 00034 00035 #define SIMPLE_TOP(OPER) \ 00036 HepGenMatrix::mcIter a=m1.m.begin(); \ 00037 HepGenMatrix::mcIter b=m2.m.begin(); \ 00038 HepGenMatrix::mIter t=mret.m.begin(); \ 00039 HepGenMatrix::mcIter e=m1.m.begin()+m1.num_size(); \ 00040 for( ;a<e; a++, b++, t++) (*t) = (*a) OPER (*b); 00041 00042 #define CHK_DIM_2(r1,r2,c1,c2,fun) \ 00043 if (r1!=r2 || c1!=c2) { \ 00044 HepGenMatrix::error("Range error in Vector function " #fun "(1)."); \ 00045 } 00046 00047 #define CHK_DIM_1(c1,r2,fun) \ 00048 if (c1!=r2) { \ 00049 HepGenMatrix::error("Range error in Vector function " #fun "(2)."); \ 00050 } 00051 00052 // Constructors. (Default constructors are inlined and in .icc file) 00053 00054 HepVector::HepVector(int p) 00055 : m(p), nrow(p) 00056 { 00057 } 00058 00059 HepVector::HepVector(int p, int init) 00060 : m(p), nrow(p) 00061 { 00062 switch (init) 00063 { 00064 case 0: 00065 m.assign(p,0); 00066 break; 00067 00068 case 1: 00069 { 00070 mIter e = m.begin() + nrow; 00071 for (mIter i=m.begin(); i<e; i++) *i = 1.0; 00072 break; 00073 } 00074 00075 default: 00076 error("Vector: initialization must be either 0 or 1."); 00077 } 00078 } 00079 00080 HepVector::HepVector(int p, HepRandom &r) 00081 : m(p), nrow(p) 00082 { 00083 HepGenMatrix::mIter a = m.begin(); 00084 HepGenMatrix::mIter b = m.begin() + nrow; 00085 for(;a<b;a++) *a = r(); 00086 } 00087 00088 00089 // 00090 // Destructor 00091 // 00092 HepVector::~HepVector() { 00093 } 00094 00095 HepVector::HepVector(const HepVector &m1) 00096 : HepGenMatrix(m1), m(m1.nrow), nrow(m1.nrow) 00097 { 00098 m = m1.m; 00099 } 00100 00101 // 00102 // Copy constructor from the class of other precision 00103 // 00104 00105 00106 HepVector::HepVector(const HepMatrix &m1) 00107 : m(m1.nrow), nrow(m1.nrow) 00108 { 00109 if (m1.num_col() != 1) 00110 error("Vector::Vector(Matrix) : Matrix is not Nx1"); 00111 00112 m = m1.m; 00113 } 00114 00115 // trivial methods 00116 00117 inline int HepVector::num_row() const {return nrow;} 00118 inline int HepVector::num_size() const {return nrow;} 00119 inline int HepVector::num_col() const { return 1; } 00120 00121 // operator() 00122 00123 #ifdef MATRIX_BOUND_CHECK 00124 inline double & HepVector::operator()(int row, int col) 00125 { 00126 if( col!=1 || row<1 || row>nrow) 00127 error("Range error in HepVector::operator(i,j)"); 00128 #else 00129 inline double & HepVector::operator()(int row, int) 00130 { 00131 #endif 00132 00133 return *(m.begin()+(row-1)); 00134 } 00135 00136 #ifdef MATRIX_BOUND_CHECK 00137 inline const double & HepVector::operator()(int row, int col) const 00138 { 00139 if( col!=1 || row<1 || row>nrow) 00140 error("Range error in HepVector::operator(i,j)"); 00141 #else 00142 inline const double & HepVector::operator()(int row, int) const 00143 { 00144 #endif 00145 00146 return *(m.begin()+(row-1)); 00147 } 00148 00149 // Sub matrix 00150 00151 HepVector HepVector::sub(int min_row, int max_row) const 00152 #ifdef HEP_GNU_OPTIMIZED_RETURN 00153 return vret(max_row-min_row+1); 00154 { 00155 #else 00156 { 00157 HepVector vret(max_row-min_row+1); 00158 #endif 00159 if(max_row > num_row()) 00160 error("HepVector::sub: Index out of range"); 00161 HepGenMatrix::mIter a = vret.m.begin(); 00162 HepGenMatrix::mcIter b = m.begin() + min_row - 1; 00163 HepGenMatrix::mIter e = vret.m.begin() + vret.num_row(); 00164 for(;a<e;) *(a++) = *(b++); 00165 return vret; 00166 } 00167 00168 HepVector HepVector::sub(int min_row, int max_row) 00169 { 00170 HepVector vret(max_row-min_row+1); 00171 if(max_row > num_row()) 00172 error("HepVector::sub: Index out of range"); 00173 HepGenMatrix::mIter a = vret.m.begin(); 00174 HepGenMatrix::mIter b = m.begin() + min_row - 1; 00175 HepGenMatrix::mIter e = vret.m.begin() + vret.num_row(); 00176 for(;a<e;) *(a++) = *(b++); 00177 return vret; 00178 } 00179 00180 void HepVector::sub(int row,const HepVector &v1) 00181 { 00182 if(row <1 || row+v1.num_row()-1 > num_row()) 00183 error("HepVector::sub: Index out of range"); 00184 HepGenMatrix::mcIter a = v1.m.begin(); 00185 HepGenMatrix::mIter b = m.begin() + row - 1; 00186 HepGenMatrix::mcIter e = v1.m.begin() + v1.num_row(); 00187 for(;a<e;) *(b++) = *(a++); 00188 } 00189 00190 // 00191 // Direct sum of two matricies 00192 // 00193 00194 HepVector dsum(const HepVector &m1, 00195 const HepVector &m2) 00196 #ifdef HEP_GNU_OPTIMIZED_RETURN 00197 return mret(m1.num_row() + m2.num_row(), 0); 00198 { 00199 #else 00200 { 00201 HepVector mret(m1.num_row() + m2.num_row(), 00202 0); 00203 #endif 00204 mret.sub(1,m1); 00205 mret.sub(m1.num_row()+1,m2); 00206 return mret; 00207 } 00208 00209 /* ----------------------------------------------------------------------- 00210 This section contains support routines for matrix.h. This section contains 00211 The two argument functions +,-. They call the copy constructor and +=,-=. 00212 ----------------------------------------------------------------------- */ 00213 HepVector HepVector::operator- () const 00214 #ifdef HEP_GNU_OPTIMIZED_RETURN 00215 return m2(nrow); 00216 { 00217 #else 00218 { 00219 HepVector m2(nrow); 00220 #endif 00221 HepGenMatrix::mcIter a=m.begin(); 00222 HepGenMatrix::mIter b=m2.m.begin(); 00223 HepGenMatrix::mcIter e=m.begin()+num_size(); 00224 for(;a<e; a++, b++) (*b) = -(*a); 00225 return m2; 00226 } 00227 00228 00229 00230 HepVector operator+(const HepMatrix &m1,const HepVector &m2) 00231 #ifdef HEP_GNU_OPTIMIZED_RETURN 00232 return mret(m2); 00233 { 00234 #else 00235 { 00236 HepVector mret(m2); 00237 #endif 00238 CHK_DIM_2(m1.num_row(),m2.num_row(),m1.num_col(),1,+); 00239 mret += m1; 00240 return mret; 00241 } 00242 00243 HepVector operator+(const HepVector &m1,const HepMatrix &m2) 00244 #ifdef HEP_GNU_OPTIMIZED_RETURN 00245 return mret(m1); 00246 { 00247 #else 00248 { 00249 HepVector mret(m1); 00250 #endif 00251 CHK_DIM_2(m1.num_row(),m2.num_row(),1,m2.num_col(),+); 00252 mret += m2; 00253 return mret; 00254 } 00255 00256 HepVector operator+(const HepVector &m1,const HepVector &m2) 00257 #ifdef HEP_GNU_OPTIMIZED_RETURN 00258 return mret(m1.num_row()); 00259 { 00260 #else 00261 { 00262 HepVector mret(m1.num_row()); 00263 #endif 00264 CHK_DIM_1(m1.num_row(),m2.num_row(),+); 00265 SIMPLE_TOP(+) 00266 return mret; 00267 } 00268 00269 // 00270 // operator - 00271 // 00272 00273 HepVector operator-(const HepMatrix &m1,const HepVector &m2) 00274 #ifdef HEP_GNU_OPTIMIZED_RETURN 00275 return mret; 00276 { 00277 #else 00278 { 00279 HepVector mret; 00280 #endif 00281 CHK_DIM_2(m1.num_row(),m2.num_row(),m1.num_col(),1,-); 00282 mret = m1; 00283 mret -= m2; 00284 return mret; 00285 } 00286 00287 HepVector operator-(const HepVector &m1,const HepMatrix &m2) 00288 #ifdef HEP_GNU_OPTIMIZED_RETURN 00289 return mret(m1); 00290 { 00291 #else 00292 { 00293 HepVector mret(m1); 00294 #endif 00295 CHK_DIM_2(m1.num_row(),m2.num_row(),1,m2.num_col(),-); 00296 mret -= m2; 00297 return mret; 00298 } 00299 00300 HepVector operator-(const HepVector &m1,const HepVector &m2) 00301 #ifdef HEP_GNU_OPTIMIZED_RETURN 00302 return mret(m1.num_row()); 00303 { 00304 #else 00305 { 00306 HepVector mret(m1.num_row()); 00307 #endif 00308 CHK_DIM_1(m1.num_row(),m2.num_row(),-); 00309 SIMPLE_TOP(-) 00310 return mret; 00311 } 00312 00313 /* ----------------------------------------------------------------------- 00314 This section contains support routines for matrix.h. This file contains 00315 The two argument functions *,/. They call copy constructor and then /=,*=. 00316 ----------------------------------------------------------------------- */ 00317 00318 HepVector operator/( 00319 const HepVector &m1,double t) 00320 #ifdef HEP_GNU_OPTIMIZED_RETURN 00321 return mret(m1); 00322 { 00323 #else 00324 { 00325 HepVector mret(m1); 00326 #endif 00327 mret /= t; 00328 return mret; 00329 } 00330 00331 HepVector operator*(const HepVector &m1,double t) 00332 #ifdef HEP_GNU_OPTIMIZED_RETURN 00333 return mret(m1); 00334 { 00335 #else 00336 { 00337 HepVector mret(m1); 00338 #endif 00339 mret *= t; 00340 return mret; 00341 } 00342 00343 HepVector operator*(double t,const HepVector &m1) 00344 #ifdef HEP_GNU_OPTIMIZED_RETURN 00345 return mret(m1); 00346 { 00347 #else 00348 { 00349 HepVector mret(m1); 00350 #endif 00351 mret *= t; 00352 return mret; 00353 } 00354 00355 HepVector operator*(const HepMatrix &m1,const HepVector &m2) 00356 #ifdef HEP_GNU_OPTIMIZED_RETURN 00357 return mret(m1.num_row()); 00358 { 00359 #else 00360 { 00361 HepVector mret(m1.num_row()); 00362 #endif 00363 CHK_DIM_1(m1.num_col(),m2.num_row(),*); 00364 HepGenMatrix::mcIter m1p,m2p,vp; 00365 HepGenMatrix::mIter m3p; 00366 double temp; 00367 m3p=mret.m.begin(); 00368 for(m1p=m1.m.begin();m1p<m1.m.begin()+m1.num_row()*m1.num_col();m1p=m2p) 00369 { 00370 temp=0; 00371 vp=m2.m.begin(); 00372 m2p=m1p; 00373 while(m2p<m1p+m1.num_col()) 00374 temp+=(*(m2p++))*(*(vp++)); 00375 *(m3p++)=temp; 00376 } 00377 return mret; 00378 } 00379 00380 HepMatrix operator*(const HepVector &m1,const HepMatrix &m2) 00381 #ifdef HEP_GNU_OPTIMIZED_RETURN 00382 return mret(m1.num_row(),m2.num_col()); 00383 { 00384 #else 00385 { 00386 HepMatrix mret(m1.num_row(),m2.num_col()); 00387 #endif 00388 CHK_DIM_1(1,m2.num_row(),*); 00389 HepGenMatrix::mcIter m1p; 00390 HepMatrix::mcIter m2p; 00391 HepMatrix::mIter mrp=mret.m.begin(); 00392 for(m1p=m1.m.begin();m1p<m1.m.begin()+m1.num_row();m1p++) 00393 for(m2p=m2.m.begin();m2p<m2.m.begin()+m2.num_col();m2p++) 00394 *(mrp++)=*m1p*(*m2p); 00395 return mret; 00396 } 00397 00398 /* ----------------------------------------------------------------------- 00399 This section contains the assignment and inplace operators =,+=,-=,*=,/=. 00400 ----------------------------------------------------------------------- */ 00401 00402 HepMatrix & HepMatrix::operator+=(const HepVector &m2) 00403 { 00404 CHK_DIM_2(num_row(),m2.num_row(),num_col(),1,+=); 00405 SIMPLE_BOP(+=) 00406 return (*this); 00407 } 00408 00409 HepVector & HepVector::operator+=(const HepMatrix &m2) 00410 { 00411 CHK_DIM_2(num_row(),m2.num_row(),1,m2.num_col(),+=); 00412 SIMPLE_BOP(+=) 00413 return (*this); 00414 } 00415 00416 HepVector & HepVector::operator+=(const HepVector &m2) 00417 { 00418 CHK_DIM_1(num_row(),m2.num_row(),+=); 00419 SIMPLE_BOP(+=) 00420 return (*this); 00421 } 00422 00423 HepMatrix & HepMatrix::operator-=(const HepVector &m2) 00424 { 00425 CHK_DIM_2(num_row(),m2.num_row(),num_col(),1,-=); 00426 SIMPLE_BOP(-=) 00427 return (*this); 00428 } 00429 00430 HepVector & HepVector::operator-=(const HepMatrix &m2) 00431 { 00432 CHK_DIM_2(num_row(),m2.num_row(),1,m2.num_col(),-=); 00433 SIMPLE_BOP(-=) 00434 return (*this); 00435 } 00436 00437 HepVector & HepVector::operator-=(const HepVector &m2) 00438 { 00439 CHK_DIM_1(num_row(),m2.num_row(),-=); 00440 SIMPLE_BOP(-=) 00441 return (*this); 00442 } 00443 00444 HepVector & HepVector::operator/=(double t) 00445 { 00446 SIMPLE_UOP(/=) 00447 return (*this); 00448 } 00449 00450 HepVector & HepVector::operator*=(double t) 00451 { 00452 SIMPLE_UOP(*=) 00453 return (*this); 00454 } 00455 00456 HepMatrix & HepMatrix::operator=(const HepVector &m1) 00457 { 00458 if(m1.nrow != size_) 00459 { 00460 size_ = m1.nrow; 00461 m.resize(size_); 00462 } 00463 nrow = m1.nrow; 00464 ncol = 1; 00465 m = m1.m; 00466 return (*this); 00467 } 00468 00469 HepVector & HepVector::operator=(const HepVector &m1) 00470 { 00471 if(m1.nrow != nrow) 00472 { 00473 nrow = m1.nrow; 00474 m.resize(nrow); 00475 } 00476 m = m1.m; 00477 return (*this); 00478 } 00479 00480 HepVector & HepVector::operator=(const HepMatrix &m1) 00481 { 00482 if (m1.num_col() != 1) 00483 error("Vector::operator=(Matrix) : Matrix is not Nx1"); 00484 00485 if(m1.nrow != nrow) 00486 { 00487 nrow = m1.nrow; 00488 m.resize(nrow); 00489 } 00490 m = m1.m; 00491 return (*this); 00492 } 00493 00494 HepVector & HepVector::operator=(const Hep3Vector &v) 00495 { 00496 if(nrow != 3) 00497 { 00498 nrow = 3; 00499 m.resize(nrow); 00500 } 00501 m[0] = v.x(); 00502 m[1] = v.y(); 00503 m[2] = v.z(); 00504 return (*this); 00505 } 00506 00507 // 00508 // Copy constructor from the class of other precision 00509 // 00510 00511 00512 // Print the Matrix. 00513 00514 std::ostream& operator<<(std::ostream &s, const HepVector &q) 00515 { 00516 s << std::endl; 00517 /* Fixed format needs 3 extra characters for field, while scientific needs 7 */ 00518 int width; 00519 if(s.flags() & std::ios::fixed) 00520 width = s.precision()+3; 00521 else 00522 width = s.precision()+7; 00523 for(int irow = 1; irow<= q.num_row(); irow++) 00524 { 00525 s.width(width); 00526 s << q(irow) << std::endl; 00527 } 00528 return s; 00529 } 00530 00531 HepMatrix HepVector::T() const 00532 #ifdef HEP_GNU_OPTIMIZED_RETURN 00533 return mret(1,num_row()); 00534 { 00535 #else 00536 { 00537 HepMatrix mret(1,num_row()); 00538 #endif 00539 mret.m = m; 00540 return mret; 00541 } 00542 00543 double dot(const HepVector &v1,const HepVector &v2) 00544 { 00545 if(v1.num_row()!=v2.num_row()) 00546 HepGenMatrix::error("v1 and v2 need to be the same size in dot(HepVector, HepVector)"); 00547 double d= 0; 00548 HepGenMatrix::mcIter a = v1.m.begin(); 00549 HepGenMatrix::mcIter b = v2.m.begin(); 00550 HepGenMatrix::mcIter e = a + v1.num_size(); 00551 for(;a<e;) d += (*(a++)) * (*(b++)); 00552 return d; 00553 } 00554 00555 HepVector HepVector:: 00556 apply(double (*f)(double, int)) const 00557 #ifdef HEP_GNU_OPTIMIZED_RETURN 00558 return mret(num_row()); 00559 { 00560 #else 00561 { 00562 HepVector mret(num_row()); 00563 #endif 00564 HepGenMatrix::mcIter a = m.begin(); 00565 HepGenMatrix::mIter b = mret.m.begin(); 00566 for(int ir=1;ir<=num_row();ir++) { 00567 *(b++) = (*f)(*(a++), ir); 00568 } 00569 return mret; 00570 } 00571 00572 void HepVector::invert(int &) { 00573 error("HepVector::invert: You cannot invert a Vector"); 00574 } 00575 00576 HepVector solve(const HepMatrix &a, const HepVector &v) 00577 #ifdef HEP_GNU_OPTIMIZED_RETURN 00578 return vret(v); 00579 { 00580 #else 00581 { 00582 HepVector vret(v); 00583 #endif 00584 static int max_array = 20; 00585 static int *ir = new int [max_array+1]; 00586 00587 if(a.ncol != a.nrow) 00588 HepGenMatrix::error("Matrix::solve Matrix is not NxN"); 00589 if(a.ncol != v.nrow) 00590 HepGenMatrix::error("Matrix::solve Vector has wrong number of rows"); 00591 00592 int n = a.ncol; 00593 if (n > max_array) { 00594 delete [] ir; 00595 max_array = n; 00596 ir = new int [max_array+1]; 00597 } 00598 double det; 00599 HepMatrix mt(a); 00600 int i = mt.dfact_matrix(det, ir); 00601 if (i!=0) { 00602 for (i=1;i<=n;i++) vret(i) = 0; 00603 return vret; 00604 } 00605 double s21, s22; 00606 int nxch = ir[n]; 00607 if (nxch!=0) { 00608 for (int mm=1;mm<=nxch;mm++) { 00609 int ij = ir[mm]; 00610 i = ij >> 12; 00611 int j = ij%4096; 00612 double te = vret(i); 00613 vret(i) = vret(j); 00614 vret(j) = te; 00615 } 00616 } 00617 vret(1) = mt(1,1) * vret(1); 00618 if (n!=1) { 00619 for (i=2;i<=n;i++) { 00620 s21 = -vret(i); 00621 for (int j=1;j<i;j++) { 00622 s21 += mt(i,j) * vret(j); 00623 } 00624 vret(i) = -mt(i,i)*s21; 00625 } 00626 for (i=1;i<n;i++) { 00627 int nmi = n-i; 00628 s22 = -vret(nmi); 00629 for (int j=1;j<=i;j++) { 00630 s22 += mt(nmi,n-j+1) * vret(n-j+1); 00631 } 00632 vret(nmi) = -s22; 00633 } 00634 } 00635 return vret; 00636 } 00637 00638 } // namespace CLHEP