Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:08

0001 // @(#)root/mathcore:$Id: FitData.h 45076 2012-07-16 13:45:18Z mborinsk $
0002 // Author: M. Borinsky
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class DataVector
0012 
0013 #ifndef ROOT_Fit_FitData
0014 #define ROOT_Fit_FitData
0015 
0016 /**
0017 @defgroup FitData Fit Data Classes
0018 
0019 Classes for describing the input data for fitting
0020 
0021 @ingroup Fit
0022 */
0023 
0024 
0025 #include "Fit/DataOptions.h"
0026 #include "Fit/DataRange.h"
0027 #include "Math/Types.h"
0028 
0029 #include <vector>
0030 #include <cassert>
0031 #include <iostream>
0032 
0033 
0034 namespace ROOT {
0035 
0036    namespace Fit {
0037 
0038 
0039       /**
0040        * Base class for all the fit data types:
0041        * Stores the coordinates and the DataOptions
0042 
0043          @ingroup FitData
0044        */
0045 
0046 
0047       /**
0048          class holding the fit data points. It is template on the type of point,
0049          which can be for example a binned or unbinned point.
0050          It is basically a wrapper on an std::vector
0051 
0052          @ingroup FitData
0053 
0054       */
0055 
0056       class FitData {
0057       public:
0058 
0059          /// construct with default option and data range
0060          explicit FitData(unsigned int maxpoints = 0, unsigned int dim = 1);
0061 
0062          /// construct passing options and default data range
0063          explicit FitData(const DataOptions &opt, unsigned int maxpoints = 0, unsigned int dim = 1);
0064 
0065 
0066          /// construct passing range and default options
0067          explicit FitData(const DataRange &range, unsigned int maxpoints = 0, unsigned int dim = 1);
0068 
0069          /// construct passing options and data range
0070          FitData(const DataOptions &opt, const DataRange &range,
0071                  unsigned int maxpoints = 0, unsigned int dim = 1);
0072 
0073          /// constructor from external data for 1D data
0074          FitData(unsigned int n, const double *dataX);
0075 
0076          /// constructor from external data for 2D data
0077          FitData(unsigned int n, const double *dataX, const double *dataY);
0078 
0079          /// constructor from external data for 3D data
0080          FitData(unsigned int n, const double *dataX, const double *dataY,
0081                  const double *dataZ);
0082 
0083          /**
0084            constructor for multi-dim external data and a range (data are copied inside according to the range)
0085            Uses as argument an iterator of a list (or vector) containing the const double * of the data
0086            An example could be the std::vector<const double *>::begin
0087          */
0088          FitData(const DataRange &range, unsigned int maxpoints, const double *dataX);
0089 
0090          /**
0091            constructor for multi-dim external data and a range (data are copied inside according to the range)
0092            Uses as argument an iterator of a list (or vector) containing the const double * of the data
0093            An example could be the std::vector<const double *>::begin
0094          */
0095          FitData(const DataRange &range, unsigned int maxpoints, const double *dataX, const double *dataY);
0096 
0097          /**
0098            constructor for multi-dim external data and a range (data are copied inside according to the range)
0099            Uses as argument an iterator of a list (or vector) containing the const double * of the data
0100            An example could be the std::vector<const double *>::begin
0101          */
0102          FitData(const DataRange &range, unsigned int maxpoints, const double *dataX, const double *dataY,
0103                  const double *dataZ);
0104 
0105          /**
0106            constructor for multi-dim external data (data are not copied inside)
0107            Uses as argument an iterator of a list (or vector) containing the const double * of the data
0108            An example could be the std::vector<const double *>::begin
0109            In case of weighted data, the external data must have a dim+1 lists of data
0110            The passed dim refers just to the coordinate size
0111          */
0112          template<class Iterator>
0113          FitData(unsigned int n, unsigned int dim, Iterator dataItr) :
0114             fWrapped(true),
0115             fMaxPoints(n),
0116             fNPoints(fMaxPoints),
0117             fDim(dim),
0118             fCoordsPtr(fDim),
0119             fpTmpCoordVector(nullptr)
0120          {
0121             assert(fDim >= 1);
0122             for (unsigned int i = 0; i < fDim; i++) {
0123                fCoordsPtr[i] = *dataItr++;
0124             }
0125 
0126             if (fpTmpCoordVector) {
0127                delete[] fpTmpCoordVector;
0128                fpTmpCoordVector = nullptr;
0129             }
0130 
0131             fpTmpCoordVector = new double [fDim];
0132          }
0133 
0134          /**
0135            constructor for multi-dim external data and a range (data are copied inside according to the range)
0136            Uses as argument an iterator of a list (or vector) containing the const double * of the data
0137            An example could be the std::vector<const double *>::begin
0138          */
0139          template<class Iterator>
0140          FitData(const DataRange &range, unsigned int maxpoints, unsigned int dim, Iterator dataItr) :
0141             fWrapped(false),
0142             fRange(range),
0143             fMaxPoints(maxpoints),
0144             fNPoints(0),
0145             fDim(dim),
0146             fpTmpCoordVector(nullptr)
0147          {
0148             assert(fDim >= 1);
0149             InitCoordsVector();
0150 
0151             InitFromRange(dataItr);
0152          }
0153 
0154          /// dummy virtual destructor
0155          virtual ~FitData();
0156 
0157          FitData(const FitData &rhs);
0158 
0159          FitData &operator= (const FitData &rhs);
0160 
0161          void Append(unsigned int newPoints, unsigned int dim = 1);
0162 
0163       protected:
0164          /**
0165           * initializer routines to set the corresponding pointers right
0166           * The vectors must NOT be resized after this initialization
0167           * without setting the corresponding pointers in the
0168           * same moment ( has to be an atomic operation in case
0169           * of multithreading ).
0170          */
0171          void InitCoordsVector()
0172          {
0173             fCoords.resize(fDim);
0174             fCoordsPtr.resize(fDim);
0175 
0176             for (unsigned int i = 0; i < fDim; i++) {
0177                fCoords[i].resize(fMaxPoints + VectorPadding(fMaxPoints));
0178                fCoordsPtr[i] = fCoords[i].empty() ? nullptr : &fCoords[i].front();
0179             }
0180 
0181             if (fpTmpCoordVector) {
0182                delete[] fpTmpCoordVector;
0183                fpTmpCoordVector = nullptr;
0184             }
0185 
0186             fpTmpCoordVector = new double [fDim];
0187          }
0188 
0189          template<class Iterator>
0190          void InitFromRange(Iterator dataItr)
0191          {
0192             for (unsigned int i = 0; i < fMaxPoints; i++) {
0193                bool isInside = true;
0194                Iterator tmpItr = dataItr;
0195 
0196                for (unsigned int j = 0; j < fDim; j++)
0197                   isInside &= fRange.IsInside((*tmpItr++)[i], j);
0198 
0199                if (isInside) {
0200                   tmpItr = dataItr;
0201 
0202                   for (unsigned int k = 0; k < fDim; k++)
0203                      fpTmpCoordVector[k] = (*tmpItr++)[i];
0204 
0205                   Add(fpTmpCoordVector);
0206                }
0207             }
0208          }
0209 
0210 
0211       public:
0212 
0213          /**
0214            returns a single coordinate component of a point.
0215            This function is threadsafe in contrast to Coords(...)
0216            and can easily get vectorized by the compiler in loops
0217            running over the ipoint-index.
0218          */
0219          const double *GetCoordComponent(unsigned int ipoint, unsigned int icoord) const
0220          {
0221             assert(ipoint < fMaxPoints + VectorPadding(fMaxPoints));
0222             assert(icoord < fDim);
0223             assert(fCoordsPtr.size() == fDim);
0224             assert(fCoordsPtr[icoord]);
0225             assert(fCoords.empty() || &fCoords[icoord].front() == fCoordsPtr[icoord]);
0226 
0227             return &fCoordsPtr[icoord][ipoint];
0228          }
0229 
0230          /**
0231            return a pointer to the coordinates data for the given fit point
0232          */
0233          // not threadsafe, to be replaced with never constructs!
0234          // for example: just return std::array or std::vector, there's
0235          // is going to be only minor overhead in c++11.
0236          const double *Coords(unsigned int ipoint) const
0237          {
0238             assert(fpTmpCoordVector);
0239             assert(ipoint < fMaxPoints + VectorPadding(fMaxPoints));
0240 
0241             for (unsigned int i = 0; i < fDim; i++) {
0242                assert(fCoordsPtr[i]);
0243                assert(fCoords.empty() || &fCoords[i].front() == fCoordsPtr[i]);
0244 
0245                fpTmpCoordVector[i] = fCoordsPtr[i][ipoint];
0246             }
0247 
0248             return fpTmpCoordVector;
0249          }
0250 
0251          /**
0252            add one dim data with only coordinate and values
0253          */
0254          void Add(double x)
0255          {
0256             assert(!fWrapped);
0257             assert(!fCoordsPtr.empty() && fCoordsPtr.size() == 1 && fCoordsPtr[0]);
0258             assert(1 == fDim);
0259             assert(fNPoints < fMaxPoints);
0260 
0261             fCoords[0][ fNPoints ] = x;
0262 
0263             fNPoints++;
0264          }
0265 
0266          /**
0267            add multi-dim coordinate data with only value
0268          */
0269          void Add(const double *x)
0270          {
0271             assert(!fWrapped);
0272             assert(!fCoordsPtr.empty() && fCoordsPtr.size() == fDim);
0273             assert(fNPoints < fMaxPoints);
0274 
0275             for (unsigned int i = 0; i < fDim; i++) {
0276                fCoords[i][ fNPoints ] = x[i];
0277             }
0278 
0279             fNPoints++;
0280          }
0281 
0282          /**
0283            return number of fit points
0284          */
0285          unsigned int NPoints() const
0286          {
0287             return fNPoints;
0288          }
0289 
0290          /**
0291            return number of fit points
0292          */
0293          unsigned int Size() const
0294          {
0295             return fNPoints;
0296          }
0297 
0298          /**
0299            return coordinate data dimension
0300          */
0301          unsigned int NDim() const
0302          {
0303             return fDim;
0304          }
0305 
0306          /**
0307            access to options
0308          */
0309          const DataOptions &Opt() const
0310          {
0311             return fOptions;
0312          }
0313          DataOptions &Opt()
0314          {
0315             return fOptions;
0316          }
0317 
0318          /**
0319            access to range
0320          */
0321          const DataRange &Range() const
0322          {
0323             return fRange;
0324          }
0325 
0326          /**
0327            direct access to coord data ptrs
0328          */
0329          const std::vector< const double * > &GetCoordDataPtrs() const
0330          {
0331             return fCoordsPtr;
0332          }
0333 
0334 
0335       protected:
0336          void UnWrap()
0337          {
0338             assert(fWrapped);
0339             assert(fCoords.empty());
0340 
0341             fCoords.resize(fDim);
0342             for (unsigned int i = 0; i < fDim; i++) {
0343                assert(fCoordsPtr[i]);
0344                unsigned padding = VectorPadding(fNPoints);
0345                fCoords[i].resize(fNPoints + padding);
0346                std::copy(fCoordsPtr[i], fCoordsPtr[i] + fNPoints + padding, fCoords[i].begin());
0347                fCoordsPtr[i] = fCoords[i].empty() ? nullptr : &fCoords[i].front();
0348             }
0349 
0350             fWrapped = false;
0351          }
0352 
0353 #ifdef R__HAS_VECCORE
0354          /**
0355           * Compute the number that should be added to dataSize in order to have a
0356           * multiple of SIMD vector size.
0357           */
0358          static unsigned VectorPadding(unsigned dataSize)
0359          {
0360             unsigned padding = 0;
0361             unsigned modP = (dataSize) % vecCore::VectorSize<ROOT::Double_v>();
0362             if (modP > 0)
0363                padding = vecCore::VectorSize<ROOT::Double_v>() - modP;
0364             return padding;
0365          }
0366 #else
0367          /**
0368           * If VecCore is not defined, there is no vectorization available and the SIMD vector
0369           * size will always be one. Then, as every number is a multiple of SIMD vector size, the
0370           * padding will always be zero.
0371           */
0372          static constexpr unsigned VectorPadding(const unsigned) { return 0; }
0373 #endif
0374 
0375       protected:
0376          bool          fWrapped;
0377 
0378       private:
0379 
0380          DataOptions   fOptions;
0381          DataRange     fRange;
0382 
0383       protected:
0384          unsigned int  fMaxPoints;
0385          unsigned int  fNPoints;
0386          unsigned int  fDim;
0387 
0388       private:
0389          /**
0390           * This vector stores the vectorizable data:
0391           * The inner vectors contain the coordinates data
0392           * fCoords[0] is the vector for the x-coords
0393           * fCoords[1] is the vector for the y-coords
0394           * etc.
0395           * The vector of pointers stores the pointers
0396           * to the first elements of the corresponding
0397           * elements
0398           *
0399           * If fWrapped is true, fCoords is empty.
0400           * the data can only be accessed by using
0401           * fCoordsPtr.
0402          */
0403          std::vector< std::vector< double > > fCoords;
0404          std::vector< const double * > fCoordsPtr;
0405 
0406          double *fpTmpCoordVector; // non threadsafe stuff!
0407 
0408       };
0409 
0410    } // end namespace Fit
0411 
0412 } // end namespace ROOT
0413 
0414 
0415 
0416 #endif /* ROOT_Fit_Data */