Project
Loading...
Searching...
No Matches
SymBDMatrix.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <iostream>
15
16#include "TClass.h"
17#include "TMath.h"
19
20using namespace o2::fwdalign;
21
23
24//___________________________________________________________
26 : fElems(nullptr)
27{
28 fSymmetric = kTRUE;
29}
30
31//___________________________________________________________
33 : MatrixSq(), fElems(nullptr)
34{
35 fNcols = size; // number of rows
36 if (w < 0) {
37 w = 0;
38 }
39 if (w >= size) {
40 w = size - 1;
41 }
42 fNrows = w;
43 fRowLwb = w + 1;
44 fSymmetric = kTRUE;
45
46 // total number of stored elements
47 fNelems = size * (w + 1) - w * (w + 1) / 2;
48
49 fElems = new Double_t[fNcols * fRowLwb];
50 memset(fElems, 0, fNcols * fRowLwb * sizeof(Double_t));
51}
52
53//___________________________________________________________
55 : MatrixSq(src), fElems(nullptr)
56{
57 if (src.GetSize() < 1) {
58 return;
59 }
60 fNcols = src.GetSize();
61 fNrows = src.GetBandHWidth();
62 fRowLwb = fNrows + 1;
63 fNelems = src.GetNElemsStored();
64 fElems = new Double_t[fNcols * fRowLwb];
65 memcpy(fElems, src.fElems, fNcols * fRowLwb * sizeof(Double_t));
66}
67
68//___________________________________________________________
73
74//___________________________________________________________
76{
77 if (this != &src) {
78 TObject::operator=(src);
79 if (fNcols != src.fNcols) {
80 // recreate the matrix
81 if (fElems) {
82 delete[] fElems;
83 }
84 fNcols = src.GetSize();
85 fNrows = src.GetBandHWidth();
86 fNelems = src.GetNElemsStored();
87 fRowLwb = src.fRowLwb;
88 fElems = new Double_t[fNcols * fRowLwb];
89 }
90 memcpy(fElems, src.fElems, fNcols * fRowLwb * sizeof(Double_t));
91 fSymmetric = kTRUE;
92 }
93 return *this;
94}
95
96//___________________________________________________________
97void SymBDMatrix::Clear(Option_t*)
98{
99 if (fElems) {
100 delete[] fElems;
101 fElems = nullptr;
102 }
103 fNelems = fNcols = fNrows = fRowLwb = 0;
104}
105
106//___________________________________________________________
108{
109 if (!fNelems) {
110 return 0;
111 }
112 Int_t nel = 0;
113 for (int i = fNelems; i--;) {
114 if (!IsZero(fElems[i])) {
115 nel++;
116 }
117 }
118 return nel / fNelems;
119}
120
121//___________________________________________________________
122void SymBDMatrix::Print(Option_t* option) const
123{
124 printf("Symmetric Band-Diagonal Matrix : Size = %d, half bandwidth = %d\n",
126 TString opt = option;
127 opt.ToLower();
128 if (opt.IsNull()) {
129 return;
130 }
131 opt = "%";
132 opt += 1 + int(TMath::Log10(double(GetSize())));
133 opt += "d|";
134 for (Int_t i = 0; i < GetSize(); i++) {
135 printf(opt, i);
136 for (Int_t j = TMath::Max(0, i - GetBandHWidth()); j <= i; j++) {
137 printf("%+.3e|", GetEl(i, j));
138 }
139 printf("\n");
140 }
141}
142
143//___________________________________________________________
144void SymBDMatrix::MultiplyByVec(const Double_t* vecIn, Double_t* vecOut) const
145{
146 if (IsDecomposed()) {
147 for (int i = 0; i < GetSize(); i++) {
148 double sm = 0;
149 int jmax = TMath::Min(GetSize(), i + fRowLwb);
150 for (int j = i + 1; j < jmax; j++) {
151 sm += vecIn[j] * Query(j, i);
152 }
153 vecOut[i] = QueryDiag(i) * (vecIn[i] + sm);
154 }
155 for (int i = GetSize(); i--;) {
156 double sm = 0;
157 int jmin = TMath::Max(0, i - GetBandHWidth());
158 int jmax = i - 1;
159 for (int j = jmin; j < jmax; j++) {
160 sm += vecOut[j] * Query(i, j);
161 }
162 vecOut[i] += sm;
163 }
164 } else { // not decomposed
165 for (int i = GetSize(); i--;) {
166 vecOut[i] = 0.0;
167 int jmin = TMath::Max(0, i - GetBandHWidth());
168 int jmax = TMath::Min(GetSize(), i + fRowLwb);
169 for (int j = jmin; j < jmax; j++) {
170 vecOut[i] += vecIn[j] * Query(i, j);
171 }
172 }
173 }
174}
175
176//___________________________________________________________
178{
179 if (fElems) {
180 memset(fElems, 0, fNcols * fRowLwb * sizeof(Double_t));
181 }
182 SetDecomposed(kFALSE);
183}
184
185//___________________________________________________________
186void SymBDMatrix::AddToRow(Int_t r, Double_t* valc, Int_t* indc, Int_t n)
187{
188 for (int i = 0; i < n; i++) {
189 (*this)(r, indc[i]) = valc[i];
190 }
191}
192
193//___________________________________________________________
195{
196 if (IsDecomposed()) {
197 return;
198 }
199
200 Double_t eps = std::numeric_limits<double>::epsilon() * std::numeric_limits<double>::epsilon();
201
202 Double_t dtmp, gamma = 0.0, xi = 0.0;
203 int iDiag;
204
205 // find max diag and number of non-0 diag.elements
206 for (dtmp = 0.0, iDiag = 0; iDiag < GetSize(); iDiag++) {
207 if ((dtmp = QueryDiag(iDiag)) <= 0.0) {
208 break;
209 }
210 if (gamma < dtmp) {
211 gamma = dtmp;
212 }
213 }
214
215 // find max. off-diag element
216 for (int ir = 1; ir < iDiag; ir++) {
217 for (int ic = ir - GetBandHWidth(); ic < ir; ic++) {
218 if (ic < 0) {
219 continue;
220 }
221 dtmp = TMath::Abs(Query(ir, ic));
222 if (xi < dtmp) {
223 xi = dtmp;
224 }
225 }
226 }
227 double delta = eps * TMath::Max(1.0, xi + gamma);
228
229 double sn = GetSize() > 1 ? 1.0 / TMath::Sqrt(GetSize() * GetSize() - 1.0) : 1.0;
230 double beta = TMath::Sqrt(TMath::Max(eps, TMath::Max(gamma, xi * sn)));
231
232 for (int kr = 1; kr < GetSize(); kr++) {
233 int colKmin = TMath::Max(0, kr - GetBandHWidth());
234 double theta = 0.0;
235
236 for (int jr = colKmin; jr <= kr; jr++) {
237 int colJmin = TMath::Max(0, jr - GetBandHWidth());
238
239 dtmp = 0.0;
240 for (int i = TMath::Max(colKmin, colJmin); i < jr; i++) {
241 dtmp += Query(kr, i) * QueryDiag(i) * Query(jr, i);
242 }
243 dtmp = (*this)(kr, jr) -= dtmp;
244
245 theta = TMath::Max(theta, TMath::Abs(dtmp));
246
247 if (jr != kr) {
248 if (!IsZero(QueryDiag(jr))) {
249 (*this)(kr, jr) /= QueryDiag(jr);
250 } else {
251 (*this)(kr, jr) = 0.0;
252 }
253 } else if (kr < iDiag) {
254 dtmp = theta / beta;
255 dtmp *= dtmp;
256 dtmp = TMath::Max(dtmp, delta);
257 (*this)(kr, jr) = TMath::Max(TMath::Abs(Query(kr, jr)), dtmp);
258 }
259 } // jr
260 } // kr
261
262 for (int i = 0; i < GetSize(); i++) {
263 dtmp = QueryDiag(i);
264 if (!IsZero(dtmp)) {
265 DiagElem(i) = 1. / dtmp;
266 }
267 }
268
270}
271
272//___________________________________________________________
273void SymBDMatrix::Solve(Double_t* rhs)
274{
275 if (!IsDecomposed()) {
277 }
278
279 for (int kr = 0; kr < GetSize(); kr++) {
280 for (int jr = TMath::Max(0, kr - GetBandHWidth()); jr < kr; jr++) {
281 rhs[kr] -= Query(kr, jr) * rhs[jr];
282 }
283 }
284
285 for (int kr = GetSize(); kr--;) {
286 rhs[kr] *= QueryDiag(kr);
287 }
288
289 for (int kr = GetSize(); kr--;) {
290 for (int jr = TMath::Max(0, kr - GetBandHWidth()); jr < kr; jr++) {
291 rhs[jr] -= Query(kr, jr) * rhs[kr];
292 }
293 }
294}
295
296//___________________________________________________________
297void SymBDMatrix::Solve(const Double_t* rhs, Double_t* sol)
298{
299 memcpy(sol, rhs, GetSize() * sizeof(Double_t));
300 Solve(sol);
301}
int32_t i
uint32_t j
Definition RawData.h:0
ClassImp(SymBDMatrix)
Symmetric Band Diagonal matrix (from AliROOT) with half band width W (+1 for diagonal)
static Bool_t IsZero(Double_t x, Double_t thresh=1e-64)
Definition MatrixSq.h:134
virtual Int_t GetSize() const
Definition MatrixSq.h:39
virtual Double_t Query(Int_t rown, Int_t coln) const
Definition MatrixSq.h:44
Bool_t fSymmetric
is the matrix symmetric? Only lower triangle is filled
Definition MatrixSq.h:145
virtual Double_t QueryDiag(Int_t rc) const
Definition MatrixSq.h:48
Symmetric Matrix Class.
Definition SymBDMatrix.h:33
Double_t DiagElem(Int_t r) const override
Definition SymBDMatrix.h:70
Float_t GetDensity() const override
get fraction of non-zero elements
void Print(Option_t *option="") const override
print data
Int_t GetBandHWidth() const
Definition SymBDMatrix.h:50
void Solve(Double_t *rhs)
solve matrix equation
void MultiplyByVec(const Double_t *vecIn, Double_t *vecOut) const override
fill vecOut by matrix*vecIn
Double_t * fElems
Elements booked by constructor.
void SetDecomposed(Bool_t v=kTRUE)
Definition SymBDMatrix.h:88
void Reset() override
set all elems to 0
void Clear(Option_t *option="") override
clear dynamic part
void DecomposeLDLT()
decomposition to L Diag L^T
void AddToRow(Int_t r, Double_t *valc, Int_t *indc, Int_t n) override
add list of elements to row r
~SymBDMatrix() override
d-tor
SymBDMatrix & operator=(const SymBDMatrix &src)
assignment operator
Double_t GetEl(Int_t row, Int_t col) const
Bool_t IsDecomposed() const
Definition SymBDMatrix.h:89
GLdouble n
Definition glcorearb.h:1982
GLenum src
Definition glcorearb.h:1767
GLsizeiptr size
Definition glcorearb.h:659
GLboolean r
Definition glcorearb.h:1233
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
o2::InteractionRecord ir(0, 0)