Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 :
16 :
17 : #include "AliCheb2DStack.h"
18 : #include "AliLog.h"
19 : #include <TMath.h>
20 :
21 176 : ClassImp(AliCheb2DStack)
22 :
23 : float AliCheb2DStack::fgkDefPrec = 1e-4;
24 : float AliCheb2DStack::fWSpace[AliCheb2DStack::kMaxPoints] = {0};
25 : //____________________________________________________________________
26 0 : AliCheb2DStack::AliCheb2DStack()
27 0 : :fDimOut(0)
28 0 : ,fNSlices(0)
29 0 : ,fNParams(0)
30 0 : ,fNCoefsTot(0)
31 0 : ,fNRowsTot(0)
32 0 : ,fRowXI(0)
33 0 : ,fNRows(0)
34 0 : ,fNCols(0)
35 0 : ,fCoeffsEntry(0)
36 0 : ,fColEntry(0)
37 0 : {
38 : // Default constructor
39 0 : for (int i=2;i--;) fBMin[i] = fBMax[i] = 0;
40 0 : fBScaleZ = fBOffsetZ = 0;
41 0 : fDead[0] = fDead[1] = 0;
42 0 : }
43 :
44 : //____________________________________________________________________
45 0 : AliCheb2DStack::AliCheb2DStack(int nSlices, int dimOut, const float bmin[2],const float bmax[2],
46 : const float* dead, const float *rowXI)
47 0 : :fDimOut(dimOut)
48 0 : ,fNSlices(nSlices)
49 0 : ,fNParams(nSlices*dimOut)
50 0 : ,fNCoefsTot(0)
51 0 : ,fNRowsTot(0)
52 0 : ,fRowXI(rowXI)
53 0 : ,fNRows(new UChar_t[nSlices*dimOut])
54 0 : ,fNCols(0)
55 0 : ,fCoeffsEntry(new Int_t[nSlices])
56 0 : ,fColEntry(new Int_t[nSlices])
57 0 : {
58 : // create stack of 2D->dimOut Chebyshev parameterizations debined in 2 dimensions between bmin and bmax,
59 : // and trained with function fun on 2D grid on np points.
60 : // Truncate each precision of each output dimension parameterization i to precD[i] if precD!=0, or prec
61 0 : for (int i=2;i--;) {
62 0 : fBMin[i] = bmin[i];
63 0 : fBMax[i] = bmax[i];
64 : }
65 0 : fBScaleZ = 2./(fBMax[1] - fBMin[1]); // prepare mapping of boundaries to [-1:1]
66 0 : fBOffsetZ = fBMin[1] + 1./fBScaleZ;
67 :
68 0 : if (dead) {
69 0 : fDead[0] = dead[0];
70 0 : fDead[1] = dead[1];
71 0 : if (!rowXI) AliError("Dead zones will be ignored since the inverse radii are not provided");
72 : }
73 0 : }
74 :
75 : //____________________________________________________________________
76 : AliCheb2DStack::~AliCheb2DStack()
77 0 : {
78 : // D-tor
79 0 : delete[] fNRows;
80 0 : delete[] fNCols;
81 0 : delete[] fCoeffsEntry;
82 0 : delete[] fColEntry;
83 0 : }
84 :
85 : //____________________________________________________________________
86 : void AliCheb2DStack::CheckDimensions(const int *np) const
87 : {
88 : // basic consistency check
89 0 : if (fDimOut>=kMaxPoints) AliFatalF("N output dimensions=%d > %d",fDimOut,kMaxPoints);
90 0 : for (int id=fDimOut;id--;) {
91 0 : for (int i=2;i--;) {
92 0 : if (np[id*2+i]<1) AliFatalF("N points=%d in input dim. %d is <1 for output dim.%d",
93 : np[id*2+i],i,id);
94 0 : if (np[id*2+i]<1) AliFatalF("N points=%d in input dim. %d is >%d for output dim.%d",
95 : np[id*2+i],i,kMaxPoints,id);
96 : }
97 : }
98 : //
99 0 : for (int i=2;i--;)
100 0 : if (fBMin[i]>=fBMax[i]) AliFatalF("Boundaries for %d-th dim. are not"
101 : " increasing: %+.4e %+.4e",i,fBMin[i],fBMax[i]);
102 : //
103 0 : }
104 :
105 : //____________________________________________________________________
106 : float* AliCheb2DStack::DefineGrid(int slice, int dim, const int np[2]) const
107 : {
108 : // prepare the grid of Chebyshev roots for dim-th output dimension
109 : // First np[1] nodes of 2nd input dimesion are stored, then np[0] nodes for 1st dim.
110 : const int kMinPoints = 1;
111 0 : float *grid = new float[np[0]+np[1]];
112 : int cnt=0;
113 0 : for (int id=2;id--;) {
114 0 : int npnt = np[id];
115 0 : for (int ip=0;ip<npnt;ip++) {
116 0 : float x = TMath::Cos( TMath::Pi()*(ip+0.5)/npnt );
117 0 : grid[cnt++] = MapToExternal(slice,x,id);
118 : }
119 : }
120 : //
121 0 : return grid;
122 : }
123 :
124 : //____________________________________________________________________
125 : Int_t AliCheb2DStack::CalcChebCoefs(const float *funval,int np, float *outCoefs, float prec)
126 : {
127 : // Calculate Chebyshev coeffs using precomputed function values at np roots.
128 : // If prec>0, estimate the highest coeff number providing the needed precision
129 : //
130 : double sm; // do summations in double to minimize the roundoff error
131 0 : for (int ic=0;ic<np;ic++) { // compute coeffs
132 : sm = 0;
133 0 : for (int ir=0;ir<np;ir++) sm += funval[ir]*TMath::Cos( ic*(ir+0.5)*TMath::Pi()/np);
134 0 : outCoefs[ic] = float( sm * ((ic==0) ? 1./np : 2./np) );
135 : }
136 0 : if (prec<=0) return np;
137 : //
138 : sm = 0;
139 : int cfMax = 0;
140 0 : for (cfMax=np;cfMax--;) {
141 0 : sm += TMath::Abs(outCoefs[cfMax]);
142 0 : if (sm>=prec) break;
143 : }
144 0 : if (++cfMax==0) cfMax=1;
145 : return cfMax;
146 : //
147 0 : }
148 :
149 : //__________________________________________________________________________________________
150 : void AliCheb2DStack::Print(const Option_t* opt) const
151 : {
152 : // print full info
153 : //
154 0 : printf("Cheb.param for %dx2D->%dD in [%+.3e:%+.3e] [%+.3e:%+.3e] | %d coefs in %d rows\n",
155 0 : fNSlices,fDimOut,fBMin[0],fBMax[0],fBMin[1],fBMax[1],fNCoefsTot,fNRowsTot);
156 0 : TString opts = opt; opts.ToLower();
157 0 : if (opts.Contains("l")) for (int isl=0;isl<fNSlices;isl++) PrintSlice(isl,opt);
158 : //
159 0 : }
|