// @(#)root/hist:$Id$
// Author: Axel Naumann, Nov 2011

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

#ifndef ROOT_THN
#define ROOT_THN

#ifndef ROOT_THnBase
#include "THnBase.h"
#endif

#ifndef ROOT_TNDArray
#include "TNDArray.h"
#endif

#ifndef ROOT_TArrayD
#include "TArrayD.h"
#endif

#ifndef ROOT_TObjArray
#include "TObjArray.h"
#endif

#ifndef ROOT_TAxis
#include "TAxis.h"
#endif

#ifndef ROOT_TMath
#include "TMath.h"
#endif

class TH1;
class TH1D;
class TH2D;
class TH3D;
class THnSparse;
class TF1;



class THn: public THnBase {
private:
   THn(const THn&); // Not implemented
   THn& operator=(const THn&); // Not implemented

protected:
   void AllocCoordBuf() const;
   void InitStorage(Int_t* nbins, Int_t chunkSize);

   THn(): fCoordBuf() {}
   THn(const char* name, const char* title, Int_t dim, const Int_t* nbins,
       const Double_t* xmin, const Double_t* xmax);

public:
   virtual ~THn();

   static THn* CreateHn(const char* name, const char* title, const TH1* h1) {
      return (THn*) CreateHnAny(name, title, h1, kFALSE /*THn*/, -1);
   }
   static THn* CreateHn(const char* name, const char* title, const THnBase* hn) {
      return (THn*) CreateHnAny(name, title, hn, kFALSE /*THn*/, -1);
   }

   ROOT::Internal::THnBaseBinIter* CreateIter(Bool_t respectAxisRange) const;
   Long64_t GetNbins() const { return GetArray().GetNbins(); }

   Long64_t GetBin(const Int_t* idx) const {
      return GetArray().GetBin(idx);
   }
   Long64_t GetBin(const Double_t* x) const {
      if (!fCoordBuf) AllocCoordBuf();
      for (Int_t d = 0; d < fNdimensions; ++d) {
         fCoordBuf[d] = GetAxis(d)->FindFixBin(x[d]);
      }
      return GetArray().GetBin(fCoordBuf);
   }
   Long64_t GetBin(const char* name[]) const {
      if (!fCoordBuf) AllocCoordBuf();
      for (Int_t d = 0; d < fNdimensions; ++d) {
         fCoordBuf[d] = GetAxis(d)->FindBin(name[d]);
      }
      return GetArray().GetBin(fCoordBuf);
   }

   Long64_t GetBin(const Int_t* idx, Bool_t /*allocate*/ = kTRUE) {
      return const_cast<const THn*>(this)->GetBin(idx);
   }
   Long64_t GetBin(const Double_t* x, Bool_t /*allocate*/ = kTRUE) {
      return const_cast<const THn*>(this)->GetBin(x);
   }
   Long64_t GetBin(const char* name[], Bool_t /*allocate*/ = kTRUE) {
      return const_cast<const THn*>(this)->GetBin(name);
   }

   void FillBin(Long64_t bin, Double_t w) {
      // Increment the bin content of "bin" by "w",
      // return the bin index.
      GetArray().AddAt(bin, w);
      if (GetCalculateErrors()) {
         fSumw2.AddAt(bin, w * w);
      }
      FillBinBase(w);
   }

   void SetBinContent(const Int_t* idx, Double_t v) {
      // Forwards to THnBase::SetBinContent().
      // Non-virtual, CINT-compatible replacement of a using declaration.
      THnBase::SetBinContent(idx, v);
   }
    void SetBinContent(Long64_t bin, Double_t v) {
      GetArray().SetAsDouble(bin, v);
   }
   void SetBinError2(Long64_t bin, Double_t e2) {
      if (!GetCalculateErrors()) Sumw2();
      fSumw2.At(bin) = e2;
   }
   void AddBinContent(const Int_t* idx, Double_t v = 1.) {
      // Forwards to THnBase::SetBinContent().
      // Non-virtual, CINT-compatible replacement of a using declaration.
      THnBase::AddBinContent(idx, v);
   }
   void AddBinContent(Long64_t bin, Double_t v = 1.) {
      GetArray().AddAt(bin, v);
   }
   void AddBinError2(Long64_t bin, Double_t e2) {
      fSumw2.At(bin) += e2;
   }
   Double_t GetBinContent(const Int_t *idx) const {
      // Forwards to THnBase::GetBinContent() overload.
      // Non-virtual, CINT-compatible replacement of a using declaration.
      return THnBase::GetBinContent(idx);
   }
   Double_t GetBinContent(Long64_t bin, Int_t* idx = 0) const {
      // Get the content of bin, and set its index if idx is != 0.
      if (idx) {
         const TNDArray& arr = GetArray();
         Long64_t prevCellSize = arr.GetNbins();
         for (Int_t i = 0; i < GetNdimensions(); ++i) {
            Long64_t cellSize = arr.GetCellSize(i);
            idx[i] = (bin % prevCellSize) / cellSize;
            prevCellSize = cellSize;
         }
      }
      return GetArray().AtAsDouble(bin);
   }
   Double_t GetBinError2(Long64_t linidx) const {
      return GetCalculateErrors() ? fSumw2.At(linidx) : GetBinContent(linidx);
   }

   virtual const TNDArray& GetArray() const = 0;
   virtual TNDArray& GetArray() = 0;

   void Sumw2();

   TH1D*      Projection(Int_t xDim, Option_t* option = "") const {
      // Forwards to THnBase::Projection().
      // Non-virtual, as a CINT-compatible replacement of a using
      // declaration.
      return THnBase::Projection(xDim, option);
   }

   TH2D*      Projection(Int_t yDim, Int_t xDim,
                         Option_t* option = "") const {
      // Forwards to THnBase::Projection().
      // Non-virtual, as a CINT-compatible replacement of a using
      // declaration.
      return THnBase::Projection(yDim, xDim, option);
   }

   TH3D*      Projection(Int_t xDim, Int_t yDim, Int_t zDim,
                         Option_t* option = "") const {
      // Forwards to THnBase::Projection().
      // Non-virtual, as a CINT-compatible replacement of a using
      // declaration.
      return THnBase::Projection(xDim, yDim, zDim, option);
   }

   THn*       Projection(Int_t ndim, const Int_t* dim,
                         Option_t* option = "") const {
      return (THn*) ProjectionND(ndim, dim, option);
   }

   THn*       Rebin(Int_t group) const {
      return (THn*) RebinBase(group);
   }
   THn*       Rebin(const Int_t* group) const {
      return (THn*) RebinBase(group);
   }

   void Reset(Option_t* option = "");

protected:
   TNDArrayT<Double_t> fSumw2; // bin error, lazy allocation happens in TNDArrayT
   mutable Int_t* fCoordBuf; //! Temporary buffer

   ClassDef(THn, 1); //Base class for multi-dimensional histogram
};



//______________________________________________________________________________
/** \class THnT
 Templated implementation of the abstract base THn.
 All functionality and the interfaces to be used are in THn!

 THn does not know how to store any bin content itself. Instead, this
 is delegated to the derived, templated class: the template parameter decides
 what the format for the bin content is. The actual storage is delegated to
 TNDArrayT<T>.

 Typedefs exist for template parematers with ROOT's generic types:

 Templated name   |     Typedef   |    Bin content type
 -----------------|---------------|--------------------
   THnT<Char_t>   |       THnC    |     Char_t
   THnT<Short_t>  |       THnS    |     Short_t
   THnT<Int_t>    |       THnI    |     Int_t
   THnT<Long_t>   |       THnL    |     Long_t
   THnT<Float_t>  |       THnF    |     Float_t
   THnT<Double_t> |       THnD    |     Double_t

 We recommend to use THnC wherever possible, and to map its value space
 of 256 possible values to e.g. float values outside the class. This saves an
 enourmous amount of memory. Only if more than 256 values need to be
 distinguished should e.g. THnS or even THnF be chosen.

 Implementation detail: the derived, templated class is kept extremely small
 on purpose. That way the (templated thus inlined) uses of this class will
 only create a small amount of machine code, in contrast to e.g. STL.
*/

template <typename T>
class THnT: public THn {
public:
   THnT() {}

   THnT(const char* name, const char* title,
       Int_t dim, const Int_t* nbins,
       const Double_t* xmin, const Double_t* xmax):
   THn(name, title, dim, nbins, xmin, xmax),
   fArray(dim, nbins, true)  {}

   const TNDArray& GetArray() const { return fArray; }
   TNDArray& GetArray() { return fArray; }

protected:
   TNDArrayT<T> fArray; // bin content
   ClassDef(THnT, 1); // multi-dimensional histogram with templated storage
};

typedef THnT<Float_t>  THnF;
typedef THnT<Double_t> THnD;
typedef THnT<Char_t>   THnC;
typedef THnT<Short_t>  THnS;
typedef THnT<Int_t>    THnI;
typedef THnT<Long_t>   THnL;
typedef THnT<Long64_t> THnL64;

#endif // ROOT_THN
 THn.h:1
 THn.h:2
 THn.h:3
 THn.h:4
 THn.h:5
 THn.h:6
 THn.h:7
 THn.h:8
 THn.h:9
 THn.h:10
 THn.h:11
 THn.h:12
 THn.h:13
 THn.h:14
 THn.h:15
 THn.h:16
 THn.h:17
 THn.h:18
 THn.h:19
 THn.h:20
 THn.h:21
 THn.h:22
 THn.h:23
 THn.h:24
 THn.h:25
 THn.h:26
 THn.h:27
 THn.h:28
 THn.h:29
 THn.h:30
 THn.h:31
 THn.h:32
 THn.h:33
 THn.h:34
 THn.h:35
 THn.h:36
 THn.h:37
 THn.h:38
 THn.h:39
 THn.h:40
 THn.h:41
 THn.h:42
 THn.h:43
 THn.h:44
 THn.h:45
 THn.h:46
 THn.h:47
 THn.h:48
 THn.h:49
 THn.h:50
 THn.h:51
 THn.h:52
 THn.h:53
 THn.h:54
 THn.h:55
 THn.h:56
 THn.h:57
 THn.h:58
 THn.h:59
 THn.h:60
 THn.h:61
 THn.h:62
 THn.h:63
 THn.h:64
 THn.h:65
 THn.h:66
 THn.h:67
 THn.h:68
 THn.h:69
 THn.h:70
 THn.h:71
 THn.h:72
 THn.h:73
 THn.h:74
 THn.h:75
 THn.h:76
 THn.h:77
 THn.h:78
 THn.h:79
 THn.h:80
 THn.h:81
 THn.h:82
 THn.h:83
 THn.h:84
 THn.h:85
 THn.h:86
 THn.h:87
 THn.h:88
 THn.h:89
 THn.h:90
 THn.h:91
 THn.h:92
 THn.h:93
 THn.h:94
 THn.h:95
 THn.h:96
 THn.h:97
 THn.h:98
 THn.h:99
 THn.h:100
 THn.h:101
 THn.h:102
 THn.h:103
 THn.h:104
 THn.h:105
 THn.h:106
 THn.h:107
 THn.h:108
 THn.h:109
 THn.h:110
 THn.h:111
 THn.h:112
 THn.h:113
 THn.h:114
 THn.h:115
 THn.h:116
 THn.h:117
 THn.h:118
 THn.h:119
 THn.h:120
 THn.h:121
 THn.h:122
 THn.h:123
 THn.h:124
 THn.h:125
 THn.h:126
 THn.h:127
 THn.h:128
 THn.h:129
 THn.h:130
 THn.h:131
 THn.h:132
 THn.h:133
 THn.h:134
 THn.h:135
 THn.h:136
 THn.h:137
 THn.h:138
 THn.h:139
 THn.h:140
 THn.h:141
 THn.h:142
 THn.h:143
 THn.h:144
 THn.h:145
 THn.h:146
 THn.h:147
 THn.h:148
 THn.h:149
 THn.h:150
 THn.h:151
 THn.h:152
 THn.h:153
 THn.h:154
 THn.h:155
 THn.h:156
 THn.h:157
 THn.h:158
 THn.h:159
 THn.h:160
 THn.h:161
 THn.h:162
 THn.h:163
 THn.h:164
 THn.h:165
 THn.h:166
 THn.h:167
 THn.h:168
 THn.h:169
 THn.h:170
 THn.h:171
 THn.h:172
 THn.h:173
 THn.h:174
 THn.h:175
 THn.h:176
 THn.h:177
 THn.h:178
 THn.h:179
 THn.h:180
 THn.h:181
 THn.h:182
 THn.h:183
 THn.h:184
 THn.h:185
 THn.h:186
 THn.h:187
 THn.h:188
 THn.h:189
 THn.h:190
 THn.h:191
 THn.h:192
 THn.h:193
 THn.h:194
 THn.h:195
 THn.h:196
 THn.h:197
 THn.h:198
 THn.h:199
 THn.h:200
 THn.h:201
 THn.h:202
 THn.h:203
 THn.h:204
 THn.h:205
 THn.h:206
 THn.h:207
 THn.h:208
 THn.h:209
 THn.h:210
 THn.h:211
 THn.h:212
 THn.h:213
 THn.h:214
 THn.h:215
 THn.h:216
 THn.h:217
 THn.h:218
 THn.h:219
 THn.h:220
 THn.h:221
 THn.h:222
 THn.h:223
 THn.h:224
 THn.h:225
 THn.h:226
 THn.h:227
 THn.h:228
 THn.h:229
 THn.h:230
 THn.h:231
 THn.h:232
 THn.h:233
 THn.h:234
 THn.h:235
 THn.h:236
 THn.h:237
 THn.h:238
 THn.h:239
 THn.h:240
 THn.h:241
 THn.h:242
 THn.h:243
 THn.h:244
 THn.h:245
 THn.h:246
 THn.h:247
 THn.h:248
 THn.h:249
 THn.h:250
 THn.h:251
 THn.h:252
 THn.h:253
 THn.h:254
 THn.h:255
 THn.h:256
 THn.h:257
 THn.h:258
 THn.h:259
 THn.h:260
 THn.h:261
 THn.h:262
 THn.h:263
 THn.h:264
 THn.h:265
 THn.h:266