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