Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooLinkedList.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$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
17/**
18\file RooLinkedList.cxx
19\class RooLinkedList
20\ingroup Roofitcore
21
22RooLinkedList is an collection class for internal use, storing
23a collection of RooAbsArg pointers in a doubly linked list.
24It can optionally add a hash table to speed up random access
25in large collections
26Use RooAbsCollection derived objects for public use
27(e.g. RooArgSet or RooArgList)
28**/
29
30#include "RooLinkedList.h"
31
32#include "RooLinkedListIter.h"
33#include "RooAbsArg.h"
34#include "RooAbsData.h"
35#include "RooMsgService.h"
36
37#include "Riostream.h"
38#include "TBuffer.h"
39#include "TROOT.h"
40
41#include <algorithm>
42#include <list>
43#include <memory>
44#include <vector>
45
46using namespace std;
47
49
50/// \cond ROOFIT_INTERNAL
51
52namespace RooLinkedListImplDetails {
53 /// a chunk of memory in a pool for quick allocation of RooLinkedListElems
54 class Chunk {
55 public:
56 /// constructor
57 Chunk(Int_t sz) :
58 _sz(sz), _free(capacity()),
59 _chunk(new RooLinkedListElem[_free]), _freelist(_chunk)
60 {
61 //cout << "RLLID::Chunk ctor(" << this << ") of size " << _free << " list elements" << endl ;
62 // initialise free list
63 for (Int_t i = 0; i < _free; ++i)
64 _chunk[i]._next = (i + 1 < _free) ? &_chunk[i + 1] : nullptr;
65 }
66 /// destructor
67 ~Chunk() { delete[] _chunk; }
68 /// chunk capacity
69 Int_t capacity() const
70 { return (1 << _sz) / sizeof(RooLinkedListElem); }
71 /// chunk free elements
72 Int_t free() const { return _free; }
73 /// chunk occupied elements
74 Int_t size() const { return capacity() - free(); }
75 /// return size class
76 int szclass() const { return _sz; }
77 /// chunk full?
78 bool full() const { return !free(); }
79 /// chunk empty?
80 bool empty() const { return capacity() == free(); }
81 /// return address of chunk
82 const void* chunkaddr() const { return _chunk; }
83 /// check if el is in this chunk
84 bool contains(RooLinkedListElem* el) const
85 { return _chunk <= el && el < &_chunk[capacity()]; }
86 /// pop a free element off the free list
87 RooLinkedListElem* pop_free_elem()
88 {
89 if (!_freelist) return nullptr;
90 RooLinkedListElem* retVal = _freelist;
91 _freelist = retVal->_next;
92 retVal->_arg = nullptr; retVal->_refCount = 0;
93 retVal->_prev = retVal->_next = nullptr;
94 --_free;
95 return retVal;
96 }
97 /// push a free element back onto the freelist
98 void push_free_elem(RooLinkedListElem* el)
99 {
100 el->_next = _freelist;
101 _freelist = el;
102 ++_free;
103 }
104 private:
105 Int_t _sz; ///< chunk capacity
106 Int_t _free; ///< length of free list
107 RooLinkedListElem* _chunk; ///< chunk from which elements come
108 RooLinkedListElem* _freelist; ///< list of free elements
109
110 /// forbid copying
111 Chunk(const Chunk&) = delete;
112 // forbid assignment
113 Chunk& operator=(const Chunk&) = delete;
114 };
115
116 class Pool {
117 private:
118 enum {
119 minsz = 7, ///< minimum chunk size (just below 1 << minsz bytes)
120 maxsz = 18, ///< maximum chunk size (just below 1 << maxsz bytes)
121 szincr = 1 ///< size class increment (sz = 1 << (minsz + k * szincr))
122 };
123 /// a chunk of memory in the pool
124 typedef RooLinkedListImplDetails::Chunk Chunk;
125 typedef std::list<Chunk*> ChunkList;
126 typedef std::map<const void*, Chunk*> AddrMap;
127 public:
128 /// constructor
129 Pool();
130 /// destructor
131 ~Pool();
132 /// acquire the pool
133 inline void acquire() { ++_refCount; }
134 /// release the pool, return true if the pool is unused
135 inline bool release() { return 0 == --_refCount; }
136 /// pop a free element out of the pool
137 RooLinkedListElem* pop_free_elem();
138 /// push a free element back into the pool
139 void push_free_elem(RooLinkedListElem* el);
140 private:
141 AddrMap _addrmap;
142 ChunkList _freelist;
143 UInt_t _szmap[(maxsz - minsz) / szincr];
144 Int_t _cursz;
145 UInt_t _refCount;
146
147 /// adjust _cursz to current largest block
148 void updateCurSz(Int_t sz, Int_t incr);
149 /// find size of next chunk to allocate (in a hopefully smart way)
150 Int_t nextChunkSz() const;
151 };
152
153 Pool::Pool() : _cursz(minsz), _refCount(0)
154 {
155 std::fill(_szmap, _szmap + ((maxsz - minsz) / szincr), 0);
156 }
157
158 Pool::~Pool()
159 {
160 _freelist.clear();
161 for (AddrMap::iterator it = _addrmap.begin(); _addrmap.end() != it; ++it)
162 delete it->second;
163 _addrmap.clear();
164 }
165
166 RooLinkedListElem* Pool::pop_free_elem()
167 {
168 if (_freelist.empty()) {
169 // allocate and register new chunk and put it on the freelist
170 const Int_t sz = nextChunkSz();
171 Chunk *c = new Chunk(sz);
172 _addrmap[c->chunkaddr()] = c;
173 _freelist.push_back(c);
174 updateCurSz(sz, +1);
175 }
176 // get free element from first chunk on _freelist
177 Chunk* c = _freelist.front();
178 RooLinkedListElem* retVal = c->pop_free_elem();
179 // full chunks are removed from _freelist
180 if (c->full()) _freelist.pop_front();
181 return retVal;
182 }
183
184 void Pool::push_free_elem(RooLinkedListElem* el)
185 {
186 // find from which chunk el came
187 AddrMap::iterator ci = _addrmap.end();
188 if (!_addrmap.empty()) {
189 ci = _addrmap.lower_bound(el);
190 if (ci == _addrmap.end()) {
191 // point beyond last element, so get last one
192 ci = (++_addrmap.rbegin()).base();
193 } else {
194 // valid ci, check if we need to decrement ci because el isn't the
195 // first element in the chunk
196 if (_addrmap.begin() != ci && ci->first != el) --ci;
197 }
198 }
199 // either empty addressmap, or ci should now point to the chunk which might
200 // contain el
201 if (_addrmap.empty() || !ci->second->contains(el)) {
202 // el is not in any chunk we know about, so just delete it
203 delete el;
204 return;
205 }
206 Chunk *c = ci->second;
207 const bool moveToFreelist = c->full();
208 c->push_free_elem(el);
209 if (c->empty()) {
210 // delete chunk if all empty
211 ChunkList::iterator it = std::find( _freelist.begin(), _freelist.end(), c);
212 if (_freelist.end() != it) _freelist.erase(it);
213 _addrmap.erase(ci->first);
214 updateCurSz(c->szclass(), -1);
215 delete c;
216 } else if (moveToFreelist) {
217 _freelist.push_back(c);
218 }
219 }
220
221 void Pool::updateCurSz(Int_t sz, Int_t incr)
222 {
223 _szmap[(sz - minsz) / szincr] += incr;
224 _cursz = minsz;
225 for (int i = (maxsz - minsz) / szincr; i--; ) {
226 if (_szmap[i]) {
227 _cursz += i * szincr;
228 break;
229 }
230 }
231 }
232
233 Int_t Pool::nextChunkSz() const
234 {
235 // no chunks with space available, figure out chunk size
236 Int_t sz = _cursz;
237 if (_addrmap.empty()) {
238 // if we start allocating chunks, we start from minsz
239 sz = minsz;
240 } else {
241 if (minsz >= sz) {
242 // minimal sized chunks are always grown
243 sz = minsz + szincr;
244 } else {
245 if (1 != _addrmap.size()) {
246 // if we have more than one completely filled chunk, grow
247 sz += szincr;
248 } else {
249 // just one chunk left, try shrinking chunk size
250 sz -= szincr;
251 }
252 }
253 }
254 // clamp size to allowed range
255 if (sz > maxsz) sz = maxsz;
256 if (sz < minsz) sz = minsz;
257 return sz;
258 }
259}
260
261/// \endcond
262
264
265////////////////////////////////////////////////////////////////////////////////
266
268 _hashThresh(htsize), _size(0), _first(nullptr), _last(nullptr), _htableName(nullptr), _htableLink(nullptr), _useNptr(true)
269{
270 if (!_pool) _pool = new Pool;
271 _pool->acquire();
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// Copy constructor
276
278 TObject(other), _hashThresh(other._hashThresh), _size(0), _first(nullptr), _last(nullptr), _htableName(nullptr), _htableLink(nullptr),
279 _name(other._name),
280 _useNptr(other._useNptr)
281{
282 if (!_pool) _pool = new Pool;
283 _pool->acquire();
284 if (other._htableName) _htableName = std::make_unique<HashTableByName>(other._htableName->size()) ;
285 if (other._htableLink) _htableLink = std::make_unique<HashTableByLink>(other._htableLink->size()) ;
286 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
287 Add(elem->_arg, elem->_refCount) ;
288 }
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
293
295{
296 RooLinkedListElem* ret = _pool->pop_free_elem();
297 ret->init(obj, elem);
298 return ret ;
299}
300
301////////////////////////////////////////////////////////////////////////////////
302
304{
305 elem->release() ;
306 _pool->push_free_elem(elem);
307 //delete elem ;
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Assignment operator, copy contents from 'other'
312
314{
315 // Prevent self-assignment
316 if (&other==this) return *this ;
317
318 // remove old elements
319 Clear();
320 // Copy elements
321 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
322 Add(elem->_arg) ;
323 }
324
325 return *this ;
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// Change the threshold for hash-table use to given size.
330/// If a hash table exists when this method is called, it is regenerated.
331
333{
334 if (size<0) {
335 coutE(InputArguments) << "RooLinkedList::setHashTable() ERROR size must be positive" << endl ;
336 return ;
337 }
338 if (size==0) {
339 if (!_htableName) {
340 // No hash table present
341 return ;
342 } else {
343 // Remove existing hash table
344 _htableName.reset();
345 _htableLink.reset();
346 }
347 } else {
348
349 // (Re)create hash tables
350 _htableName = std::make_unique<HashTableByName>(size) ;
351 _htableLink = std::make_unique<HashTableByLink>(size) ;
352
353 // Fill hash table with existing entries
355 while(ptr) {
356 _htableName->insert({ptr->_arg->GetName(), ptr->_arg}) ;
357 _htableLink->insert({ptr->_arg, (TObject*)ptr}) ;
358 ptr = ptr->_next ;
359 }
360 }
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// Destructor
365
367{
368 // Required since we overload TObject::Hash.
370
371 _htableName.reset();
372 _htableLink.reset();
373
374 Clear() ;
375 if (_pool->release()) {
376 delete _pool;
377 _pool = nullptr;
378 }
379}
380
381////////////////////////////////////////////////////////////////////////////////
382/// Find the element link containing the given object
383
385{
386 if (_htableLink) {
387 auto found = _htableLink->find(arg);
388 if (found == _htableLink->end()) return nullptr;
389 return (RooLinkedListElem*)found->second;
390 }
391
393 while(ptr) {
394 if (ptr->_arg == arg) {
395 return ptr ;
396 }
397 ptr = ptr->_next ;
398 }
399 return nullptr ;
400
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Insert object into collection with given reference count value
405
406void RooLinkedList::Add(TObject* arg, Int_t refCount)
407{
408 if (!arg) return ;
409
410 // Only use RooAbsArg::namePtr() in lookup-by-name if all elements have it
411 if (!dynamic_cast<RooAbsArg*>(arg) && !dynamic_cast<RooAbsData*>(arg)) _useNptr = false;
412
413 // Add to hash table
414 if (_htableName) {
415
416 // Expand capacity of hash table if #entries>#slots
417 if (static_cast<size_t>(_size) > _htableName->size()) {
419 }
420
421 } else if (_hashThresh>0 && _size>_hashThresh) {
422
424 }
425
426 if (_last) {
427 // Append element at end of list
428 _last = createElement(arg,_last) ;
429 } else {
430 // Append first element, set first,last
431 _last = createElement(arg) ;
432 _first=_last ;
433 }
434
435 if (_htableName){
436 //cout << "storing link " << _last << " with hash arg " << arg << endl ;
437 _htableName->insert({arg->GetName(), arg});
438 _htableLink->insert({arg, (TObject*)_last});
439 }
440
441 _size++ ;
442 _last->_refCount = refCount ;
443
444 _at.push_back(_last);
445}
446
447////////////////////////////////////////////////////////////////////////////////
448/// Remove object from collection
449
451{
452 // Find link element
453 RooLinkedListElem* elem = findLink(arg) ;
454 if (!elem) return false ;
455
456 // Remove from hash table
457 if (_htableName) {
458 _htableName->erase(arg->GetName()) ;
459 }
460 if (_htableLink) {
461 _htableLink->erase(arg) ;
462 }
463
464 // Update first,last if necessary
465 if (elem==_first) _first=elem->_next ;
466 if (elem==_last) _last=elem->_prev ;
467
468 // Remove from index array
469 auto at_elem_it = std::find(_at.begin(), _at.end(), elem);
470 _at.erase(at_elem_it);
471
472 // Delete and shrink
473 _size-- ;
474 deleteElement(elem) ;
475 return true ;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// If one of the TObject we have a referenced to is deleted, remove the
480/// reference.
481
483{
484 Remove(obj); // This is a nop if the obj is not in the collection.
485}
486
487////////////////////////////////////////////////////////////////////////////////
488/// Return object stored in sequential position given by index.
489/// If index is out of range, a null pointer is returned.
490
492{
493 // Check range
494 if (index<0 || index>=_size) return nullptr ;
495
496 return _at[index]->_arg;
497//
498//
499// // Walk list
500// RooLinkedListElem* ptr = _first;
501// while(index--) ptr = ptr->_next ;
502//
503// // Return arg
504// return ptr->_arg ;
505}
506
507////////////////////////////////////////////////////////////////////////////////
508/// Replace object 'oldArg' in collection with new object 'newArg'.
509/// If 'oldArg' is not found in collection false is returned
510
511bool RooLinkedList::Replace(const TObject* oldArg, const TObject* newArg)
512{
513 // Find existing element and replace arg
514 RooLinkedListElem* elem = findLink(oldArg) ;
515 if (!elem) return false ;
516
517 if (_htableName) {
518 _htableName->erase(oldArg->GetName());
519 _htableName->insert({newArg->GetName(), newArg});
520 }
521 if (_htableLink) {
522 // Link is hashed by contents and may change slot in hash table
523 _htableLink->erase(oldArg) ;
524 _htableLink->insert({newArg, (TObject*)elem}) ;
525 }
526
527 elem->_arg = (TObject*)newArg ;
528 return true ;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Return pointer to object with given name. If no such object
533/// is found return a null pointer.
534
536{
537 return find(name) ;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Find object in list. If list contains object return
542/// (same) pointer to object, otherwise return null pointer
543
545{
546 RooLinkedListElem *elem = findLink((TObject*)obj) ;
547 return elem ? elem->_arg : nullptr ;
548}
549
550////////////////////////////////////////////////////////////////////////////////
551/// Remove all elements from collection
552
554{
555 for (RooLinkedListElem *elem = _first, *next; elem; elem = next) {
556 next = elem->_next ;
557 deleteElement(elem) ;
558 }
559 _first = nullptr ;
560 _last = nullptr ;
561 _size = 0 ;
562
563 if (_htableName) {
564 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
565 }
566 if (_htableLink) {
567 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
568 }
569
570 // empty index array
571 _at.clear();
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Remove all elements in collection and delete all elements
576/// NB: Collection does not own elements, this function should
577/// be used judiciously by caller.
578
580{
582 while(elem) {
583 RooLinkedListElem* next = elem->_next ;
584 delete elem->_arg ;
585 deleteElement(elem) ;
586 elem = next ;
587 }
588 _first = nullptr ;
589 _last = nullptr ;
590 _size = 0 ;
591
592 if (_htableName) {
593 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
594 }
595 if (_htableLink) {
596 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
597 }
598
599 // empty index array
600 _at.clear();
601}
602
603////////////////////////////////////////////////////////////////////////////////
604/// Return pointer to object with given name in collection.
605/// If no such object is found, return null pointer.
606
608{
609
610 if (_htableName) {
611 auto found = _htableName->find(name);
612 TObject *a = found != _htableName->end() ? const_cast<TObject*>(found->second) : nullptr;
613 // RooHashTable::find could return false negative if element was renamed to 'name'.
614 // The list search means it won't return false positive, so can return here.
615 if (a) return a;
616 if (_useNptr) {
617 // See if it might have been renamed
618 const TNamed* nptr= RooNameReg::known(name);
619 //cout << "RooLinkedList::find: possibly renamed '" << name << "', kRenamedArg=" << (nptr&&nptr->TestBit(RooNameReg::kRenamedArg)) << endl;
620 if (nptr && nptr->TestBit(RooNameReg::kRenamedArg)) {
622 while(ptr) {
623 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
624 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
625 return ptr->_arg ;
626 }
627 ptr = ptr->_next ;
628 }
629 }
630 return nullptr ;
631 }
632 //cout << "RooLinkedList::find: possibly renamed '" << name << "'" << endl;
633 }
634
636
637 // The penalty for RooNameReg lookup seems to be outweighted by the faster search
638 // when the size list is longer than ~7, but let's be a bit conservative.
639 if (_useNptr && _size>9) {
640 const TNamed* nptr= RooNameReg::known(name);
641 if (!nptr) return nullptr;
642
643 while(ptr) {
644 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
645 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
646 return ptr->_arg ;
647 }
648 ptr = ptr->_next ;
649 }
650 return nullptr ;
651 }
652
653 while(ptr) {
654 if (!strcmp(ptr->_arg->GetName(),name)) {
655 return ptr->_arg ;
656 }
657 ptr = ptr->_next ;
658 }
659 return nullptr ;
660}
661
662////////////////////////////////////////////////////////////////////////////////
663/// Return pointer to object with given name in collection.
664/// If no such object is found, return null pointer.
665
667{
668 if (_htableName) {
669 RooAbsArg* a = (RooAbsArg*) (*_htableName)[arg->GetName()] ;
670 if (a) return a;
671 //cout << "RooLinkedList::findArg: possibly renamed '" << arg->GetName() << "', kRenamedArg=" << arg->namePtr()->TestBit(RooNameReg::kRenamedArg) << endl;
672 // See if it might have been renamed
673 if (!arg->namePtr()->TestBit(RooNameReg::kRenamedArg)) return nullptr;
674 }
675
677 const TNamed* nptr = arg->namePtr();
678 while(ptr) {
679 if (((RooAbsArg*)(ptr->_arg))->namePtr() == nptr) {
680 return (RooAbsArg*) ptr->_arg ;
681 }
682 ptr = ptr->_next ;
683 }
684 return nullptr ;
685}
686
687////////////////////////////////////////////////////////////////////////////////
688/// Return position of given object in list. If object
689/// is not contained in list, return -1
690
692{
694 Int_t idx(0) ;
695 while(ptr) {
696 if (ptr->_arg==arg) return idx ;
697 ptr = ptr->_next ;
698 idx++ ;
699 }
700 return -1 ;
701}
702
703////////////////////////////////////////////////////////////////////////////////
704/// Return position of given object in list. If object
705/// is not contained in list, return -1
706
708{
710 Int_t idx(0) ;
711 while(ptr) {
712 if (strcmp(ptr->_arg->GetName(),name)==0) return idx ;
713 ptr = ptr->_next ;
714 idx++ ;
715 }
716 return -1 ;
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// Print contents of list, defers to Print() function
721/// of contained objects
722
723void RooLinkedList::Print(const char* opt) const
724{
725 RooLinkedListElem* elem = _first ;
726 while(elem) {
727 cout << elem->_arg << " : " ;
728 elem->_arg->Print(opt) ;
729 elem = elem->_next ;
730 }
731}
732
733////////////////////////////////////////////////////////////////////////////////
734/// Create a TIterator for this list.
735/// \param forward Run in forward direction (default).
736/// \return Pointer to a TIterator. The caller owns the pointer.
737
739 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
740 return new RooLinkedListIter(std::move(iterImpl));
741}
742
743////////////////////////////////////////////////////////////////////////////////
744/// Create an iterator for this list.
745/// \param forward Run in forward direction (default).
746/// \return RooLinkedListIter (subclass of TIterator) over this list
747
749 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
750 return RooLinkedListIter(std::move(iterImpl));
751}
752
753////////////////////////////////////////////////////////////////////////////////
754/// Create a one-time-use forward iterator for this list.
755/// \return RooFIter that only supports next()
756
758 auto iterImpl = std::make_unique<RooFIterForLinkedList>(this);
759 return RooFIter(std::move(iterImpl));
760}
761
763 return {this, true};
764}
765
767 return {this, nullptr, true};
768}
769
771 return {this, false};
772}
773
775 return {this, nullptr, false};
776}
777
778////////////////////////////////////////////////////////////////////////////////
779
780void RooLinkedList::Sort(bool ascend)
781{
782 if (ascend) _first = mergesort_impl<true>(_first, _size, &_last);
783 else _first = mergesort_impl<false>(_first, _size, &_last);
784
785 // rebuild index array
787 for (auto it = _at.begin(); it != _at.end(); ++it, elem = elem->_next) {
788 *it = elem;
789 }
790}
791
792////////////////////////////////////////////////////////////////////////////////
793/// length 0, 1 lists are sorted
794
795template <bool ascending>
797 RooLinkedListElem* l1, const unsigned sz, RooLinkedListElem** tail)
798{
799 if (!l1 || sz < 2) {
800 // if desired, update the tail of the (newly merged sorted) list
801 if (tail) *tail = l1;
802 return l1;
803 }
804 if (sz <= 16) {
805 // for short lists, we sort in an array
806 std::vector<RooLinkedListElem *> arr(sz, nullptr);
807 for (int i = 0; l1; l1 = l1->_next, ++i) arr[i] = l1;
808 // straight insertion sort
809 {
810 int i = 1;
811 do {
812 int j = i - 1;
813 RooLinkedListElem *tmp = arr[i];
814 while (0 <= j) {
815 const bool inOrder = ascending ?
816 (tmp->_arg->Compare(arr[j]->_arg) <= 0) :
817 (arr[j]->_arg->Compare(tmp->_arg) <= 0);
818 if (!inOrder) break;
819 arr[j + 1] = arr[j];
820 --j;
821 }
822 arr[j + 1] = tmp;
823 ++i;
824 } while (int(sz) != i);
825 }
826 // link elements in array
827 arr[0]->_prev = arr[sz - 1]->_next = nullptr;
828 for (int i = 0; i < int(sz - 1); ++i) {
829 arr[i]->_next = arr[i + 1];
830 arr[i + 1]->_prev = arr[i];
831 }
832 if (tail) *tail = arr[sz - 1];
833 return arr[0];
834 }
835 // find middle of l1, and let a second list l2 start there
836 RooLinkedListElem *l2 = l1;
837 for (RooLinkedListElem *end = l2; end->_next; end = end->_next) {
838 end = end->_next;
839 l2 = l2->_next;
840 if (!end->_next) break;
841 }
842 // disconnect the two sublists
843 l2->_prev->_next = nullptr;
844 l2->_prev = nullptr;
845 // sort the two sublists (only recurse if we have to)
846 if (l1->_next) l1 = mergesort_impl<ascending>(l1, sz / 2);
847 if (l2->_next) l2 = mergesort_impl<ascending>(l2, sz - sz / 2);
848 // merge the two (sorted) sublists
849 // l: list head, t: list tail of merged list
850 RooLinkedListElem *l = (ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
851 (l2->_arg->Compare(l1->_arg) <= 0)) ? l1 : l2;
852 RooLinkedListElem *t = l;
853 if (l == l2) {
854 RooLinkedListElem* tmp = l1;
855 l1 = l2;
856 l2 = tmp;
857 }
858 l1 = l1->_next;
859 while (l1 && l2) {
860 const bool inOrder = ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
861 (l2->_arg->Compare(l1->_arg) <= 0);
862 if (!inOrder) {
863 // insert l2 just before l1
864 if (l1->_prev) {
865 l1->_prev->_next = l2;
866 l2->_prev = l1->_prev;
867 }
868 // swap l2 and l1
869 RooLinkedListElem *tmp = l1;
870 l1 = l2;
871 l2 = tmp;
872 }
873 // move forward in l1
874 t = l1;
875 l1 = l1->_next;
876 }
877 // attach l2 at t
878 if (l2) {
879 l2->_prev = t;
880 if (t) t->_next = l2;
881 }
882 // if desired, update the tail of the (newly merged sorted) list
883 if (tail) {
884 for (l1 = t; l1; l1 = l1->_next) t = l1;
885 *tail = t;
886 }
887 // return the head of the sorted list
888 return l;
889}
890// void Roo1DTable::Streamer(TBuffer &R__b)
891// {
892// // Stream an object of class Roo1DTable.
893
894// if (R__b.IsReading()) {
895// R__b.ReadClassBuffer(Roo1DTable::Class(),this);
896// } else {
897// R__b.WriteClassBuffer(Roo1DTable::Class(),this);
898// }
899// }
900
901////////////////////////////////////////////////////////////////////////////////
902/// Custom streaming handling schema evolution w.r.t past implementations
903
905{
906 if (R__b.IsReading()) {
907
908 Version_t v = R__b.ReadVersion();
909 //R__b.ReadVersion();
910 TObject::Streamer(R__b);
911
912 Int_t size ;
913 TObject* arg ;
914
915 R__b >> size ;
916 while(size--) {
917 R__b >> arg ;
918 Add(arg) ;
919 }
920
921 if (v > 1 && v < 4) {
922 R__b >> _name;
923 }
924
925 } else {
927 TObject::Streamer(R__b);
928 R__b << _size ;
929
931 while(ptr) {
932 R__b << ptr->_arg ;
933 ptr = ptr->_next ;
934 }
935
936 R__b << _name ;
937 }
938}
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutE(a)
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
char name[80]
Definition TGX11.cxx:110
Binding & operator=(OUT(*fun)(void))
#define free
Definition civetweb.c:1539
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:79
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:563
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsData.h:297
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooLinkedListElem is an link element for the RooLinkedList class.
TObject * _arg
Link to contents.
Int_t _refCount
! Reference count
void init(TObject *arg, RooLinkedListElem *after=nullptr)
RooLinkedListElem * _prev
Link to previous element in list.
RooLinkedListElem * _next
Link to next element in list.
Implementation of the actual iterator on RooLinkedLists.
A wrapper around TIterator derivatives.
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
RooLinkedListIterImpl rend() const
TObject * At(int index) const
Return object stored in sequential position given by index.
RooLinkedListIter iterator(bool forward=true) const
Create an iterator for this list.
static Pool * _pool
shared memory pool for allocation of RooLinkedListElems
~RooLinkedList() override
Destructor.
RooLinkedListIterImpl end() const
RooLinkedListImplDetails::Pool Pool
memory pool for quick allocation of RooLinkedListElems
std::vector< RooLinkedListElem * > _at
! index list for quick index through At
std::unique_ptr< HashTableByName > _htableName
! Hash table by name
void RecursiveRemove(TObject *obj) override
If one of the TObject we have a referenced to is deleted, remove the reference.
bool Replace(const TObject *oldArg, const TObject *newArg)
Replace object 'oldArg' in collection with new object 'newArg'.
RooLinkedList(Int_t htsize=0)
void Print(const char *opt) const override
Print contents of list, defers to Print() function of contained objects.
std::unique_ptr< HashTableByLink > _htableLink
! Hash table by link pointer
RooFIter fwdIterator() const
Create a one-time-use forward iterator for this list.
void deleteElement(RooLinkedListElem *)
RooLinkedListElem * findLink(const TObject *arg) const
Find the element link containing the given object.
void Streamer(TBuffer &) override
Custom streaming handling schema evolution w.r.t past implementations.
RooLinkedListIterImpl rbegin() const
std::size_t size() const
TClass * IsA() const override
Int_t _hashThresh
Size threshold for hashing.
RooLinkedListElem * createElement(TObject *obj, RooLinkedListElem *elem=nullptr)
cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
RooAbsArg * findArg(const RooAbsArg *) const
Return pointer to object with given name in collection.
void Delete(Option_t *o=nullptr) override
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
TObject * find(const char *name) const
Return pointer to object with given name in collection.
RooLinkedList & operator=(const RooLinkedList &other)
Assignment operator, copy contents from 'other'.
virtual void Add(TObject *arg)
Int_t _size
Current size of list.
RooLinkedListIterImpl begin() const
RooLinkedListElem * _last
! Link to last element of list
void setHashTableSize(Int_t size)
Change the threshold for hash-table use to given size.
TObject * FindObject(const char *name) const override
Return pointer to object with given name.
RooLinkedListElem * _first
! Link to first element of list
TIterator * MakeIterator(bool forward=true) const
Create a TIterator for this list.
void Clear(Option_t *o=nullptr) override
Remove all elements from collection.
static RooLinkedListElem * mergesort_impl(RooLinkedListElem *l1, const unsigned sz, RooLinkedListElem **tail=nullptr)
length 0, 1 lists are sorted
void Sort(bool ascend=true)
Int_t IndexOf(const char *name) const
Return position of given object in list.
virtual bool Remove(TObject *arg)
Remove object from collection.
@ kRenamedArg
TNamed flag to indicate that some RooAbsArg has been renamed (flag set in new name)
Definition RooNameReg.h:44
static const TNamed * known(const char *stringPtr)
If the name is already known, return its TNamed pointer. Otherwise return 0 (don't register the name)...
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Iterator abstract base class.
Definition TIterator.h:30
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:888
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition TObject.cxx:238
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition TObject.cxx:636
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:396
TLine l
Definition textangle.C:4