Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooVectorDataStore.h
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * File: $Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 #ifndef ROO_VECTOR_DATA_STORE
17 #define ROO_VECTOR_DATA_STORE
18 
19 #include <list>
20 #include <vector>
21 #include <string>
22 #include <algorithm>
23 #include "RooAbsDataStore.h"
24 #include "TString.h"
25 #include "RooCatType.h"
26 #include "RooAbsCategory.h"
27 #include "RooAbsReal.h"
28 #include "RooChangeTracker.h"
29 
30 #define VECTOR_BUFFER_SIZE 1024
31 
32 class RooAbsArg ;
33 class RooArgList ;
34 class TTree ;
35 class RooFormulaVar ;
36 class RooArgSet ;
37 
38 class RooVectorDataStore : public RooAbsDataStore {
39 public:
40 
41  RooVectorDataStore() ;
42 
43  // Empty ctor
44  RooVectorDataStore(const char* name, const char* title, const RooArgSet& vars, const char* wgtVarName=0) ;
45  virtual RooAbsDataStore* clone(const char* newname=0) const override { return new RooVectorDataStore(*this,newname) ; }
46  virtual RooAbsDataStore* clone(const RooArgSet& vars, const char* newname=0) const override { return new RooVectorDataStore(*this,vars,newname) ; }
47 
48  RooVectorDataStore(const RooVectorDataStore& other, const char* newname=0) ;
49  RooVectorDataStore(const RooTreeDataStore& other, const RooArgSet& vars, const char* newname=0) ;
50  RooVectorDataStore(const RooVectorDataStore& other, const RooArgSet& vars, const char* newname=0) ;
51 
52 
53  RooVectorDataStore(const char *name, const char *title, RooAbsDataStore& tds,
54  const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
55  Int_t nStart, Int_t nStop, Bool_t /*copyCache*/, const char* wgtVarName=0) ;
56 
57  virtual ~RooVectorDataStore() ;
58 
59 private:
60  RooArgSet varsNoWeight(const RooArgSet& allVars, const char* wgtName);
61  RooRealVar* weightVar(const RooArgSet& allVars, const char* wgtName);
62 
63  // reserve storage for nEvt entries
64  void reserve(Int_t nEvt);
65 
66 public:
67  // Write current row
68  virtual Int_t fill() override;
69 
70  // Retrieve a row
71  using RooAbsDataStore::get;
72  virtual const RooArgSet* get(Int_t index) const override;
73 
74  virtual const RooArgSet* getNative(Int_t index) const;
75 
76  virtual Double_t weight() const override;
77  virtual Double_t weightError(RooAbsData::ErrorType etype=RooAbsData::Poisson) const override;
78  virtual void weightError(Double_t& lo, Double_t& hi, RooAbsData::ErrorType etype=RooAbsData::Poisson) const override;
79  virtual Double_t weight(Int_t index) const override;
80  virtual Bool_t isWeighted() const override { return (_wgtVar!=0||_extWgtArray!=0) ; }
81 
82  virtual std::vector<RooSpan<const double>> getBatch(std::size_t first, std::size_t last) const override;
83  virtual RooSpan<const double> getWeightBatch(std::size_t first, std::size_t last) const override;
84 
85  // Change observable name
86  virtual Bool_t changeObservableName(const char* from, const char* to) override;
87 
88  // Add one or more columns
89  virtual RooAbsArg* addColumn(RooAbsArg& var, Bool_t adjustRange=kTRUE) override;
90  virtual RooArgSet* addColumns(const RooArgList& varList) override;
91 
92  // Merge column-wise
93  RooAbsDataStore* merge(const RooArgSet& allvars, std::list<RooAbsDataStore*> dstoreList) override;
94 
95  // Add rows
96  virtual void append(RooAbsDataStore& other) override;
97 
98  // General & bookkeeping methods
99  virtual Bool_t valid() const override;
100  virtual Int_t numEntries() const override;
101  virtual Double_t sumEntries() const override { return _sumWeight ; }
102  virtual void reset() override;
103 
104  // Buffer redirection routines used in inside RooAbsOptTestStatistics
105  virtual void attachBuffers(const RooArgSet& extObs) override;
106  virtual void resetBuffers() override;
107 
108 
109  // Constant term optimizer interface
110  virtual const RooAbsArg* cacheOwner() override { return _cacheOwner ; }
111  virtual void cacheArgs(const RooAbsArg* owner, RooArgSet& varSet, const RooArgSet* nset=0, Bool_t skipZeroWeights=kTRUE) override;
112  virtual void attachCache(const RooAbsArg* newOwner, const RooArgSet& cachedVars) override;
113  virtual void resetCache() override;
114  virtual void recalculateCache(const RooArgSet* /*proj*/, Int_t firstEvent, Int_t lastEvent, Int_t stepSize, Bool_t skipZeroWeights) override;
115 
116  virtual void setArgStatus(const RooArgSet& set, Bool_t active) override;
117 
118  const RooVectorDataStore* cache() const { return _cache ; }
119 
120  void loadValues(const RooAbsDataStore *tds, const RooFormulaVar* select=0, const char* rangeName=0, Int_t nStart=0, Int_t nStop=2000000000) override;
121 
122  void dump() override;
123 
124  void setExternalWeightArray(const Double_t* arrayWgt, const Double_t* arrayWgtErrLo,
125  const Double_t* arrayWgtErrHi, const Double_t* arraySumW2) override {
126  _extWgtArray = arrayWgt ;
127  _extWgtErrLoArray = arrayWgtErrLo ;
128  _extWgtErrHiArray = arrayWgtErrHi ;
129  _extSumW2Array = arraySumW2 ;
130  }
131 
132  virtual void setDirtyProp(Bool_t flag) override {
133  _doDirtyProp = flag ;
134  if (_cache) {
135  _cache->setDirtyProp(flag) ;
136  }
137  }
138 
139  const RooArgSet& row() { return _varsww ; }
140 
141  class RealVector {
142  public:
143 
144  RealVector(UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(Double_t))) :
145  _nativeReal(0), _real(0), _buf(0), _nativeBuf(0), _tracker(0), _nset(0) {
146  _vec.reserve(initialCapacity);
147  }
148 
149  RealVector(RooAbsReal* arg, UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(Double_t))) :
150  _nativeReal(arg), _real(0), _buf(0), _nativeBuf(0), _tracker(0), _nset(0) {
151  _vec.reserve(initialCapacity);
152  }
153 
154  virtual ~RealVector() {
155  delete _tracker;
156  if (_nset) delete _nset ;
157  }
158 
159  RealVector(const RealVector& other, RooAbsReal* real=0) :
160  _vec(other._vec), _nativeReal(real?real:other._nativeReal), _real(real?real:other._real), _buf(other._buf), _nativeBuf(other._nativeBuf), _nset(0) {
161  if (other._tracker) {
162  _tracker = new RooChangeTracker(Form("track_%s",_nativeReal->GetName()),"tracker",other._tracker->parameters()) ;
163  } else {
164  _tracker = 0 ;
165  }
166  if (other._nset) {
167  _nset = new RooArgSet(*other._nset) ;
168  }
169  }
170 
171  RealVector& operator=(const RealVector& other) {
172  if (&other==this) return *this;
173  _nativeReal = other._nativeReal;
174  _real = other._real;
175  _buf = other._buf;
176  _nativeBuf = other._nativeBuf;
177  if (other._vec.size() <= _vec.capacity() / 2 && _vec.capacity() > (VECTOR_BUFFER_SIZE / sizeof(Double_t))) {
178  std::vector<Double_t> tmp;
179  tmp.reserve(std::max(other._vec.size(), VECTOR_BUFFER_SIZE / sizeof(Double_t)));
180  tmp.assign(other._vec.begin(), other._vec.end());
181  _vec.swap(tmp);
182  } else {
183  _vec = other._vec;
184  }
185 
186  return *this;
187  }
188 
189  void setNset(RooArgSet* newNset) { _nset = newNset ? new RooArgSet(*newNset) : 0 ; }
190 
191  RooArgSet* nset() const { return _nset ; }
192 
193  void setBufArg(RooAbsReal* arg) { _nativeReal = arg ; }
194  const RooAbsReal* bufArg() const { return _nativeReal ; }
195 
196  void setBuffer(RooAbsReal* real, Double_t* newBuf) {
197  _real = real ;
198  _buf = newBuf ;
199  if (_nativeBuf==0) {
200  _nativeBuf=newBuf ;
201  }
202  }
203 
204  void setNativeBuffer(Double_t* newBuf=0) {
205  _nativeBuf = newBuf ? newBuf : _buf ;
206  }
207 
208  void setDependents(const RooArgSet& deps) {
209  if (_tracker) {
210  delete _tracker ;
211  }
212  _tracker = new RooChangeTracker(Form("track_%s",_nativeReal->GetName()),"tracker",deps) ;
213  }
214 
215  Bool_t needRecalc() {
216  if (!_tracker) return kFALSE ;
217  return _tracker->hasChanged(kTRUE) ;
218  }
219 
220  void fill() {
221  _vec.push_back(*_buf);
222  }
223 
224  void write(Int_t i) {
225  _vec[i] = *_buf ;
226  }
227 
228  void reset() {
229  // make sure the vector releases the underlying memory
230  std::vector<Double_t> tmp;
231  _vec.swap(tmp);
232  }
233 
234  inline void get(Int_t idx) const {
235  *_buf = *(_vec.begin() + idx) ;
236  }
237 
238  RooSpan<const double> getRange(std::size_t first, std::size_t last) const {
239  auto beg = std::min(_vec.cbegin() + first, _vec.cend());
240  auto end = std::min(_vec.cbegin() + last, _vec.cend());
241 
242  return RooSpan<const double>(beg, end);
243  }
244 
245  inline void getNative(Int_t idx) const {
246  *_nativeBuf = *(_vec.begin() + idx) ;
247  }
248 
249  Int_t size() const { return _vec.size() ; }
250 
251  void resize(Int_t siz) {
252  if (siz < Int_t(_vec.capacity()) / 2 && _vec.capacity() > (VECTOR_BUFFER_SIZE / sizeof(Double_t))) {
253  // do an expensive copy, if we save at least a factor 2 in size
254  std::vector<Double_t> tmp;
255  tmp.reserve(std::max(siz, Int_t(VECTOR_BUFFER_SIZE / sizeof(Double_t))));
256  if (!_vec.empty())
257  tmp.assign(_vec.begin(), std::min(_vec.end(), _vec.begin() + siz));
258  if (Int_t(tmp.size()) != siz)
259  tmp.resize(siz);
260  _vec.swap(tmp);
261  } else {
262  _vec.resize(siz);
263  }
264  }
265 
266  void reserve(Int_t siz) {
267  _vec.reserve(siz);
268  }
269 
270  const std::vector<double>& data() const {
271  return _vec;
272  }
273 
274  protected:
275  std::vector<double> _vec;
276 
277  private:
278  friend class RooVectorDataStore ;
279  RooAbsReal* _nativeReal ;
280  RooAbsReal* _real ;
281  Double_t* _buf ; //!
282  Double_t* _nativeBuf ; //!
283  RooChangeTracker* _tracker ; //
284  RooArgSet* _nset ; //!
285  ClassDef(RealVector,1) // STL-vector-based Data Storage class
286  } ;
287 
288 
289  class RealFullVector : public RealVector {
290  public:
291  RealFullVector(UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(Double_t))) : RealVector(initialCapacity),
292  _bufE(0), _bufEL(0), _bufEH(0),
293  _nativeBufE(0), _nativeBufEL(0), _nativeBufEH(0),
294  _vecE(0), _vecEL(0), _vecEH(0) {
295  }
296 
297  RealFullVector(RooAbsReal* arg, UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(Double_t))) :
298  RealVector(arg,initialCapacity),
299  _bufE(0), _bufEL(0), _bufEH(0),
300  _nativeBufE(0), _nativeBufEL(0), _nativeBufEH(0),
301  _vecE(0), _vecEL(0), _vecEH(0) {
302  }
303 
304  virtual ~RealFullVector() {
305  if (_vecE) delete _vecE ;
306  if (_vecEL) delete _vecEL ;
307  if (_vecEH) delete _vecEH ;
308  }
309 
310  RealFullVector(const RealFullVector& other, RooAbsReal* real=0) : RealVector(other,real),
311  _bufE(other._bufE), _bufEL(other._bufEL), _bufEH(other._bufEH),
312  _nativeBufE(other._nativeBufE), _nativeBufEL(other._nativeBufEL), _nativeBufEH(other._nativeBufEH) {
313  _vecE = (other._vecE) ? new std::vector<Double_t>(*other._vecE) : 0 ;
314  _vecEL = (other._vecEL) ? new std::vector<Double_t>(*other._vecEL) : 0 ;
315  _vecEH = (other._vecEH) ? new std::vector<Double_t>(*other._vecEH) : 0 ;
316  }
317 
318  RealFullVector(const RealVector& other, RooAbsReal* real=0) : RealVector(other,real),
319  _bufE(0), _bufEL(0), _bufEH(0),
320  _nativeBufE(0), _nativeBufEL(0), _nativeBufEH(0) {
321  _vecE = 0 ;
322  _vecEL = 0 ;
323  _vecEH = 0 ;
324  }
325 
326  RealFullVector& operator=(const RealFullVector& other) {
327  if (&other==this) return *this;
328  RealVector::operator=(other);
329  _bufE = other._bufE;
330  _bufEL = other._bufEL;
331  _bufEH = other._bufEH;
332  _nativeBufE = other._nativeBufE;
333  _nativeBufEL = other._nativeBufEL;
334  _nativeBufEH = other._nativeBufEH;
335  std::vector<Double_t>* src[3] = { other._vecE, other._vecEL, other._vecEH };
336  std::vector<Double_t>* dst[3] = { _vecE, _vecEL, _vecEH };
337  for (unsigned i = 0; i < 3; ++i) {
338  if (src[i]) {
339  if (dst[i]) {
340  if (dst[i]->size() <= src[i]->capacity() / 2 &&
341  src[i]->capacity() > (VECTOR_BUFFER_SIZE / sizeof(Double_t))) {
342  std::vector<Double_t> tmp;
343  tmp.reserve(std::max(src[i]->size(), VECTOR_BUFFER_SIZE / sizeof(Double_t)));
344  tmp.assign(src[i]->begin(), src[i]->end());
345  dst[i]->swap(tmp);
346  } else {
347  *dst[i] = *src[i];
348  }
349  } else {
350  dst[i] = new std::vector<Double_t>(*src[i]);
351  }
352  } else {
353  delete dst[i];
354  dst[i] = 0;
355  }
356  }
357  return *this;
358  }
359 
360  void setErrorBuffer(Double_t* newBuf) {
361  /* std::cout << "setErrorBuffer(" << _nativeReal->GetName() << ") newBuf = " << newBuf << std::endl ; */
362  _bufE = newBuf ;
363  if (!_vecE) _vecE = new std::vector<Double_t> ;
364  _vecE->reserve(_vec.capacity()) ;
365  if (!_nativeBufE) _nativeBufE = _bufE ;
366  }
367  void setAsymErrorBuffer(Double_t* newBufL, Double_t* newBufH) {
368  _bufEL = newBufL ; _bufEH = newBufH ;
369  if (!_vecEL) {
370  _vecEL = new std::vector<Double_t> ;
371  _vecEH = new std::vector<Double_t> ;
372  _vecEL->reserve(_vec.capacity()) ;
373  _vecEH->reserve(_vec.capacity()) ;
374  }
375  if (!_nativeBufEL) {
376  _nativeBufEL = _bufEL ;
377  _nativeBufEH = _bufEH ;
378  }
379  }
380 
381  inline void getNative(Int_t idx) const {
382  RealVector::getNative(idx) ;
383  if (_vecE) {
384  *_nativeBufE = (*_vecE)[idx] ;
385  }
386  if (_vecEL) {
387  *_nativeBufEL = (*_vecEL)[idx] ;
388  *_nativeBufEH = (*_vecEH)[idx] ;
389  }
390  }
391 
392  void fill() {
393  RealVector::fill() ;
394  if (_vecE) _vecE->push_back(*_bufE) ;
395  if (_vecEL) _vecEL->push_back(*_bufEL) ;
396  if (_vecEH) _vecEH->push_back(*_bufEH) ;
397  } ;
398 
399  void write(Int_t i) {
400  RealVector::write(i) ;
401  if (_vecE) (*_vecE)[i] = *_bufE ;
402  if (_vecEL) (*_vecEL)[i] = *_bufEL ;
403  if (_vecEH) (*_vecEH)[i] = *_bufEH ;
404  }
405 
406  void reset() {
407  RealVector::reset();
408  if (_vecE) {
409  std::vector<Double_t> tmp;
410  _vecE->swap(tmp);
411  }
412  if (_vecEL) {
413  std::vector<Double_t> tmp;
414  _vecEL->swap(tmp);
415  }
416  if (_vecEH) {
417  std::vector<Double_t> tmp;
418  _vecEH->swap(tmp);
419  }
420  }
421 
422  inline void get(Int_t idx) const {
423  RealVector::get(idx) ;
424  if (_vecE) *_bufE = (*_vecE)[idx];
425  if (_vecEL) *_bufEL = (*_vecEL)[idx] ;
426  if (_vecEH) *_bufEH = (*_vecEH)[idx] ;
427  }
428 
429  void resize(Int_t siz) {
430  RealVector::resize(siz);
431  std::vector<Double_t>* vlist[3] = { _vecE, _vecEL, _vecEH };
432  for (unsigned i = 0; i < 3; ++i) {
433  if (!vlist[i]) continue;
434  if (vlist[i]) {
435  if (siz < Int_t(vlist[i]->capacity()) / 2 && vlist[i]->capacity() > (VECTOR_BUFFER_SIZE / sizeof(Double_t))) {
436  // if we gain a factor of 2 in memory, we copy and swap
437  std::vector<Double_t> tmp;
438  tmp.reserve(std::max(siz, Int_t(VECTOR_BUFFER_SIZE / sizeof(Double_t))));
439  if (!vlist[i]->empty())
440  tmp.assign(vlist[i]->begin(),
441  std::min(_vec.end(), _vec.begin() + siz));
442  if (Int_t(tmp.size()) != siz)
443  tmp.resize(siz);
444  vlist[i]->swap(tmp);
445  } else {
446  vlist[i]->resize(siz);
447  }
448  }
449  }
450  }
451 
452  void reserve(Int_t siz) {
453  RealVector::reserve(siz);
454  if (_vecE) _vecE->reserve(siz);
455  if (_vecEL) _vecEL->reserve(siz);
456  if (_vecEH) _vecEH->reserve(siz);
457  }
458 
459  private:
460  friend class RooVectorDataStore ;
461  Double_t *_bufE ; //!
462  Double_t *_bufEL ; //!
463  Double_t *_bufEH ; //!
464  Double_t *_nativeBufE ; //!
465  Double_t *_nativeBufEL ; //!
466  Double_t *_nativeBufEH ; //!
467  std::vector<double> *_vecE, *_vecEL, *_vecEH ;
468  ClassDef(RealFullVector,1) // STL-vector-based Data Storage class
469  } ;
470 
471 
472  class CatVector {
473  public:
474  CatVector(UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(RooCatType))) :
475  _cat(0), _buf(0), _nativeBuf(0), _vec0(0)
476  {
477  _vec.reserve(initialCapacity);
478  }
479 
480  CatVector(RooAbsCategory* cat, UInt_t initialCapacity=(VECTOR_BUFFER_SIZE / sizeof(RooCatType))) :
481  _cat(cat), _buf(0), _nativeBuf(0), _vec0(0)
482  {
483  _vec.reserve(initialCapacity);
484  }
485 
486  virtual ~CatVector() {
487  }
488 
489  CatVector(const CatVector& other, RooAbsCategory* cat=0) :
490  _cat(cat?cat:other._cat), _buf(other._buf), _nativeBuf(other._nativeBuf), _vec(other._vec)
491  {
492  _vec0 = _vec.size()>0 ? &_vec.front() : 0 ;
493  }
494 
495  CatVector& operator=(const CatVector& other) {
496  if (&other==this) return *this;
497  _cat = other._cat;
498  _buf = other._buf;
499  _nativeBuf = other._nativeBuf;
500  if (other._vec.size() <= _vec.capacity() / 2 && _vec.capacity() > (VECTOR_BUFFER_SIZE / sizeof(RooCatType))) {
501  std::vector<RooCatType> tmp;
502  tmp.reserve(std::max(other._vec.size(), VECTOR_BUFFER_SIZE / sizeof(RooCatType)));
503  tmp.assign(other._vec.begin(), other._vec.end());
504  _vec.swap(tmp);
505  } else {
506  _vec = other._vec;
507  }
508  _vec0 = _vec.size()>0 ? &_vec.front() : 0;
509  return *this;
510  }
511 
512  void setBuffer(RooCatType* newBuf) {
513  _buf = newBuf ;
514  if (_nativeBuf==0) _nativeBuf=newBuf ;
515  }
516 
517  void setNativeBuffer(RooCatType* newBuf=0) {
518  _nativeBuf = newBuf ? newBuf : _buf ;
519  }
520 
521  void fill() {
522  _vec.push_back(*_buf) ;
523  _vec0 = &_vec.front() ;
524  } ;
525  void write(Int_t i) {
526  _vec[i]=*_buf ;
527  } ;
528  void reset() {
529  // make sure the vector releases the underlying memory
530  std::vector<RooCatType> tmp;
531  _vec.swap(tmp);
532  _vec0 = 0;
533  }
534  inline void get(Int_t idx) const {
535  _buf->assignFast(*(_vec0+idx)) ;
536  }
537  inline void getNative(Int_t idx) const {
538  _nativeBuf->assignFast(*(_vec0+idx)) ;
539  }
540  Int_t size() const { return _vec.size() ; }
541 
542  void resize(Int_t siz) {
543  if (siz < Int_t(_vec.capacity()) / 2 && _vec.capacity() > (VECTOR_BUFFER_SIZE / sizeof(RooCatType))) {
544  // do an expensive copy, if we save at least a factor 2 in size
545  std::vector<RooCatType> tmp;
546  tmp.reserve(std::max(siz, Int_t(VECTOR_BUFFER_SIZE / sizeof(RooCatType))));
547  if (!_vec.empty())
548  tmp.assign(_vec.begin(), std::min(_vec.end(), _vec.begin() + siz));
549  if (Int_t(tmp.size()) != siz)
550  tmp.resize(siz);
551  _vec.swap(tmp);
552  } else {
553  _vec.resize(siz);
554  }
555  _vec0 = _vec.size() > 0 ? &_vec.front() : 0;
556  }
557 
558  void reserve(Int_t siz) {
559  _vec.reserve(siz);
560  _vec0 = _vec.size() > 0 ? &_vec.front() : 0;
561  }
562 
563  void setBufArg(RooAbsCategory* arg) { _cat = arg; }
564  const RooAbsCategory* bufArg() const { return _cat; }
565 
566  private:
567  friend class RooVectorDataStore ;
568  RooAbsCategory* _cat ;
569  RooCatType* _buf ; //!
570  RooCatType* _nativeBuf ; //!
571  std::vector<RooCatType> _vec ;
572  RooCatType* _vec0 ; //!
573  ClassDef(CatVector,1) // STL-vector-based Data Storage class
574  } ;
575 
576 
577  protected:
578 
579  friend class RooAbsReal ;
580  friend class RooAbsCategory ;
581  friend class RooRealVar ;
582  std::vector<RealVector*>& realStoreList() { return _realStoreList ; }
583  std::vector<RealFullVector*>& realfStoreList() { return _realfStoreList ; }
584  std::vector<CatVector*>& catStoreList() { return _catStoreList ; }
585 
586  CatVector* addCategory(RooAbsCategory* cat) {
587 
588  // First try a match by name
589  for (auto catVec : _catStoreList) {
590  if (std::string(catVec->bufArg()->GetName())==cat->GetName()) {
591  return catVec;
592  }
593  }
594 
595  // If nothing found this will make an entry
596  _catStoreList.push_back(new CatVector(cat)) ;
597  _nCat++ ;
598 
599  // Update cached ptr to first element as push_back may have reallocated
600  _firstCat = &_catStoreList.front() ;
601 
602  return _catStoreList.back() ;
603  }
604 
605  RealVector* addReal(RooAbsReal* real) {
606 
607  // First try a match by name
608  for (auto realVec : _realStoreList) {
609  if (realVec->bufArg()->namePtr()==real->namePtr()) {
610  return realVec;
611  }
612  }
613 
614  // Then check if an entry already exists for a full real
615  for (auto fullVec : _realfStoreList) {
616  if (fullVec->bufArg()->namePtr()==real->namePtr()) {
617  // Return full vector as RealVector base class here
618  return fullVec;
619  }
620  }
621 
622  // If nothing found this will make an entry
623  _realStoreList.push_back(new RealVector(real)) ;
624 
625  return _realStoreList.back() ;
626  }
627 
628  Bool_t isFullReal(RooAbsReal* real) {
629 
630  // First try a match by name
631  for (auto fullVec : _realfStoreList) {
632  if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
633  return kTRUE ;
634  }
635  }
636  return kFALSE ;
637  }
638 
639  Bool_t hasError(RooAbsReal* real) {
640 
641  // First try a match by name
642  for (auto fullVec : _realfStoreList) {
643  if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
644  return fullVec->_vecE ? kTRUE : kFALSE ;
645  }
646  }
647  return kFALSE ;
648  }
649 
650  Bool_t hasAsymError(RooAbsReal* real) {
651 
652  // First try a match by name
653  for (auto fullVec : _realfStoreList) {
654  if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
655  return fullVec->_vecEL ? kTRUE : kFALSE ;
656  }
657  }
658  return kFALSE ;
659  }
660 
661  RealFullVector* addRealFull(RooAbsReal* real) {
662 
663  // First try a match by name
664  for (auto fullVec : _realfStoreList) {
665  if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
666  return fullVec;
667  }
668  }
669 
670  // Then check if an entry already exists for a bare real
671  for (auto realVec : _realStoreList) {
672  if (std::string(realVec->bufArg()->GetName())==real->GetName()) {
673 
674  // Convert element to full and add to full list
675  _realfStoreList.push_back(new RealFullVector(*realVec,real)) ;
676  _nRealF++ ;
677  _firstRealF = &_realfStoreList.front() ;
678 
679  // Delete bare element
680  _realStoreList.erase(std::find(_realStoreList.begin(), _realStoreList.end(), realVec));
681  delete realVec;
682 
683  return _realfStoreList.back() ;
684  }
685  }
686 
687  // If nothing found this will make an entry
688  _realfStoreList.push_back(new RealFullVector(real)) ;
689  _nRealF++ ;
690 
691  // Update cached ptr to first element as push_back may have reallocated
692  _firstRealF = &_realfStoreList.front() ;
693 
694 
695  return _realfStoreList.back() ;
696  }
697 
698  virtual Bool_t hasFilledCache() const override { return _cache ? kTRUE : kFALSE ; }
699 
700  void forceCacheUpdate() override;
701 
702  private:
703  RooArgSet _varsww ;
704  RooRealVar* _wgtVar ; // Pointer to weight variable (if set)
705 
706  std::vector<RealVector*> _realStoreList ;
707  std::vector<RealFullVector*> _realfStoreList ;
708  std::vector<CatVector*> _catStoreList ;
709  std::vector<double> _weights;
710 
711  void setAllBuffersNative() ;
712 
713  Int_t _nRealF ;
714  Int_t _nCat ;
715  Int_t _nEntries ;
716  RealFullVector** _firstRealF ; //! do not persist
717  CatVector** _firstCat ; //! do not persist
718  Double_t _sumWeight ;
719  Double_t _sumWeightCarry;
720 
721  const Double_t* _extWgtArray ; //! External weight array
722  const Double_t* _extWgtErrLoArray ; //! External weight array - low error
723  const Double_t* _extWgtErrHiArray ; //! External weight array - high error
724  const Double_t* _extSumW2Array ; //! External sum of weights array
725 
726  mutable Double_t _curWgt ; // Weight of current event
727  mutable Double_t _curWgtErrLo ; // Weight of current event
728  mutable Double_t _curWgtErrHi ; // Weight of current event
729  mutable Double_t _curWgtErr ; // Weight of current event
730 
731  RooVectorDataStore* _cache ; //! Optimization cache
732  RooAbsArg* _cacheOwner ; //! Cache owner
733 
734  Bool_t _forcedUpdate ; //! Request for forced cache update
735 
736  ClassDefOverride(RooVectorDataStore,3) // STL-vector-based Data Storage class
737 };
738 
739 
740 #endif