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
22Collection 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
46
47/// \cond ROOFIT_INTERNAL
48
50 /// a chunk of memory in a pool for quick allocation of RooLinkedListElems
51 class Chunk {
52 public:
53 /// constructor
54 Chunk(Int_t sz) :
55 _sz(sz), _free(capacity()),
57 {
58 // initialise free list
59 for (Int_t i = 0; i < _free; ++i)
60 _chunk[i]._next = (i + 1 < _free) ? &_chunk[i + 1] : nullptr;
61 }
62 /// forbid copying
63 Chunk(const Chunk&) = delete;
64 // forbid assignment
65 Chunk& operator=(const Chunk&) = delete;
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
88 {
89 if (!_freelist) return nullptr;
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
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
111 class Pool {
112 private:
113 enum {
114 minsz = 7, ///< minimum chunk size (just below 1 << minsz bytes)
115 maxsz = 18, ///< maximum chunk size (just below 1 << maxsz bytes)
116 szincr = 1 ///< size class increment (sz = 1 << (minsz + k * szincr))
117 };
118 /// a chunk of memory in the pool
119 typedef RooLinkedListImplDetails::Chunk Chunk;
120 typedef std::list<Chunk*> ChunkList;
121 typedef std::map<const void*, Chunk*> AddrMap;
122 public:
123 /// constructor
124 Pool();
125 /// destructor
126 ~Pool();
127 /// acquire the pool
128 inline void acquire() { ++_refCount; }
129 /// release the pool, return true if the pool is unused
130 inline bool release() { return 0 == --_refCount; }
131 /// pop a free element out of the pool
133 /// push a free element back into the pool
135 private:
140 UInt_t _refCount = 0;
141
142 /// adjust _cursz to current largest block
144 /// find size of next chunk to allocate (in a hopefully smart way)
145 Int_t nextChunkSz() const;
146 };
147
148 Pool::Pool()
149 {
150 std::fill(_szmap, _szmap + ((maxsz - minsz) / szincr), 0);
151 }
152
153 Pool::~Pool()
154 {
155 _freelist.clear();
156 for (AddrMap::iterator it = _addrmap.begin(); _addrmap.end() != it; ++it)
157 delete it->second;
158 _addrmap.clear();
159 }
160
161 RooLinkedListElem* Pool::pop_free_elem()
162 {
163 if (_freelist.empty()) {
164 // allocate and register new chunk and put it on the freelist
165 const Int_t sz = nextChunkSz();
166 Chunk *c = new Chunk(sz);
167 _addrmap[c->chunkaddr()] = c;
168 _freelist.push_back(c);
169 updateCurSz(sz, +1);
170 }
171 // get free element from first chunk on _freelist
172 Chunk* c = _freelist.front();
173 RooLinkedListElem* retVal = c->pop_free_elem();
174 // full chunks are removed from _freelist
175 if (c->full()) _freelist.pop_front();
176 return retVal;
177 }
178
179 void Pool::push_free_elem(RooLinkedListElem* el)
180 {
181 // find from which chunk el came
183 if (!_addrmap.empty()) {
184 ci = _addrmap.lower_bound(el);
185 if (ci == _addrmap.end()) {
186 // point beyond last element, so get last one
187 ci = (++_addrmap.rbegin()).base();
188 } else {
189 // valid ci, check if we need to decrement ci because el isn't the
190 // first element in the chunk
191 if (_addrmap.begin() != ci && ci->first != el) --ci;
192 }
193 }
194 // either empty addressmap, or ci should now point to the chunk which might
195 // contain el
196 if (_addrmap.empty() || !ci->second->contains(el)) {
197 // el is not in any chunk we know about, so just delete it
198 delete el;
199 return;
200 }
201 Chunk *c = ci->second;
202 const bool moveToFreelist = c->full();
203 c->push_free_elem(el);
204 if (c->empty()) {
205 // delete chunk if all empty
206 ChunkList::iterator it = std::find( _freelist.begin(), _freelist.end(), c);
207 if (_freelist.end() != it) _freelist.erase(it);
208 _addrmap.erase(ci->first);
209 updateCurSz(c->szclass(), -1);
210 delete c;
211 } else if (moveToFreelist) {
212 _freelist.push_back(c);
213 }
214 }
215
216 void Pool::updateCurSz(Int_t sz, Int_t incr)
217 {
218 _szmap[(sz - minsz) / szincr] += incr;
219 _cursz = minsz;
220 for (int i = (maxsz - minsz) / szincr; i--; ) {
221 if (_szmap[i]) {
222 _cursz += i * szincr;
223 break;
224 }
225 }
226 }
227
228 Int_t Pool::nextChunkSz() const
229 {
230 // no chunks with space available, figure out chunk size
231 Int_t sz = _cursz;
232 if (_addrmap.empty()) {
233 // if we start allocating chunks, we start from minsz
234 sz = minsz;
235 } else {
236 if (minsz >= sz) {
237 // minimal sized chunks are always grown
238 sz = minsz + szincr;
239 } else {
240 if (1 != _addrmap.size()) {
241 // if we have more than one completely filled chunk, grow
242 sz += szincr;
243 } else {
244 // just one chunk left, try shrinking chunk size
245 sz -= szincr;
246 }
247 }
248 }
249 // clamp size to allowed range
250 if (sz > maxsz) sz = maxsz;
251 if (sz < minsz) sz = minsz;
252 return sz;
253 }
254}
255
256/// \endcond
257
259
260////////////////////////////////////////////////////////////////////////////////
261
263 _hashThresh(htsize), _size(0), _first(nullptr), _last(nullptr), _htableName(nullptr), _htableLink(nullptr), _useNptr(true)
264{
265 if (!_pool) _pool = new Pool;
266 _pool->acquire();
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// Copy constructor
271
273 TObject(other), _hashThresh(other._hashThresh), _size(0), _first(nullptr), _last(nullptr), _htableName(nullptr), _htableLink(nullptr),
274 _name(other._name),
275 _useNptr(other._useNptr)
276{
277 if (!_pool) _pool = new Pool;
278 _pool->acquire();
279 if (other._htableName) _htableName = std::make_unique<HashTableByName>(other._htableName->size()) ;
280 if (other._htableLink) _htableLink = std::make_unique<HashTableByLink>(other._htableLink->size()) ;
281 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
282 Add(elem->_arg, elem->_refCount) ;
283 }
284}
285
286////////////////////////////////////////////////////////////////////////////////
287
289{
290 RooLinkedListElem* ret = _pool->pop_free_elem();
291 ret->init(obj, elem);
292 return ret ;
293}
294
295////////////////////////////////////////////////////////////////////////////////
296
298{
299 elem->release() ;
300 _pool->push_free_elem(elem);
301 //delete elem ;
302}
303
304////////////////////////////////////////////////////////////////////////////////
305/// Assignment operator, copy contents from 'other'
306
308{
309 // Prevent self-assignment
310 if (&other==this) return *this ;
311
312 // remove old elements
313 Clear();
314 // Copy elements
315 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
316 Add(elem->_arg) ;
317 }
318
319 return *this ;
320}
321
322////////////////////////////////////////////////////////////////////////////////
323/// Change the threshold for hash-table use to given size.
324/// If a hash table exists when this method is called, it is regenerated.
325
327{
328 if (size < 0) {
329 coutE(InputArguments) << "RooLinkedList::setHashTable() ERROR size must be positive" << std::endl;
330 return;
331 }
332 if (size == 0) {
333 // Remove existing hash table
334 _htableName.reset();
335 _htableLink.reset();
336 return;
337 }
338
339 if (!_htableName) {
340 // (Re)create hash tables
341 _htableName = std::make_unique<HashTableByName>(size);
342 _htableLink = std::make_unique<HashTableByLink>(size);
343
344 for (RooLinkedListElem *elem = _first; elem; elem = elem->_next) {
345 _htableName->insert({elem->_arg->GetName(), elem->_arg});
346 _htableLink->insert({elem->_arg, reinterpret_cast<TObject *>(elem)});
347 }
348 }
349
350 _htableName->reserve(size);
351 _htableLink->reserve(size);
352}
353
354////////////////////////////////////////////////////////////////////////////////
355/// Destructor
356
358{
359 // Required since we overload TObject::Hash.
361
362 _htableName.reset();
363 _htableLink.reset();
364
365 Clear() ;
366 if (_pool->release()) {
367 delete _pool;
368 _pool = nullptr;
369 }
370}
371
372////////////////////////////////////////////////////////////////////////////////
373/// Find the element link containing the given object
374
376{
377 if (_htableLink) {
378 auto found = _htableLink->find(arg);
379 if (found == _htableLink->end()) return nullptr;
380 return const_cast<RooLinkedListElem *>(reinterpret_cast<RooLinkedListElem const*>(found->second));
381 }
382
384 while(ptr) {
385 if (ptr->_arg == arg) {
386 return ptr ;
387 }
388 ptr = ptr->_next ;
389 }
390 return nullptr ;
391
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// Insert object into collection with given reference count value
396
397void RooLinkedList::Add(TObject* arg, Int_t refCount)
398{
399 if (!arg) return ;
400
401 // Only use RooAbsArg::namePtr() in lookup-by-name if all elements have it
402 if (!dynamic_cast<RooAbsArg*>(arg) && !dynamic_cast<RooAbsData*>(arg)) _useNptr = false;
403
404 // Add to hash table
405 if (_htableName) {
406
407 // Expand capacity of hash table if #entries>#slots
408 if (static_cast<size_t>(_size) > _htableName->size()) {
410 }
411
412 } else if (_hashThresh>0 && _size>_hashThresh) {
413
415 }
416
417 if (_last) {
418 // Append element at end of list
419 _last = createElement(arg,_last) ;
420 } else {
421 // Append first element, set first,last
422 _last = createElement(arg) ;
423 _first=_last ;
424 }
425
426 if (_htableName){
427 _htableName->insert({arg->GetName(), arg});
428 _htableLink->insert({arg, reinterpret_cast<TObject *>(_last)});
429 }
430
431 _size++ ;
432 _last->_refCount = refCount ;
433
434 _at.push_back(_last);
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Remove object from collection
439
441{
442 // Find link element
444 if (!elem) return false ;
445
446 // Remove from hash table
447 if (_htableName) {
448 _htableName->erase(arg->GetName()) ;
449 }
450 if (_htableLink) {
451 _htableLink->erase(arg) ;
452 }
453
454 // Update first,last if necessary
455 if (elem==_first) _first=elem->_next ;
456 if (elem==_last) _last=elem->_prev ;
457
458 // Remove from index array
459 auto at_elem_it = std::find(_at.begin(), _at.end(), elem);
460 _at.erase(at_elem_it);
461
462 // Delete and shrink
463 _size-- ;
465 return true ;
466}
467
468////////////////////////////////////////////////////////////////////////////////
469/// If one of the TObject we have a referenced to is deleted, remove the
470/// reference.
471
473{
474 Remove(obj); // This is a nop if the obj is not in the collection.
475}
476
477////////////////////////////////////////////////////////////////////////////////
478/// Return object stored in sequential position given by index.
479/// If index is out of range, a null pointer is returned.
480
482{
483 // Check range
484 if (index<0 || index>=_size) return nullptr ;
485
486 return _at[index]->_arg;
487//
488//
489// // Walk list
490// RooLinkedListElem* ptr = _first;
491// while(index--) ptr = ptr->_next ;
492//
493// // Return arg
494// return ptr->_arg ;
495}
496
497////////////////////////////////////////////////////////////////////////////////
498/// Replace object 'oldArg' in collection with new object 'newArg'.
499/// If 'oldArg' is not found in collection false is returned
500
502{
503 // Find existing element and replace arg
505 if (!elem) return false ;
506
507 if (_htableName) {
508 _htableName->erase(oldArg->GetName());
509 _htableName->insert({newArg->GetName(), newArg});
510 }
511 if (_htableLink) {
512 // Link is hashed by contents and may change slot in hash table
513 _htableLink->erase(oldArg) ;
514 _htableLink->insert({newArg, reinterpret_cast<TObject*>(elem)}) ;
515 }
516
517 elem->_arg = const_cast<TObject*>(newArg);
518 return true ;
519}
520
521////////////////////////////////////////////////////////////////////////////////
522/// Return pointer to object with given name. If no such object
523/// is found return a null pointer.
524
526{
527 return find(name) ;
528}
529
530////////////////////////////////////////////////////////////////////////////////
531/// Find object in list. If list contains object return
532/// (same) pointer to object, otherwise return null pointer
533
535{
536 RooLinkedListElem *elem = findLink(const_cast<TObject*>(obj));
537 return elem ? elem->_arg : nullptr ;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Remove all elements from collection
542
544{
545 for (RooLinkedListElem *elem = _first, *next; elem; elem = next) {
546 next = elem->_next ;
548 }
549 _first = nullptr ;
550 _last = nullptr ;
551 _size = 0 ;
552
553 if (_htableName) {
554 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
555 }
556 if (_htableLink) {
557 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
558 }
559
560 // empty index array
561 _at.clear();
562}
563
564////////////////////////////////////////////////////////////////////////////////
565/// Remove all elements in collection and delete all elements
566/// NB: Collection does not own elements, this function should
567/// be used judiciously by caller.
568
570{
572 while(elem) {
573 RooLinkedListElem* next = elem->_next ;
574 delete elem->_arg ;
576 elem = next ;
577 }
578 _first = nullptr ;
579 _last = nullptr ;
580 _size = 0 ;
581
582 if (_htableName) {
583 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
584 }
585 if (_htableLink) {
586 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
587 }
588
589 // empty index array
590 _at.clear();
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Return pointer to object with given name in collection.
595/// If no such object is found, return null pointer.
596
598{
599
600 if (_htableName) {
601 auto found = _htableName->find(name);
602 TObject *a = found != _htableName->end() ? const_cast<TObject*>(found->second) : nullptr;
603 // RooHashTable::find could return false negative if element was renamed to 'name'.
604 // The list search means it won't return false positive, so can return here.
605 if (a) return a;
606 if (_useNptr) {
607 // See if it might have been renamed
609 if (nptr && nptr->TestBit(RooNameReg::kRenamedArg)) {
611 while(ptr) {
612 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
613 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
614 return ptr->_arg ;
615 }
616 ptr = ptr->_next ;
617 }
618 }
619 return nullptr ;
620 }
621 }
622
624
625 // The penalty for RooNameReg lookup seems to be outweighted by the faster search
626 // when the size list is longer than ~7, but let's be a bit conservative.
627 if (_useNptr && _size>9) {
629 if (!nptr) return nullptr;
630
631 while(ptr) {
632 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
633 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
634 return ptr->_arg ;
635 }
636 ptr = ptr->_next ;
637 }
638 return nullptr ;
639 }
640
641 while(ptr) {
642 if (!strcmp(ptr->_arg->GetName(),name)) {
643 return ptr->_arg ;
644 }
645 ptr = ptr->_next ;
646 }
647 return nullptr ;
648}
649
650////////////////////////////////////////////////////////////////////////////////
651/// Return pointer to object with given name in collection.
652/// If no such object is found, return null pointer.
653
655{
656 if (_htableName) {
657 RooAbsArg* a = const_cast<RooAbsArg *>(static_cast<RooAbsArg const*>((*_htableName)[arg->GetName()]));
658 if (a) return a;
659 // See if it might have been renamed
660 if (!arg->namePtr()->TestBit(RooNameReg::kRenamedArg)) return nullptr;
661 }
662
664 const TNamed* nptr = arg->namePtr();
665 while(ptr) {
666 if ((static_cast<RooAbsArg*>(ptr->_arg))->namePtr() == nptr) {
667 return static_cast<RooAbsArg*>(ptr->_arg) ;
668 }
669 ptr = ptr->_next ;
670 }
671 return nullptr ;
672}
673
674////////////////////////////////////////////////////////////////////////////////
675/// Return position of given object in list. If object
676/// is not contained in list, return -1
677
679{
681 Int_t idx(0) ;
682 while(ptr) {
683 if (ptr->_arg==arg) return idx ;
684 ptr = ptr->_next ;
685 idx++ ;
686 }
687 return -1 ;
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// Return position of given object in list. If object
692/// is not contained in list, return -1
693
695{
697 Int_t idx(0) ;
698 while(ptr) {
699 if (strcmp(ptr->_arg->GetName(),name)==0) return idx ;
700 ptr = ptr->_next ;
701 idx++ ;
702 }
703 return -1 ;
704}
705
706////////////////////////////////////////////////////////////////////////////////
707/// Print contents of list, defers to Print() function
708/// of contained objects
709
710void RooLinkedList::Print(const char* opt) const
711{
713 while(elem) {
714 std::cout << elem->_arg << " : " ;
715 elem->_arg->Print(opt) ;
716 elem = elem->_next ;
717 }
718}
719
720////////////////////////////////////////////////////////////////////////////////
721/// Create a TIterator for this list.
722/// \param forward Run in forward direction (default).
723/// \return Pointer to a TIterator. The caller owns the pointer.
724
726 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
727 return new RooLinkedListIter(std::move(iterImpl));
728}
729
730////////////////////////////////////////////////////////////////////////////////
731/// Create an iterator for this list.
732/// \param forward Run in forward direction (default).
733/// \return RooLinkedListIter (subclass of TIterator) over this list
734
736 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
737 return RooLinkedListIter(std::move(iterImpl));
738}
739
740////////////////////////////////////////////////////////////////////////////////
741/// Create a one-time-use forward iterator for this list.
742/// \return RooFIter that only supports next()
743
745 auto iterImpl = std::make_unique<RooFIterForLinkedList>(this);
746 return RooFIter(std::move(iterImpl));
747}
748
750 return {this, true};
751}
752
754 return {this, nullptr, true};
755}
756
758 return {this, false};
759}
760
762 return {this, nullptr, false};
763}
764
765////////////////////////////////////////////////////////////////////////////////
766
768{
771
772 // rebuild index array
774 for (auto it = _at.begin(); it != _at.end(); ++it, elem = elem->_next) {
775 *it = elem;
776 }
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// length 0, 1 lists are sorted
781
782template <bool ascending>
784 RooLinkedListElem* l1, const unsigned sz, RooLinkedListElem** tail)
785{
786 if (!l1 || sz < 2) {
787 // if desired, update the tail of the (newly merged sorted) list
788 if (tail) *tail = l1;
789 return l1;
790 }
791 if (sz <= 16) {
792 // for short lists, we sort in an array
793 std::vector<RooLinkedListElem *> arr(sz, nullptr);
794 for (int i = 0; l1; l1 = l1->_next, ++i) arr[i] = l1;
795 // straight insertion sort
796 {
797 int i = 1;
798 do {
799 int j = i - 1;
801 while (0 <= j) {
802 const bool inOrder = ascending ?
803 (tmp->_arg->Compare(arr[j]->_arg) <= 0) :
804 (arr[j]->_arg->Compare(tmp->_arg) <= 0);
805 if (!inOrder) break;
806 arr[j + 1] = arr[j];
807 --j;
808 }
809 arr[j + 1] = tmp;
810 ++i;
811 } while (int(sz) != i);
812 }
813 // link elements in array
814 arr[0]->_prev = arr[sz - 1]->_next = nullptr;
815 for (int i = 0; i < int(sz - 1); ++i) {
816 arr[i]->_next = arr[i + 1];
817 arr[i + 1]->_prev = arr[i];
818 }
819 if (tail) *tail = arr[sz - 1];
820 return arr[0];
821 }
822 // find middle of l1, and let a second list l2 start there
824 for (RooLinkedListElem *end = l2; end->_next; end = end->_next) {
825 end = end->_next;
826 l2 = l2->_next;
827 if (!end->_next) break;
828 }
829 // disconnect the two sublists
830 l2->_prev->_next = nullptr;
831 l2->_prev = nullptr;
832 // sort the two sublists (only recurse if we have to)
833 if (l1->_next) l1 = mergesort_impl<ascending>(l1, sz / 2);
834 if (l2->_next) l2 = mergesort_impl<ascending>(l2, sz - sz / 2);
835 // merge the two (sorted) sublists
836 // l: list head, t: list tail of merged list
837 RooLinkedListElem *l = (ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
838 (l2->_arg->Compare(l1->_arg) <= 0)) ? l1 : l2;
839 RooLinkedListElem *t = l;
840 if (l == l2) {
842 l1 = l2;
843 l2 = tmp;
844 }
845 l1 = l1->_next;
846 while (l1 && l2) {
847 const bool inOrder = ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
848 (l2->_arg->Compare(l1->_arg) <= 0);
849 if (!inOrder) {
850 // insert l2 just before l1
851 if (l1->_prev) {
852 l1->_prev->_next = l2;
853 l2->_prev = l1->_prev;
854 }
855 // swap l2 and l1
857 l1 = l2;
858 l2 = tmp;
859 }
860 // move forward in l1
861 t = l1;
862 l1 = l1->_next;
863 }
864 // attach l2 at t
865 if (l2) {
866 l2->_prev = t;
867 if (t) t->_next = l2;
868 }
869 // if desired, update the tail of the (newly merged sorted) list
870 if (tail) {
871 for (l1 = t; l1; l1 = l1->_next) t = l1;
872 *tail = t;
873 }
874 // return the head of the sorted list
875 return l;
876}
877// void Roo1DTable::Streamer(TBuffer &R__b)
878// {
879// // Stream an object of class Roo1DTable.
880
881// if (R__b.IsReading()) {
882// R__b.ReadClassBuffer(Roo1DTable::Class(),this);
883// } else {
884// R__b.WriteClassBuffer(Roo1DTable::Class(),this);
885// }
886// }
887
888////////////////////////////////////////////////////////////////////////////////
889/// Custom streaming handling schema evolution w.r.t past implementations
890
892{
893 if (R__b.IsReading()) {
894
895 Version_t v = R__b.ReadVersion();
896 //R__b.ReadVersion();
898
899 Int_t size ;
900 TObject* arg ;
901
902 R__b >> size ;
903 while(size--) {
904 R__b >> arg ;
905 Add(arg) ;
906 }
907
908 if (v > 1 && v < 4) {
909 R__b >> _name;
910 }
911
912 } else {
913 R__b.WriteVersion(RooLinkedList::IsA());
915 R__b << _size ;
916
918 while(ptr) {
919 R__b << ptr->_arg ;
920 ptr = ptr->_next ;
921 }
922
923 R__b << _name ;
924 }
925}
#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
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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:145
Binding & operator=(OUT(*fun)(void))
#define free
Definition civetweb.c:1578
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:503
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:56
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsData.h:283
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
Link element for the RooLinkedList class.
TObject * _arg
Link to contents.
Int_t _refCount
! Reference count
RooLinkedListElem * _next
Link to next element in list.
Implementation of the actual iterator on RooLinkedLists.
A wrapper around TIterator derivatives.
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
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)
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:46
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
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:49
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:459
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:994
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:415
bool contains(bvh::v2::BBox< T, 3 > const &box, bvh::v2::Vec< T, 3 > const &p)
TLine l
Definition textangle.C:4