Project
Loading...
Searching...
No Matches
Chebyshev3DCalc.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
15
17#include <TSystem.h> // for TSystem, gSystem
18#include "TNamed.h" // for TNamed
19#include "TString.h" // for TString, TString::EStripType::kBoth
20
21using namespace o2::math_utils;
22
24
26 : mNumberOfCoefficients(0),
27 mNumberOfRows(0),
28 mNumberOfColumns(0),
29 mNumberOfElementsBound2D(0),
30 mPrecision(0),
31 mNumberOfColumnsAtRow(nullptr),
32 mColumnAtRowBeginning(nullptr),
33 mCoefficientBound2D0(nullptr),
34 mCoefficientBound2D1(nullptr),
35 mCoefficients(nullptr),
36 mTemporaryCoefficients2D(nullptr),
37 mTemporaryCoefficients1D(nullptr)
38{
39}
40
42 : TNamed(src),
43 mNumberOfCoefficients(src.mNumberOfCoefficients),
44 mNumberOfRows(src.mNumberOfRows),
45 mNumberOfColumns(src.mNumberOfColumns),
46 mNumberOfElementsBound2D(src.mNumberOfElementsBound2D),
47 mPrecision(src.mPrecision),
48 mNumberOfColumnsAtRow(nullptr),
49 mColumnAtRowBeginning(nullptr),
50 mCoefficientBound2D0(nullptr),
51 mCoefficientBound2D1(nullptr),
52 mCoefficients(nullptr),
53 mTemporaryCoefficients2D(nullptr),
54 mTemporaryCoefficients1D(nullptr)
55{
56 if (src.mNumberOfColumnsAtRow) {
57 mNumberOfColumnsAtRow = new UShort_t[mNumberOfRows];
58 for (int i = mNumberOfRows; i--;) {
59 mNumberOfColumnsAtRow[i] = src.mNumberOfColumnsAtRow[i];
60 }
61 }
62 if (src.mColumnAtRowBeginning) {
63 mColumnAtRowBeginning = new UShort_t[mNumberOfRows];
64 for (int i = mNumberOfRows; i--;) {
65 mColumnAtRowBeginning[i] = src.mColumnAtRowBeginning[i];
66 }
67 }
68 if (src.mCoefficientBound2D0) {
69 mCoefficientBound2D0 = new UShort_t[mNumberOfElementsBound2D];
70 for (int i = mNumberOfElementsBound2D; i--;) {
71 mCoefficientBound2D0[i] = src.mCoefficientBound2D0[i];
72 }
73 }
74 if (src.mCoefficientBound2D1) {
75 mCoefficientBound2D1 = new UShort_t[mNumberOfElementsBound2D];
76 for (int i = mNumberOfElementsBound2D; i--;) {
77 mCoefficientBound2D1[i] = src.mCoefficientBound2D1[i];
78 }
79 }
80 if (src.mCoefficients) {
81 mCoefficients = new Float_t[mNumberOfCoefficients];
82 for (int i = mNumberOfCoefficients; i--;) {
83 mCoefficients[i] = src.mCoefficients[i];
84 }
85 }
86 if (src.mTemporaryCoefficients2D) {
87 mTemporaryCoefficients2D = new Float_t[mNumberOfColumns];
88 }
89 if (src.mTemporaryCoefficients1D) {
90 mTemporaryCoefficients1D = new Float_t[mNumberOfRows];
91 }
92}
93
95 : mNumberOfCoefficients(0),
96 mNumberOfRows(0),
97 mNumberOfColumns(0),
98 mNumberOfElementsBound2D(0),
99 mPrecision(0),
100 mNumberOfColumnsAtRow(nullptr),
101 mColumnAtRowBeginning(nullptr),
102 mCoefficientBound2D0(nullptr),
103 mCoefficientBound2D1(nullptr),
104 mCoefficients(nullptr),
105 mTemporaryCoefficients2D(nullptr),
106 mTemporaryCoefficients1D(nullptr)
107{
109}
110
112{
113 if (this != &rhs) {
114 Clear();
115 SetName(rhs.GetName());
116 SetTitle(rhs.GetTitle());
117 mNumberOfCoefficients = rhs.mNumberOfCoefficients;
118 mNumberOfRows = rhs.mNumberOfRows;
119 mNumberOfColumns = rhs.mNumberOfColumns;
120 mPrecision = rhs.mPrecision;
121 if (rhs.mNumberOfColumnsAtRow) {
122 mNumberOfColumnsAtRow = new UShort_t[mNumberOfRows];
123 for (int i = mNumberOfRows; i--;) {
124 mNumberOfColumnsAtRow[i] = rhs.mNumberOfColumnsAtRow[i];
125 }
126 }
127 if (rhs.mColumnAtRowBeginning) {
128 mColumnAtRowBeginning = new UShort_t[mNumberOfRows];
129 for (int i = mNumberOfRows; i--;) {
130 mColumnAtRowBeginning[i] = rhs.mColumnAtRowBeginning[i];
131 }
132 }
133 if (rhs.mCoefficientBound2D0) {
134 mCoefficientBound2D0 = new UShort_t[mNumberOfElementsBound2D];
135 for (int i = mNumberOfElementsBound2D; i--;) {
136 mCoefficientBound2D0[i] = rhs.mCoefficientBound2D0[i];
137 }
138 }
139 if (rhs.mCoefficientBound2D1) {
140 mCoefficientBound2D1 = new UShort_t[mNumberOfElementsBound2D];
141 for (int i = mNumberOfElementsBound2D; i--;) {
142 mCoefficientBound2D1[i] = rhs.mCoefficientBound2D1[i];
143 }
144 }
145 if (rhs.mCoefficients) {
146 mCoefficients = new Float_t[mNumberOfCoefficients];
147 for (int i = mNumberOfCoefficients; i--;) {
148 mCoefficients[i] = rhs.mCoefficients[i];
149 }
150 }
151 if (rhs.mTemporaryCoefficients2D) {
152 mTemporaryCoefficients2D = new Float_t[mNumberOfColumns];
153 }
154 if (rhs.mTemporaryCoefficients1D) {
155 mTemporaryCoefficients1D = new Float_t[mNumberOfRows];
156 }
157 }
158 return *this;
159}
160
161void Chebyshev3DCalc::Clear(const Option_t*)
162{
163 if (mTemporaryCoefficients2D) {
164 delete[] mTemporaryCoefficients2D;
165 mTemporaryCoefficients2D = nullptr;
166 }
167 if (mTemporaryCoefficients1D) {
168 delete[] mTemporaryCoefficients1D;
169 mTemporaryCoefficients1D = nullptr;
170 }
171 if (mCoefficients) {
172 delete[] mCoefficients;
173 mCoefficients = nullptr;
174 }
175 if (mCoefficientBound2D0) {
176 delete[] mCoefficientBound2D0;
177 mCoefficientBound2D0 = nullptr;
178 }
179 if (mCoefficientBound2D1) {
180 delete[] mCoefficientBound2D1;
181 mCoefficientBound2D1 = nullptr;
182 }
183 if (mNumberOfColumnsAtRow) {
184 delete[] mNumberOfColumnsAtRow;
185 mNumberOfColumnsAtRow = nullptr;
186 }
187 if (mColumnAtRowBeginning) {
188 delete[] mColumnAtRowBeginning;
189 mColumnAtRowBeginning = nullptr;
190 }
191}
192
193void Chebyshev3DCalc::Print(const Option_t*) const
194{
195 printf("Chebyshev parameterization data %s for 3D->1 function, precision: %e\n",
196 GetName(), mPrecision);
197 int nmax3d = 0;
198 for (int i = mNumberOfElementsBound2D; i--;) {
199 if (mCoefficientBound2D0[i] > nmax3d) {
200 nmax3d = mCoefficientBound2D0[i];
201 }
202 }
203 printf("%d coefficients in %dx%dx%d matrix\n", mNumberOfCoefficients, mNumberOfRows, mNumberOfColumns, nmax3d);
204}
205
207{
208 int ncfRC;
209 for (int id0 = mNumberOfRows; id0--;) {
210 int nCLoc = mNumberOfColumnsAtRow[id0]; // number of significant coefs on this row
211 if (!nCLoc) {
212 mTemporaryCoefficients1D[id0] = 0;
213 continue;
214 }
215 //
216 int col0 = mColumnAtRowBeginning[id0]; // beginning of local column in the 2D boundary matrix
217 for (int id1 = nCLoc; id1--;) {
218 int id = id1 + col0;
219 if (!(ncfRC = mCoefficientBound2D0[id])) {
220 mTemporaryCoefficients2D[id1] = 0;
221 continue;
222 }
223 if (dim == 2) {
224 mTemporaryCoefficients2D[id1] =
225 chebyshevEvaluation1Derivative(par[2], mCoefficients + mCoefficientBound2D1[id], ncfRC);
226 } else {
227 mTemporaryCoefficients2D[id1] = chebyshevEvaluation1D(par[2], mCoefficients + mCoefficientBound2D1[id], ncfRC);
228 }
229 }
230 if (dim == 1) {
231 mTemporaryCoefficients1D[id0] = chebyshevEvaluation1Derivative(par[1], mTemporaryCoefficients2D, nCLoc);
232 } else {
233 mTemporaryCoefficients1D[id0] = chebyshevEvaluation1D(par[1], mTemporaryCoefficients2D, nCLoc);
234 }
235 }
236 return (dim == 0) ? chebyshevEvaluation1Derivative(par[0], mTemporaryCoefficients1D, mNumberOfRows)
237 : chebyshevEvaluation1D(par[0], mTemporaryCoefficients1D, mNumberOfRows);
238}
239
240Float_t Chebyshev3DCalc::evaluateDerivative2(int dim1, int dim2, const Float_t* par) const
241{
242 Bool_t same = dim1 == dim2;
243 int ncfRC;
244 for (int id0 = mNumberOfRows; id0--;) {
245 int nCLoc = mNumberOfColumnsAtRow[id0]; // number of significant coefs on this row
246 if (!nCLoc) {
247 mTemporaryCoefficients1D[id0] = 0;
248 continue;
249 }
250 int col0 = mColumnAtRowBeginning[id0]; // beginning of local column in the 2D boundary matrix
251 for (int id1 = nCLoc; id1--;) {
252 int id = id1 + col0;
253 if (!(ncfRC = mCoefficientBound2D0[id])) {
254 mTemporaryCoefficients2D[id1] = 0;
255 continue;
256 }
257 if (dim1 == 2 || dim2 == 2) {
258 mTemporaryCoefficients2D[id1] =
259 same ? chebyshevEvaluation1Derivative2(par[2], mCoefficients + mCoefficientBound2D1[id], ncfRC)
260 : chebyshevEvaluation1Derivative(par[2], mCoefficients + mCoefficientBound2D1[id], ncfRC);
261 } else {
262 mTemporaryCoefficients2D[id1] = chebyshevEvaluation1D(par[2], mCoefficients + mCoefficientBound2D1[id], ncfRC);
263 }
264 }
265 if (dim1 == 1 || dim2 == 1) {
266 mTemporaryCoefficients1D[id0] = same ? chebyshevEvaluation1Derivative2(par[1], mTemporaryCoefficients2D, nCLoc)
267 : chebyshevEvaluation1Derivative(par[1], mTemporaryCoefficients2D, nCLoc);
268 } else {
269 mTemporaryCoefficients1D[id0] = chebyshevEvaluation1D(par[1], mTemporaryCoefficients2D, nCLoc);
270 }
271 }
272 return (dim1 == 0 || dim2 == 0)
273 ? (same ? chebyshevEvaluation1Derivative2(par[0], mTemporaryCoefficients1D, mNumberOfRows)
274 : chebyshevEvaluation1Derivative(par[0], mTemporaryCoefficients1D, mNumberOfRows))
275 : chebyshevEvaluation1D(par[0], mTemporaryCoefficients1D, mNumberOfRows);
276}
277
278#ifdef _INC_CREATION_Chebyshev3D_
279void Chebyshev3DCalc::saveData(const char* outfile, Bool_t append) const
280{
281 TString strf = outfile;
282 gSystem->ExpandPathName(strf);
283 FILE* stream = fopen(strf, append ? "a" : "w");
285 fclose(stream);
286}
287#endif
288
289#ifdef _INC_CREATION_Chebyshev3D_
290void Chebyshev3DCalc::saveData(FILE* stream) const
291{
292 fprintf(stream, "#\nSTART %s\n", GetName());
293 fprintf(stream, "# Number of rows\n%d\n", mNumberOfRows);
294
295 fprintf(stream, "# Number of columns per row\n");
296 for (int i = 0; i < mNumberOfRows; i++) {
297 fprintf(stream, "%d\n", mNumberOfColumnsAtRow[i]);
298 }
299
300 fprintf(stream, "# Number of Coefs in each significant block of third dimension\n");
301 for (int i = 0; i < mNumberOfElementsBound2D; i++) {
302 fprintf(stream, "%d\n", mCoefficientBound2D0[i]);
303 }
304
305 fprintf(stream, "# Coefficients\n");
306 for (int i = 0; i < mNumberOfCoefficients; i++) {
307 fprintf(stream, "%+.8e\n", mCoefficients[i]);
308 }
309 fprintf(stream, "# Precision\n");
310 fprintf(stream, "%+.8e\n", mPrecision);
311 //
312 fprintf(stream, "END %s\n", GetName());
313}
314#endif
315
317{
318 if (!stream) {
319 Error("LoadData", "No stream provided.\nStop");
320 exit(1);
321 }
322 TString buffs;
323 Clear();
324 readLine(buffs, stream);
325
326 if (!buffs.BeginsWith("START")) {
327 Error("LoadData", "Expected: \"START <fit_name>\", found \"%s\"\nStop\n", buffs.Data());
328 exit(1);
329 }
330
331 if (buffs.First(' ') > 0) {
332 SetName(buffs.Data() + buffs.First(' ') + 1);
333 }
334
335 readLine(buffs, stream); // NRows
336 mNumberOfRows = buffs.Atoi();
337
338 if (mNumberOfRows < 0 || !buffs.IsDigit()) {
339 Error("LoadData", "Expected: '<number_of_rows>', found \"%s\"\nStop\n", buffs.Data());
340 exit(1);
341 }
342
343 mNumberOfColumns = 0;
344 mNumberOfElementsBound2D = 0;
345 initializeRows(mNumberOfRows);
346
347 for (int id0 = 0; id0 < mNumberOfRows; id0++) {
348 readLine(buffs, stream); // n.cols at this row
349 mNumberOfColumnsAtRow[id0] = buffs.Atoi();
350 mColumnAtRowBeginning[id0] = mNumberOfElementsBound2D; // begining of this row in 2D boundary surface
351 mNumberOfElementsBound2D += mNumberOfColumnsAtRow[id0];
352 if (mNumberOfColumns < mNumberOfColumnsAtRow[id0]) {
353 mNumberOfColumns = mNumberOfColumnsAtRow[id0];
354 }
355 }
356 initializeColumns(mNumberOfColumns);
357
358 mNumberOfCoefficients = 0;
359 initializeElementBound2D(mNumberOfElementsBound2D);
360
361 for (int i = 0; i < mNumberOfElementsBound2D; i++) {
362 readLine(buffs, stream); // n.coeffs at 3-d dimension for the given column/row
363 mCoefficientBound2D0[i] = buffs.Atoi();
364 mCoefficientBound2D1[i] = mNumberOfCoefficients;
365 mNumberOfCoefficients += mCoefficientBound2D0[i];
366 }
367
368 initializeCoefficients(mNumberOfCoefficients);
369 for (int i = 0; i < mNumberOfCoefficients; i++) {
370 readLine(buffs, stream);
371 mCoefficients[i] = buffs.Atof();
372 }
373 // read precision
374 readLine(buffs, stream);
375 mPrecision = buffs.Atof();
376
377 // check end_of_data record
378 readLine(buffs, stream);
379 if (!buffs.BeginsWith("END") || !buffs.Contains(GetName())) {
380 Error("LoadData", "Expected \"END %s\", found \"%s\".\nStop\n", GetName(), buffs.Data());
381 exit(1);
382 }
383}
384
386{
387 while (str.Gets(stream)) {
388 str = str.Strip(TString::kBoth, ' ');
389 if (str.IsNull() || str.BeginsWith("#")) {
390 continue;
391 }
392 return;
393 }
394 fprintf(stderr, "Chebyshev3D::readLine: Failed to read from stream.\nStop");
395 exit(1); // normally, should not reach here
396}
397
399{
400 if (mNumberOfColumnsAtRow) {
401 delete[] mNumberOfColumnsAtRow;
402 mNumberOfColumnsAtRow = nullptr;
403 }
404 if (mColumnAtRowBeginning) {
405 delete[] mColumnAtRowBeginning;
406 mColumnAtRowBeginning = nullptr;
407 }
408 if (mTemporaryCoefficients1D) {
409 delete[] mTemporaryCoefficients1D;
410 mTemporaryCoefficients1D = nullptr;
411 }
412 mNumberOfRows = nr;
413 if (mNumberOfRows) {
414 mNumberOfColumnsAtRow = new UShort_t[mNumberOfRows];
415 mTemporaryCoefficients1D = new Float_t[mNumberOfRows];
416 mColumnAtRowBeginning = new UShort_t[mNumberOfRows];
417 for (int i = mNumberOfRows; i--;) {
418 mNumberOfColumnsAtRow[i] = mColumnAtRowBeginning[i] = 0;
419 }
420 }
421}
422
424{
425 mNumberOfColumns = nc;
426 if (mTemporaryCoefficients2D) {
427 delete[] mTemporaryCoefficients2D;
428 mTemporaryCoefficients2D = nullptr;
429 }
430 if (mNumberOfColumns) {
431 mTemporaryCoefficients2D = new Float_t[mNumberOfColumns];
432 }
433}
434
436{
437 if (mCoefficientBound2D0) {
438 delete[] mCoefficientBound2D0;
439 mCoefficientBound2D0 = nullptr;
440 }
441 if (mCoefficientBound2D1) {
442 delete[] mCoefficientBound2D1;
443 mCoefficientBound2D1 = nullptr;
444 }
445 mNumberOfElementsBound2D = ne;
446 if (mNumberOfElementsBound2D) {
447 mCoefficientBound2D0 = new UShort_t[mNumberOfElementsBound2D];
448 mCoefficientBound2D1 = new UShort_t[mNumberOfElementsBound2D];
449 for (int i = mNumberOfElementsBound2D; i--;) {
450 mCoefficientBound2D0[i] = mCoefficientBound2D1[i] = 0;
451 }
452 }
453}
454
456{
457 if (mCoefficients) {
458 delete[] mCoefficients;
459 mCoefficients = nullptr;
460 }
461 mNumberOfCoefficients = nc;
462 if (mNumberOfCoefficients) {
463 mCoefficients = new Float_t[mNumberOfCoefficients];
464 for (int i = mNumberOfCoefficients; i--;) {
465 mCoefficients[i] = 0.0;
466 }
467 }
468}
469
471{
472 if (--ncf < 1) {
473 return 0;
474 }
475 Float_t b0, b1, b2;
476 Float_t x2 = x + x;
477 b1 = b2 = 0;
478 float dcf0 = 0, dcf1, dcf2 = 0;
479 b0 = dcf1 = 2 * ncf * array[ncf];
480 if (!(--ncf)) {
481 return b0 / 2;
482 }
483
484 for (int i = ncf; i--;) {
485 b2 = b1;
486 b1 = b0;
487 dcf0 = dcf2 + 2 * (i + 1) * array[i + 1];
488 b0 = dcf0 + x2 * b1 - b2;
489 dcf2 = dcf1;
490 dcf1 = dcf0;
491 }
492
493 return b0 - x * b1 - dcf0 / 2;
494}
495
497{
498 if (--ncf < 2) {
499 return 0;
500 }
501 Float_t b0, b1, b2;
502 Float_t x2 = x + x;
503 b1 = b2 = 0;
504 float dcf0 = 0, dcf1 = 0, dcf2 = 0;
505 float ddcf0 = 0, ddcf1, ddcf2 = 0;
506
507 dcf2 = 2 * ncf * array[ncf];
508 --ncf;
509
510 dcf1 = 2 * ncf * array[ncf];
511 b0 = ddcf1 = 2 * ncf * dcf2;
512
513 if (!(--ncf)) {
514 return b0 / 2;
515 }
516
517 for (int i = ncf; i--;) {
518 b2 = b1;
519 b1 = b0;
520 dcf0 = dcf2 + 2 * (i + 1) * array[i + 1];
521 ddcf0 = ddcf2 + 2 * (i + 1) * dcf1;
522 b0 = ddcf0 + x2 * b1 - b2;
523
524 ddcf2 = ddcf1;
525 ddcf1 = ddcf0;
526
527 dcf2 = dcf1;
528 dcf1 = dcf0;
529 }
530 return b0 - x * b1 - ddcf0 / 2;
531}
532
534{
535 int nmax3d = 0;
536 for (int i = mNumberOfElementsBound2D; i--;) {
537 if (mCoefficientBound2D0[i] > nmax3d) {
538 nmax3d = mCoefficientBound2D0[i];
539 }
540 }
541 return nmax3d;
542}
ClassImp(Chebyshev3DCalc)
int32_t i
const GPUTPCGMMerger::trackCluster & b1
void Print(const Option_t *opt="") const override
Prints info.
static Float_t chebyshevEvaluation1Derivative2(Float_t x, const Float_t *array, int ncf)
Evaluates 1D Chebyshev parameterization's 2nd derivative. x is the argument mapped to [-1:1] interval...
void Clear(const Option_t *option="") override
Deletes all dynamically allocated structures.
Chebyshev3DCalc & operator=(const Chebyshev3DCalc &rhs)
Assignment operator.
Float_t evaluateDerivative(int dim, const Float_t *par) const
void saveData(const char *outfile, Bool_t append=kFALSE) const
Writes coefficients data to output text file, optionally appending on the end of existing file.
static Float_t chebyshevEvaluation1D(Float_t x, const Float_t *array, int ncf)
Evaluates 1D Chebyshev parameterization. x is the argument mapped to [-1:1] interval.
void loadData(FILE *stream)
Loads coefficients from the stream.
Float_t evaluateDerivative2(int dim1, int dim2, const Float_t *par) const
static Float_t chebyshevEvaluation1Derivative(Float_t x, const Float_t *array, int ncf)
Evaluates 1D Chebyshev parameterization's derivative. x is the argument mapped to [-1:1] interval.
void initializeElementBound2D(int ne)
Sets maximum number of significant coefficients for given row/column of coefficients 3D matrix.
static void readLine(TString &str, FILE *stream)
Reads single line from the stream, skipping empty and commented lines. EOF is not expected.
void initializeRows(int nr)
Sets maximum number of significant rows in the coefficients matrix.
void initializeCoefficients(int nc)
Sets total number of significant coefficients.
Chebyshev3DCalc()
Default constructor.
void initializeColumns(int nc)
Sets maximum number of significant columns in the coefficients matrix.
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum src
Definition glcorearb.h:1767
GLenum array
Definition glcorearb.h:4274
GLuint GLuint stream
Definition glcorearb.h:1806
const std::string str