RooLinkedList.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooLinkedList.cxx 36207 2010-10-08 19:00:29Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 // RooLinkedList is an collection class for internal use, storing
00021 // a collection of RooAbsArg pointers in a doubly linked list.
00022 // It can optionally add a hash table to speed up random access
00023 // in large collections
00024 // Use RooAbsCollection derived objects for public use
00025 // (e.g. RooArgSet or RooArgList) 
00026 // END_HTML
00027 //
00028 
00029 #include "RooFit.h"
00030 #include "Riostream.h"
00031 
00032 #include "RooLinkedList.h"
00033 #include "RooLinkedListIter.h"
00034 #include "RooHashTable.h"
00035 #include "RooAbsArg.h"
00036 #include "RooMsgService.h"
00037 
00038 
00039 
00040 ClassImp(RooLinkedList)
00041 ;
00042 
00043 
00044 //_____________________________________________________________________________
00045 RooLinkedList::RooLinkedList(Int_t htsize) : 
00046   _hashThresh(htsize), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0)
00047 {
00048   // Constructor with hashing threshold. If collection size exceeds threshold
00049   // a hash table is added.
00050 }
00051 
00052 
00053 
00054 
00055 //_____________________________________________________________________________
00056 RooLinkedList::RooLinkedList(const RooLinkedList& other) :
00057   TObject(other), _hashThresh(other._hashThresh), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0), _name(other._name)
00058 {
00059   // Copy constructor
00060 
00061   if (other._htableName) _htableName = new RooHashTable(other._htableName->size()) ;
00062   if (other._htableLink) _htableLink = new RooHashTable(other._htableLink->size(),RooHashTable::Pointer) ;
00063   RooLinkedListElem* elem = other._first ;
00064   while(elem) {
00065     Add(elem->_arg, elem->_refCount) ;
00066     elem = elem->_next ;
00067   }
00068 }
00069 
00070 
00071 
00072 //_____________________________________________________________________________
00073 RooLinkedList& RooLinkedList::operator=(const RooLinkedList& other) 
00074 {
00075   // Assignment operator, copy contents from 'other'
00076   
00077   // Prevent self-assignment
00078   if (&other==this) return *this ;
00079   
00080   // Copy elements
00081   RooLinkedListElem* elem = other._first ;
00082   while(elem) {
00083     Add(elem->_arg) ;
00084     elem = elem->_next ;
00085   }    
00086   
00087   return *this ;
00088 }
00089 
00090 
00091 
00092 //_____________________________________________________________________________
00093 void RooLinkedList::setHashTableSize(Int_t size) 
00094 {        
00095   // Change the threshold for hash-table use to given size.
00096   // If a hash table exists when this method is called, it is regenerated.
00097 
00098   if (size<0) {
00099     coutE(InputArguments) << "RooLinkedList::setHashTable() ERROR size must be positive" << endl ;
00100     return ;
00101   }
00102   if (size==0) {
00103     if (!_htableName) {
00104       // No hash table present
00105       return ;
00106     } else {
00107       // Remove existing hash table
00108       delete _htableName ;
00109       delete _htableLink ;
00110       _htableName = 0 ;
00111       _htableLink = 0 ;
00112     }
00113   } else {
00114 
00115     // (Re)create hash tables
00116     if (_htableName) delete _htableName ;
00117     _htableName = new RooHashTable(size) ;
00118 
00119      if (_htableLink) delete _htableLink ;
00120      _htableLink = new RooHashTable(size,RooHashTable::Pointer) ;
00121     
00122     // Fill hash table with existing entries
00123     RooLinkedListElem* ptr = _first ;
00124     while(ptr) {
00125       _htableName->add(ptr->_arg) ;
00126       _htableLink->add((TObject*)ptr,ptr->_arg) ;
00127       ptr = ptr->_next ;
00128     }      
00129   }
00130 }
00131 
00132 
00133  
00134 
00135 //_____________________________________________________________________________
00136 RooLinkedList::~RooLinkedList() 
00137 {
00138   // Destructor
00139 
00140   if (_htableName) {
00141     delete _htableName ;
00142     _htableName=0 ;
00143   }
00144   if (_htableLink) {
00145     delete _htableLink ;
00146     _htableLink=0 ;
00147   }
00148 
00149   Clear() ;
00150 }
00151 
00152 
00153 
00154 //_____________________________________________________________________________
00155 RooLinkedListElem* RooLinkedList::findLink(const TObject* arg) const 
00156 {    
00157   // Find the element link containing the given object
00158 
00159   if (_htableLink) {
00160     return _htableLink->findLinkTo(arg) ;  
00161   }
00162   
00163   RooLinkedListElem* ptr = _first;
00164   while(ptr) {
00165     if (ptr->_arg == arg) {
00166       return ptr ;
00167     }
00168     ptr = ptr->_next ;
00169   }
00170   return 0 ;
00171   
00172 }
00173 
00174 
00175 
00176 //_____________________________________________________________________________
00177 void RooLinkedList::Add(TObject* arg, Int_t refCount)
00178 {
00179   // Insert object into collection with given reference count value
00180 
00181   if (!arg) return ;
00182   
00183   // Add to hash table 
00184   if (_htableName) {
00185 
00186     // Expand capacity of hash table if #entries>#slots
00187     if (_size > _htableName->size()) {
00188       setHashTableSize(_size*2) ;
00189     }
00190 
00191   } else if (_hashThresh>0 && _size>_hashThresh) {
00192 
00193     setHashTableSize(_hashThresh) ;
00194   }  
00195 
00196   if (_last) {
00197     // Append element at end of list
00198     _last = new RooLinkedListElem(arg,_last) ;
00199   } else {
00200     // Append first element, set first,last 
00201     _last = new RooLinkedListElem(arg) ;
00202     _first=_last ;
00203   }
00204 
00205   if (_htableName){
00206     //cout << "storing link " << _last << " with hash arg " << arg << endl ;
00207     _htableName->add(arg) ;
00208     _htableLink->add((TObject*)_last,arg) ;
00209   }
00210 
00211   _size++ ;
00212   _last->_refCount = refCount ;
00213   
00214 }
00215 
00216 
00217 
00218 
00219 //_____________________________________________________________________________
00220 Bool_t RooLinkedList::Remove(TObject* arg) 
00221 {
00222   // Remove object from collection
00223 
00224   // Find link element
00225   RooLinkedListElem* elem = findLink(arg) ;
00226   if (!elem) return kFALSE ;
00227   
00228   // Remove from hash table
00229   if (_htableName) {
00230     _htableName->remove(arg) ;
00231   }
00232   if (_htableLink) {
00233     _htableLink->remove((TObject*)elem,arg) ;
00234   }
00235   
00236   // Update first,last if necessary
00237   if (elem==_first) _first=elem->_next ;
00238   if (elem==_last) _last=elem->_prev ;
00239   
00240   // Delete and shrink
00241   _size-- ;
00242   delete elem ; 
00243   return kTRUE ;
00244 }
00245 
00246 
00247 
00248 
00249 //_____________________________________________________________________________
00250 TObject* RooLinkedList::At(Int_t index) const 
00251 {
00252   // Return object stored in sequential position given by index.
00253   // If index is out of range, a null pointer is returned.
00254 
00255   // Check range
00256   if (index<0 || index>=_size) return 0 ;
00257 
00258   
00259   // Walk list
00260   RooLinkedListElem* ptr = _first;
00261   while(index--) ptr = ptr->_next ;
00262   
00263   // Return arg
00264   return ptr->_arg ;
00265 }
00266 
00267 
00268 
00269 
00270 //_____________________________________________________________________________
00271 Bool_t RooLinkedList::Replace(const TObject* oldArg, const TObject* newArg) 
00272 {
00273   // Replace object 'oldArg' in collection with new object 'newArg'.
00274   // If 'oldArg' is not found in collection kFALSE is returned
00275 
00276   // Find existing element and replace arg
00277   RooLinkedListElem* elem = findLink(oldArg) ;
00278   if (!elem) return kFALSE ;
00279   
00280   if (_htableName) {
00281     _htableName->replace(oldArg,newArg) ;
00282   }
00283   if (_htableLink) {
00284     // Link is hashed by contents and may change slot in hash table
00285     _htableLink->remove((TObject*)elem,(TObject*)oldArg) ;
00286     _htableLink->add((TObject*)elem,(TObject*)newArg) ;
00287   }
00288 
00289   elem->_arg = (TObject*)newArg ;
00290   return kTRUE ;
00291 }
00292 
00293 
00294 
00295 //_____________________________________________________________________________
00296 TObject* RooLinkedList::FindObject(const char* name) const 
00297 {
00298   // Return pointer to obejct with given name. If no such object
00299   // is found return a null pointer
00300 
00301   return find(name) ;
00302 }
00303 
00304 
00305 
00306 //_____________________________________________________________________________
00307 TObject* RooLinkedList::FindObject(const TObject* obj) const 
00308 {
00309   // Find object in list. If list contains object return 
00310   // (same) pointer to object, otherwise return null pointer
00311 
00312   RooLinkedListElem *elem = findLink((TObject*)obj) ;
00313   return elem ? elem->_arg : 0 ;
00314 }
00315 
00316 
00317 
00318 //_____________________________________________________________________________
00319 void RooLinkedList::Clear(Option_t *) 
00320 {
00321   // Remove all elements from collection
00322 
00323   RooLinkedListElem* elem = _first;
00324   while(elem) {
00325     RooLinkedListElem* next = elem->_next ;
00326       delete elem ;
00327       elem = next ;
00328   }
00329   _first = 0 ;
00330   _last = 0 ;
00331   _size = 0 ;
00332   
00333   if (_htableName) {
00334     Int_t hsize = _htableName->size() ;
00335     delete _htableName ;
00336     _htableName = new RooHashTable(hsize) ;   
00337   }
00338   if (_htableLink) {
00339     Int_t hsize = _htableLink->size() ;
00340     delete _htableLink ;
00341     _htableLink = new RooHashTable(hsize,RooHashTable::Pointer) ;       
00342   }
00343 }
00344 
00345 
00346 
00347 //_____________________________________________________________________________
00348 void RooLinkedList::Delete(Option_t *) 
00349 {
00350   // Remove all elements in collection and delete all elements
00351   // NB: Collection does not own elements, this function should
00352   // be used judiciously by caller. 
00353 
00354   RooLinkedListElem* elem = _first;
00355   while(elem) {
00356     RooLinkedListElem* next = elem->_next ;
00357     delete elem->_arg ;
00358     delete elem ;
00359     elem = next ;
00360   }
00361   _first = 0 ;
00362   _last = 0 ;
00363   _size = 0 ;
00364 
00365   if (_htableName) {
00366     Int_t hsize = _htableName->size() ;
00367     delete _htableName ;
00368     _htableName = new RooHashTable(hsize) ;   
00369   }
00370   if (_htableLink) {
00371     Int_t hsize = _htableLink->size() ;
00372     delete _htableLink ;
00373     _htableLink = new RooHashTable(hsize,RooHashTable::Pointer) ;       
00374   }
00375 }
00376 
00377 
00378   
00379 
00380 //_____________________________________________________________________________
00381 TObject* RooLinkedList::find(const char* name) const 
00382 {
00383   // Return pointer to object with given name in collection.
00384   // If no such object is found, return null pointer.
00385 
00386   if (_htableName) return _htableName->find(name) ;
00387 
00388   RooLinkedListElem* ptr = _first ;
00389   while(ptr) {
00390     if (!strcmp(ptr->_arg->GetName(),name)) {
00391       return ptr->_arg ;
00392     }
00393     ptr = ptr->_next ;
00394   }
00395   return 0 ;
00396 }
00397 
00398 
00399 
00400 //_____________________________________________________________________________
00401 Int_t RooLinkedList::IndexOf(const TObject* arg) const 
00402 {
00403   // Return position of given object in list. If object
00404   // is not contained in list, return -1
00405 
00406   RooLinkedListElem* ptr = _first;
00407   Int_t idx(0) ;
00408   while(ptr) {
00409     if (ptr->_arg==arg) return idx ;
00410     ptr = ptr->_next ;
00411     idx++ ;
00412   }
00413   return -1 ;
00414 }
00415 
00416 
00417 
00418 //_____________________________________________________________________________
00419 Int_t RooLinkedList::IndexOf(const char* name) const 
00420 {
00421   // Return position of given object in list. If object
00422   // is not contained in list, return -1
00423 
00424   RooLinkedListElem* ptr = _first;
00425   Int_t idx(0) ;
00426   while(ptr) {
00427     if (strcmp(ptr->_arg->GetName(),name)==0) return idx ;
00428     ptr = ptr->_next ;
00429     idx++ ;
00430   }
00431   return -1 ;
00432 }
00433 
00434 
00435 
00436 //_____________________________________________________________________________
00437 void RooLinkedList::Print(const char* opt) const 
00438 {
00439   // Print contents of list, defers to Print() function
00440   // of contained objects
00441   RooLinkedListElem* elem = _first ;
00442   while(elem) {
00443     cout << elem->_arg << " : " ; 
00444     elem->_arg->Print(opt) ;
00445     elem = elem->_next ;
00446   }    
00447 }
00448 
00449 
00450 
00451 //_____________________________________________________________________________
00452 TIterator* RooLinkedList::MakeIterator(Bool_t dir) const 
00453 {
00454   // Return an iterator over this list
00455   return new RooLinkedListIter(this,dir) ;
00456 }
00457 
00458 
00459 //_____________________________________________________________________________
00460 RooLinkedListIter RooLinkedList::iterator(Bool_t dir) const 
00461 {
00462   // Return an iterator over this list
00463   return RooLinkedListIter(this,dir) ;
00464 }
00465 
00466 
00467 
00468 //_____________________________________________________________________________
00469 void RooLinkedList::Sort(Bool_t ascend) 
00470 {
00471   // Sort elements of this list according to their
00472   // TObject::Compare() ranking via a simple
00473   // bubble sort algorithm
00474 
00475   if (_size<2) return ;
00476 
00477   Bool_t working(kTRUE) ;
00478   while(working) {
00479     working = kFALSE ;
00480     RooLinkedListElem* ptr = _first;
00481     while(ptr && ptr->_next) {    
00482       if ((ascend && ptr->_arg->Compare(ptr->_next->_arg)>0) ||
00483           (!ascend && ptr->_arg->Compare(ptr->_next->_arg)<0)) {
00484         swapWithNext(ptr) ;
00485         working = kTRUE ;
00486       }
00487       ptr = ptr->_next ;
00488     }
00489   }
00490 
00491   return ;
00492 }
00493 
00494 
00495 
00496 //_____________________________________________________________________________
00497 void RooLinkedList::swapWithNext(RooLinkedListElem* elemB) 
00498 {
00499   // Swap given to elements in the linked list. Auxiliary function for Sort()
00500 
00501   RooLinkedListElem* elemA = elemB->_prev ;
00502   RooLinkedListElem* elemC = elemB->_next ;
00503   if (!elemC) return ;
00504 
00505   RooLinkedListElem* elemD = elemC->_next ;
00506 
00507   if (elemA) {
00508     elemA->_next = elemC ;
00509   } else {
00510     _first = elemC ;
00511   }
00512   elemB->_prev = elemC ;
00513   elemB->_next = elemD ;
00514   elemC->_prev = elemA ;
00515   elemC->_next = elemB ;
00516   if (elemD) {
00517     elemD->_prev = elemB ;
00518   } else {
00519     _last = elemB ;
00520   }
00521   return ;
00522 }
00523 
00524 
00525 
00526 // void Roo1DTable::Streamer(TBuffer &R__b)
00527 // {
00528 //    // Stream an object of class Roo1DTable.
00529 
00530 //    if (R__b.IsReading()) {
00531 //       R__b.ReadClassBuffer(Roo1DTable::Class(),this);
00532 //    } else {
00533 //       R__b.WriteClassBuffer(Roo1DTable::Class(),this);
00534 //    }
00535 // }
00536 
00537 
00538 
00539 //_____________________________________________________________________________
00540 void RooLinkedList::Streamer(TBuffer &R__b)
00541 {
00542   // Custom streaming handling schema evolution w.r.t past implementations
00543 
00544   if (R__b.IsReading()) {
00545 
00546     Version_t v = R__b.ReadVersion();
00547     //R__b.ReadVersion();
00548     TObject::Streamer(R__b);
00549 
00550     Int_t size ;
00551     TObject* arg ;
00552 
00553     R__b >> size ;
00554     while(size--) {
00555       R__b >> arg ;
00556       Add(arg) ;      
00557     }
00558 
00559     if (v>1) {
00560       R__b >> _name ;
00561     }
00562 
00563   } else {
00564     R__b.WriteVersion(RooLinkedList::IsA());
00565     TObject::Streamer(R__b);
00566     R__b << _size ;
00567 
00568     RooLinkedListElem* ptr = _first;
00569     while(ptr) {
00570       R__b << ptr->_arg ;
00571       ptr = ptr->_next ;
00572     } 
00573 
00574     R__b << _name ;
00575   }
00576 }
00577 

Generated on Tue Jul 5 15:06:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1