CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
SymMatrix.cc
Go to the documentation of this file.
1// -*- C++ -*-
2// ---------------------------------------------------------------------------
3//
4// This file is a part of the CLHEP - a Class Library for High Energy Physics.
5//
6
7#include <iostream>
8#include <string.h>
9#include <float.h> // for DBL_EPSILON
10
11#include "CLHEP/Matrix/defs.h"
12#include "CLHEP/Random/Random.h"
13#include "CLHEP/Matrix/SymMatrix.h"
14#include "CLHEP/Matrix/Matrix.h"
15#include "CLHEP/Matrix/DiagMatrix.h"
16#include "CLHEP/Matrix/Vector.h"
17
18#ifdef HEP_DEBUG_INLINE
19#include "CLHEP/Matrix/SymMatrix.icc"
20#endif
21
22namespace CLHEP {
23
24// Simple operation for all elements
25
26#define SIMPLE_UOP(OPER) \
27 HepMatrix::mIter a=m.begin(); \
28 HepMatrix::mIter e=m.begin()+num_size(); \
29 for(;a<e; a++) (*a) OPER t;
30
31#define SIMPLE_BOP(OPER) \
32 HepMatrix::mIter a=m.begin(); \
33 HepMatrix::mcIter b=hm2.m.begin(); \
34 HepMatrix::mcIter e=m.begin()+num_size(); \
35 for(;a<e; a++, b++) (*a) OPER (*b);
36
37#define SIMPLE_TOP(OPER) \
38 HepMatrix::mcIter a=hm1.m.begin(); \
39 HepMatrix::mcIter b=hm2.m.begin(); \
40 HepMatrix::mIter t=mret.m.begin(); \
41 HepMatrix::mcIter e=hm1.m.begin()+hm1.num_size(); \
42 for( ;a<e; a++, b++, t++) (*t) = (*a) OPER (*b);
43
44#define CHK_DIM_2(r1,r2,c1,c2,fun) \
45 if (r1!=r2 || c1!=c2) { \
46 HepGenMatrix::error("Range error in SymMatrix function " #fun "(1)."); \
47 }
48
49#define CHK_DIM_1(c1,r2,fun) \
50 if (c1!=r2) { \
51 HepGenMatrix::error("Range error in SymMatrix function " #fun "(2)."); \
52 }
53
54// Constructors. (Default constructors are inlined and in .icc file)
55
57 : m(p*(p+1)/2), nrow(p)
58{
59 size_ = nrow * (nrow+1) / 2;
60 m.assign(size_,0);
61}
62
64 : m(p*(p+1)/2), nrow(p)
65{
66 size_ = nrow * (nrow+1) / 2;
67
68 m.assign(size_,0);
69 switch(init)
70 {
71 case 0:
72 break;
73
74 case 1:
75 {
77 for(int i=0;i<nrow;++i) {
78 a = m.begin() + (i+1)*i/2 + i;
79 *a = 1.0;
80 }
81 break;
82 }
83 default:
84 error("SymMatrix: initialization must be either 0 or 1.");
85 }
86}
87
89 : m(p*(p+1)/2), nrow(p)
90{
91 size_ = nrow * (nrow+1) / 2;
92 HepMatrix::mIter a = m.begin();
93 HepMatrix::mIter b = m.begin() + size_;
94 for(;a<b;a++) *a = r();
95}
96
97//
98// Destructor
99//
101}
102
104 : HepGenMatrix(hm1), m(hm1.size_), nrow(hm1.nrow), size_(hm1.size_)
105{
106 m = hm1.m;
107}
108
110 : m(hm1.nrow*(hm1.nrow+1)/2), nrow(hm1.nrow)
111{
112 size_ = nrow * (nrow+1) / 2;
113
114 int n = num_row();
115 m.assign(size_,0);
116
117 HepMatrix::mIter mrr = m.begin();
118 HepMatrix::mcIter mr = hm1.m.begin();
119 for(int r=1;r<=n;r++) {
120 *mrr = *(mr++);
121 if(r<n) mrr += (r+1);
122 }
123}
124
125//
126//
127// Sub matrix
128//
129//
130
131HepSymMatrix HepSymMatrix::sub(int min_row, int max_row) const
132#ifdef HEP_GNU_OPTIMIZED_RETURN
133return mret(max_row-min_row+1);
134{
135#else
136{
137 HepSymMatrix mret(max_row-min_row+1);
138#endif
139 if(max_row > num_row())
140 error("HepSymMatrix::sub: Index out of range");
141 HepMatrix::mIter a = mret.m.begin();
142 HepMatrix::mcIter b1 = m.begin() + (min_row+2)*(min_row-1)/2;
143 int rowsize=mret.num_row();
144 for(int irow=1; irow<=rowsize; irow++) {
145 HepMatrix::mcIter b = b1;
146 for(int icol=0; icol<irow; ++icol) {
147 *(a++) = *(b++);
148 }
149 if(irow<rowsize) b1 += irow+min_row-1;
150 }
151 return mret;
152}
153
154HepSymMatrix HepSymMatrix::sub(int min_row, int max_row)
155{
156 HepSymMatrix mret(max_row-min_row+1);
157 if(max_row > num_row())
158 error("HepSymMatrix::sub: Index out of range");
159 HepMatrix::mIter a = mret.m.begin();
160 HepMatrix::mIter b1 = m.begin() + (min_row+2)*(min_row-1)/2;
161 int rowsize=mret.num_row();
162 for(int irow=1; irow<=rowsize; irow++) {
163 HepMatrix::mIter b = b1;
164 for(int icol=0; icol<irow; ++icol) {
165 *(a++) = *(b++);
166 }
167 if(irow<rowsize) b1 += irow+min_row-1;
168 }
169 return mret;
170}
171
172void HepSymMatrix::sub(int row,const HepSymMatrix &hm1)
173{
174 if(row <1 || row+hm1.num_row()-1 > num_row() )
175 error("HepSymMatrix::sub: Index out of range");
176 HepMatrix::mcIter a = hm1.m.begin();
177 HepMatrix::mIter b1 = m.begin() + (row+2)*(row-1)/2;
178 int rowsize=hm1.num_row();
179 for(int irow=1; irow<=rowsize; ++irow) {
180 HepMatrix::mIter b = b1;
181 for(int icol=0; icol<irow; ++icol) {
182 *(b++) = *(a++);
183 }
184 if(irow<rowsize) b1 += irow+row-1;
185 }
186}
187
188//
189// Direct sum of two matricies
190//
191
193 const HepSymMatrix &hm2)
194#ifdef HEP_GNU_OPTIMIZED_RETURN
195 return mret(hm1.num_row() + hm2.num_row(), 0);
196{
197#else
198{
199 HepSymMatrix mret(hm1.num_row() + hm2.num_row(),
200 0);
201#endif
202 mret.sub(1,hm1);
203 mret.sub(hm1.num_row()+1,hm2);
204 return mret;
205}
206
207/* -----------------------------------------------------------------------
208 This section contains support routines for matrix.h. This section contains
209 The two argument functions +,-. They call the copy constructor and +=,-=.
210 ----------------------------------------------------------------------- */
212#ifdef HEP_GNU_OPTIMIZED_RETURN
213 return hm2(nrow);
214{
215#else
216{
217 HepSymMatrix hm2(nrow);
218#endif
219 HepMatrix::mcIter a=m.begin();
220 HepMatrix::mIter b=hm2.m.begin();
221 HepMatrix::mcIter e=m.begin()+num_size();
222 for(;a<e; a++, b++) (*b) = -(*a);
223 return hm2;
224}
225
226
227
229#ifdef HEP_GNU_OPTIMIZED_RETURN
230 return mret(hm1);
231{
232#else
233{
234 HepMatrix mret(hm1);
235#endif
236 CHK_DIM_2(hm1.num_row(),hm2.num_row(), hm1.num_col(),hm2.num_col(),+);
237 mret += hm2;
238 return mret;
239}
241#ifdef HEP_GNU_OPTIMIZED_RETURN
242 return mret(hm2);
243{
244#else
245{
246 HepMatrix mret(hm2);
247#endif
248 CHK_DIM_2(hm1.num_row(),hm2.num_row(),hm1.num_col(),hm2.num_col(),+);
249 mret += hm1;
250 return mret;
251}
252
254#ifdef HEP_GNU_OPTIMIZED_RETURN
255 return mret(hm1.nrow);
256{
257#else
258{
259 HepSymMatrix mret(hm1.nrow);
260#endif
261 CHK_DIM_1(hm1.nrow, hm2.nrow,+);
262 SIMPLE_TOP(+)
263 return mret;
264}
265
266//
267// operator -
268//
269
270HepMatrix operator-(const HepMatrix &hm1,const HepSymMatrix &hm2)
271#ifdef HEP_GNU_OPTIMIZED_RETURN
272 return mret(hm1);
273{
274#else
275{
276 HepMatrix mret(hm1);
277#endif
278 CHK_DIM_2(hm1.num_row(),hm2.num_row(),
279 hm1.num_col(),hm2.num_col(),-);
280 mret -= hm2;
281 return mret;
282}
284#ifdef HEP_GNU_OPTIMIZED_RETURN
285 return mret(hm1);
286{
287#else
288{
289 HepMatrix mret(hm1);
290#endif
291 CHK_DIM_2(hm1.num_row(),hm2.num_row(),
292 hm1.num_col(),hm2.num_col(),-);
293 mret -= hm2;
294 return mret;
295}
296
298#ifdef HEP_GNU_OPTIMIZED_RETURN
299 return mret(hm1.num_row());
300{
301#else
302{
303 HepSymMatrix mret(hm1.num_row());
304#endif
305 CHK_DIM_1(hm1.num_row(),hm2.num_row(),-);
306 SIMPLE_TOP(-)
307 return mret;
308}
309
310/* -----------------------------------------------------------------------
311 This section contains support routines for matrix.h. This file contains
312 The two argument functions *,/. They call copy constructor and then /=,*=.
313 ----------------------------------------------------------------------- */
314
315HepSymMatrix operator/(
316const HepSymMatrix &hm1,double t)
317#ifdef HEP_GNU_OPTIMIZED_RETURN
318 return mret(hm1);
319{
320#else
321{
322 HepSymMatrix mret(hm1);
323#endif
324 mret /= t;
325 return mret;
326}
327
329#ifdef HEP_GNU_OPTIMIZED_RETURN
330 return mret(hm1);
331{
332#else
333{
334 HepSymMatrix mret(hm1);
335#endif
336 mret *= t;
337 return mret;
338}
339
341#ifdef HEP_GNU_OPTIMIZED_RETURN
342 return mret(hm1);
343{
344#else
345{
346 HepSymMatrix mret(hm1);
347#endif
348 mret *= t;
349 return mret;
350}
351
352
354#ifdef HEP_GNU_OPTIMIZED_RETURN
355 return mret(hm1.num_row(),hm2.num_col());
356{
357#else
358 {
359 HepMatrix mret(hm1.num_row(),hm2.num_col());
360#endif
361 CHK_DIM_1(hm1.num_col(),hm2.num_row(),*);
362 HepMatrix::mcIter mit1, mit2, sp,snp; //mit2=0
363 double temp;
364 HepMatrix::mIter mir=mret.m.begin();
365 for(mit1=hm1.m.begin();
366 mit1<hm1.m.begin()+hm1.num_row()*hm1.num_col();
367 mit1 = mit2)
368 {
369 snp=hm2.m.begin();
370 for(int step=1;step<=hm2.num_row();++step)
371 {
372 mit2=mit1;
373 sp=snp;
374 snp+=step;
375 temp=0;
376 while(sp<snp)
377 temp+=*(sp++)*(*(mit2++));
378 if( step<hm2.num_row() ) { // only if we aren't on the last row
379 sp+=step-1;
380 for(int stept=step+1;stept<=hm2.num_row();stept++)
381 {
382 temp+=*sp*(*(mit2++));
383 if(stept<hm2.num_row()) sp+=stept;
384 }
385 } // if(step
386 *(mir++)=temp;
387 } // for(step
388 } // for(mit1
389 return mret;
390 }
391
393#ifdef HEP_GNU_OPTIMIZED_RETURN
394 return mret(hm1.num_row(),hm2.num_col());
395{
396#else
397{
398 HepMatrix mret(hm1.num_row(),hm2.num_col());
399#endif
400 CHK_DIM_1(hm1.num_col(),hm2.num_row(),*);
401 int step,stept;
402 HepMatrix::mcIter mit1,mit2,sp,snp;
403 double temp;
404 HepMatrix::mIter mir=mret.m.begin();
405 for(step=1,snp=hm1.m.begin();step<=hm1.num_row();snp+=step++)
406 for(mit1=hm2.m.begin();mit1<hm2.m.begin()+hm2.num_col();mit1++)
407 {
408 mit2=mit1;
409 sp=snp;
410 temp=0;
411 while(sp<snp+step)
412 {
413 temp+=*mit2*(*(sp++));
414 if( hm2.num_size()-(mit2-hm2.m.begin())>hm2.num_col() ){
415 mit2+=hm2.num_col();
416 }
417 }
418 if(step<hm1.num_row()) { // only if we aren't on the last row
419 sp+=step-1;
420 for(stept=step+1;stept<=hm1.num_row();stept++)
421 {
422 temp+=*mit2*(*sp);
423 if(stept<hm1.num_row()) {
424 mit2+=hm2.num_col();
425 sp+=stept;
426 }
427 }
428 } // if(step
429 *(mir++)=temp;
430 } // for(mit1
431 return mret;
432}
433
435#ifdef HEP_GNU_OPTIMIZED_RETURN
436 return mret(hm1.num_row(),hm1.num_row());
437{
438#else
439{
440 HepMatrix mret(hm1.num_row(),hm1.num_row());
441#endif
442 CHK_DIM_1(hm1.num_col(),hm2.num_row(),*);
443 int step1,stept1,step2,stept2;
444 HepMatrix::mcIter snp1,sp1,snp2,sp2;
445 double temp;
446 HepMatrix::mIter mr = mret.m.begin();
447 snp1=hm1.m.begin();
448 for(step1=1;step1<=hm1.num_row();++step1) {
449 snp2=hm2.m.begin();
450 for(step2=1;step2<=hm2.num_row();++step2)
451 {
452 sp1=snp1;
453 sp2=snp2;
454 snp2+=step2;
455 temp=0;
456 if(step1<step2)
457 {
458 while(sp1<snp1+step1) {
459 temp+=(*(sp1++))*(*(sp2++));
460 }
461 sp1+=step1-1;
462 for(stept1=step1+1;stept1!=step2+1;++stept1) {
463 temp+=(*sp1)*(*(sp2++));
464 if(stept1<hm2.num_row()) sp1+=stept1;
465 }
466 if(step2<hm2.num_row()) { // only if we aren't on the last row
467 sp2+=step2-1;
468 for(stept2=step2+1;stept2<=hm2.num_row();stept1++,stept2++) {
469 temp+=(*sp1)*(*sp2);
470 if(stept2<hm2.num_row()) {
471 sp1+=stept1;
472 sp2+=stept2;
473 }
474 } // for(stept2
475 } // if(step2
476 } // step1<step2
477 else
478 {
479 while(sp2<snp2) {
480 temp+=(*(sp1++))*(*(sp2++));
481 }
482 if(step2<hm2.num_row()) { // only if we aren't on the last row
483 sp2+=step2-1;
484 for(stept2=step2+1;stept2!=step1+1;stept2++) {
485 temp+=(*(sp1++))*(*sp2);
486 if(stept2<hm1.num_row()) sp2+=stept2;
487 }
488 if(step1<hm1.num_row()) { // only if we aren't on the last row
489 sp1+=step1-1;
490 for(stept1=step1+1;stept1<=hm1.num_row();stept1++,stept2++) {
491 temp+=(*sp1)*(*sp2);
492 if(stept1<hm1.num_row()) {
493 sp1+=stept1;
494 sp2+=stept2;
495 }
496 } // for(stept1
497 } // if(step1
498 } // if(step2
499 } // else
500 *(mr++)=temp;
501 } // for(step2
502 if(step1<hm1.num_row()) snp1+=step1;
503 } // for(step1
504 return mret;
505}
506
508#ifdef HEP_GNU_OPTIMIZED_RETURN
509 return mret(hm1.num_row());
510{
511#else
512{
513 HepVector mret(hm1.num_row());
514#endif
515 CHK_DIM_1(hm1.num_col(),hm2.num_row(),*);
516 HepMatrix::mcIter sp,snp,vpt;
517 double temp;
518 int step,stept;
519 HepMatrix::mIter vrp=mret.m.begin();
520 for(step=1,snp=hm1.m.begin();step<=hm1.num_row();++step)
521 {
522 sp=snp;
523 vpt=hm2.m.begin();
524 snp+=step;
525 temp=0;
526 while(sp<snp)
527 temp+=*(sp++)*(*(vpt++));
528 if(step<hm1.num_row()) sp+=step-1;
529 for(stept=step+1;stept<=hm1.num_row();stept++)
530 {
531 temp+=*sp*(*(vpt++));
532 if(stept<hm1.num_row()) sp+=stept;
533 }
534 *(vrp++)=temp;
535 } // for(step
536 return mret;
537}
538
540#ifdef HEP_GNU_OPTIMIZED_RETURN
541 return mret(v.num_row());
542{
543#else
544{
545 HepSymMatrix mret(v.num_row());
546#endif
547 HepMatrix::mIter mr=mret.m.begin();
548 HepMatrix::mcIter vt1,vt2;
549 for(vt1=v.m.begin();vt1<v.m.begin()+v.num_row();vt1++)
550 for(vt2=v.m.begin();vt2<=vt1;vt2++)
551 *(mr++)=(*vt1)*(*vt2);
552 return mret;
553}
554
555/* -----------------------------------------------------------------------
556 This section contains the assignment and inplace operators =,+=,-=,*=,/=.
557 ----------------------------------------------------------------------- */
558
560{
561 CHK_DIM_2(num_row(),hm2.num_row(),num_col(),hm2.num_col(),+=);
562 HepMatrix::mcIter sjk = hm2.m.begin();
563 // j >= k
564 for(int j=0; j!=nrow; ++j) {
565 for(int k=0; k<=j; ++k) {
566 m[j*ncol+k] += *sjk;
567 // make sure this is not a diagonal element
568 if(k!=j) m[k*nrow+j] += *sjk;
569 ++sjk;
570 }
571 }
572 return (*this);
573}
574
576{
577 CHK_DIM_2(num_row(),hm2.num_row(),num_col(),hm2.num_col(),+=);
578 SIMPLE_BOP(+=)
579 return (*this);
580}
581
583{
584 CHK_DIM_2(num_row(),hm2.num_row(),num_col(),hm2.num_col(),-=);
585 HepMatrix::mcIter sjk = hm2.m.begin();
586 // j >= k
587 for(int j=0; j!=nrow; ++j) {
588 for(int k=0; k<=j; ++k) {
589 m[j*ncol+k] -= *sjk;
590 // make sure this is not a diagonal element
591 if(k!=j) m[k*nrow+j] -= *sjk;
592 ++sjk;
593 }
594 }
595 return (*this);
596}
597
599{
600 CHK_DIM_2(num_row(),hm2.num_row(),num_col(),hm2.num_col(),-=);
601 SIMPLE_BOP(-=)
602 return (*this);
603}
604
606{
607 SIMPLE_UOP(/=)
608 return (*this);
609}
610
612{
613 SIMPLE_UOP(*=)
614 return (*this);
615}
616
618{
619 // define size, rows, and columns of *this
620 nrow = ncol = hm1.nrow;
621 if(nrow*ncol != size_)
622 {
623 size_ = nrow*ncol;
624 m.resize(size_);
625 }
626 // begin copy
627 mcIter sjk = hm1.m.begin();
628 // j >= k
629 for(int j=0; j!=nrow; ++j) {
630 for(int k=0; k<=j; ++k) {
631 m[j*ncol+k] = *sjk;
632 // we could copy the diagonal element twice or check
633 // doing the check may be a tiny bit faster,
634 // so we choose that option for now
635 if(k!=j) m[k*nrow+j] = *sjk;
636 ++sjk;
637 }
638 }
639 return (*this);
640}
641
643{
644 if(hm1.nrow != nrow)
645 {
646 nrow = hm1.nrow;
647 size_ = hm1.size_;
648 m.resize(size_);
649 }
650 m = hm1.m;
651 return (*this);
652}
653
655{
656 if(hm1.nrow != nrow)
657 {
658 nrow = hm1.nrow;
659 size_ = nrow * (nrow+1) / 2;
660 m.resize(size_);
661 }
662
663 m.assign(size_,0);
664 HepMatrix::mIter mrr = m.begin();
665 HepMatrix::mcIter mr = hm1.m.begin();
666 for(int r=1; r<=nrow; r++) {
667 *mrr = *(mr++);
668 if(r<nrow) mrr += (r+1);
669 }
670 return (*this);
671}
672
673// Print the Matrix.
674
675std::ostream& operator<<(std::ostream &os, const HepSymMatrix &q)
676{
677 os << std::endl;
678/* Fixed format needs 3 extra characters for field, while scientific needs 7 */
679 long width;
680 if(os.flags() & std::ios::fixed)
681 width = os.precision()+3;
682 else
683 width = os.precision()+7;
684 for(int irow = 1; irow<= q.num_row(); irow++)
685 {
686 for(int icol = 1; icol <= q.num_col(); icol++)
687 {
688 os.width(width);
689 os << q(irow,icol) << " ";
690 }
691 os << std::endl;
692 }
693 return os;
694}
695
697apply(double (*f)(double, int, int)) const
698#ifdef HEP_GNU_OPTIMIZED_RETURN
699return mret(num_row());
700{
701#else
702{
703 HepSymMatrix mret(num_row());
704#endif
705 HepMatrix::mcIter a = m.begin();
706 HepMatrix::mIter b = mret.m.begin();
707 for(int ir=1;ir<=num_row();ir++) {
708 for(int ic=1;ic<=ir;ic++) {
709 *(b++) = (*f)(*(a++), ir, ic);
710 }
711 }
712 return mret;
713}
714
716{
717 if(hm1.nrow != nrow)
718 {
719 nrow = hm1.nrow;
720 size_ = nrow * (nrow+1) / 2;
721 m.resize(size_);
722 }
723 HepMatrix::mcIter a = hm1.m.begin();
724 HepMatrix::mIter b = m.begin();
725 for(int r=1;r<=nrow;r++) {
726 HepMatrix::mcIter d = a;
727 for(int c=1;c<=r;c++) {
728 *(b++) = *(d++);
729 }
730 if(r<nrow) a += nrow;
731 }
732}
733
735#ifdef HEP_GNU_OPTIMIZED_RETURN
736 return mret(hm1.num_row());
737{
738#else
739{
740 HepSymMatrix mret(hm1.num_row());
741#endif
742 HepMatrix temp = hm1*(*this);
743// If hm1*(*this) has correct dimensions, then so will the hm1.T multiplication.
744// So there is no need to check dimensions again.
745 int n = hm1.num_col();
746 HepMatrix::mIter mr = mret.m.begin();
747 HepMatrix::mIter tempr1 = temp.m.begin();
748 for(int r=1;r<=mret.num_row();r++) {
749 HepMatrix::mcIter hm1c1 = hm1.m.begin();
750 for(int c=1;c<=r;c++) {
751 double tmp = 0.0;
752 HepMatrix::mIter tempri = tempr1;
753 HepMatrix::mcIter hm1ci = hm1c1;
754 for(int i=1;i<=hm1.num_col();i++) {
755 tmp+=(*(tempri++))*(*(hm1ci++));
756 }
757 *(mr++) = tmp;
758 hm1c1 += n;
759 }
760 tempr1 += n;
761 }
762 return mret;
763}
764
766#ifdef HEP_GNU_OPTIMIZED_RETURN
767 return mret(hm1.num_row());
768{
769#else
770{
771 HepSymMatrix mret(hm1.num_row());
772#endif
773 HepMatrix temp = hm1*(*this);
774 int n = hm1.num_col();
775 HepMatrix::mIter mr = mret.m.begin();
776 HepMatrix::mIter tempr1 = temp.m.begin();
777 for(int r=1;r<=mret.num_row();r++) {
778 HepMatrix::mcIter hm1c1 = hm1.m.begin();
779 int c;
780 for(c=1;c<=r;c++) {
781 double tmp = 0.0;
782 HepMatrix::mIter tempri = tempr1;
783 HepMatrix::mcIter hm1ci = hm1c1;
784 int i;
785 for(i=1;i<c;i++) {
786 tmp+=(*(tempri++))*(*(hm1ci++));
787 }
788 for(i=c;i<=hm1.num_col();i++) {
789 tmp+=(*(tempri++))*(*(hm1ci));
790 if(i<hm1.num_col()) hm1ci += i;
791 }
792 *(mr++) = tmp;
793 hm1c1 += c;
794 }
795 tempr1 += n;
796 }
797 return mret;
798}
799
801const {
802 double mret = 0.0;
803 HepVector temp = (*this) *hm1;
804// If hm1*(*this) has correct dimensions, then so will the hm1.T multiplication.
805// So there is no need to check dimensions again.
806 HepMatrix::mIter a=temp.m.begin();
807 HepMatrix::mcIter b=hm1.m.begin();
808 HepMatrix::mIter e=a+hm1.num_row();
809 for(;a<e;) mret += (*(a++)) * (*(b++));
810 return mret;
811}
812
814#ifdef HEP_GNU_OPTIMIZED_RETURN
815 return mret(hm1.num_col());
816{
817#else
818{
819 HepSymMatrix mret(hm1.num_col());
820#endif
821 HepMatrix temp = (*this)*hm1;
822 int n = hm1.num_col();
823 HepMatrix::mIter mrc = mret.m.begin();
824 HepMatrix::mIter temp1r = temp.m.begin();
825 for(int r=1;r<=mret.num_row();r++) {
826 HepMatrix::mcIter m11c = hm1.m.begin();
827 for(int c=1;c<=r;c++) {
828 double tmp = 0.0;
829 for(int i=1;i<=hm1.num_row();i++) {
830 HepMatrix::mIter tempir = temp1r + n*(i-1);
831 HepMatrix::mcIter hm1ic = m11c + n*(i-1);
832 tmp+=(*(tempir))*(*(hm1ic));
833 }
834 *(mrc++) = tmp;
835 m11c++;
836 }
837 temp1r++;
838 }
839 return mret;
840}
841
842void HepSymMatrix::invert(int &ifail) {
843
844 ifail = 0;
845
846 switch(nrow) {
847 case 3:
848 {
849 double det, temp;
850 double t1, t2, t3;
851 double c11,c12,c13,c22,c23,c33;
852 c11 = (*(m.begin()+2)) * (*(m.begin()+5)) - (*(m.begin()+4)) * (*(m.begin()+4));
853 c12 = (*(m.begin()+4)) * (*(m.begin()+3)) - (*(m.begin()+1)) * (*(m.begin()+5));
854 c13 = (*(m.begin()+1)) * (*(m.begin()+4)) - (*(m.begin()+2)) * (*(m.begin()+3));
855 c22 = (*(m.begin()+5)) * (*m.begin()) - (*(m.begin()+3)) * (*(m.begin()+3));
856 c23 = (*(m.begin()+3)) * (*(m.begin()+1)) - (*(m.begin()+4)) * (*m.begin());
857 c33 = (*m.begin()) * (*(m.begin()+2)) - (*(m.begin()+1)) * (*(m.begin()+1));
858 t1 = fabs(*m.begin());
859 t2 = fabs(*(m.begin()+1));
860 t3 = fabs(*(m.begin()+3));
861 if (t1 >= t2) {
862 if (t3 >= t1) {
863 temp = *(m.begin()+3);
864 det = c23*c12-c22*c13;
865 } else {
866 temp = *m.begin();
867 det = c22*c33-c23*c23;
868 }
869 } else if (t3 >= t2) {
870 temp = *(m.begin()+3);
871 det = c23*c12-c22*c13;
872 } else {
873 temp = *(m.begin()+1);
874 det = c13*c23-c12*c33;
875 }
876 if (det==0) {
877 ifail = 1;
878 return;
879 }
880 {
881 double ds = temp/det;
882 HepMatrix::mIter hmm = m.begin();
883 *(hmm++) = ds*c11;
884 *(hmm++) = ds*c12;
885 *(hmm++) = ds*c22;
886 *(hmm++) = ds*c13;
887 *(hmm++) = ds*c23;
888 *(hmm) = ds*c33;
889 }
890 }
891 break;
892 case 2:
893 {
894 double det, temp, ds;
895 det = (*m.begin())*(*(m.begin()+2)) - (*(m.begin()+1))*(*(m.begin()+1));
896 if (det==0) {
897 ifail = 1;
898 return;
899 }
900 ds = 1.0/det;
901 *(m.begin()+1) *= -ds;
902 temp = ds*(*(m.begin()+2));
903 *(m.begin()+2) = ds*(*m.begin());
904 *m.begin() = temp;
905 break;
906 }
907 case 1:
908 {
909 if ((*m.begin())==0) {
910 ifail = 1;
911 return;
912 }
913 *m.begin() = 1.0/(*m.begin());
914 break;
915 }
916 case 5:
917 {
918 invert5(ifail);
919 return;
920 }
921 case 6:
922 {
923 invert6(ifail);
924 return;
925 }
926 case 4:
927 {
928 invert4(ifail);
929 return;
930 }
931 default:
932 {
933 invertBunchKaufman(ifail);
934 return;
935 }
936 }
937 return; // inversion successful
938}
939
941 static const int max_array = 20;
942 // ir must point to an array which is ***1 longer than*** nrow
943 static std::vector<int> ir_vec (max_array+1);
944 if (ir_vec.size() <= static_cast<unsigned int>(nrow)) ir_vec.resize(nrow+1);
945 int * ir = &ir_vec[0];
946
947 double det;
948 HepMatrix mt(*this);
949 int i = mt.dfact_matrix(det, ir);
950 if(i==0) return det;
951 return 0.0;
952}
953
954double HepSymMatrix::trace() const {
955 double t = 0.0;
956 for (int i=0; i<nrow; i++)
957 t += *(m.begin() + (i+3)*i/2);
958 return t;
959}
960
962 // Bunch-Kaufman diagonal pivoting method
963 // It is decribed in J.R. Bunch, L. Kaufman (1977).
964 // "Some Stable Methods for Calculating Inertia and Solving Symmetric
965 // Linear Systems", Math. Comp. 31, p. 162-179. or in Gene H. Golub,
966 // Charles F. van Loan, "Matrix Computations" (the second edition
967 // has a bug.) and implemented in "lapack"
968 // Mario Stanke, 09/97
969
970 int i, j, k, is;
971 int pivrow;
972
973 // Establish the two working-space arrays needed: x and piv are
974 // used as pointers to arrays of doubles and ints respectively, each
975 // of length nrow. We do not want to reallocate each time through
976 // unless the size needs to grow. We do not want to leak memory, even
977 // by having a new without a delete that is only done once.
978
979 static const int max_array = 25;
980#ifdef DISABLE_ALLOC
981 static std::vector<double> xvec (max_array);
982 static std::vector<int> pivv (max_array);
983 typedef std::vector<int>::iterator pivIter;
984#else
985 static std::vector<double,Alloc<double,25> > xvec (max_array);
986 static std::vector<int, Alloc<int, 25> > pivv (max_array);
987 typedef std::vector<int,Alloc<int,25> >::iterator pivIter;
988#endif
989 if (xvec.size() < static_cast<unsigned int>(nrow)) xvec.resize(nrow);
990 if (pivv.size() < static_cast<unsigned int>(nrow)) pivv.resize(nrow);
991 // Note - resize shuld do nothing if the size is already larger than nrow,
992 // but on VC++ there are indications that it does so we check.
993 // Note - the data elements in a vector are guaranteed to be contiguous,
994 // so x[i] and piv[i] are optimally fast.
995 mIter x = xvec.begin();
996 // x[i] is used as helper storage, needs to have at least size nrow.
997 pivIter piv = pivv.begin();
998 // piv[i] is used to store details of exchanges
999
1000 double temp1, temp2;
1001 HepMatrix::mIter ip, mjj, iq;
1002 double lambda, sigma;
1003 const double alpha = .6404; // = (1+sqrt(17))/8
1004 const double epsilon = 32*DBL_EPSILON;
1005 // whenever a sum of two doubles is below or equal to epsilon
1006 // it is set to zero.
1007 // this constant could be set to zero but then the algorithm
1008 // doesn't neccessarily detect that a matrix is singular
1009
1010 for (i = 0; i < nrow; ++i) piv[i] = i+1;
1011
1012 ifail = 0;
1013
1014 // compute the factorization P*A*P^T = L * D * L^T
1015 // L is unit lower triangular, D is direct sum of 1x1 and 2x2 matrices
1016 // L and D^-1 are stored in A = *this, P is stored in piv[]
1017
1018 for (j=1; j < nrow; j+=is) // main loop over columns
1019 {
1020 mjj = m.begin() + j*(j-1)/2 + j-1;
1021 lambda = 0; // compute lambda = max of A(j+1:n,j)
1022 pivrow = j+1;
1023 //ip = m.begin() + (j+1)*j/2 + j-1;
1024 for (i=j+1; i <= nrow ; ++i) {
1025 // calculate ip to avoid going off end of storage array
1026 ip = m.begin() + (i-1)*i/2 + j-1;
1027 if (fabs(*ip) > lambda) {
1028 lambda = fabs(*ip);
1029 pivrow = i;
1030 }
1031 } // for i
1032 if (lambda == 0 ) {
1033 if (*mjj == 0) {
1034 ifail = 1;
1035 return;
1036 }
1037 is=1;
1038 *mjj = 1./ *mjj;
1039 } else { // lambda == 0
1040 if (fabs(*mjj) >= lambda*alpha) {
1041 is=1;
1042 pivrow=j;
1043 } else { // fabs(*mjj) >= lambda*alpha
1044 sigma = 0; // compute sigma = max A(pivrow, j:pivrow-1)
1045 ip = m.begin() + pivrow*(pivrow-1)/2+j-1;
1046 for (k=j; k < pivrow; k++) {
1047 if (fabs(*ip) > sigma) sigma = fabs(*ip);
1048 ip++;
1049 } // for k
1050 if (sigma * fabs(*mjj) >= alpha * lambda * lambda) {
1051 is=1;
1052 pivrow = j;
1053 } else if (fabs(*(m.begin()+pivrow*(pivrow-1)/2+pivrow-1))
1054 >= alpha * sigma) {
1055 is=1;
1056 } else {
1057 is=2;
1058 } // if sigma...
1059 } // fabs(*mjj) >= lambda*alpha
1060 if (pivrow == j) { // no permutation neccessary
1061 piv[j-1] = pivrow;
1062 if (*mjj == 0) {
1063 ifail=1;
1064 return;
1065 }
1066 temp2 = *mjj = 1./ *mjj; // invert D(j,j)
1067
1068 // update A(j+1:n, j+1,n)
1069 for (i=j+1; i <= nrow; i++) {
1070 temp1 = *(m.begin() + i*(i-1)/2 + j-1) * temp2;
1071 ip = m.begin()+i*(i-1)/2+j;
1072 for (k=j+1; k<=i; k++) {
1073 *ip -= temp1 * *(m.begin() + k*(k-1)/2 + j-1);
1074 if (fabs(*ip) <= epsilon)
1075 *ip=0;
1076 ip++;
1077 }
1078 } // for i
1079 // update L
1080 //ip = m.begin() + (j+1)*j/2 + j-1;
1081 for (i=j+1; i <= nrow; ++i) {
1082 // calculate ip to avoid going off end of storage array
1083 ip = m.begin() + (i-1)*i/2 + j-1;
1084 *ip *= temp2;
1085 }
1086 } else if (is==1) { // 1x1 pivot
1087 piv[j-1] = pivrow;
1088
1089 // interchange rows and columns j and pivrow in
1090 // submatrix (j:n,j:n)
1091 ip = m.begin() + pivrow*(pivrow-1)/2 + j;
1092 for (i=j+1; i < pivrow; i++, ip++) {
1093 temp1 = *(m.begin() + i*(i-1)/2 + j-1);
1094 *(m.begin() + i*(i-1)/2 + j-1)= *ip;
1095 *ip = temp1;
1096 } // for i
1097 temp1 = *mjj;
1098 *mjj = *(m.begin()+pivrow*(pivrow-1)/2+pivrow-1);
1099 *(m.begin()+pivrow*(pivrow-1)/2+pivrow-1) = temp1;
1100 ip = m.begin() + (pivrow+1)*pivrow/2 + j-1;
1101 iq = ip + pivrow-j;
1102 for (i = pivrow+1; i <= nrow; ip += i, iq += i++) {
1103 temp1 = *iq;
1104 *iq = *ip;
1105 *ip = temp1;
1106 } // for i
1107
1108 if (*mjj == 0) {
1109 ifail = 1;
1110 return;
1111 } // *mjj == 0
1112 temp2 = *mjj = 1./ *mjj; // invert D(j,j)
1113
1114 // update A(j+1:n, j+1:n)
1115 for (i = j+1; i <= nrow; i++) {
1116 temp1 = *(m.begin() + i*(i-1)/2 + j-1) * temp2;
1117 ip = m.begin()+i*(i-1)/2+j;
1118 for (k=j+1; k<=i; k++) {
1119 *ip -= temp1 * *(m.begin() + k*(k-1)/2 + j-1);
1120 if (fabs(*ip) <= epsilon)
1121 *ip=0;
1122 ip++;
1123 } // for k
1124 } // for i
1125 // update L
1126 //ip = m.begin() + (j+1)*j/2 + j-1;
1127 for (i=j+1; i <= nrow; ++i) {
1128 // calculate ip to avoid going off end of storage array
1129 ip = m.begin() + (i-1)*i/2 + j-1;
1130 *ip *= temp2;
1131 }
1132 } else { // is=2, ie use a 2x2 pivot
1133 piv[j-1] = -pivrow;
1134 piv[j] = 0; // that means this is the second row of a 2x2 pivot
1135
1136 if (j+1 != pivrow) {
1137 // interchange rows and columns j+1 and pivrow in
1138 // submatrix (j:n,j:n)
1139 ip = m.begin() + pivrow*(pivrow-1)/2 + j+1;
1140 for (i=j+2; i < pivrow; i++, ip++) {
1141 temp1 = *(m.begin() + i*(i-1)/2 + j);
1142 *(m.begin() + i*(i-1)/2 + j) = *ip;
1143 *ip = temp1;
1144 } // for i
1145 temp1 = *(mjj + j + 1);
1146 *(mjj + j + 1) =
1147 *(m.begin() + pivrow*(pivrow-1)/2 + pivrow-1);
1148 *(m.begin() + pivrow*(pivrow-1)/2 + pivrow-1) = temp1;
1149 temp1 = *(mjj + j);
1150 *(mjj + j) = *(m.begin() + pivrow*(pivrow-1)/2 + j-1);
1151 *(m.begin() + pivrow*(pivrow-1)/2 + j-1) = temp1;
1152 ip = m.begin() + (pivrow+1)*pivrow/2 + j;
1153 iq = ip + pivrow-(j+1);
1154 for (i = pivrow+1; i <= nrow; ip += i, iq += i++) {
1155 temp1 = *iq;
1156 *iq = *ip;
1157 *ip = temp1;
1158 } // for i
1159 } // j+1 != pivrow
1160 // invert D(j:j+1,j:j+1)
1161 temp2 = *mjj * *(mjj + j + 1) - *(mjj + j) * *(mjj + j);
1162 if (temp2 == 0) {
1163 std::cerr
1164 << "SymMatrix::bunch_invert: error in pivot choice"
1165 << std::endl;
1166 }
1167 temp2 = 1. / temp2;
1168 // this quotient is guaranteed to exist by the choice
1169 // of the pivot
1170 temp1 = *mjj;
1171 *mjj = *(mjj + j + 1) * temp2;
1172 *(mjj + j + 1) = temp1 * temp2;
1173 *(mjj + j) = - *(mjj + j) * temp2;
1174
1175 if (j < nrow-1) { // otherwise do nothing
1176 // update A(j+2:n, j+2:n)
1177 for (i=j+2; i <= nrow ; i++) {
1178 ip = m.begin() + i*(i-1)/2 + j-1;
1179 temp1 = *ip * *mjj + *(ip + 1) * *(mjj + j);
1180 if (fabs(temp1 ) <= epsilon) temp1 = 0;
1181 temp2 = *ip * *(mjj + j) + *(ip + 1) * *(mjj + j + 1);
1182 if (fabs(temp2 ) <= epsilon) temp2 = 0;
1183 for (k = j+2; k <= i ; k++) {
1184 ip = m.begin() + i*(i-1)/2 + k-1;
1185 iq = m.begin() + k*(k-1)/2 + j-1;
1186 *ip -= temp1 * *iq + temp2 * *(iq+1);
1187 if (fabs(*ip) <= epsilon)
1188 *ip = 0;
1189 } // for k
1190 } // for i
1191 // update L
1192 for (i=j+2; i <= nrow ; i++) {
1193 ip = m.begin() + i*(i-1)/2 + j-1;
1194 temp1 = *ip * *mjj + *(ip+1) * *(mjj + j);
1195 if (fabs(temp1) <= epsilon) temp1 = 0;
1196 *(ip+1) = *ip * *(mjj + j)
1197 + *(ip+1) * *(mjj + j + 1);
1198 if (fabs(*(ip+1)) <= epsilon) *(ip+1) = 0;
1199 *ip = temp1;
1200 } // for k
1201 } // j < nrow-1
1202 }
1203 }
1204 } // end of main loop over columns
1205
1206 if (j == nrow) { // the the last pivot is 1x1
1207 mjj = m.begin() + j*(j-1)/2 + j-1;
1208 if (*mjj == 0) {
1209 ifail = 1;
1210 return;
1211 } else { *mjj = 1. / *mjj; }
1212 } // end of last pivot code
1213
1214 // computing the inverse from the factorization
1215
1216 for (j = nrow ; j >= 1 ; j -= is) // loop over columns
1217 {
1218 mjj = m.begin() + j*(j-1)/2 + j-1;
1219 if (piv[j-1] > 0) { // 1x1 pivot, compute column j of inverse
1220 is = 1;
1221 if (j < nrow) {
1222 //ip = m.begin() + (j+1)*j/2 + j-1;
1223 //for (i=0; i < nrow-j; ip += 1+j+i++) x[i] = *ip;
1224 ip = m.begin() + (j+1)*j/2 - 1;
1225 for (i=0; i < nrow-j; ++i) {
1226 ip += i + j;
1227 x[i] = *ip;
1228 }
1229 for (i=j+1; i<=nrow ; i++) {
1230 temp2=0;
1231 ip = m.begin() + i*(i-1)/2 + j;
1232 for (k=0; k <= i-j-1; k++) temp2 += *ip++ * x[k];
1233 // avoid setting ip outside the bounds of the storage array
1234 ip -= 1;
1235 // using the value of k from the previous loop
1236 for ( ; k < nrow-j; ++k) {
1237 ip += j+k;
1238 temp2 += *ip * x[k];
1239 }
1240 *(m.begin()+ i*(i-1)/2 + j-1) = -temp2;
1241 } // for i
1242 temp2 = 0;
1243 //ip = m.begin() + (j+1)*j/2 + j-1;
1244 //for (k=0; k < nrow-j; ip += 1+j+k++)
1245 //temp2 += x[k] * *ip;
1246 ip = m.begin() + (j+1)*j/2 - 1;
1247 for (k=0; k < nrow-j; ++k) {
1248 ip += j+k;
1249 temp2 += x[k] * *ip;
1250 }
1251 *mjj -= temp2;
1252 } // j < nrow
1253 } else { //2x2 pivot, compute columns j and j-1 of the inverse
1254 if (piv[j-1] != 0)
1255 std::cerr << "error in piv" << piv[j-1] << std::endl;
1256 is=2;
1257 if (j < nrow) {
1258 //ip = m.begin() + (j+1)*j/2 + j-1;
1259 //for (i=0; i < nrow-j; ip += 1+j+i++) x[i] = *ip;
1260 ip = m.begin() + (j+1)*j/2 - 1;
1261 for (i=0; i < nrow-j; ++i) {
1262 ip += i + j;
1263 x[i] = *ip;
1264 }
1265 for (i=j+1; i<=nrow ; i++) {
1266 temp2 = 0;
1267 ip = m.begin() + i*(i-1)/2 + j;
1268 for (k=0; k <= i-j-1; k++)
1269 temp2 += *ip++ * x[k];
1270 for (ip += i-1; k < nrow-j; ip += 1+j+k++)
1271 temp2 += *ip * x[k];
1272 *(m.begin()+ i*(i-1)/2 + j-1) = -temp2;
1273 } // for i
1274 temp2 = 0;
1275 //ip = m.begin() + (j+1)*j/2 + j-1;
1276 //for (k=0; k < nrow-j; ip += 1+j+k++) temp2 += x[k] * *ip;
1277 ip = m.begin() + (j+1)*j/2 - 1;
1278 for (k=0; k < nrow-j; ++k) {
1279 ip += k + j;
1280 temp2 += x[k] * *ip;
1281 }
1282 *mjj -= temp2;
1283 temp2 = 0;
1284 //ip = m.begin() + (j+1)*j/2 + j-2;
1285 //for (i=j+1; i <= nrow; ip += i++) temp2 += *ip * *(ip+1);
1286 ip = m.begin() + (j+1)*j/2 - 2;
1287 for (i=j+1; i <= nrow; ++i) {
1288 ip += i - 1;
1289 temp2 += *ip * *(ip+1);
1290 }
1291 *(mjj-1) -= temp2;
1292 //ip = m.begin() + (j+1)*j/2 + j-2;
1293 //for (i=0; i < nrow-j; ip += 1+j+i++) x[i] = *ip;
1294 ip = m.begin() + (j+1)*j/2 - 2;
1295 for (i=0; i < nrow-j; ++i) {
1296 ip += i + j;
1297 x[i] = *ip;
1298 }
1299 for (i=j+1; i <= nrow ; i++) {
1300 temp2 = 0;
1301 ip = m.begin() + i*(i-1)/2 + j;
1302 for (k=0; k <= i-j-1; k++)
1303 temp2 += *ip++ * x[k];
1304 for (ip += i-1; k < nrow-j; ip += 1+j+k++)
1305 temp2 += *ip * x[k];
1306 *(m.begin()+ i*(i-1)/2 + j-2)= -temp2;
1307 } // for i
1308 temp2 = 0;
1309 //ip = m.begin() + (j+1)*j/2 + j-2;
1310 //for (k=0; k < nrow-j; ip += 1+j+k++)
1311 // temp2 += x[k] * *ip;
1312 ip = m.begin() + (j+1)*j/2 - 2;
1313 for (k=0; k < nrow-j; ++k) {
1314 ip += k + j;
1315 temp2 += x[k] * *ip;
1316 }
1317 *(mjj-j) -= temp2;
1318 } // j < nrow
1319 } // else piv[j-1] > 0
1320
1321 // interchange rows and columns j and piv[j-1]
1322 // or rows and columns j and -piv[j-2]
1323
1324 pivrow = (piv[j-1]==0)? -piv[j-2] : piv[j-1];
1325 ip = m.begin() + pivrow*(pivrow-1)/2 + j;
1326 for (i=j+1;i < pivrow; i++, ip++) {
1327 temp1 = *(m.begin() + i*(i-1)/2 + j-1);
1328 *(m.begin() + i*(i-1)/2 + j-1) = *ip;
1329 *ip = temp1;
1330 } // for i
1331 temp1 = *mjj;
1332 *mjj = *(m.begin() + pivrow*(pivrow-1)/2 + pivrow-1);
1333 *(m.begin() + pivrow*(pivrow-1)/2 + pivrow-1) = temp1;
1334 if (is==2) {
1335 temp1 = *(mjj-1);
1336 *(mjj-1) = *( m.begin() + pivrow*(pivrow-1)/2 + j-2);
1337 *( m.begin() + pivrow*(pivrow-1)/2 + j-2) = temp1;
1338 } // is==2
1339
1340 // problem right here
1341 if( pivrow < nrow ) {
1342 ip = m.begin() + (pivrow+1)*pivrow/2 + j-1; // &A(i,j)
1343 // adding parenthesis for VC++
1344 iq = ip + (pivrow-j);
1345 for (i = pivrow+1; i <= nrow; i++) {
1346 temp1 = *iq;
1347 *iq = *ip;
1348 *ip = temp1;
1349 if( i < nrow ) {
1350 ip += i;
1351 iq += i;
1352 }
1353 } // for i
1354 } // pivrow < nrow
1355 } // end of loop over columns (in computing inverse from factorization)
1356
1357 return; // inversion successful
1358
1359}
1360
1361} // namespace CLHEP
#define CHK_DIM_2(r1, r2, c1, c2, fun)
Definition: DiagMatrix.cc:44
#define SIMPLE_BOP(OPER)
Definition: DiagMatrix.cc:31
#define SIMPLE_UOP(OPER)
Definition: DiagMatrix.cc:26
#define SIMPLE_TOP(OPER)
Definition: DiagMatrix.cc:37
#define CHK_DIM_1(c1, r2, fun)
Definition: DiagMatrix.cc:49
std::vector< double, Alloc< double, 25 > >::const_iterator mcIter
Definition: GenMatrix.h:74
std::vector< double, Alloc< double, 25 > >::iterator mIter
Definition: GenMatrix.h:73
static void error(const char *s)
Definition: GenMatrix.cc:70
HepMatrix & operator=(const HepMatrix &)
Definition: Matrix.cc:415
virtual int num_col() const
Definition: Matrix.cc:120
virtual int num_row() const
Definition: Matrix.cc:118
HepMatrix & operator+=(const HepMatrix &)
Definition: Matrix.cc:389
HepMatrix & operator-=(const HepMatrix &)
Definition: Matrix.cc:396
virtual int num_size() const
Definition: Matrix.cc:122
HepSymMatrix & operator*=(double t)
Definition: SymMatrix.cc:611
double trace() const
Definition: SymMatrix.cc:954
double determinant() const
Definition: SymMatrix.cc:940
int num_row() const
HepSymMatrix & operator+=(const HepSymMatrix &hm2)
Definition: SymMatrix.cc:575
int num_col() const
void assign(const HepMatrix &hm2)
Definition: SymMatrix.cc:715
HepSymMatrix apply(double(*f)(double, int, int)) const
Definition: SymMatrix.cc:697
HepSymMatrix similarityT(const HepMatrix &hm1) const
Definition: SymMatrix.cc:813
HepSymMatrix & operator=(const HepSymMatrix &hm2)
Definition: SymMatrix.cc:642
HepSymMatrix sub(int min_row, int max_row) const
Definition: SymMatrix.cc:131
HepSymMatrix operator-() const
Definition: SymMatrix.cc:211
HepSymMatrix & operator-=(const HepSymMatrix &hm2)
Definition: SymMatrix.cc:598
HepSymMatrix similarity(const HepMatrix &hm1) const
Definition: SymMatrix.cc:734
void invertBunchKaufman(int &ifail)
Definition: SymMatrix.cc:961
virtual ~HepSymMatrix()
Definition: SymMatrix.cc:100
HepSymMatrix & operator/=(double t)
Definition: SymMatrix.cc:605
virtual int num_row() const
Definition: Vector.cc:116
void f(void g())
Definition: excDblThrow.cc:38
HepSymMatrix vT_times_v(const HepVector &v)
Definition: SymMatrix.cc:539
std::ostream & operator<<(std::ostream &s, const HepDiagMatrix &q)
Definition: DiagMatrix.cc:560
HepMatrix operator+(const HepMatrix &hm1, const HepDiagMatrix &d2)
Definition: DiagMatrix.cc:193
HepMatrix operator-(const HepMatrix &hm1, const HepDiagMatrix &d2)
Definition: DiagMatrix.cc:264
HepMatrix operator*(const HepMatrix &hm1, const HepDiagMatrix &hm2)
Definition: DiagMatrix.cc:372
HepDiagMatrix dsum(const HepDiagMatrix &s1, const HepDiagMatrix &s2)
Definition: DiagMatrix.cc:161
void init()
Definition: testRandom.cc:29