Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-25 09:27:49

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