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