2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
10 //____________________________________________________________________
12 inline FlexErrArray<T>::FlexErrArray( unsigned nbins )
13 : m_indices(reinterpret_cast<char*>(this)+sizeof(*this)),
14 m_fastloop_group2check(0),
16 m_fastloop_isuper2check(0),
17 m_fastloop_igr2check(0)
18 #ifdef LW_STRICT_ROOT_BEHAVIOUR
19 , m_pretendSumWMode(false)
22 //Check that the implementation makes sense at all:
23 assert(sizeof(unsigned short)>sizeof(unsigned char));
24 assert(sizeof(T)>sizeof(unsigned short));
26 memset(groups(),0,nGroupsNeeded(nbins)*sizeof(void*));
27 // cppcheck-suppress assertWithSideEffect
29 // cppcheck-suppress assertWithSideEffect
30 assert(!groups()[nGroupsNeeded(nbins)-1]);
32 memset(superGroups(),0,nSuperGroups(nbins)*sizeof(void*));
33 // cppcheck-suppress assertWithSideEffect
34 assert(!superGroups()[0]);
35 // cppcheck-suppress assertWithSideEffect
36 assert(!superGroups()[nSuperGroups(nbins)-1]);
40 //____________________________________________________________________
42 inline FlexErrArray<T>::~FlexErrArray()
45 const unsigned n(nGroupsNeeded(m_nbins));
46 FlexErrArrayGroup<T> ** grps(groups());
47 for (unsigned igr = 0; igr < n; ++igr) {
48 FlexErrArrayGroup<T> *gr = grps[igr];
53 unsigned nsuper(nSuperGroups(m_nbins));
54 FlexErrArrayGroup<T> *** supergroups(superGroups());
55 for (unsigned isuper = 0; isuper<nsuper;++isuper) {
56 FlexErrArrayGroup<T> ** supergroup = supergroups[isuper];
58 unsigned upper(isuper+1==nsuper?entriesInSuperGroup(isuper):FLEX1DERRARRAY_NGROUPSPERINDEX);
59 for (unsigned igr = 0; igr<upper;++igr) {
60 FlexErrArrayGroup<T> *gr = supergroup[igr];
64 if (upper==FLEX1DERRARRAY_NGROUPSPERINDEX)
65 LWPools::release<FlexErrArrayGroup<T>*,FLEX1DERRARRAY_NGROUPSPERINDEX>(supergroup);
67 LWPools::release<FlexErrArrayGroup<T>*>(supergroup,upper);
73 //____________________________________________________________________
75 inline unsigned FlexErrArray<T>::getNBins() const
80 //____________________________________________________________________
82 inline void FlexErrArray<T>::copyContents(T*__restrict__ cont,double*__restrict__ err) const
84 //It is faster to null-out the entire arrays at the beginning, and
85 //then not have to null-out the missing pieces later:
86 memset(&(cont[0]),0,m_nbins*sizeof(*cont));
88 memset(&(err[0]),0,m_nbins*sizeof(*err));
89 //Process group for group:
91 const unsigned n(nGroupsNeeded(m_nbins));
92 const FlexErrArrayGroup<T> * const* grps(groups());
93 for (unsigned igr = 0; igr < n; ++igr) {
94 const FlexErrArrayGroup<T> *gr = grps[igr];
96 unsigned low(FLEXERRARRAYGROUP_MAXBINS*igr);
97 assert(low+gr->getNBins()<=m_nbins);
98 gr->copyContents(&(cont[low]),(err?&(err[low]):0));
102 unsigned nsuper(nSuperGroups(m_nbins));
103 const FlexErrArrayGroup<T> * const* const* supergroups(superGroups());
104 for (unsigned isuper = 0; isuper<nsuper;++isuper) {
105 const FlexErrArrayGroup<T> * const* supergroup = supergroups[isuper];
107 unsigned upper(isuper+1==nsuper?entriesInSuperGroup(isuper):FLEX1DERRARRAY_NGROUPSPERINDEX);
108 for (unsigned igr = 0; igr<upper;++igr) {
109 const FlexErrArrayGroup<T> *gr = supergroup[igr];
111 unsigned low(FLEXERRARRAYGROUP_MAXBINS*(FLEX1DERRARRAY_NGROUPSPERINDEX*isuper+igr));
112 assert(low+gr->getNBins()<=m_nbins);
113 gr->copyContents(&(cont[low]),(err?&(err[low]):0));
120 for (unsigned ibin=0;ibin<m_nbins;++ibin)
121 assert(cont[ibin]==getBinContent(ibin));
123 for (unsigned ibin=0;ibin<m_nbins;++ibin) {
124 const double e1(sqrt(fabs(err[ibin]))),e2(getBinError(ibin));
125 if ((fabs(e1-e2)/(1+std::max(e1,e2)))>1.0e-5&&!bothNaN(e1,e2)) {
126 std::cout<<"e1 = "<<e1<<std::endl;
127 std::cout<<"e2 = "<<e2<<std::endl;
128 std::cout<<"test: "<<(e1-e2)/(1.0+std::max(e1,e2))<<std::endl;
129 assert((e1-e2)/(1.0+std::max(e1,e2))<1.0e-3||bothNaN(e1,e2));//fixme: Investigate if really need to go up to 1.0e-3
135 //____________________________________________________________________
137 inline double FlexErrArray<T>::Integral() const
141 const unsigned n(nGroupsNeeded(m_nbins));
142 const FlexErrArrayGroup<T> * const* grps(groups());
143 for (unsigned igr = 0; igr < n; ++igr) {
144 const FlexErrArrayGroup<T> *gr = grps[igr];
146 result += gr->Integral();
149 unsigned nsuper(nSuperGroups(m_nbins));
150 const FlexErrArrayGroup<T> * const* const* supergroups(superGroups());
151 for (unsigned isuper = 0; isuper<nsuper;++isuper) {
152 const FlexErrArrayGroup<T> * const* supergroup = supergroups[isuper];
154 unsigned upper(isuper+1==nsuper?entriesInSuperGroup(isuper):FLEX1DERRARRAY_NGROUPSPERINDEX);
155 for (unsigned igr = 0; igr<upper;++igr) {
156 const FlexErrArrayGroup<T> *gr = supergroup[igr];
158 result += gr->Integral();
166 //____________________________________________________________________
168 inline bool FlexErrArray<T>::holdsSeparateSumW2Info() const
170 #ifdef LW_STRICT_ROOT_BEHAVIOUR
171 return m_pretendSumWMode;
173 unsigned nsuper(nSuperGroups(m_nbins));
175 const unsigned n(nGroupsNeeded(m_nbins));
176 const FlexErrArrayGroup<T> ** grps(groups());
177 for (unsigned igr = 0; igr < n; ++igr)
178 if (grps[igr]&&grps[igr]->holdsSeparateSumW2Info())
182 const FlexErrArrayGroup<T> *** supergroups(superGroups());
183 for (unsigned isuper = 0; isuper<nsuper;++isuper) {
184 const FlexErrArrayGroup<T> ** supergroup = supergroups[isuper];
186 unsigned upper(isuper+1==nsuper?entriesInSuperGroup(isuper):FLEX1DERRARRAY_NGROUPSPERINDEX);
187 for (unsigned igr = 0; igr<upper;++igr) {
188 const FlexErrArrayGroup<T> *gr = supergroup[igr];
189 if (gr&&gr->holdsSeparateSumW2Info())
199 //____________________________________________________________________
201 inline T FlexErrArray<T>::getBinContent(unsigned bin) const
204 const FlexErrArrayGroup<T> * gr = getGroupNoAlloc(bin);
205 return gr ? gr->getBinContent(groupBin(bin)) : 0;
209 //____________________________________________________________________
211 inline double FlexErrArray<T>::getBinError(unsigned bin) const
214 const FlexErrArrayGroup<T> * gr = getGroupNoAlloc(bin);
215 return gr ? gr->getBinError(groupBin(bin)) : 0;
218 //____________________________________________________________________
220 inline void FlexErrArray<T>::getBinContentAndError(unsigned bin, T& content, double& error ) const
223 const FlexErrArrayGroup<T> * gr = getGroupNoAlloc(bin);
225 gr->getBinContentAndError(groupBin(bin),content,error);
232 //____________________________________________________________________
234 inline void FlexErrArray<T>::setBinContent(unsigned bin, const T& content)
237 FlexErrArrayGroup<T> * gr;
239 gr = getGroupNoAlloc(bin);
246 gr->setBinContent(groupBin(bin),content STRICT_ROOT_PAR(m_pretendSumWMode));
247 assert(getBinContent(bin)==content||bothNaN(getBinContent(bin),content));
251 //____________________________________________________________________
253 inline void FlexErrArray<T>::setBinError(unsigned bin, const double& error )
256 #ifdef LW_STRICT_ROOT_BEHAVIOUR
257 m_pretendSumWMode = true;
259 FlexErrArrayGroup<T> * gr;
261 gr = getGroupNoAlloc(bin);
268 gr->setBinError(groupBin(bin),error);
269 assert(fabs(getBinError(bin)-fabs(error))<1.0e-10||bothNaN(error,getBinError(bin)));
272 //____________________________________________________________________
274 inline void FlexErrArray<T>::setBinContentAndError(unsigned bin, const T& content, const double& error )
277 #ifdef LW_STRICT_ROOT_BEHAVIOUR
278 m_pretendSumWMode = true;
281 FlexErrArrayGroup<T> * gr;
282 if (content==0&&error==0) {
283 //Special case: Maybe we do not need an allocation:
284 gr = getGroupNoAlloc(bin);
291 gr->setBinContentAndError( groupBin(bin),
296 //____________________________________________________________________
298 inline void FlexErrArray<T>::fill(unsigned bin)
301 T expectedval = getBinContent(bin)+1;
304 getGroup(bin)->fill(groupBin(bin) STRICT_ROOT_PAR(m_pretendSumWMode));
306 T resval=getBinContent(bin);
307 assert(static_cast<double>(std::abs(resval-expectedval))/(1.0+std::max<T>(std::abs(resval),std::abs(expectedval)))<1.0e-5);
311 //____________________________________________________________________
313 inline void FlexErrArray<T>::fill(unsigned bin, const double& weight)
316 T expectedval = getBinContent(bin)+T(weight);
319 #ifdef LW_STRICT_ROOT_BEHAVIOUR
320 if (weight != 1) m_pretendSumWMode = true;
322 getGroup(bin)->fill(groupBin(bin),weight STRICT_ROOT_PAR(m_pretendSumWMode));
324 T resval=getBinContent(bin);
325 assert(static_cast<double>(std::abs(resval-expectedval))/(1.0+std::max<T>(std::abs(resval),std::abs(expectedval)))<1.0e-5);
329 //____________________________________________________________________
331 inline FlexErrArrayGroup<T> * FlexErrArray<T>::getGroup(unsigned bin)
333 FlexErrArrayGroup<T> ** gr(0);
338 gr = &(groups()[igr]);
340 //1) Get the super-group
341 isuper = iSuperGroup(bin);
342 FlexErrArrayGroup<T> ** supergroup = superGroups()[isuper];
344 unsigned l(entriesInSuperGroup(isuper));
345 if (l==FLEX1DERRARRAY_NGROUPSPERINDEX)
346 supergroup = LWPools::acquire<FlexErrArrayGroup<T>*,FLEX1DERRARRAY_NGROUPSPERINDEX>();
348 supergroup = LWPools::acquire<FlexErrArrayGroup<T>*>(l);
349 memset(supergroup,0,l*sizeof(supergroup[0]));
350 superGroups()[iSuperGroup(bin)] = supergroup;
351 assert(superGroupBin(bin)<l);
354 igr = superGroupBin(bin);
355 gr = &(supergroup[igr]);
360 unsigned nbinsGr(FLEXERRARRAYGROUP_MAXBINS);
361 unsigned lastBin(FLEXERRARRAYGROUP_MAXBINS*(isuper*FLEX1DERRARRAY_NGROUPSPERINDEX+igr+1));
362 assert(!(unsigned(igr+1)==nGroupsNeeded(m_nbins))||lastBin>=m_nbins);
363 assert(m_nbins+FLEXERRARRAYGROUP_MAXBINS>lastBin);
365 nbinsGr -= (lastBin-m_nbins);
366 FlexErrArrayGroup<T> * g = MP_NEW(FlexErrArrayGroup<T>)(nbinsGr);
368 assert((*gr)->getNBins()==nbinsGr);
376 //____________________________________________________________________
378 inline void FlexErrArray<T>::fastLoop_findAndResetNextGroup( )
380 //Fixme: We should actually always find the two next, and use
381 //__builtin_prefetch() on the second. We could also call "prefetch
382 //all data" on the group (since we know we will need all chunks/errchunks)
384 assert(!m_fastloop_group2check);
386 const unsigned n(nGroupsNeeded(m_nbins));
387 FlexErrArrayGroup<T> ** grps(groups());
388 for (;m_fastloop_igr2check < n; ++m_fastloop_igr2check) {
389 m_fastloop_group2check = grps[m_fastloop_igr2check];
390 if (m_fastloop_group2check)
394 unsigned nsuper(nSuperGroups(m_nbins));
395 FlexErrArrayGroup<T> *** supergroups(superGroups());
396 for (;m_fastloop_isuper2check<nsuper;++m_fastloop_isuper2check) {
397 FlexErrArrayGroup<T> ** supergroup = supergroups[m_fastloop_isuper2check];
399 unsigned upper(m_fastloop_isuper2check+1==nsuper?entriesInSuperGroup(m_fastloop_isuper2check):FLEX1DERRARRAY_NGROUPSPERINDEX);
400 for (;m_fastloop_igr2check < upper; ++m_fastloop_igr2check) {
401 m_fastloop_group2check = supergroup[m_fastloop_igr2check];
402 if (m_fastloop_group2check)
405 if (m_fastloop_group2check)
408 m_fastloop_igr2check = 0;
412 if (m_fastloop_group2check)
413 m_fastloop_group2check->resetActiveBinLoop();
417 //____________________________________________________________________
419 inline void FlexErrArray<T>::resetActiveBinLoop()
421 m_fastloop_isuper2check = 0;
422 m_fastloop_igr2check = 0;
423 m_fastloop_group2check = 0;
424 fastLoop_findAndResetNextGroup();
427 //____________________________________________________________________
429 inline bool FlexErrArray<T>::getNextActiveBin(unsigned& bin, T& content, double& error)
431 if (m_fastloop_group2check) {
432 //Just check the group once more:
433 if (m_fastloop_group2check->getNextActiveBin(bin, content, error)) {
434 //"bin" is now local. Put into global mode:
435 bin += ( m_fastloop_isuper2check * FLEX1DERRARRAY_NGROUPSPERINDEX + m_fastloop_igr2check) * FLEXERRARRAYGROUP_MAXBINS;//fixme: cache this offset?
439 m_fastloop_group2check=0;
441 //Attempt to find the next group (if any):
442 ++m_fastloop_igr2check;
443 if (m_fastloop_igr2check==FLEX1DERRARRAY_NGROUPSPERINDEX&&!small()) {
444 ++m_fastloop_isuper2check;
445 m_fastloop_igr2check = 0;
447 fastLoop_findAndResetNextGroup();
450 return m_fastloop_group2check ? getNextActiveBin(bin,content,error) : false;
453 //____________________________________________________________________
455 inline void FlexErrArray<T>::scaleContentsAndErrors( const double& fact )
457 //We simply use the fast-looping functionality here. Just to be
458 //safe, we save the state of the fastlooping temporary variables:
459 unsigned save_fastloop_isuper2check = m_fastloop_isuper2check;
460 unsigned save_fastloop_igr2check = m_fastloop_igr2check;
462 unsigned bin; T cont; double err;
463 resetActiveBinLoop();
464 while (getNextActiveBin(bin, cont, err))
465 setBinContentAndError(bin, static_cast<T>(cont*fact), err*fact );
467 m_fastloop_isuper2check = save_fastloop_isuper2check;
468 m_fastloop_igr2check = save_fastloop_igr2check;