Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:17

0001 // @(#)root/hist:$Id$
0002 // Author: Axel Naumann, Nov 2011
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TNDArray
0013 #define ROOT_TNDArray
0014 
0015 #include "TObject.h"
0016 #include "TError.h"
0017 
0018 /** \class TNDArray
0019 
0020 N-Dim array class.
0021 
0022 Storage layout:
0023 Assume 3 dimensions, array sizes 2, 4 and 3 i.e. 24 bins:
0024 Data is stored as [0,0,0], [0,0,1], [0,0,2], [0,1,0],...
0025 
0026 fSizes stores the combined size of each bin in a dimension, i.e. in
0027 above example it would contain 24, 12, 3, 1.
0028 
0029 Storage is allocated lazily, only when data is written to the array.
0030 */
0031 
0032 
0033 /** \class TNDArrayRef
0034 
0035 gives access to a sub-dimension, e.g. arr[0][1] in above
0036 three-dimensional example, up to an element with conversion operator
0037 to double: double value = arr[0][1][2];
0038 */
0039 
0040 
0041 // Array layout:
0042 // nbins[0] = 2, nbins[1] = 4, nbins[2] = 3 => 24 bins
0043 //
0044 // fSizes: 24, 12, 3 [, 1
0045 
0046 class TNDArray: public TObject {
0047 public:
0048    TNDArray() : fSizes() {}
0049 
0050    TNDArray(Int_t ndim, const Int_t *nbins, bool addOverflow = false) : fSizes()
0051    {
0052       TNDArray::Init(ndim, nbins, addOverflow);
0053    }
0054 
0055    virtual void Init(Int_t ndim, const Int_t* nbins, bool addOverflow = false) {
0056       // Calculate fSize based on ndim dimensions, nbins for each dimension,
0057       // possibly adding over- and underflow bin to each dimensions' nbins.
0058       fSizes.resize(ndim + 1);
0059       Int_t overBins = addOverflow ? 2 : 0;
0060       fSizes[ndim] = 1;
0061       for (Int_t i = 0; i < ndim; ++i) {
0062          fSizes[ndim - i - 1] = fSizes[ndim - i] * (nbins[ndim - i - 1] + overBins);
0063       }
0064    }
0065 
0066    virtual void Reset(Option_t* option = "") = 0;
0067 
0068    Int_t GetNdimensions() const { return fSizes.size() - 1; }
0069    Long64_t GetNbins() const { return fSizes[0]; }
0070    Long64_t GetCellSize(Int_t dim) const { return fSizes[dim + 1]; }
0071 
0072    Long64_t GetBin(const Int_t* idx) const {
0073       // Get the linear bin number for each dimension's bin index
0074       Long64_t bin = idx[fSizes.size() - 2];
0075       for (unsigned int d = 0; d < fSizes.size() - 2; ++d) {
0076          bin += fSizes[d + 1] * idx[d];
0077       }
0078       return bin;
0079    }
0080 
0081    virtual Double_t AtAsDouble(ULong64_t linidx) const = 0;
0082    virtual void SetAsDouble(ULong64_t linidx, Double_t value) = 0;
0083    virtual void AddAt(ULong64_t linidx, Double_t value) = 0;
0084 
0085 protected:
0086    std::vector<Long64_t> fSizes; ///< bin count
0087    ClassDefOverride(TNDArray, 2);        ///< Base for n-dimensional array
0088 };
0089 
0090 template <typename T>
0091 class TNDArrayRef {
0092 public:
0093    TNDArrayRef(const T* data, const Long64_t* sizes):
0094    fData(data), fSizes(sizes) {}
0095 
0096    TNDArrayRef<T> operator[] (Int_t idx) const {
0097       if (!fData) return TNDArrayRef<T>(0, 0);
0098       R__ASSERT(idx < fSizes[-1] / fSizes[0] && "index out of range!");
0099       return TNDArrayRef<T>(fData + idx * fSizes[0], (fSizes[0] == 1) ? nullptr : (fSizes + 1));
0100    }
0101    operator T() const {
0102       if (!fData) return T();
0103       R__ASSERT(fSizes == nullptr && "Element operator can only be used on non-array element. Missing an operator[] level?");
0104       return *fData;
0105    }
0106 
0107 private:
0108    const T* fData;             ///< Pointer into TNDArray's fData
0109    const Long64_t* fSizes;     ///< Pointer into TNDArray's fSizes
0110    ClassDefNV(TNDArrayRef, 0); ///< Subdimension of a TNDArray
0111 };
0112 
0113 template <typename T>
0114 class TNDArrayT: public TNDArray {
0115 public:
0116    TNDArrayT() : fData() {}
0117 
0118    TNDArrayT(Int_t ndim, const Int_t *nbins, bool addOverflow = false) : TNDArray(ndim, nbins, addOverflow), fData() {}
0119 
0120    void Init(Int_t ndim, const Int_t* nbins, bool addOverflow = false) override {
0121       fData.clear();
0122       TNDArray::Init(ndim, nbins, addOverflow);
0123    }
0124 
0125    void Reset(Option_t* /*option*/ = "") override {
0126       // Reset the content
0127       fData.assign(fSizes[0], T());
0128    }
0129 
0130    TNDArrayRef<T> operator[](Int_t idx) const {
0131       if (!fData) return TNDArrayRef<T>(0, 0);
0132       R__ASSERT(idx < fSizes[0] / fSizes[1] && "index out of range!");
0133       return TNDArrayRef<T>(fData.data() + idx * fSizes[1], fSizes.data() + 2);
0134    }
0135 
0136    T At(const Int_t* idx) const {
0137       return At(GetBin(idx));
0138    }
0139    T& At(const Int_t* idx) {
0140       return At(GetBin(idx));
0141    }
0142    T At(ULong64_t linidx) const {
0143       if (fData.empty())
0144          return T();
0145       return fData[linidx];
0146    }
0147    T& At(ULong64_t linidx) {
0148       if (fData.empty())
0149          fData.resize(fSizes[0], T());
0150       return fData[linidx];
0151    }
0152 
0153    Double_t AtAsDouble(ULong64_t linidx) const override {
0154       if (fData.empty())
0155          return 0.;
0156       return fData[linidx];
0157    }
0158    void SetAsDouble(ULong64_t linidx, Double_t value) override {
0159       if (fData.empty())
0160          fData.resize(fSizes[0], T());
0161       fData[linidx] = (T) value;
0162    }
0163    void AddAt(ULong64_t linidx, Double_t value) override {
0164       if (fData.empty())
0165          fData.resize(fSizes[0], T());
0166       fData[linidx] += (T) value;
0167    }
0168 
0169 protected:
0170    std::vector<T> fData;   // data
0171    ClassDefOverride(TNDArrayT, 2); // N-dimensional array
0172 };
0173 
0174 // FIXME: Remove once we implement https://sft.its.cern.ch/jira/browse/ROOT-6284
0175 // When building with -fmodules, it instantiates all pending instantiations,
0176 // instead of delaying them until the end of the translation unit.
0177 // We 'got away with' probably because the use and the definition of the
0178 // explicit specialization do not occur in the same TU.
0179 //
0180 // In case we are building with -fmodules, we need to forward declare the
0181 // specialization in order to compile the dictionary G__Hist.cxx.
0182 template<> void TNDArrayT<double>::Streamer(TBuffer &R__b);
0183 template<> TClass *TNDArrayT<double>::Class();
0184 
0185 
0186 #endif // ROOT_TNDArray