TSeqCollection.cxx

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TSeqCollection.cxx 37361 2010-12-07 08:19:24Z rdm $
00002 // Author: Fons Rademakers   04/08/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TSeqCollection                                                       //
00015 //                                                                      //
00016 // Sequenceable collection abstract base class. TSeqCollection's have   //
00017 // an ordering relation, i.e. there is a first and last element.        //
00018 //                                                                      //
00019 //////////////////////////////////////////////////////////////////////////
00020 
00021 #include "TSeqCollection.h"
00022 #include "TCollection.h"
00023 #include "TVirtualMutex.h"
00024 #include "TClass.h"
00025 #include "TMethodCall.h"
00026 
00027 ClassImp(TSeqCollection)
00028 
00029 //______________________________________________________________________________
00030 Int_t TSeqCollection::IndexOf(const TObject *obj) const
00031 {
00032    // Return index of object in collection. Returns -1 when object not found.
00033    // Uses member IsEqual() to find object.
00034 
00035    Int_t   idx = 0;
00036    TIter   next(this);
00037    TObject *ob;
00038 
00039    while ((ob = next())) {
00040       if (ob->IsEqual(obj)) return idx;
00041       idx++;
00042    }
00043    return -1;
00044 }
00045 
00046 //______________________________________________________________________________
00047 Int_t TSeqCollection::ObjCompare(TObject *a, TObject *b)
00048 {
00049    // Compare to objects in the collection. Use member Compare() of object a.
00050 
00051    if (a == 0 && b == 0) return 0;
00052    if (a == 0) return 1;
00053    if (b == 0) return -1;
00054    return a->Compare(b);
00055 }
00056 
00057 //______________________________________________________________________________
00058 void TSeqCollection::QSort(TObject **a, Int_t first, Int_t last)
00059 {
00060    // Sort array of TObject pointers using a quicksort algorithm.
00061    // The algorithm used is a non stable sort (i.e. already sorted
00062    // elements might switch/change places).
00063    // Uses ObjCompare() to compare objects.
00064 
00065    R__LOCKGUARD2(gCollectionMutex);
00066 
00067    static TObject *tmp;
00068    static int i;           // "static" to save stack space
00069    int j;
00070 
00071    while (last - first > 1) {
00072       i = first;
00073       j = last;
00074       for (;;) {
00075          while (++i < last && ObjCompare(a[i], a[first]) < 0)
00076             ;
00077          while (--j > first && ObjCompare(a[j], a[first]) > 0)
00078             ;
00079          if (i >= j)
00080             break;
00081 
00082          tmp  = a[i];
00083          a[i] = a[j];
00084          a[j] = tmp;
00085       }
00086       if (j == first) {
00087          ++first;
00088          continue;
00089       }
00090       tmp = a[first];
00091       a[first] = a[j];
00092       a[j] = tmp;
00093       if (j - first < last - (j + 1)) {
00094          QSort(a, first, j);
00095          first = j + 1;   // QSort(j + 1, last);
00096       } else {
00097          QSort(a, j + 1, last);
00098          last = j;        // QSort(first, j);
00099       }
00100    }
00101 }
00102 
00103 //______________________________________________________________________________
00104 void TSeqCollection::QSort(TObject **a, Int_t nBs, TObject ***b, Int_t first, Int_t last)
00105 {
00106    // Sort array a of TObject pointers using a quicksort algorithm.
00107    // Arrays b will be sorted just like a (a determines the sort).
00108    // Argument nBs is the number of TObject** arrays in b.
00109    // The algorithm used is a non stable sort (i.e. already sorted
00110    // elements might switch/change places).
00111    // Uses ObjCompare() to compare objects.
00112 
00113    R__LOCKGUARD2(gCollectionMutex);
00114 
00115    static TObject *tmp1, **tmp2;
00116    static int i; // "static" to save stack space
00117    int j,k;
00118 
00119    static int depth = 0;
00120    if (depth == 0 && nBs > 0) tmp2 = new TObject*[nBs];
00121    depth++;
00122 
00123    while (last - first > 1) {
00124       i = first;
00125       j = last;
00126       for (;;) {
00127          while (++i < last && ObjCompare(a[i], a[first]) < 0) {}
00128          while (--j > first && ObjCompare(a[j], a[first]) > 0) {}
00129          if (i >= j) break;
00130 
00131          tmp1 = a[i]; for(k=0;k<nBs;k++) tmp2[k] = b[k][i];
00132          a[i] = a[j]; for(k=0;k<nBs;k++) b[k][i] = b[k][j];
00133          a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
00134       }
00135       if (j == first) {
00136          ++first;
00137          continue;
00138       }
00139       tmp1 = a[first]; for(k=0;k<nBs;k++) tmp2[k] = b[k][first];
00140       a[first] = a[j]; for(k=0;k<nBs;k++) b[k][first] = b[k][j];
00141       a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
00142       if (j - first < last - (j + 1)) {
00143          QSort(a, nBs, b, first, j);
00144          first = j + 1; // QSort(j + 1, last);
00145       } else {
00146          QSort(a, nBs, b, j + 1, last);
00147          last = j; // QSort(first, j);
00148       }
00149    }
00150    depth--;
00151 
00152    if (depth == 0 && nBs > 0) delete [] tmp2;
00153 }
00154 
00155 //______________________________________________________________________________
00156 Long64_t TSeqCollection::Merge(TCollection *list)
00157 {
00158    // Merge this collection with all collections coming in the input list. The
00159    // input list must contain other collections of objects compatible with the
00160    // ones in this collection and ordered in the same manner. For example, if this
00161    // collection contains a TH1 object and a tree, all collections in the input
00162    // list have to contain a histogram and a tree. In case the list contains
00163    // collections, the objects in the input lists must also be collections with
00164    // the same structure and number of objects.
00165    //
00166    // Example
00167    // =========
00168    //   this                          list
00169    // ____________                  ---------------------|
00170    // | A (TH1F) |  __________      | L1 (TSeqCollection)|- [A1, B1(C1,D1,E1)]
00171    // | B (TList)|-| C (TTree)|     | L1 (TSeqCollection)|- [A2, B2(C2,D2,E2)]
00172    // |__________| | D (TH1F) |     | ...                |- [...]
00173    //              | E (TH1F) |     |____________________|
00174    //              |__________|
00175 
00176    Long64_t nmerged = 0;
00177    if (IsEmpty() || !list) {
00178       Warning("Merge", "list is empty - nothing to merge");
00179       return 0;
00180    }
00181    if (list->IsEmpty()) {
00182       Warning("Merge", "input list is empty - nothing to merge with");
00183       return 0;
00184    }
00185    TIter nextobject(this);
00186    TIter nextlist(list);
00187    TObject *object;
00188    TObject *objtomerge;
00189    TObject *collcrt;
00190    TSeqCollection *templist;
00191    TMethodCall callEnv;
00192    Int_t indobj = 0;
00193    while ((object = nextobject())) {   // loop objects in this collection
00194       // If current object is not mergeable just skip it
00195       if (!object->IsA()) {
00196          indobj++;  // current object non-mergeable, go to next object
00197          continue;
00198       }
00199       callEnv.InitWithPrototype(object->IsA(), "Merge", "TCollection*");
00200       if (!callEnv.IsValid()) {
00201          indobj++;  // no Merge() interface, go to next object
00202          continue;
00203       }
00204       // Current object mergeable - get corresponding objects in input lists
00205       templist = (TSeqCollection*)IsA()->New();
00206       nextlist.Reset();
00207       Int_t indcoll = 0;
00208       while ((collcrt = nextlist())) {      // loop input lists
00209          if (!collcrt->InheritsFrom(TSeqCollection::Class())) {
00210             Error("Merge", "some objects in the input list are not collections - merging aborted");
00211             delete templist;
00212             return 0;
00213          }
00214          // The next object to be merged with is a collection
00215          // the iterator skips the 'holes' the collections, we also need to do so.
00216          objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
00217          if (!objtomerge) {
00218             Warning("Merge", "Object of type %s (position %d in list) not found in list %d. Continuing...", object->ClassName(), indobj, indcoll);
00219             continue;
00220          }
00221 /*
00222          // Dangerous - may try to merge non-corresponding histograms (A.G)
00223          while (objtomerge == 0
00224                 && indobj < ((TSeqCollection*)collcrt)->LastIndex()
00225                ) {
00226             ++indobj;
00227             objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
00228          }
00229 */
00230          if (object->IsA() != objtomerge->IsA()) {
00231             Error("Merge", "object of type %s at index %d not matching object of type %s in input list",
00232                   object->ClassName(), indobj, objtomerge->ClassName());
00233             delete templist;
00234             return 0;
00235          }
00236          // Add object at index indobj in the temporary list
00237          templist->Add(objtomerge);
00238          nmerged++;
00239       }
00240       // Merge current object with objects in the temporary list
00241       callEnv.SetParam((Long_t) templist);
00242       callEnv.Execute(object);
00243       delete templist;
00244       indobj++;
00245    }
00246    return nmerged;
00247 }

Generated on Tue Jul 5 14:11:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1