<commit_before>// @(#)root/hist:$Id$
// Author: <NAME> (2011-12-13)

/*************************************************************************
 * Copyright (C) 1995-2012, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "THn.h"

#include "TClass.h"

namespace {
   //______________________________________________________________________________
   //
   // Helper struct to hold one dimension's bin range for THnBinIter.
   /////////////////////////////////////////////////////////////////////////////

   struct CounterRange_t {
      Int_t i;
      Int_t first;
      Int_t last;
      Int_t len;
      Long64_t cellSize;
   };

   //______________________________________________________________________________
   //
   // THnBinIter iterates over all bins of a THn, recursing over all dimensions.
   /////////////////////////////////////////////////////////////////////////////

   class THnBinIter: public ROOT::Internal::THnBaseBinIter {
   public:
      THnBinIter(Int_t dim, const TObjArray* axes, const TNDArray* arr,
                 Bool_t respectAxisRange);
      ~THnBinIter() { delete [] fCounter; }

      Long64_t Next(Int_t* coord = 0);
      Int_t GetCoord(Int_t dim) const { return fCounter[dim].i; }
   private:
      THnBinIter(const THnBinIter&); // intentionally unimplemented
      THnBinIter& operator=(const THnBinIter&); // intentionally unimplemented

   public:
      Int_t fNdimensions;
      Long64_t fIndex;
      const TNDArray* fArray;
      CounterRange_t* fCounter;
   };


   /////////////////////////////////////////////////////////////////////////////
   /// Construct a THnBinIter.

   THnBinIter::THnBinIter(Int_t dim, const TObjArray* axes,
                              const TNDArray* arr, Bool_t respectAxisRange):
      ROOT::Internal::THnBaseBinIter(respectAxisRange),
      fNdimensions(dim), fIndex(-1), fArray(arr) {
      fCounter = new CounterRange_t[dim]();
      for (Int_t i = 0; i < dim; ++i) {
         TAxis *axis = (TAxis*) axes->At(i);
         fCounter[i].len  = axis->GetNbins() + 2;
         fCounter[i].cellSize  = arr->GetCellSize(i);
         if (!respectAxisRange || !axis->TestBit(TAxis::kAxisRange)) {
            fCounter[i].first = 0;
            fCounter[i].last  = fCounter[i].len - 1;
            fCounter[i].i     = 0;
            continue;
         }
         fHaveSkippedBin = kTRUE;
         Int_t min = axis->GetFirst();
         Int_t max = axis->GetLast();
         if (min == 0 && max == 0) {
            // special case where TAxis::SetBit(kAxisRange) and
            // over- and underflow bins are de-selected.
            // first and last are == 0 due to axis12->SetRange(1, axis12->GetNbins());
            min = 1;
            max = axis->GetNbins();
         }
         fCounter[i].first = min;
         fCounter[i].last  = max;
         fCounter[i].i     = min;
         fIndex += fCounter[i].first * fCounter[i].cellSize;
      }
      // First Next() will increment it:
      --fCounter[dim - 1].i;
   }

   /////////////////////////////////////////////////////////////////////////////
   /// Return the current linear bin index (in range), then go to the next bin.
   /// If all bins have been visited, return -1.

   Long64_t THnBinIter::Next(Int_t* coord /*= 0*/) {
      if (fNdimensions < 0) return -1; // end
      ++fCounter[fNdimensions - 1].i;
      ++fIndex;
      // Wrap around if needed
      for (Int_t d = fNdimensions - 1; d > 0 && fCounter[d].i > fCounter[d].last; --d) {
         // We skip last + 1..size and 0..first - 1, adjust fIndex
         Int_t skippedCells = fCounter[d].len - (fCounter[d].last + 1);
         skippedCells += fCounter[d].first;
         fIndex += skippedCells * fCounter[d].cellSize;
         fCounter[d].i = fCounter[d].first;
         ++fCounter[d - 1].i;
      }
      if (fCounter[0].i > fCounter[0].last) {
         fNdimensions = -1;
         return -1;
      }
      if (coord) {
         for (Int_t d = 0; d < fNdimensions; ++d) {
            coord[d] = fCounter[d].i;
         }
      }
      return fIndex;
   }
} // unnamed namespce



/** \class THn
    \ingroup Hist
Multidimensional histogram.

Use a THn if you really, really have to store more than three dimensions,
and if a large fraction of all bins are filled.
Better alternatives are
  -  THnSparse if a fraction of all bins are filled
  - TTree

The major problem of THn is the memory use caused by n-dimensional
histogramming: a THnD with 8 dimensions and 100 bins per dimension needs
more than 2.5GB of RAM!

To construct a THn object you must use one of its templated, derived
classes:

    THnD (typedef for THnT<Double_t>): bin content held by a Double_t,
    THnF (typedef for THnT<Float_t>): bin content held by a Float_t,
    THnL (typedef for THnT<Long_t>): bin content held by a Long_t,
    THnI (typedef for THnT<Int_t>): bin content held by an Int_t,
    THnS (typedef for THnT<Short_t>): bin content held by a Short_t,
    THnC (typedef for THnT<Char_t>): bin content held by a Char_t,

They take name and title, the number of dimensions, and for each dimension
the number of bins, the minimal, and the maximal value on the dimension's
axis. A TH2F h("h","h",10, 0., 10., 20, -5., 5.) would correspond to

    Int_t bins[2] = {10, 20};
    Double_t xmin[2] = {0., -5.};
    Double_t xmax[2] = {10., 5.};
    THnF hn("hn", "hn", 2, bins, min, max);

## Filling
A THn is filled just like a regular histogram, using
THn::Fill(x, weight), where x is a n-dimensional Double_t value.
To take errors into account, Sumw2() must be called before filling the
histogram.
Storage is allocated when the first bin content is stored.
<commit_msg>Fix example code.<commit_after>// @(#)root/hist:$Id$
// Author: <NAME> (2011-12-13)

/*************************************************************************
 * Copyright (C) 1995-2012, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "THn.h"

#include "TClass.h"

namespace {
   //______________________________________________________________________________
   //
   // Helper struct to hold one dimension's bin range for THnBinIter.
   /////////////////////////////////////////////////////////////////////////////

   struct CounterRange_t {
      Int_t i;
      Int_t first;
      Int_t last;
      Int_t len;
      Long64_t cellSize;
   };

   //______________________________________________________________________________
   //
   // THnBinIter iterates over all bins of a THn, recursing over all dimensions.
   /////////////////////////////////////////////////////////////////////////////

   class THnBinIter: public ROOT::Internal::THnBaseBinIter {
   public:
      THnBinIter(Int_t dim, const TObjArray* axes, const TNDArray* arr,
                 Bool_t respectAxisRange);
      ~THnBinIter() { delete [] fCounter; }

      Long64_t Next(Int_t* coord = 0);
      Int_t GetCoord(Int_t dim) const { return fCounter[dim].i; }
   private:
      THnBinIter(const THnBinIter&); // intentionally unimplemented
      THnBinIter& operator=(const THnBinIter&); // intentionally unimplemented

   public:
      Int_t fNdimensions;
      Long64_t fIndex;
      const TNDArray* fArray;
      CounterRange_t* fCounter;
   };


   /////////////////////////////////////////////////////////////////////////////
   /// Construct a THnBinIter.

   THnBinIter::THnBinIter(Int_t dim, const TObjArray* axes,
                              const TNDArray* arr, Bool_t respectAxisRange):
      ROOT::Internal::THnBaseBinIter(respectAxisRange),
      fNdimensions(dim), fIndex(-1), fArray(arr) {
      fCounter = new CounterRange_t[dim]();
      for (Int_t i = 0; i < dim; ++i) {
         TAxis *axis = (TAxis*) axes->At(i);
         fCounter[i].len  = axis->GetNbins() + 2;
         fCounter[i].cellSize  = arr->GetCellSize(i);
         if (!respectAxisRange || !axis->TestBit(TAxis::kAxisRange)) {
            fCounter[i].first = 0;
            fCounter[i].last  = fCounter[i].len - 1;
            fCounter[i].i     = 0;
            continue;
         }
         fHaveSkippedBin = kTRUE;
         Int_t min = axis->GetFirst();
         Int_t max = axis->GetLast();
         if (min == 0 && max == 0) {
            // special case where TAxis::SetBit(kAxisRange) and
            // over- and underflow bins are de-selected.
            // first and last are == 0 due to axis12->SetRange(1, axis12->GetNbins());
            min = 1;
            max = axis->GetNbins();
         }
         fCounter[i].first = min;
         fCounter[i].last  = max;
         fCounter[i].i     = min;
         fIndex += fCounter[i].first * fCounter[i].cellSize;
      }
      // First Next() will increment it:
      --fCounter[dim - 1].i;
   }

   /////////////////////////////////////////////////////////////////////////////
   /// Return the current linear bin index (in range), then go to the next bin.
   /// If all bins have been visited, return -1.

   Long64_t THnBinIter::Next(Int_t* coord /*= 0*/) {
      if (fNdimensions < 0) return -1; // end
      ++fCounter[fNdimensions - 1].i;
      ++fIndex;
      // Wrap around if needed
      for (Int_t d = fNdimensions - 1; d > 0 && fCounter[d].i > fCounter[d].last; --d) {
         // We skip last + 1..size and 0..first - 1, adjust fIndex
         Int_t skippedCells = fCounter[d].len - (fCounter[d].last + 1);
         skippedCells += fCounter[d].first;
         fIndex += skippedCells * fCounter[d].cellSize;
         fCounter[d].i = fCounter[d].first;
         ++fCounter[d - 1].i;
      }
      if (fCounter[0].i > fCounter[0].last) {
         fNdimensions = -1;
         return -1;
      }
      if (coord) {
         for (Int_t d = 0; d < fNdimensions; ++d) {
            coord[d] = fCounter[d].i;
         }
      }
      return fIndex;
   }
} // unnamed namespce



/** \class THn
    \ingroup Hist
Multidimensional histogram.

Use a THn if you really, really have to store more than three dimensions,
and if a large fraction of all bins are filled.
Better alternatives are
  -  THnSparse if a fraction of all bins are filled
  - TTree

The major problem of THn is the memory use caused by n-dimensional
histogramming: a THnD with 8 dimensions and 100 bins per dimension needs
more than 2.5GB of RAM!

To construct a THn object you must use one of its templated, derived
classes:

    THnD (typedef for THnT<Double_t>): bin content held by a Double_t,
    THnF (typedef for THnT<Float_t>): bin content held by a Float_t,
    THnL (typedef for THnT<Long_t>): bin content held by a Long_t,
    THnI (typedef for THnT<Int_t>): bin content held by an Int_t,
    THnS (typedef for THnT<Short_t>): bin content held by a Short_t,
    THnC (typedef for THnT<Char_t>): bin content held by a Char_t,

They take name and title, the number of dimensions, and for each dimension
the number of bins, the minimal, and the maximal value on the dimension's
axis. A TH2F h("h","h",10, 0., 10., 20, -5., 5.) would correspond to

    Int_t bins[2] = {10, 20};
    Double_t xmin[2] = {0., -5.};
    Double_t xmax[2] = {10., 5.};
    THnF hn("hn", "hn", 2, bins, xmin, xmax);

## Filling
A THn is filled just like a regular histogram, using
THn::Fill(x, weight), where x is a n-dimensional Double_t value.
To take errors into account, Sumw2() must be called before filling the
histogram.
Storage is allocated when the first bin content is stored.

{'fraction_non_alphanumeric': 0.18048416514674184, 'fraction_numerical': 0.014591278394959377, 'mean_word_length': 1.9436310395314789, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3585808', 'n_tokens_mistral': 3783, 'n_tokens_neox': 3526, 'n_words': 1110}