// @(#)root/table:$Id$ // Author: Valery Fine 26/01/99 (E-mail: fine@bnl.gov) /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #include #include "TTableSorter.h" #include "TTable.h" #include "TClass.h" #include "TDataMember.h" #include "TDataType.h" #include "TMemberInspector.h" extern "C" { typedef Int_t (*CALLQSORT) (const void *, const void *); } ///////////////////////////////////////////////////////////////////////////////////////// // // TTableSorter - Is an "observer" class to sort the TTable objects // The class provides an interface to the standard "C/C++" // // qsort and bsearch subroutines (for further information see your local C/C++ docs) // ===== ======= // // - This class DOESN'T change / touch the "host" table itself // For any TTable object one can create as many different "sorter" // as he/she finds useful for his/her code // - Any instance of this class is meaningful as long as the "host" object // "TTable" does exist and is not changed // - Any attempt to access this TTableSorter after the "host" object deleted // causes the program abnormal termination // - Any attempt to access this TTableSorter after the "host" object been changed // causes an unpredictable result // - Any instance (object) of this class is NOT deleted "by automatic" just // the "host object "TTable" deleted. It is the responsibility of the user's code // keeping TTableSorter and the the "host" TTable objects consistent. // // "To do" list // // 1. A separate method to provide lexicographical sort if the "sorted" column is a kind of array // // Usage: // 1. Create an instance of the sorter for the selected column of your table // // new TTableSorter(TTable &table, TString &colName,Int_t firstRow,Int_t numberRows) // // All sort actions are performed within TTableSorter ctor. // This means one needs no extra effort to SORT table. "Sorter" contains // the "sorted index array" as soon as you create the sorter // // TTableSorter sorter(MyTable,"id",20, 34); // - Creates a sorter for MyTable column "id" ordering // its 34 rows from 20 row with standard "C" qsort subroutine // // 2. You may use this instance to search any "id" value with operator [] // to get the table row index as follows: // // Int_t id = 5; // Int_t index = sorter[id]; // Look for the row index with id = 5 // // using the standard "C" "bsearch" binary search // // subroutine // Int_t index = sorter(id); // Look for the row index with id "nearest" to 5 // // using the internal "BinarySearch" method // // 3. Some useful methods of this class: // // 3.1. CountKeys() // 3.2 CountKey(const void *key, Int_t firstIndx=0,Bool_t bSearch=kTRUE,Int_t *firstRow=0) // 3.3. FindFirstKey(const void *key) // 3.4. GetIndex(UInt_t sortedIndex) // ///////////////////////////////////////////////////////////////////////////////////////// ClassImp(TTableSorter) //_____________________________________________________________________________ //TTableSorter::TTableSorter() : fsimpleArray(0),fParentTable(*((const TTable *)0)) TTableSorter::TTableSorter() : fsimpleArray(0),fParentTable(0) { // default ctor for RootCint dictionary fLastFound = -1; fFirstRow = 0; fSortIndex = 0; fSearchMethod = 0; fNumberOfRows = 0; fColType = TTable::kNAN; fsimpleArray = 0; fParentRowSize = 0; fFirstParentRow = 0; fCompareMethod = 0; fIndexArray = 0; fColDimensions = 0; fColOffset = 0; fColSize = 0; } //_____________________________________________________________________________ TTableSorter::TTableSorter(const TTable &table, TString &colName,Int_t firstRow ,Int_t numberRows):fsimpleArray(0),fParentTable(&table) { // // TTableSorter ctor sorts the input table along its column defined with colName // // - colName - may be followed by the square brackets with integer number inside, // if that columm is an array (for example "phys[3]"). // NO expression inside of [], only a single integer number allowed ! // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // fCompareMethod = 0; fSearchMethod = 0; BuildSorter(colName, firstRow, numberRows); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const TTable *table, TString &colName,Int_t firstRow ,Int_t numberRows):fsimpleArray(0),fParentTable(table) { // // TTableSorter ctor sorts the input table along its column defined with colName // // - colName - may be followed by the square brackets with integer number inside, // if that columm is an array (for example "phys[3]"). // NO expression inside of [], only a single integer number allowed ! // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // fCompareMethod = 0; fSearchMethod = 0; BuildSorter(colName, firstRow, numberRows); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const TTable &table, SEARCHMETHOD search, COMPAREMETHOD compare, Int_t firstRow,Int_t numberRows) :fsimpleArray(0),fParentTable(&table) { // // TTableSorter ctor sorts the input table according the function "search" // // - search - the function to compare the "key" and the table rows during sorting // typedef Int_t (*SEARCHMETHOD) (const void *, const void **); // // - compare - the function to compare two table rows during searching // typedef Int_t (*COMPAREMETHOD)(const void **, const void **); // // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // Note: This is a base class. If one fears it is not safe // ----- to allow "void *" one may potect the end-user code // providing a derived class with the appropriated type // of the parameters. // fCompareMethod = compare; fSearchMethod = search; TString colName = "user's defined"; BuildSorter(colName, firstRow, numberRows); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const TTable *table, SEARCHMETHOD search, COMPAREMETHOD compare, Int_t firstRow,Int_t numberRows) :fsimpleArray(0),fParentTable(table) { // // TTableSorter ctor sorts the input table according the function "search" // // - search - the function to compare the "key" and the table rows during sorting // typedef Int_t (*SEARCHMETHOD) (const void *, const void **); // // - compare - the function to compare two table rows during searching // typedef Int_t (*COMPAREMETHOD)(const void **, const void **); // // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // Note: This is a base class. If one fears it is not safe // ----- to allow "void *" one may potect the end-user code // providing a derived class with the appropriated type // of the parameters. // fCompareMethod = compare; fSearchMethod = search; TString colName = "user's defined"; BuildSorter(colName, firstRow, numberRows); } //_____________________________________________________________________________ void TTableSorter::BuildSorter(TString &colName, Int_t firstRow, Int_t numberRows) { // // BuildSorter backs TTableSorter ctor // // - colName - may be followed by the square brackets with integer number inside, // if that columm is an array (for example "phys[3]"). // NO expression inside of [], only a single integer number allowed ! // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // assert(fParentTable!=0); fLastFound = -1; fNumberOfRows = 0; fColType = TTable::kNAN; fsimpleArray = 0; //yf fCompareMethod = 0; fSortIndex = 0; //yf fSearchMethod = 0; fColDimensions = 0; fColOffset = 0; // Generate new object name TString n = fParentTable->GetName(); n += "."; n += colName; SetName(n); Char_t *name = (Char_t *) colName.Data(); if (!(name || strlen(colName.Data()))) { MakeZombie(); delete [] name; return; } name = StrDup(colName.Data()); // check bounds: if (firstRow > fParentTable->GetNRows()) { MakeZombie(); delete [] name; return; } fFirstRow = firstRow; fNumberOfRows = fParentTable->GetNRows()- fFirstRow; if (numberRows > 0) fNumberOfRows = TMath::Min(numberRows,fNumberOfRows); fParentRowSize = fParentTable->GetRowSize(); fFirstParentRow= (const char *)fParentTable->GetArray(); // Allocate index array if (fNumberOfRows <=0 ) { MakeZombie(); delete [] name; return; } fSortIndex = new void*[fNumberOfRows]; // define dimensions if any; // count the open "[" Char_t *br = name - 1; while((br = strchr(br+1,'['))) { if (!fColDimensions) *br = 0; fColDimensions++; } // Define the column name fColName = name; delete [] name; fIndexArray = 0; if (fColDimensions) { fIndexArray = new Int_t[fColDimensions]; memset(fIndexArray,0,fColDimensions*sizeof(Int_t)); // Define the index const char *openBracket = colName.Data()-1; const char *closeBracket = colName.Data()-1; for (Int_t i=0; i< fColDimensions; i++) { openBracket = strchr(openBracket+1, '['); closeBracket = strchr(closeBracket+1,']'); if (closeBracket > openBracket) fIndexArray[i] = atoi(openBracket+1); else { Error("TTable ctor", "Wrong parethethis <%s>",colName.Data()); MakeZombie(); return; } } } if (colName != "user's defined") { LearnTable(); SetSearchMethod(); } if (!FillIndexArray()) QSort(); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const Float_t *simpleArray, Int_t arraySize, Int_t firstRow ,Int_t numberRows) :fsimpleArray((const Char_t*)simpleArray) ,fParentTable(0) { // // TTableSorter ctor sort the input "simpleArray" // // - arraySize - the size of the full array // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // fLastFound = -1; SetSimpleArray(arraySize,firstRow,numberRows); if (!fsimpleArray) { MakeZombie(); return; } // LearnTable(); fColName = "Float"; fColType = TTable::kFloat; fColSize = sizeof(Float_t); fParentRowSize = fColSize; // FillIndexArray(); Float_t *p = ((Float_t *)fsimpleArray) + fFirstRow; Bool_t isPreSorted = kTRUE; Float_t sample = *p; for (Int_t i=0; i < fNumberOfRows;i++,p++) { fSortIndex[i-fFirstRow] = p; if ( isPreSorted) { if (sample > *p) isPreSorted = kFALSE; else sample = *p; } } SetSearchMethod(); if (!isPreSorted) QSort(); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const Double_t *simpleArray, Int_t arraySize, Int_t firstRow ,Int_t numberRows) :fsimpleArray((const Char_t*)simpleArray) ,fParentTable(0) { // // TTableSorter ctor sort the input "simpleArray" // // - arraySize - the size of the full array // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // fLastFound = -1; SetSimpleArray(arraySize,firstRow,numberRows); if (!fsimpleArray) {MakeZombie(); return; } // LearnTable(); fColName = "Double"; fColType = TTable::kDouble; fColSize = sizeof(Double_t); fParentRowSize = fColSize; // FillIndexArray(); Double_t *p = ((Double_t *)simpleArray) + fFirstRow; Bool_t isPreSorted = kTRUE; Double_t sample = *p; for (Int_t i=0; i < fNumberOfRows;i++,p++) { fSortIndex[i-fFirstRow] = p; if ( isPreSorted) { if (sample > *p) isPreSorted = kFALSE; else sample = *p; } } SetSearchMethod(); if (!isPreSorted) QSort(); } //_____________________________________________________________________________ TTableSorter::TTableSorter(const Long_t *simpleArray, Int_t arraySize, Int_t firstRow ,Int_t numberRows) :fsimpleArray((const Char_t*)simpleArray) ,fParentTable(0) { // // TTableSorter ctor sort the input "simpleArray" // // - arraySize - the sie of the full array // - firstRow - the first table row to sort from (=0 by default) // - numberRows - the number of the table rows to sort (=0 by default) // = 0 means sort all rows from the "firstRow" by the end of table // fLastFound = -1; SetSimpleArray(arraySize,firstRow,numberRows); if (!simpleArray) { MakeZombie(); return; } // LearnTable(); fColName = "Long"; fColType = TTable::kLong; fColSize = sizeof(Long_t); fParentRowSize = fColSize; // FillIndexArray(); Long_t *p = ((Long_t *)simpleArray) + fFirstRow; Bool_t isPreSorted = kTRUE; Long_t sample = *p; for (Int_t i=0; i < fNumberOfRows;i++,p++) { fSortIndex[i-fFirstRow] = p; if ( isPreSorted) { if (sample > *p) isPreSorted = kFALSE; else sample = *p; } } SetSearchMethod(); if (!isPreSorted) QSort(); } //_____________________________________________________________________________ void TTableSorter::SetSimpleArray(Int_t arraySize, Int_t firstRow,Int_t numberRows) { // Set some common parameteres for the "simple" arrays SetName("Array"); fSortIndex = 0; fSearchMethod = 0; fColDimensions = 0; delete [] fIndexArray; fIndexArray = 0; fColOffset = 0; // check bounds: if (firstRow > arraySize) return; fFirstRow = firstRow; fNumberOfRows = arraySize - fFirstRow; if (numberRows > 0) fNumberOfRows = TMath::Min(numberRows,fNumberOfRows); // Allocate index array delete [] fSortIndex; if (fNumberOfRows > 0) fSortIndex = new void*[fNumberOfRows]; } //_____________________________________________________________________________ TTableSorter::~TTableSorter() { //to be documented delete [] fSortIndex; fSortIndex = 0; fNumberOfRows=0; delete [] fIndexArray; } //_____________________________________________________________________________ //______________________________________________________________________________ //*-*-*-*-*-*-*Binary search in an array of n values to locate value*-*-*-*-*-*-* //*-* ================================================== //*-* If match is found, the function returns the position (index) of the element. //*-* If no match found, the function gives the index of the nearest element //*-* smaller than key value. //*-* Note: The function returns the negative result if the key value //*-* ---- is smaller any table value. //*-* //*-* This method is based on TMath::BinarySearch //*-* //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* #define BINARYSEARCH(valuetype) Int_t TTableSorter::BinarySearch(valuetype value) const {\ switch (fColType) { \ case TTable::kFloat: \ return SelectSearch(Float_t(value)); \ case TTable::kInt : \ return SelectSearch(Int_t(value)); \ case TTable::kLong : \ return SelectSearch(Long_t(value)); \ case TTable::kShort : \ return SelectSearch(Short_t(value)); \ case TTable::kDouble : \ return SelectSearch(Double_t(value)); \ case TTable::kUInt: \ return SelectSearch(UInt_t(value)); \ case TTable::kULong : \ return SelectSearch(ULong_t(value)); \ case TTable::kUShort: \ return SelectSearch(UShort_t(value)); \ case TTable::kBool: \ return SelectSearch(Bool_t(value)); \ case TTable::kUChar: \ return SelectSearch(UChar_t(value)); \ case TTable::kChar: \ return SelectSearch(Char_t(value)); \ default: \ return -1; \ break; \ }; \ } \ Int_t TTableSorter::BSearch(valuetype value) const{ \ union { Bool_t Bool; \ Char_t Char; \ UChar_t UChar; \ Short_t Short; \ UShort_t UShort; \ Int_t Int; \ UInt_t UInt; \ Long_t Long; \ ULong_t ULong; \ Float_t Float; \ Double_t Double; \ } value_; \ \ switch (fColType) { \ case TTable::kFloat: \ value_.Float = Float_t(value); break; \ case TTable::kInt : \ value_.Int = Int_t(value); break; \ case TTable::kLong : \ value_.Long = Long_t(value); break; \ case TTable::kShort : \ value_.Short = Short_t(value); break; \ case TTable::kDouble : \ value_.Double= Double_t(value);break; \ case TTable::kUInt: \ value_.UInt = UInt_t(value); break; \ case TTable::kULong : \ value_.ULong = ULong_t(value); break; \ case TTable::kUShort: \ value_.UShort= UShort_t(value);break; \ case TTable::kUChar: \ value_.UChar = UChar_t(value); break; \ case TTable::kChar: \ value_.Char = Char_t(value); break; \ case TTable::kBool: \ value_.Bool = Bool_t(value); break; \ default: \ return -1; \ break; \ }; \ return BSearch(&value_); \ } \ Int_t TTableSorter::SelectSearch(valuetype value) const { \ valuetype **array = (valuetype **)fSortIndex; \ Int_t nabove, nbelow, middle; \ nabove = fNumberOfRows+1; \ nbelow = 0; \ while(nabove-nbelow > 1) { \ middle = (nabove+nbelow)/2; \ if (value == *array[middle-1]) { nbelow = middle; break; } \ if (value < *array[middle-1]) nabove = middle; \ else nbelow = middle; \ } \ nbelow--; \ ((TTableSorter *)this)->fLastFound = nbelow; \ if (nbelow < 0) return nbelow; \ return GetIndex(nbelow); \ } #define COMPAREFLOATVALUES(valuetype) \ int TTableSorter::Search##valuetype (const void *elem1, const void **elem2) { \ valuetype *value1 = (valuetype *)(elem1); \ valuetype *value2 = (valuetype *)(*elem2); \ valuetype diff = *value1-*value2; \ Int_t res = 0; \ if (diff > 0) res = 1; \ else if (diff < 0) res = -1; \ return res; \ } \ int TTableSorter::Compare##valuetype (const void **elem1, const void **elem2) {\ valuetype *value1 = (valuetype *)(*elem1); \ valuetype *value2 = (valuetype *)(*elem2); \ valuetype diff = *value1-*value2; \ Int_t res = 0; \ if (diff > 0 ) res = 1; \ else if (diff < 0) res = -1; \ if (res) return res; \ return int(value1-value2); \ } \ BINARYSEARCH(valuetype) //_____________________________________________________________________________ #define COMPAREVALUES(valuetype) \ int TTableSorter::Search##valuetype (const void *elem1, const void **elem2) { \ valuetype *value1 = (valuetype *)(elem1); \ valuetype *value2 = (valuetype *)(*elem2); \ return int(*value1-*value2); \ } \ int TTableSorter::Compare##valuetype (const void **elem1, const void **elem2) { \ valuetype *value1 = (valuetype *)(*elem1); \ valuetype *value2 = (valuetype *)(*elem2); \ valuetype diff = *value1-*value2; \ if (diff ) return diff; \ return int(value1-value2); \ } \ BINARYSEARCH(valuetype) COMPAREFLOATVALUES(Float_t) COMPAREVALUES(Int_t) COMPAREVALUES(Long_t) COMPAREVALUES(ULong_t) COMPAREVALUES(UInt_t) COMPAREVALUES(Short_t) COMPAREFLOATVALUES(Double_t) COMPAREVALUES(UShort_t) COMPAREVALUES(UChar_t) COMPAREVALUES(Char_t) COMPAREVALUES(Bool_t) #define COMPAREORDER(valuetype) Compare##valuetype #define SEARCHORDER(valuetype) Search##valuetype //_____________________________________________________________________________ Int_t TTableSorter::BSearch(const void *value) const { //to be documented Int_t index = -1; if (fSearchMethod) { void **p = (void **)::bsearch((void *) value, // Object to search for fSortIndex, // Pointer to base of search data fNumberOfRows, // Number of elements sizeof(void *), // Width of elements CALLQSORT(fSearchMethod)); ((TTableSorter *)this)->fLastFound = -1; if (p) { const Char_t *res = (const Char_t *)(*p); ((TTableSorter *)this)->fLastFound = ((Char_t *)p - (Char_t *)fSortIndex)/sizeof(void *); // calculate index: if (!fsimpleArray) index = fFirstRow + (res - (At(fFirstRow)+ fColOffset))/fParentRowSize; else index = ULong_t(res) - ULong_t(fsimpleArray)/fColSize; } } return index; } //_____________________________________________________________________________ Int_t TTableSorter::GetIndex(UInt_t sortedIndex) const { // returns the original index of the row by its sorted index Int_t indx = -1; if (sortedIndex < UInt_t(fNumberOfRows) ) { void *p = fSortIndex[sortedIndex]; if (p) { const Char_t *res = (const Char_t *)p; // calculate index: if (!fsimpleArray) indx = fFirstRow + (res - (At(fFirstRow) + fColOffset))/fParentRowSize; else indx = (ULong_t(res) - ULong_t(fsimpleArray))/fColSize; } } return indx; } #if 0 //_____________________________________________________________________________ int TTableSorter::CompareUChar (const void *elem1, const void *elem2) { //to be documented UChar_t *value1 = (UChar_t *)(*elem1); UChar_t *value2 = (UChar_t *)(*elem2); COMPAREVALUES(value1,value2) } //_____________________________________________________________________________ int TTableSorter::CompareChar (const void *elem1, const void *elem2) { //to be documented Char_t *value1 = (Char_t *)(*elem1); Char_t *value2 = (Char_t *)(*elem2); COMPAREVALUES(value1,value2) } #endif //_____________________________________________________________________________ Int_t TTableSorter::CountKey(const void *key, Int_t firstIndx, Bool_t bSearch, Int_t *firstRow) const { // // CountKey counts the number of rows with the key value equal "key" // // key - it is a POINTER to the key value // fistIndx - the first index within sorted array to star search // = 0 by default // bSearch = kTRUE - binary search (by default) is used otherwise linear one // Int_t count = 0; if (firstRow) *firstRow = -1; if (fSearchMethod) { Int_t indx = firstIndx; Int_t nRows = GetNRows(); if (!bSearch) { while ( indx < nRows && fSearchMethod(key,(const void **)&fSortIndex[indx])){indx++;} // Remember the first row been asked: } else { indx = FindFirstKey(key); if (indx >= 0 ) { // Key was found let's count it count = TMath::Max(0,GetLastFound() - indx + 1); indx = TMath::Max(GetLastFound()+1,firstIndx); // Forward pass } } if (indx >= 0) { while ( indx < nRows &&!fSearchMethod(key,(const void **)&fSortIndex[indx])){indx++; count++;} if (firstRow && count) *firstRow = indx-count; } } return count; } //_____________________________________________________________________________ Int_t TTableSorter::CountKeys() const { // // Counts the number of different key values // Int_t count = 0; if (fSortIndex && fSortIndex[0]) { void *key = fSortIndex[0]; Int_t indx = 0; while (indx < GetNRows()){ indx += CountKey(key,indx,kFALSE); count++; key = fSortIndex[indx]; } } return count; } //_____________________________________________________________________________ Bool_t TTableSorter::FillIndexArray(){ ////////////////////////////////////////////////////////////// // File the array of the pointers and check whether // the original table has been sorted to avoid an extra job. // // Return: kTRUE - the table has been sorted // kFALSE - otherwise ////////////////////////////////////////////////////////////// assert(fSortIndex!=0); const char *row = At(fFirstRow) + fColOffset; Bool_t isPreSorted = kTRUE; const void *sample = row; for (Int_t i=fFirstRow; i < fFirstRow+fNumberOfRows;i++,row += fParentRowSize) { fSortIndex[i-fFirstRow] = (char *)row; if ( isPreSorted) { void *ptr = &row; if (fCompareMethod(&sample,(const void **)ptr)>0) isPreSorted = kFALSE; else sample = row; } } return isPreSorted; } //_____________________________________________________________________________ Int_t TTableSorter::FindFirstKey(const void *key) const { // // Looks for the first index of the "key" // within SORTED table AFTER sorting // // Returns: = -1 if the "key" was not found // // Note: This method has no sense for // ==== the float and double key // // To get the index within the original // unsorted table the GetIndex() method // may be used like this: // GetIndex(FindFirstKey(key)) // Int_t indx = -1; if (BSearch(key)>=0) { indx = GetLastFound(); if (indx >=0) while (indx > 0 && !fSearchMethod(key,(const void **)&fSortIndex[indx-1])) indx--; } return indx; } //_____________________________________________________________________________ const char * TTableSorter::GetTableName() const { //to be documented return fParentTable ? fParentTable->GetName():""; } //_____________________________________________________________________________ const char * TTableSorter::GetTableTitle() const { //to be documented return fParentTable ? fParentTable->GetTitle():""; } //_____________________________________________________________________________ const char * TTableSorter::GetTableType() const { //to be documented return fParentTable ? fParentTable->GetType():""; } //_____________________________________________________________________________ TTable *TTableSorter::GetTable() const { //to be documented return (TTable *)fParentTable; } //_____________________________________________________________________________ void TTableSorter::SetSearchMethod() { // Select search function at once if (!fSearchMethod) { switch (fColType) { case TTable::kFloat: fSearchMethod = SEARCHORDER(Float_t); fCompareMethod = COMPAREORDER(Float_t); break; case TTable::kInt : fSearchMethod = SEARCHORDER(Int_t); fCompareMethod = COMPAREORDER(Int_t); break; case TTable::kLong : fSearchMethod = SEARCHORDER(Long_t); fCompareMethod = COMPAREORDER(Long_t); break; case TTable::kShort : fSearchMethod = SEARCHORDER(Short_t); fCompareMethod = COMPAREORDER(Short_t); break; case TTable::kDouble : fSearchMethod = SEARCHORDER(Double_t); fCompareMethod = COMPAREORDER(Double_t); break; case TTable::kUInt: fSearchMethod = SEARCHORDER(UInt_t); fCompareMethod = COMPAREORDER(UInt_t); break; case TTable::kULong : fSearchMethod= SEARCHORDER(ULong_t); fCompareMethod = COMPAREORDER(ULong_t); break; case TTable::kUShort: fSearchMethod = SEARCHORDER(UShort_t); fCompareMethod = COMPAREORDER(UShort_t); break; case TTable::kUChar: fSearchMethod = SEARCHORDER(UChar_t); fCompareMethod = COMPAREORDER(UChar_t); break; case TTable::kChar: fSearchMethod = SEARCHORDER(Char_t); fCompareMethod = COMPAREORDER(Char_t); break; case TTable::kBool: fSearchMethod = SEARCHORDER(Bool_t); fCompareMethod = COMPAREORDER(Bool_t); break; default: break; }; } } //____________________________________________________________________________ void TTableSorter::QSort(){ // Call the standard C run-time library "qsort" function // if (fCompareMethod) ::qsort(fSortIndex, //Start of target array fNumberOfRows, //Array size in elements sizeof(void *), //Element size in bytes CALLQSORT(fCompareMethod)); } //____________________________________________________________________________ void TTableSorter::LearnTable() { // // LearnTable() allows the TTableSorter to learn the structure of the // tables used to fill the ntuple. // table - the name of the table // buildTree - if kTRUE, then add TBranches to the TTree for each table // column (default=kFALSE) // TClass *classPtr = fParentTable->GetRowClass(); if (!classPtr) return; if (!classPtr->GetListOfRealData()) classPtr->BuildRealData(); if (!(classPtr->GetNdata())) return; const Char_t *types; Char_t *varname; TIter next(classPtr->GetListOfDataMembers()); TDataMember *member = 0; while ( (member = (TDataMember *) next()) ) { varname = (Char_t *) member->GetName(); if (strcmp(varname,fColName.Data())) continue; TDataType *memberType = member->GetDataType(); types = memberType->GetTypeName(); SetTitle(types); if (!strcmp("float", types)) fColType = TTable::kFloat ; else if (!strcmp("int", types)) fColType = TTable::kInt ; else if (!strcmp("long", types)) fColType = TTable::kLong ; else if (!strcmp("short", types)) fColType = TTable::kShort ; else if (!strcmp("double", types)) fColType = TTable::kDouble; else if (!strcmp("unsigned int", types)) fColType = TTable::kUInt ; else if (!strcmp("unsigned long", types)) fColType = TTable::kULong ; else if (!strcmp("unsigned short", types)) fColType = TTable::kUShort; else if (!strcmp("unsigned char", types)) fColType = TTable::kUChar; else if (!strcmp("char", types)) fColType= TTable::kChar; else if (!strcmp("bool", types)) fColType= TTable::kBool; if (fColType != TTable::kNAN) { Int_t dim = 0; Int_t globalIndex = 0; if ( (dim = member->GetArrayDim()) ) { // Check dimensions if (dim != fColDimensions) { Error("LearnTable","Wrong dimension"); TTable *t = (TTable *)fParentTable; t->Print(); return; } // Calculate the global index for( Int_t indx=0; indx < fColDimensions; indx++ ){ globalIndex *= member->GetMaxIndex(indx); globalIndex += fIndexArray[indx]; } } fColSize = memberType->Size(); fColOffset = member->GetOffset() + memberType->Size() * globalIndex; } break; } } #undef COMPAREVALUES #undef COMPAREORDER #undef COMPAREFLOATVALUES #undef BINARYSEARCH