Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
MnMatrix.h
Go to the documentation of this file.
1// @(#)root/minuit2:$Id$
2// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT *
7 * *
8 **********************************************************************/
9
10#ifndef ROOT_Minuit2_MnMatrix
11#define ROOT_Minuit2_MnMatrix
12
13#include <Minuit2/MnMatrixfwd.h> // For typedefs
14
15#include <ROOT/RSpan.hxx>
16
17#include <cassert>
18#include <cstdlib>
19#include <cstring>
20#include <new>
21#include <ostream>
22
23// comment out this line and recompile if you want to gain additional
24// performance (the gain is mainly for "simple" functions which are easy
25// to calculate and vanishes quickly if going to cost-intensive functions)
26// the library is no longer thread save however
27
28#ifdef MN_USE_STACK_ALLOC
29#define _MN_NO_THREAD_SAVE_
30#endif
31
32namespace ROOT {
33
34namespace Minuit2 {
35
36namespace MnMatrix {
37
38// Whether to cut the maximum number of parameters shown for vector and matrices
39// set maximum number of printed parameters and return previous value
40// A negative value will mean all parameters are printed
41int SetMaxNP(int value);
42
43// retrieve maximum number of printed parameters
44int MaxNP();
45
46} // namespace MnMatrix
47
48/// define stack allocator symbol
49
51class StackError {};
52
53/** StackAllocator controls the memory allocation/deallocation of Minuit. If
54 _MN_NO_THREAD_SAVE_ is defined, memory is taken from a pre-allocated piece
55 of heap memory which is then used like a stack, otherwise via standard
56 malloc/free. Note that defining _MN_NO_THREAD_SAVE_ makes the code thread-
57 unsave. The gain in performance is mainly for cost-cheap FCN functions.
58 */
59
61
62public:
63 // enum {default_size = 1048576};
64 enum {
65 default_size = 524288
66 };
67
69 {
70#ifdef _MN_NO_THREAD_SAVE_
71 // std::cout<<"StackAllocator Allocate "<<default_size<<std::endl;
72 fStack = new unsigned char[default_size];
73#endif
74 fStackOffset = 0;
75 fBlockCount = 0;
76 }
77
79 {
80#ifdef _MN_NO_THREAD_SAVE_
81 // std::cout<<"StackAllocator destruct "<<fStackOffset<<std::endl;
82 if (fStack)
83 delete[] fStack;
84#endif
85 }
86
87 void *Allocate(size_t nBytes)
88 {
89#ifdef _MN_NO_THREAD_SAVE_
90 if (fStack == 0)
91 fStack = new unsigned char[default_size];
94
95 // std::cout << "Allocating " << nAlloc << " bytes, requested = " << nBytes << std::endl;
96
97 // write the start position of the next block at the start of the block
99 // write the start position of the new block at the end of the block
100 WriteInt(fStackOffset + nAlloc - sizeof(int), fStackOffset);
101
102 void *result = fStack + fStackOffset + sizeof(int);
104 fBlockCount++;
105
106#ifdef DEBUG_ALLOCATOR
108#endif
109
110#else
111 void *result = malloc(nBytes);
112 if (!result)
113 throw std::bad_alloc();
114#endif
115
116 return result;
117 }
118
119 void Deallocate(void *p)
120 {
121#ifdef _MN_NO_THREAD_SAVE_
122 // int previousOffset = ReadInt( fStackOffset - sizeof(int));
123 int delBlock = ToInt(p);
125 int previousBlock = ReadInt(nextBlock - sizeof(int));
126 if (nextBlock == fStackOffset) {
127 // deallocating last allocated
129 } else {
130 // overwrite previous adr of next block
132 WriteInt(nextNextBlock - sizeof(int), previousBlock);
133 // overwrite head of deleted block
135 }
136 fBlockCount--;
137
138#ifdef DEBUG_ALLOCATOR
140#endif
141#else
142 free(p);
143#endif
144 // std::cout << "Block at " << delBlock
145 // << " deallocated, fStackOffset = " << fStackOffset << std::endl;
146 }
147
149 {
150 int *ip = (int *)(fStack + offset);
151
152 // std::cout << "read " << *ip << " from offset " << offset << std::endl;
153
154 return *ip;
155 }
156
157 void WriteInt(int offset, int Value)
158 {
159
160 // std::cout << "writing " << Value << " to offset " << offset << std::endl;
161
162 int *ip = reinterpret_cast<int *>(fStack + offset);
163 *ip = Value;
164 }
165
166 int ToInt(void *p)
167 {
168 unsigned char *pc = static_cast<unsigned char *>(p);
169
170 // std::cout << "toInt: p = " << p << " fStack = " << (void*) fStack << std::endl;
171 // VC 7.1 warning:conversion from __w64 int to int
172 int userBlock = pc - fStack;
173 return userBlock - sizeof(int); // correct for starting int
174 }
175
177 {
178 const int fAlignment = 4;
179 int needed = nBytes % fAlignment == 0 ? nBytes : (nBytes / fAlignment + 1) * fAlignment;
180 return needed + 2 * sizeof(int);
181 }
182
183 void CheckOverflow(int n)
184 {
185 if (fStackOffset + n >= default_size) {
186 // std::cout << " no more space on stack allocator" << std::endl;
187 throw StackOverflow();
188 }
189 }
190
192 {
193
194 // std::cout << "checking consistency for " << fBlockCount << " blocks"<< std::endl;
195
196 // loop over all blocks
197 int beg = 0;
198 int end = fStackOffset;
199 int nblocks = 0;
200 while (beg < fStackOffset) {
201 end = ReadInt(beg);
202
203 // std::cout << "beg = " << beg << " end = " << end
204 // << " fStackOffset = " << fStackOffset << std::endl;
205
206 int beg2 = ReadInt(end - sizeof(int));
207 if (beg != beg2) {
208 // std::cout << " beg != beg2 " << std::endl;
209 return false;
210 }
211 nblocks++;
212 beg = end;
213 }
214 if (end != fStackOffset) {
215 // std::cout << " end != fStackOffset" << std::endl;
216 return false;
217 }
218 if (nblocks != fBlockCount) {
219 // std::cout << "nblocks != fBlockCount" << std::endl;
220 return false;
221 }
222 // std::cout << "Allocator is in consistent state, nblocks = " << nblocks << std::endl;
223 return true;
224 }
225
226private:
227 unsigned char *fStack;
228 // unsigned char fStack[default_size];
231};
232
234
235 // t.b.d need to use same trick as Boost singleton.hpp to be sure that
236 // StackAllocator is created before main()
237
238public:
240 {
242 return gStackAllocator;
243 }
244};
245
246class sym {};
247class vec {};
248
249// Helper base class to delete assignment.
250//
251// Note that base classes without any data members or virtual functions don't
252// cause any runtime overhead.
253//
254// Assignment is often historically deleted (that was done probably to avoid
255// mistakes from accidental re-assignment). Also define destructor and copy
256// constructor in this case, according to the rule of five.
266
267template <class Type, class M, class T = double>
268class ABObj : public DeleteAssignment {
269
270public:
271 ABObj(const M &obj, T factor = 1.) : fObject(obj), fFactor(factor) {}
272
273 const M &Obj() const { return fObject; }
274
275 T f() const { return fFactor; }
276
277private:
280};
281
282// templated scaling operator *
283template <class mt, class M, class T>
285{
286 return {obj, f};
287}
288
289// templated operator /
290template <class mt, class M, class T>
292{
293 return {obj, T(1.) / f};
294}
295
296// templated unary operator -
297template <class mt, class M, class T>
299{
300 return {obj, -1.};
301}
302
303// factor * ABObj
304template <class mt, class M, class T>
306{
307 return {obj.Obj(), obj.f() * f};
308}
309
310// ABObj / factor
311template <class mt, class M, class T>
313{
314 return {obj.Obj(), obj.f() / f};
315}
316
317// -ABObj
318template <class mt, class M, class T>
320{
321 return {obj.Obj(), T(-1.) * obj.f()};
322}
323
324template <class M1, class M2>
325class ABSum : public DeleteAssignment {
326public:
327 ABSum(const M1 &a, const M2 &b) : fA(a), fB(b) {}
328
329 const M1 &A() const { return fA; }
330 const M2 &B() const { return fB; }
331
332private:
333 M1 fA;
334 M2 fB;
335};
336
337// ABObj + ABObj
338template <class atype, class A, class B, class T>
345
346// ABObj - ABObj
347template <class atype, class A, class B, class T>
350{
351
352 return {ABSum<ABObj<atype, A, T>, ABObj<atype, B, T>>(a, ABObj<atype, B, T>(b.Obj(), T(-1.) * b.f()))};
353}
354
355template <class M1, class M2>
356class ABProd : public DeleteAssignment {
357public:
358 ABProd(const M1 &a, const M2 &b) : fA(a), fB(b) {}
359
360 const M1 &A() const { return fA; }
361 const M2 &B() const { return fB; }
362
363private:
364 M1 fA;
365 M2 fB;
366};
367
368// ABObj * ABObj (only supported for sym * vec)
369template <class A, class B, class T>
376
377template <class M, class T>
379
380public:
381 VectorOuterProduct(const M &obj) : fObject(obj) {}
382
383 const M &Obj() const { return fObject; }
384
385private:
387};
388
389template <class M, class T>
394
395template <class mtype, class M, class T>
397
398public:
399 MatrixInverse(const M &obj) : fObject(obj) {}
400
401 const M &Obj() const { return fObject; }
402
403private:
405};
406
407// Matrix inverse of a vector is not possible.
408template <class M, class T>
409class MatrixInverse<vec, M, T> {
410 MatrixInverse() = delete;
411 MatrixInverse(const MatrixInverse &) = delete;
413};
414
415template <class mt, class M, class T>
420
421void Mndaxpy(unsigned int, double, const double *, double *);
422void Mndscal(unsigned int, double, double *);
423
424class LASymMatrix;
425class LAVector;
426
427int Invert(LASymMatrix &);
428
429/**
430 Class describing a symmetric matrix of size n.
431 The size is specified as a run-time argument passed in the
432 constructor.
433 The class uses expression templates for the operations and functions.
434 Only the independent data are kept in the fdata array of size n*(n+1)/2
435 containing the lower triangular data
436 */
437
439
440public:
441 typedef sym Type;
442
443 LASymMatrix(unsigned int n)
444 : fSize(n * (n + 1) / 2),
445 fNRow(n),
446 fData((n > 0) ? (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * n * (n + 1) / 2) : nullptr)
447 {
448 // assert(fSize>0);
449 if (fData)
450 std::memset(fData, 0, fSize * sizeof(double));
451 }
452
454 {
455 if (fData)
456 StackAllocatorHolder::Get().Deallocate(fData);
457 }
458
460 : fSize(v.size()),
461 fNRow(v.Nrow()),
462 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.size()))
463 {
464 std::memcpy(fData, v.Data(), fSize * sizeof(double));
465 }
466
468 : fSize(v.size()),
469 fNRow(v.Nrow()),
470 fData(v.fData)
471 {
472 v.fData = nullptr;
473 }
474
475
477 {
478 if (fSize < v.size()) {
479 if (fData)
480 StackAllocatorHolder::Get().Deallocate(fData);
481 fSize = v.size();
482 fNRow = v.Nrow();
483 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
484 } else if (fSize > v.size()) {
485 throw std::runtime_error("Can't assign smaller LASymMatrix to larger LASymMatrix");
486 }
487 std::memcpy(fData, v.Data(), fSize * sizeof(double));
488 return *this;
489 }
490
492 {
493 fSize = v.size();
494 fNRow = v.Nrow();
495 fData = v.Data();
496 v.fData = nullptr;
497 return *this;
498 }
499
500 template <class T>
502 : fSize(v.Obj().size()),
503 fNRow(v.Obj().Nrow()),
504 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size()))
505 {
506 // std::cout<<"LASymMatrix(const ABObj<sym, LASymMatrix, T>& v)"<<std::endl;
507 // std::cout<<"allocate "<<fSize<<std::endl;
508 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(double));
509 Mndscal(fSize, double(v.f()), fData);
510 // std::cout<<"fData= "<<fData[0]<<" "<<fData[1]<<std::endl;
511 }
512
513 template <class A, class B, class T>
515 {
516 // std::cout<<"template<class A, class B, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, A, T>,
517 // ABObj<sym, B, T> > >& sum)"<<std::endl; recursive construction
518 (*this) = sum.Obj().A();
519 (*this) += sum.Obj().B();
520 // std::cout<<"leaving template<class A, class B, class T> LASymMatrix(const ABObj..."<<std::endl;
521 }
522
523 template <class A, class T>
525 {
526 // std::cout<<"template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix, T>,
527 // ABObj<sym, A, T> >,T>& sum)"<<std::endl;
528
529 // recursive construction
530 // std::cout<<"(*this)=sum.Obj().B();"<<std::endl;
531 (*this) = sum.Obj().B();
532 // std::cout<<"(*this)+=sum.Obj().A();"<<std::endl;
533 (*this) += sum.Obj().A();
534 // std::cout<<"leaving template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym,
535 // LASymMatrix,.."<<std::endl;
536 }
537
538 template <class A, class T>
540 {
541 // std::cout<<"template<class A, class T> LASymMatrix(const ABObj<sym, ABObj<sym, A, T>, T>&
542 // something)"<<std::endl;
543 (*this) = something.Obj();
544 (*this) *= something.f();
545 // std::cout<<"leaving template<class A, class T> LASymMatrix(const ABObj<sym, ABObj<sym, A, T>, T>&
546 // something)"<<std::endl;
547 }
548
549 template <class T>
551 : fSize(inv.Obj().Obj().Obj().size()),
552 fNRow(inv.Obj().Obj().Obj().Nrow()),
553 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * inv.Obj().Obj().Obj().size()))
554 {
555 std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double));
556 Mndscal(fSize, double(inv.Obj().Obj().f()), fData);
557 Invert(*this);
558 Mndscal(fSize, double(inv.f()), fData);
559 }
560
561 template <class A, class T>
564 &sum)
565 {
566 // std::cout<<"template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, MatrixInverse<sym,
567 // ABObj<sym, LASymMatrix, T>, T>, T>, ABObj<sym, A, T> >, T>& sum)"<<std::endl;
568
569 // recursive construction
570 (*this) = sum.Obj().B();
571 (*this) += sum.Obj().A();
572 // std::cout<<"leaving template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym,
573 // LASymMatrix,.."<<std::endl;
574 }
575
577
578 template <class A, class T>
581 {
582 // std::cout<<"template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym,
583 // VectorOuterProduct<ABObj<vec, LAVector, T>, T>, T> ABObj<sym, A, T> >,T>& sum)"<<std::endl;
584
585 // recursive construction
586 (*this) = sum.Obj().B();
587 (*this) += sum.Obj().A();
588 // std::cout<<"leaving template<class A, class T> LASymMatrix(const ABObj<sym, ABSum<ABObj<sym,
589 // LASymMatrix,.."<<std::endl;
590 }
591
593 {
594 // std::cout<<"LASymMatrix& operator+=(const LASymMatrix& m)"<<std::endl;
595 assert(fSize == m.size());
596 Mndaxpy(fSize, 1., m.Data(), fData);
597 return *this;
598 }
599
601 {
602 // std::cout<<"LASymMatrix& operator-=(const LASymMatrix& m)"<<std::endl;
603 assert(fSize == m.size());
604 Mndaxpy(fSize, -1., m.Data(), fData);
605 return *this;
606 }
607
608 template <class T>
610 {
611 // std::cout<<"template<class T> LASymMatrix& operator+=(const ABObj<sym, LASymMatrix, T>& m)"<<std::endl;
612 assert(fSize == m.Obj().size());
613 if (m.Obj().Data() == fData) {
614 Mndscal(fSize, 1. + double(m.f()), fData);
615 } else {
616 Mndaxpy(fSize, double(m.f()), m.Obj().Data(), fData);
617 }
618 // std::cout<<"fData= "<<fData[0]<<" "<<fData[1]<<std::endl;
619 return *this;
620 }
621
622 template <class A, class T>
624 {
625 // std::cout<<"template<class A, class T> LASymMatrix& operator+=(const ABObj<sym, A,T>& m)"<<std::endl;
626 (*this) += LASymMatrix(m);
627 return *this;
628 }
629
630 template <class T>
632 {
633 // std::cout<<"template<class T> LASymMatrix& operator+=(const ABObj<sym, MatrixInverse<sym, ABObj<sym,
634 // LASymMatrix, T>, T>, T>& m)"<<std::endl;
635 assert(fNRow > 0);
636 LASymMatrix tmp(m.Obj().Obj());
637 Invert(tmp);
638 tmp *= double(m.f());
639 (*this) += tmp;
640 return *this;
641 }
642
643 template <class T>
645 {
646 // std::cout<<"template<class T> LASymMatrix& operator+=(const ABObj<sym, VectorOuterProduct<ABObj<vec,
647 // LAVector, T>, T>, T>&"<<std::endl;
648 assert(fNRow > 0);
649 Outer_prod(*this, m.Obj().Obj().Obj(), m.f() * m.Obj().Obj().f() * m.Obj().Obj().f());
650 return *this;
651 }
652
654 {
656 return *this;
657 }
658
659 double operator()(unsigned int row, unsigned int col) const
660 {
661 assert(row < fNRow && col < fNRow);
662 if (row > col)
663 return fData[col + row * (row + 1) / 2];
664 else
665 return fData[row + col * (col + 1) / 2];
666 }
667
668 double &operator()(unsigned int row, unsigned int col)
669 {
670 assert(row < fNRow && col < fNRow);
671 if (row > col)
672 return fData[col + row * (row + 1) / 2];
673 else
674 return fData[row + col * (col + 1) / 2];
675 }
676
677 const double *Data() const { return fData; }
678
679 double *Data() { return fData; }
680
681 unsigned int size() const { return fSize; }
682
683 unsigned int Nrow() const { return fNRow; }
684
685 unsigned int Ncol() const { return Nrow(); }
686
687private:
688 unsigned int fSize = 0;
689 unsigned int fNRow = 0;
690 double *fData = nullptr;
691
692public:
693 template <class T>
695 {
696 // std::cout<<"template<class T> LASymMatrix& operator=(ABObj<sym, LASymMatrix, T>& v)"<<std::endl;
697 if (fSize == 0 && !fData) {
698 fSize = v.Obj().size();
699 fNRow = v.Obj().Nrow();
700 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
701 } else {
702 assert(fSize == v.Obj().size());
703 }
704 // std::cout<<"fData= "<<fData[0]<<" "<<fData[1]<<std::endl;
705 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(double));
706 (*this) *= v.f();
707 return *this;
708 }
709
710 template <class A, class T>
712 {
713 // std::cout<<"template<class A, class T> LASymMatrix& operator=(const ABObj<sym, ABObj<sym, A, T>, T>&
714 // something)"<<std::endl;
715 if (fSize == 0 && fData == nullptr) {
716 (*this) = something.Obj();
717 (*this) *= something.f();
718 } else {
719 LASymMatrix tmp(something.Obj());
720 tmp *= something.f();
721 assert(fSize == tmp.size());
722 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
723 }
724 // std::cout<<"template<class A, class T> LASymMatrix& operator=(const ABObj<sym, ABObj<sym, A, T>, T>&
725 // something)"<<std::endl;
726 return *this;
727 }
728
729 template <class A, class B, class T>
731 {
732 // std::cout<<"template<class A, class B, class T> LASymMatrix& operator=(const ABObj<sym, ABSum<ABObj<sym, A, T>,
733 // ABObj<sym, B, T> >,T>& sum)"<<std::endl;
734 // recursive construction
735 if (fSize == 0 && fData == nullptr) {
736 (*this) = sum.Obj().A();
737 (*this) += sum.Obj().B();
738 (*this) *= sum.f();
739 } else {
740 LASymMatrix tmp(sum.Obj().A());
741 tmp += sum.Obj().B();
742 tmp *= sum.f();
743 assert(fSize == tmp.size());
744 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
745 }
746 return *this;
747 }
748
749 template <class A, class T>
751 {
752 // std::cout<<"template<class A, class T> LASymMatrix& operator=(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix,
753 // T>, ABObj<sym, A, T> >,T>& sum)"<<std::endl;
754
755 if (fSize == 0 && fData == nullptr) {
756 // std::cout<<"fSize == 0 && fData == 0"<<std::endl;
757 (*this) = sum.Obj().B();
758 (*this) += sum.Obj().A();
759 (*this) *= sum.f();
760 } else {
761 // std::cout<<"creating tmp variable"<<std::endl;
762 LASymMatrix tmp(sum.Obj().B());
763 tmp += sum.Obj().A();
764 tmp *= sum.f();
765 assert(fSize == tmp.size());
766 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
767 }
768 // std::cout<<"leaving LASymMatrix& operator=(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix..."<<std::endl;
769 return *this;
770 }
771
772 template <class T>
774 {
775 if (fSize == 0 && fData == nullptr) {
776 fSize = inv.Obj().Obj().Obj().size();
777 fNRow = inv.Obj().Obj().Obj().Nrow();
778 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
779 std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double));
780 (*this) *= inv.Obj().Obj().f();
781 Invert(*this);
782 (*this) *= inv.f();
783 } else {
784 LASymMatrix tmp(inv.Obj().Obj());
785 Invert(tmp);
786 tmp *= double(inv.f());
787 assert(fSize == tmp.size());
788 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
789 }
790 return *this;
791 }
792
794};
795
801
807
809{
810 return {obj, f};
811}
812
814{
815 return {obj, 1. / f};
816}
817
819{
820 return {obj, -1.};
821}
822
823void Mndaxpy(unsigned int, double, const double *, double *);
824void Mndscal(unsigned int, double, double *);
825void Mndspmv(unsigned int, double, const double *, const double *, double, double *);
826
827class LAVector {
828
829public:
830 typedef vec Type;
831
832 LAVector(unsigned int n)
833 : fSize(n), fData((n > 0) ? (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * n) : nullptr)
834 {
835 if (fData)
836 std::memset(fData, 0, size() * sizeof(double));
837 }
838
840 {
841 if (fData)
842 StackAllocatorHolder::Get().Deallocate(fData);
843 }
844
846 : fSize(v.size()), fData(v.Data())
847 {
848 v.fData = nullptr;
849 }
850
851 LAVector(const LAVector &v) : LAVector{std::span<const double>{v.Data(), v.size()}} {}
852
853 explicit LAVector(std::span<const double> v)
854 : fSize(v.size()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.size()))
855 {
856 std::memcpy(fData, v.data(), fSize * sizeof(double));
857 }
858
860 {
861 // implement proper copy constructor in case size is different
862 if (v.size() > fSize) {
863 if (fData)
864 StackAllocatorHolder::Get().Deallocate(fData);
865 fSize = v.size();
866 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
867 } else if (fSize > v.size()) {
868 throw std::runtime_error("Can't assign smaller LAVector to larger LAVector");
869 }
870 std::memcpy(fData, v.Data(), fSize * sizeof(double));
871 return *this;
872 }
873
875 {
876 fSize = v.fSize;
877 fData = v.fData;
878 v.fData = nullptr;
879 return *this;
880 }
881
882 template <class T>
884 : fSize(v.Obj().size()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size()))
885 {
886 // std::cout<<"LAVector(const ABObj<LAVector, T>& v)"<<std::endl;
887 // std::cout<<"allocate "<<fSize<<std::endl;
888 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(T));
889 (*this) *= T(v.f());
890 // std::cout<<"fData= "<<fData[0]<<" "<<fData[1]<<std::endl;
891 }
892
893 template <class A, class B, class T>
895 {
896 // std::cout<<"template<class A, class B, class T> LAVector(const ABObj<ABSum<ABObj<A, T>, ABObj<B, T> > >&
897 // sum)"<<std::endl;
898 (*this) = sum.Obj().A();
899 (*this) += sum.Obj().B();
900 (*this) *= double(sum.f());
901 }
902
903 template <class A, class T>
905 {
906 // std::cout<<"template<class A, class T> LAVector(const ABObj<ABSum<ABObj<LAVector, T>, ABObj<A, T> >,T>&
907 // sum)"<<std::endl;
908
909 // recursive construction
910 // std::cout<<"(*this)=sum.Obj().B();"<<std::endl;
911 (*this) = sum.Obj().B();
912 // std::cout<<"(*this)+=sum.Obj().A();"<<std::endl;
913 (*this) += sum.Obj().A();
914 (*this) *= double(sum.f());
915 // std::cout<<"leaving template<class A, class T> LAVector(const ABObj<ABSum<ABObj<LAVector,.."<<std::endl;
916 }
917
918 template <class A, class T>
920 {
921 // std::cout<<"template<class A, class T> LAVector(const ABObj<ABObj<A, T>, T>& something)"<<std::endl;
922 (*this) = something.Obj();
923 (*this) *= something.f();
924 }
925
926 //
927 template <class T>
929 : fSize(prod.Obj().B().Obj().size()),
930 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * prod.Obj().B().Obj().size()))
931 {
932 // std::cout<<"template<class T> LAVector(const ABObj<vec, ABProd<ABObj<sym, LASymMatrix, T>, ABObj<vec,
933 // LAVector, T> >, T>& prod)"<<std::endl;
934
935 Mndspmv(fSize, prod.f() * prod.Obj().A().f() * prod.Obj().B().f(), prod.Obj().A().Obj().Data(),
936 prod.Obj().B().Obj().Data(), 0., fData);
937 }
938
939 //
940 template <class T>
942 vec,
944 T> &prod)
945 {
946 (*this) = prod.Obj().B();
947 (*this) += prod.Obj().A();
948 (*this) *= double(prod.f());
949 }
950
951 //
953 {
954 // std::cout<<"LAVector& operator+=(const LAVector& m)"<<std::endl;
955 assert(fSize == m.size());
956 Mndaxpy(fSize, 1., m.Data(), fData);
957 return *this;
958 }
959
961 {
962 // std::cout<<"LAVector& operator-=(const LAVector& m)"<<std::endl;
963 assert(fSize == m.size());
964 Mndaxpy(fSize, -1., m.Data(), fData);
965 return *this;
966 }
967
968 template <class T>
970 {
971 // std::cout<<"template<class T> LAVector& operator+=(const ABObj<LAVector, T>& m)"<<std::endl;
972 assert(fSize == m.Obj().size());
973 if (m.Obj().Data() == fData) {
974 Mndscal(fSize, 1. + double(m.f()), fData);
975 } else {
976 Mndaxpy(fSize, double(m.f()), m.Obj().Data(), fData);
977 }
978 // std::cout<<"fData= "<<fData[0]<<" "<<fData[1]<<std::endl;
979 return *this;
980 }
981
982 template <class A, class T>
984 {
985 // std::cout<<"template<class A, class T> LAVector& operator+=(const ABObj<A,T>& m)"<<std::endl;
986 (*this) += LAVector(m);
987 return *this;
988 }
989
990 template <class T>
992 {
993 Mndspmv(fSize, prod.f() * prod.Obj().A().f() * prod.Obj().B().f(), prod.Obj().A().Obj().Data(),
994 prod.Obj().B().Data(), 1., fData);
995 return *this;
996 }
997
999 {
1000 Mndscal(fSize, scal, fData);
1001 return *this;
1002 }
1003
1004 double operator()(unsigned int i) const
1005 {
1006 assert(i < fSize);
1007 return fData[i];
1008 }
1009
1010 double &operator()(unsigned int i)
1011 {
1012 assert(i < fSize);
1013 return fData[i];
1014 }
1015
1016 double operator[](unsigned int i) const
1017 {
1018 assert(i < fSize);
1019 return fData[i];
1020 }
1021
1022 double &operator[](unsigned int i)
1023 {
1024 assert(i < fSize);
1025 return fData[i];
1026 }
1027
1028 const double *Data() const { return fData; }
1029
1030 double *Data() { return fData; }
1031
1032 unsigned int size() const { return fSize; }
1033
1034private:
1035 unsigned int fSize = 0;
1036 double *fData = nullptr;
1037
1038public:
1039 template <class T>
1041 {
1042 // std::cout<<"template<class T> LAVector& operator=(ABObj<LAVector, T>& v)"<<std::endl;
1043 if (fSize == 0 && !fData) {
1044 fSize = v.Obj().size();
1045 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
1046 } else {
1047 assert(fSize == v.Obj().size());
1048 }
1049 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(double));
1050 (*this) *= T(v.f());
1051 return *this;
1052 }
1053
1054 template <class A, class T>
1056 {
1057 // std::cout<<"template<class A, class T> LAVector& operator=(const ABObj<ABObj<A, T>, T>&
1058 // something)"<<std::endl;
1059 if (fSize == 0 && !fData) {
1060 (*this) = something.Obj();
1061 } else {
1062 LAVector tmp(something.Obj());
1063 assert(fSize == tmp.size());
1064 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
1065 }
1066 (*this) *= something.f();
1067 return *this;
1068 }
1069
1070 template <class A, class B, class T>
1072 {
1073 if (fSize == 0 && !fData) {
1074 (*this) = sum.Obj().A();
1075 (*this) += sum.Obj().B();
1076 } else {
1077 LAVector tmp(sum.Obj().A());
1078 tmp += sum.Obj().B();
1079 assert(fSize == tmp.size());
1080 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
1081 }
1082 (*this) *= sum.f();
1083 return *this;
1084 }
1085
1086 template <class A, class T>
1088 {
1089 if (fSize == 0 && !fData) {
1090 (*this) = sum.Obj().B();
1091 (*this) += sum.Obj().A();
1092 } else {
1093 LAVector tmp(sum.Obj().A());
1094 tmp += sum.Obj().B();
1095 assert(fSize == tmp.size());
1096 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
1097 }
1098 (*this) *= sum.f();
1099 return *this;
1100 }
1101
1102 //
1103 template <class T>
1105 {
1106 if (fSize == 0 && !fData) {
1107 fSize = prod.Obj().B().Obj().size();
1108 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
1109 Mndspmv(fSize, double(prod.f() * prod.Obj().A().f() * prod.Obj().B().f()), prod.Obj().A().Obj().Data(),
1110 prod.Obj().B().Obj().Data(), 0., fData);
1111 } else {
1112 LAVector tmp(prod.Obj().B());
1113 assert(fSize == tmp.size());
1114 Mndspmv(fSize, double(prod.f() * prod.Obj().A().f()), prod.Obj().A().Obj().Data(), tmp.Data(), 0., fData);
1115 }
1116 return *this;
1117 }
1118
1119 //
1120 template <class T>
1121 LAVector &
1123 vec,
1125 T> &prod)
1126 {
1127 if (fSize == 0 && !fData) {
1128 (*this) = prod.Obj().B();
1129 (*this) += prod.Obj().A();
1130 } else {
1131 // std::cout<<"creating tmp variable"<<std::endl;
1132 LAVector tmp(prod.Obj().B());
1133 tmp += prod.Obj().A();
1134 assert(fSize == tmp.size());
1135 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
1136 }
1137 (*this) *= prod.f();
1138 return *this;
1139 }
1140};
1141
1147
1148template <class V>
1153
1159
1160inline ABObj<vec, LAVector> operator*(double f, const LAVector &obj)
1161{
1162 return {obj, f};
1163}
1164inline ABObj<vec, LAVector> operator/(const LAVector &obj, double f)
1165{
1166 return {obj, 1. / f};
1167}
1169{
1170 return {obj, -1.};
1171}
1172
1173// Matrix-vector product
1179
1180/// LAPACK Algebra functions
1181/// specialize the Invert function for LASymMatrix
1182
1187
1188int Invert(LASymMatrix &);
1189
1191
1192/// LAPACK Algebra function
1193/// specialize the Outer_product function for LAVector;
1194
1199
1200void Outer_prod(LASymMatrix &, const LAVector &, double f = 1.);
1201
1202double inner_product(const LAVector &, const LAVector &);
1203double similarity(const LAVector &, const LASymMatrix &);
1204double sum_of_elements(const LASymMatrix &);
1205LAVector eigenvalues(const LASymMatrix &);
1206
1207std::ostream &operator<<(std::ostream &, const LAVector &);
1208
1209std::ostream &operator<<(std::ostream &, const LASymMatrix &);
1210
1211} // namespace Minuit2
1212
1213} // namespace ROOT
1214
1215#endif // ROOT_Minuit2_MnMatrix
dim_t fSize
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
TTime operator*(const TTime &t1, const TTime &t2)
Definition TTime.h:85
TTime operator/(const TTime &t1, const TTime &t2)
Definition TTime.h:87
TTime operator-(const TTime &t1, const TTime &t2)
Definition TTime.h:83
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
ABObj(const M &obj, T factor=1.)
Definition MnMatrix.h:271
const M & Obj() const
Definition MnMatrix.h:273
const M1 & A() const
Definition MnMatrix.h:360
const M2 & B() const
Definition MnMatrix.h:361
ABProd(const M1 &a, const M2 &b)
Definition MnMatrix.h:358
const M1 & A() const
Definition MnMatrix.h:329
const M2 & B() const
Definition MnMatrix.h:330
ABSum(const M1 &a, const M2 &b)
Definition MnMatrix.h:327
DeleteAssignment & operator=(const DeleteAssignment &)=delete
DeleteAssignment(DeleteAssignment &&)=default
DeleteAssignment(const DeleteAssignment &)=default
DeleteAssignment & operator=(DeleteAssignment &&)=delete
Class describing a symmetric matrix of size n.
Definition MnMatrix.h:438
LASymMatrix(const ABObj< sym, MatrixInverse< sym, ABObj< sym, LASymMatrix, T >, T >, T > &inv)
Definition MnMatrix.h:550
LASymMatrix & operator=(const ABObj< sym, LASymMatrix, T > &v)
Definition MnMatrix.h:694
LASymMatrix & operator-=(const LASymMatrix &m)
Definition MnMatrix.h:600
LASymMatrix(const ABObj< sym, ABSum< ABObj< sym, LASymMatrix, T >, ABObj< sym, A, T > >, T > &sum)
Definition MnMatrix.h:524
double & operator()(unsigned int row, unsigned int col)
Definition MnMatrix.h:668
const double * Data() const
Definition MnMatrix.h:677
unsigned int Ncol() const
Definition MnMatrix.h:685
double operator()(unsigned int row, unsigned int col) const
Definition MnMatrix.h:659
LASymMatrix & operator=(const LASymMatrix &v)
Definition MnMatrix.h:476
LASymMatrix & operator+=(const ABObj< sym, LASymMatrix, T > &m)
Definition MnMatrix.h:609
LASymMatrix(const ABObj< sym, ABSum< ABObj< sym, MatrixInverse< sym, ABObj< sym, LASymMatrix, T >, T >, T >, ABObj< sym, A, T > >, T > &sum)
Definition MnMatrix.h:562
LASymMatrix(const ABObj< sym, ABSum< ABObj< sym, A, T >, ABObj< sym, B, T > >, T > &sum)
Definition MnMatrix.h:514
LASymMatrix(LASymMatrix &&v)
Definition MnMatrix.h:467
LASymMatrix & operator*=(double scal)
Definition MnMatrix.h:653
LASymMatrix & operator+=(const ABObj< sym, A, T > &m)
Definition MnMatrix.h:623
LASymMatrix & operator=(const ABObj< sym, MatrixInverse< sym, ABObj< sym, LASymMatrix, T >, T >, T > &inv)
Definition MnMatrix.h:773
LASymMatrix(unsigned int n)
Definition MnMatrix.h:443
LASymMatrix(const ABObj< sym, LASymMatrix, T > &v)
Definition MnMatrix.h:501
LASymMatrix & operator=(const ABObj< sym, ABSum< ABObj< sym, A, T >, ABObj< sym, B, T > >, T > &sum)
Definition MnMatrix.h:730
LASymMatrix & operator=(LASymMatrix &&v)
Definition MnMatrix.h:491
LASymMatrix(const LASymMatrix &v)
Definition MnMatrix.h:459
unsigned int Nrow() const
Definition MnMatrix.h:683
LASymMatrix(const ABObj< sym, ABObj< sym, A, T >, T > &something)
Definition MnMatrix.h:539
LASymMatrix & operator+=(const ABObj< sym, MatrixInverse< sym, ABObj< sym, LASymMatrix, T >, T >, T > &m)
Definition MnMatrix.h:631
LASymMatrix & operator=(const ABObj< sym, ABSum< ABObj< sym, LASymMatrix, T >, ABObj< sym, A, T > >, T > &sum)
Definition MnMatrix.h:750
LASymMatrix(const ABObj< sym, ABSum< ABObj< sym, VectorOuterProduct< ABObj< vec, LAVector, T >, T >, T >, ABObj< sym, A, T > >, T > &sum)
Definition MnMatrix.h:579
LASymMatrix & operator+=(const LASymMatrix &m)
Definition MnMatrix.h:592
LASymMatrix & operator+=(const ABObj< sym, VectorOuterProduct< ABObj< vec, LAVector, T >, T >, T > &m)
Definition MnMatrix.h:644
unsigned int size() const
Definition MnMatrix.h:681
LASymMatrix & operator=(const ABObj< sym, ABObj< sym, A, T >, T > &something)
Definition MnMatrix.h:711
LAVector & operator=(const ABObj< vec, ABSum< ABObj< vec, A, T >, ABObj< vec, B, T > >, T > &sum)
Definition MnMatrix.h:1071
const double * Data() const
Definition MnMatrix.h:1028
LAVector & operator*=(double scal)
Definition MnMatrix.h:998
unsigned int size() const
Definition MnMatrix.h:1032
double operator[](unsigned int i) const
Definition MnMatrix.h:1016
LAVector(unsigned int n)
Definition MnMatrix.h:832
double operator()(unsigned int i) const
Definition MnMatrix.h:1004
LAVector & operator+=(const LAVector &m)
Definition MnMatrix.h:952
LAVector(const ABObj< vec, ABProd< ABObj< sym, LASymMatrix, T >, ABObj< vec, LAVector, T > >, T > &prod)
Definition MnMatrix.h:928
LAVector(const ABObj< vec, ABObj< vec, A, T >, T > &something)
Definition MnMatrix.h:919
LAVector & operator=(const ABObj< vec, LAVector, T > &v)
Definition MnMatrix.h:1040
LAVector(const ABObj< vec, ABSum< ABObj< vec, A, T >, ABObj< vec, B, T > >, T > &sum)
Definition MnMatrix.h:894
double & operator[](unsigned int i)
Definition MnMatrix.h:1022
LAVector & operator=(const ABObj< vec, ABObj< vec, A, T >, T > &something)
Definition MnMatrix.h:1055
LAVector & operator=(LAVector &&v)
Definition MnMatrix.h:874
LAVector & operator=(const LAVector &v)
Definition MnMatrix.h:859
LAVector(LAVector &&v)
Definition MnMatrix.h:845
LAVector(const ABObj< vec, ABSum< ABObj< vec, LAVector, T >, ABObj< vec, A, T > >, T > &sum)
Definition MnMatrix.h:904
LAVector & operator+=(const ABObj< vec, A, T > &m)
Definition MnMatrix.h:983
LAVector(const ABObj< vec, ABSum< ABObj< vec, ABProd< ABObj< sym, LASymMatrix, T >, ABObj< vec, LAVector, T > >, T >, ABObj< vec, LAVector, T > >, T > &prod)
Definition MnMatrix.h:941
LAVector(const ABObj< vec, LAVector, T > &v)
Definition MnMatrix.h:883
LAVector & operator-=(const LAVector &m)
Definition MnMatrix.h:960
LAVector(std::span< const double > v)
Definition MnMatrix.h:853
LAVector(const LAVector &v)
Definition MnMatrix.h:851
LAVector & operator=(const ABObj< vec, ABSum< ABObj< vec, ABProd< ABObj< sym, LASymMatrix, T >, ABObj< vec, LAVector, T > >, T >, ABObj< vec, LAVector, T > >, T > &prod)
Definition MnMatrix.h:1122
double & operator()(unsigned int i)
Definition MnMatrix.h:1010
LAVector & operator=(const ABObj< vec, ABSum< ABObj< vec, LAVector, T >, ABObj< vec, A, T > >, T > &sum)
Definition MnMatrix.h:1087
LAVector & operator=(const ABObj< vec, ABProd< ABObj< sym, LASymMatrix, T >, ABObj< vec, LAVector, T > >, T > &prod)
Definition MnMatrix.h:1104
LAVector & operator+=(const ABObj< vec, ABProd< ABObj< sym, LASymMatrix, T >, ABObj< vec, LAVector, T > >, T > &prod)
Definition MnMatrix.h:991
LAVector & operator+=(const ABObj< vec, LAVector, T > &m)
Definition MnMatrix.h:969
MatrixInverse(MatrixInverse &&)=delete
MatrixInverse(const MatrixInverse &)=delete
MatrixInverse(const M &obj)
Definition MnMatrix.h:399
const M & Obj() const
Definition MnMatrix.h:401
static StackAllocator & Get()
Definition MnMatrix.h:239
StackAllocator controls the memory allocation/deallocation of Minuit.
Definition MnMatrix.h:60
void WriteInt(int offset, int Value)
Definition MnMatrix.h:157
void * Allocate(size_t nBytes)
Definition MnMatrix.h:87
int AlignedSize(int nBytes)
Definition MnMatrix.h:176
define stack allocator symbol
Definition MnMatrix.h:50
const Int_t n
Definition legend1.C:16
std::ostream & operator<<(std::ostream &os, const RConcurrentHashColl::HashValue &h)
int SetMaxNP(int value)
Definition MnMatrix.cxx:648
ABObj< mt, M, T > operator*(T f, const M &obj)
Definition MnMatrix.h:284
int Invert_undef_sym(LASymMatrix &)
void Mndaxpy(unsigned int, double, const double *, double *)
Definition MnMatrix.cxx:255
int Invert(LASymMatrix &)
Definition MnMatrix.cxx:296
void Mndscal(unsigned int, double, double *)
Definition MnMatrix.cxx:639
ABObj< mt, MatrixInverse< mt, ABObj< mt, M, T >, T >, T > Inverse(const ABObj< mt, M, T > &obj)
Definition MnMatrix.h:416
void Mndspmv(unsigned int, double, const double *, const double *, double, double *)
Definition MnMatrix.cxx:148
ABObj< mt, M, T > operator-(const M &obj)
Definition MnMatrix.h:298
void Outer_prod(LASymMatrix &, const LAVector &, double f=1.)
Definition MnMatrix.cxx:249
ABObj< mt, M, T > operator/(const M &obj, T f)
Definition MnMatrix.h:291
ABObj< atype, ABSum< ABObj< atype, A, T >, ABObj< atype, B, T > >, T > operator+(const ABObj< atype, A, T > &a, const ABObj< atype, B, T > &b)
Definition MnMatrix.h:340
ABObj< sym, VectorOuterProduct< ABObj< vec, M, T >, T >, T > Outer_product(const ABObj< vec, M, T > &obj)
Definition MnMatrix.h:390
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
ELogLevel operator+(ELogLevel severity, int offset)
Definition RLogger.hxx:42
void inv(rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *)
Definition rsaaux.cxx:949
TMarker m
Definition textangle.C:8
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345