Logo ROOT   6.08/07
Reference Guide
TNDArray.h
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Axel Naumann, Nov 2011
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TNDArray
13 #define ROOT_TNDArray
14 
15 #ifndef ROOT_TObject
16 #include "TObject.h"
17 #endif
18 #ifndef ROOT_TError
19 #include "TError.h"
20 #endif
21 
22 //////////////////////////////////////////////////////////////////////////
23 // //
24 // TNDArray //
25 // //
26 // N-Dim array class. //
27 // //
28 // Storage layout: //
29 // Assume 3 dimensions, array sizes 2, 4 and 3 i.e. 24 bins: //
30 // Data is stored as [0,0,0], [0,0,1], [0,0,2], [0,1,0],... //
31 // //
32 // fSizes stores the combined size of each bin in a dimension, i.e. in //
33 // above example it would contain 24, 12, 3, 1. //
34 // //
35 // Storage is allocated lazily, only when data is written to the array. //
36 // //
37 // TNDArrayRef gives access to a sub-dimension, e.g. arr[0][1] in above //
38 // three-dimensional example, up to an element with conversion operator //
39 // to double: double value = arr[0][1][2]; //
40 // //
41 //////////////////////////////////////////////////////////////////////////
42 
43 // Array layout:
44 // nbins[0] = 2, nbins[1] = 4, nbins[2] = 3 => 24 bins
45 //
46 // fSizes: 24, 12, 3 [, 1
47 
48 class TNDArray: public TObject {
49 public:
51 
52  TNDArray(Int_t ndim, const Int_t* nbins, bool addOverflow = false):
53  fNdimPlusOne(), fSizes() {
54  TNDArray::Init(ndim, nbins, addOverflow);
55  }
57  delete[] fSizes;
58  }
59 
60  virtual void Init(Int_t ndim, const Int_t* nbins, bool addOverflow = false) {
61  // Calculate fSize based on ndim dimensions, nbins for each dimension,
62  // possibly adding over- and underflow bin to each dimensions' nbins.
63  delete[] fSizes;
64  fNdimPlusOne = ndim + 1;
65  fSizes = new Long64_t[ndim + 1];
66  Int_t overBins = addOverflow ? 2 : 0;
67  fSizes[ndim] = 1;
68  for (Int_t i = 0; i < ndim; ++i) {
69  fSizes[ndim - i - 1] = fSizes[ndim - i] * (nbins[ndim - i - 1] + overBins);
70  }
71  }
72 
73  virtual void Reset(Option_t* option = "") = 0;
74 
75  Int_t GetNdimensions() const { return fNdimPlusOne - 1; }
76  Long64_t GetNbins() const { return fSizes[0]; }
77  Long64_t GetCellSize(Int_t dim) const { return fSizes[dim + 1]; }
78 
79  Long64_t GetBin(const Int_t* idx) const {
80  // Get the linear bin number for each dimension's bin index
81  Long64_t bin = idx[fNdimPlusOne - 2];
82  for (Int_t d = 0; d < fNdimPlusOne - 2; ++d) {
83  bin += fSizes[d + 1] * idx[d];
84  }
85  return bin;
86  }
87 
88  virtual Double_t AtAsDouble(ULong64_t linidx) const = 0;
89  virtual void SetAsDouble(ULong64_t linidx, Double_t value) = 0;
90  virtual void AddAt(ULong64_t linidx, Double_t value) = 0;
91 
92 private:
93  TNDArray(const TNDArray&); // intentionally not implemented
94  TNDArray& operator=(const TNDArray&); // intentionally not implemented
95 
96 protected:
97  Int_t fNdimPlusOne; // Number of dimensions plus one
98  Long64_t* fSizes; //[fNdimPlusOne] bin count
99  ClassDef(TNDArray, 1); //Base for n-dimensional array
100 };
101 
102 template <typename T>
103 class TNDArrayRef {
104 public:
105  TNDArrayRef(const T* data, const Long64_t* sizes):
106  fData(data), fSizes(sizes) {}
107 
108  TNDArrayRef<T> operator[] (Int_t idx) const {
109  if (!fData) return TNDArrayRef<T>(0, 0);
110  R__ASSERT(idx < fSizes[-1] / fSizes[0] && "index out of range!");
111  return TNDArrayRef<T>(fData + idx * fSizes[0], (fSizes[0] == 1) ? 0 : (fSizes + 1));
112  }
113  operator T() const {
114  if (!fData) return T();
115  R__ASSERT(fSizes == 0 && "Element operator can only be used on non-array element. Missing an operator[] level?");
116  return *fData;
117  }
118 
119 private:
120  const T* fData; // pointer into TNDArray's fData
121  const Long64_t* fSizes; // pointer into TNDArray's fSizes
122  ClassDefNV(TNDArrayRef, 0); // subdimension of a TNDArray
123 };
124 
125 template <typename T>
126 class TNDArrayT: public TNDArray {
127 public:
128  TNDArrayT(): fNumData(), fData() {}
129 
130  TNDArrayT(Int_t ndim, const Int_t* nbins, bool addOverflow = false):
131  TNDArray(ndim, nbins, addOverflow),
132  fNumData(), fData() {
133  fNumData = fSizes[0];
134  }
136  delete[] fData;
137  }
138 
139  void Init(Int_t ndim, const Int_t* nbins, bool addOverflow = false) {
140  delete[] fData;
141  fData = 0;
142  TNDArray::Init(ndim, nbins, addOverflow);
143  fNumData = fSizes[0];
144  }
145 
146  void Reset(Option_t* /*option*/ = "") {
147  // Reset the content
148 
149  // Use placement-new with value initialization:
150  if (fData) {
151  new (fData) T[fNumData]();
152  }
153  }
154 
155 #ifndef __CINT__
157  if (!fData) return TNDArrayRef<T>(0, 0);
158  R__ASSERT(idx < fSizes[0] / fSizes[1] && "index out of range!");
159  return TNDArrayRef<T>(fData + idx * fSizes[1], fSizes + 2);
160  }
161 #endif // __CINT__
162 
163  T At(const Int_t* idx) const {
164  return At(GetBin(idx));
165  }
166  T& At(const Int_t* idx) {
167  return At(GetBin(idx));
168  }
169  T At(ULong64_t linidx) const {
170  if (!fData) return T();
171  return fData[linidx];
172  }
173  T& At(ULong64_t linidx) {
174  if (!fData) fData = new T[fNumData]();
175  return fData[linidx];
176  }
177 
178  Double_t AtAsDouble(ULong64_t linidx) const {
179  if (!fData) return 0.;
180  return fData[linidx];
181  }
182  void SetAsDouble(ULong64_t linidx, Double_t value) {
183  if (!fData) fData = new T[fNumData]();
184  fData[linidx] = (T) value;
185  }
186  void AddAt(ULong64_t linidx, Double_t value) {
187  if (!fData) fData = new T[fNumData]();
188  fData[linidx] += (T) value;
189  }
190 
191 protected:
192  int fNumData; // number of bins, product of fSizes
193  T* fData; //[fNumData] data
194  ClassDef(TNDArrayT, 1); // N-dimensional array
195 };
196 
197 #ifndef __CINT__
198 // When building with -fmodules, it instantiates all pending instantiations,
199 // instead of delaying them until the end of the translation unit.
200 // We 'got away with' probably because the use and the definition of the
201 // explicit specialization do not occur in the same TU.
202 //
203 // In case we are building with -fmodules, we need to forward declare the
204 // specialization in order to compile the dictionary G__Hist.cxx.
205 template<> void TNDArrayT<double>::Streamer(TBuffer &R__b);
206 template<> TClass *TNDArrayT<double>::Class();
207 #endif // __CINT__
208 
209 
210 #endif // ROOT_TNDArray
TNDArrayT(Int_t ndim, const Int_t *nbins, bool addOverflow=false)
Definition: TNDArray.h:130
long long Long64_t
Definition: RtypesCore.h:69
const char Option_t
Definition: RtypesCore.h:62
double T(double x)
Definition: ChebyshevPol.h:34
virtual Double_t AtAsDouble(ULong64_t linidx) const =0
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
void SetAsDouble(ULong64_t linidx, Double_t value)
Definition: TNDArray.h:182
Int_t fNdimPlusOne
Definition: TNDArray.h:97
#define R__ASSERT(e)
Definition: TError.h:98
int Int_t
Definition: RtypesCore.h:41
int nbins[3]
T * fData
Definition: TNDArray.h:193
const char * Class
Definition: TXMLSetup.cxx:64
virtual void SetAsDouble(ULong64_t linidx, Double_t value)=0
Long64_t GetNbins() const
Definition: TNDArray.h:76
TNDArray & operator=(const TNDArray &)
void Init(Int_t ndim, const Int_t *nbins, bool addOverflow=false)
Definition: TNDArray.h:139
#define ClassDef(name, id)
Definition: Rtypes.h:254
virtual void Reset(Option_t *option="")=0
const Long64_t * fSizes
Definition: TNDArray.h:121
T & At(ULong64_t linidx)
Definition: TNDArray.h:173
~TNDArrayT()
Definition: TNDArray.h:135
void Streamer(TBuffer &R__b)
TNDArray(Int_t ndim, const Int_t *nbins, bool addOverflow=false)
Definition: TNDArray.h:52
T At(const Int_t *idx) const
Definition: TNDArray.h:163
void Reset(Option_t *="")
Definition: TNDArray.h:146
#define ClassDefNV(name, id)
Definition: Rtypes.h:262
TNDArrayT()
Definition: TNDArray.h:128
void AddAt(ULong64_t linidx, Double_t value)
Definition: TNDArray.h:186
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
const T * fData
Definition: TNDArray.h:120
TNDArray()
Definition: TNDArray.h:50
int fNumData
Definition: TNDArray.h:192
TNDArrayRef< T > operator[](Int_t idx) const
Definition: TNDArray.h:156
double Double_t
Definition: RtypesCore.h:55
TNDArrayRef(const T *data, const Long64_t *sizes)
Definition: TNDArray.h:105
T & At(const Int_t *idx)
Definition: TNDArray.h:166
unsigned long long ULong64_t
Definition: RtypesCore.h:70
Double_t AtAsDouble(ULong64_t linidx) const
Definition: TNDArray.h:178
virtual void Init(Int_t ndim, const Int_t *nbins, bool addOverflow=false)
Definition: TNDArray.h:60
Long64_t * fSizes
Definition: TNDArray.h:98
Mother of all ROOT objects.
Definition: TObject.h:37
Int_t GetNdimensions() const
Definition: TNDArray.h:75
Long64_t GetBin(const Int_t *idx) const
Definition: TNDArray.h:79
Long64_t GetCellSize(Int_t dim) const
Definition: TNDArray.h:77
~TNDArray()
Definition: TNDArray.h:56
T At(ULong64_t linidx) const
Definition: TNDArray.h:169
virtual void AddAt(ULong64_t linidx, Double_t value)=0