@@ -39,6 +39,7 @@ StepTHn::StepTHn() : mNBins(0),
3939 mNbinsCache(nullptr ),
4040 mLastVars(nullptr ),
4141 mLastBins(nullptr ),
42+ mLookup(nullptr ),
4243 mPrototype(nullptr )
4344{
4445 // Default constructor (for streaming)
@@ -55,6 +56,7 @@ StepTHn::StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, co
5556 mNbinsCache(nullptr ),
5657 mLastVars(nullptr ),
5758 mLastBins(nullptr ),
59+ mLookup(nullptr ),
5860 mPrototype(nullptr )
5961{
6062 // Constructor
@@ -130,6 +132,7 @@ StepTHn::StepTHn(const StepTHn& c) : mNBins(c.mNBins),
130132 mNbinsCache(nullptr ),
131133 mLastVars(nullptr ),
132134 mLastBins(nullptr ),
135+ mLookup(nullptr ),
133136 mPrototype(nullptr )
134137{
135138 //
@@ -152,6 +155,7 @@ StepTHn::~StepTHn()
152155 delete[] mNbinsCache ;
153156 delete[] mLastVars ;
154157 delete[] mLastBins ;
158+ delete[] mLookup ;
155159 delete mPrototype ;
156160}
157161
@@ -392,13 +396,35 @@ void StepTHn::Fill(int iStep, int nParams, double positionAndWeight[])
392396 LOGF (fatal, " Fill called with invalid number of parameters (%d vs %d)" , mNVars , nParams);
393397 }
394398
395- // fill axis cache
399+ // fill axis cache and build lookup tables on first call
396400 if (!mAxisCache ) {
397401 mAxisCache = new TAxis*[mNVars ];
398402 mNbinsCache = new Int_t[mNVars ];
403+ mLookup = new AxisLookup[mNVars ];
399404 for (Int_t i = 0 ; i < mNVars ; i++) {
400405 mAxisCache [i] = mPrototype ->GetAxis (i);
401406 mNbinsCache [i] = mAxisCache [i]->GetNbins ();
407+
408+ // Build lookup table for this axis
409+ auto & lut = mLookup [i];
410+ lut.nBins = mNbinsCache [i];
411+ lut.edges = mAxisCache [i]->GetXbins ()->GetArray ();
412+ lut.xmin = mAxisCache [i]->GetXmin ();
413+ lut.xmax = mAxisCache [i]->GetXmax ();
414+
415+ if (lut.edges && lut.xmax > lut.xmin ) {
416+ // Variable-width binning: build slot->bin mapping
417+ Double_t slotWidth = (lut.xmax - lut.xmin ) / kLookupSize ;
418+ lut.invSlotWidth = 1.0 / slotWidth;
419+ for (Int_t s = 0 ; s < kLookupSize ; s++) {
420+ Double_t x = lut.xmin + (s + 0.5 ) * slotWidth;
421+ lut.table [s] = mAxisCache [i]->FindBin (x);
422+ }
423+ } else {
424+ // Uniform binning or degenerate axis: direct formula, no table needed
425+ lut.edges = nullptr ;
426+ lut.invSlotWidth = lut.xmax > lut.xmin ? lut.nBins / (lut.xmax - lut.xmin ) : 0 ;
427+ }
402428 }
403429
404430 mLastVars = new Double_t[mNVars ];
@@ -420,11 +446,39 @@ void StepTHn::Fill(int iStep, int nParams, double positionAndWeight[])
420446 if (mLastVars [i] == positionAndWeight[i]) {
421447 tmpBin = mLastBins [i];
422448 } else {
423- tmpBin = mAxisCache [i]->FindBin (positionAndWeight[i]);
449+ const auto & lut = mLookup [i];
450+ Double_t x = positionAndWeight[i];
451+
452+ if (!lut.edges ) {
453+ // Uniform binning: direct computation
454+ tmpBin = 1 + static_cast <Int_t>((x - lut.xmin ) * lut.invSlotWidth );
455+ if (tmpBin < 1 ) {
456+ tmpBin = 0 ; // underflow
457+ } else if (tmpBin > lut.nBins ) {
458+ tmpBin = lut.nBins + 1 ; // overflow
459+ }
460+ } else {
461+ // Variable-width binning: lookup table + refine
462+ Int_t slot = static_cast <Int_t>((x - lut.xmin ) * lut.invSlotWidth );
463+ if (slot < 0 || slot >= kLookupSize ) {
464+ tmpBin = (slot < 0 ) ? 0 : lut.nBins + 1 ; // under/overflow
465+ } else {
466+ tmpBin = lut.table [slot];
467+ // Refine: the lookup gives an approximate bin, check edges
468+ // Move left if x is below the lower edge of tmpBin
469+ while (tmpBin > 1 && x < lut.edges [tmpBin - 1 ]) {
470+ tmpBin--;
471+ }
472+ // Move right if x is at or above the upper edge of tmpBin
473+ while (tmpBin < lut.nBins && x >= lut.edges [tmpBin]) {
474+ tmpBin++;
475+ }
476+ }
477+ }
478+
424479 mLastBins [i] = tmpBin;
425- mLastVars [i] = positionAndWeight[i] ;
480+ mLastVars [i] = x ;
426481 }
427- // Printf("%d", tmpBin);
428482
429483 // under/overflow not supported
430484 if (tmpBin < 1 || tmpBin > mNbinsCache [i]) {
@@ -433,7 +487,6 @@ void StepTHn::Fill(int iStep, int nParams, double positionAndWeight[])
433487
434488 // bins start from 0 here
435489 bin += tmpBin - 1 ;
436- // Printf("%lld", bin);
437490 }
438491
439492 updateBin (iStep, bin, weight);
0 commit comments