// @(#)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 <stdlib.h>
#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 one finds useful for one's 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
 TTableSorter.cxx:1
 TTableSorter.cxx:2
 TTableSorter.cxx:3
 TTableSorter.cxx:4
 TTableSorter.cxx:5
 TTableSorter.cxx:6
 TTableSorter.cxx:7
 TTableSorter.cxx:8
 TTableSorter.cxx:9
 TTableSorter.cxx:10
 TTableSorter.cxx:11
 TTableSorter.cxx:12
 TTableSorter.cxx:13
 TTableSorter.cxx:14
 TTableSorter.cxx:15
 TTableSorter.cxx:16
 TTableSorter.cxx:17
 TTableSorter.cxx:18
 TTableSorter.cxx:19
 TTableSorter.cxx:20
 TTableSorter.cxx:21
 TTableSorter.cxx:22
 TTableSorter.cxx:23
 TTableSorter.cxx:24
 TTableSorter.cxx:25
 TTableSorter.cxx:26
 TTableSorter.cxx:27
 TTableSorter.cxx:28
 TTableSorter.cxx:29
 TTableSorter.cxx:30
 TTableSorter.cxx:31
 TTableSorter.cxx:32
 TTableSorter.cxx:33
 TTableSorter.cxx:34
 TTableSorter.cxx:35
 TTableSorter.cxx:36
 TTableSorter.cxx:37
 TTableSorter.cxx:38
 TTableSorter.cxx:39
 TTableSorter.cxx:40
 TTableSorter.cxx:41
 TTableSorter.cxx:42
 TTableSorter.cxx:43
 TTableSorter.cxx:44
 TTableSorter.cxx:45
 TTableSorter.cxx:46
 TTableSorter.cxx:47
 TTableSorter.cxx:48
 TTableSorter.cxx:49
 TTableSorter.cxx:50
 TTableSorter.cxx:51
 TTableSorter.cxx:52
 TTableSorter.cxx:53
 TTableSorter.cxx:54
 TTableSorter.cxx:55
 TTableSorter.cxx:56
 TTableSorter.cxx:57
 TTableSorter.cxx:58
 TTableSorter.cxx:59
 TTableSorter.cxx:60
 TTableSorter.cxx:61
 TTableSorter.cxx:62
 TTableSorter.cxx:63
 TTableSorter.cxx:64
 TTableSorter.cxx:65
 TTableSorter.cxx:66
 TTableSorter.cxx:67
 TTableSorter.cxx:68
 TTableSorter.cxx:69
 TTableSorter.cxx:70
 TTableSorter.cxx:71
 TTableSorter.cxx:72
 TTableSorter.cxx:73
 TTableSorter.cxx:74
 TTableSorter.cxx:75
 TTableSorter.cxx:76
 TTableSorter.cxx:77
 TTableSorter.cxx:78
 TTableSorter.cxx:79
 TTableSorter.cxx:80
 TTableSorter.cxx:81
 TTableSorter.cxx:82
 TTableSorter.cxx:83
 TTableSorter.cxx:84
 TTableSorter.cxx:85
 TTableSorter.cxx:86
 TTableSorter.cxx:87
 TTableSorter.cxx:88
 TTableSorter.cxx:89
 TTableSorter.cxx:90
 TTableSorter.cxx:91
 TTableSorter.cxx:92
 TTableSorter.cxx:93
 TTableSorter.cxx:94
 TTableSorter.cxx:95
 TTableSorter.cxx:96
 TTableSorter.cxx:97
 TTableSorter.cxx:98
 TTableSorter.cxx:99
 TTableSorter.cxx:100
 TTableSorter.cxx:101
 TTableSorter.cxx:102
 TTableSorter.cxx:103
 TTableSorter.cxx:104
 TTableSorter.cxx:105
 TTableSorter.cxx:106
 TTableSorter.cxx:107
 TTableSorter.cxx:108
 TTableSorter.cxx:109
 TTableSorter.cxx:110
 TTableSorter.cxx:111
 TTableSorter.cxx:112
 TTableSorter.cxx:113
 TTableSorter.cxx:114
 TTableSorter.cxx:115
 TTableSorter.cxx:116
 TTableSorter.cxx:117
 TTableSorter.cxx:118
 TTableSorter.cxx:119
 TTableSorter.cxx:120
 TTableSorter.cxx:121
 TTableSorter.cxx:122
 TTableSorter.cxx:123
 TTableSorter.cxx:124
 TTableSorter.cxx:125
 TTableSorter.cxx:126
 TTableSorter.cxx:127
 TTableSorter.cxx:128
 TTableSorter.cxx:129
 TTableSorter.cxx:130
 TTableSorter.cxx:131
 TTableSorter.cxx:132
 TTableSorter.cxx:133
 TTableSorter.cxx:134
 TTableSorter.cxx:135
 TTableSorter.cxx:136
 TTableSorter.cxx:137
 TTableSorter.cxx:138
 TTableSorter.cxx:139
 TTableSorter.cxx:140
 TTableSorter.cxx:141
 TTableSorter.cxx:142
 TTableSorter.cxx:143
 TTableSorter.cxx:144
 TTableSorter.cxx:145
 TTableSorter.cxx:146
 TTableSorter.cxx:147
 TTableSorter.cxx:148
 TTableSorter.cxx:149
 TTableSorter.cxx:150
 TTableSorter.cxx:151
 TTableSorter.cxx:152
 TTableSorter.cxx:153
 TTableSorter.cxx:154
 TTableSorter.cxx:155
 TTableSorter.cxx:156
 TTableSorter.cxx:157
 TTableSorter.cxx:158
 TTableSorter.cxx:159
 TTableSorter.cxx:160
 TTableSorter.cxx:161
 TTableSorter.cxx:162
 TTableSorter.cxx:163
 TTableSorter.cxx:164
 TTableSorter.cxx:165
 TTableSorter.cxx:166
 TTableSorter.cxx:167
 TTableSorter.cxx:168
 TTableSorter.cxx:169
 TTableSorter.cxx:170
 TTableSorter.cxx:171
 TTableSorter.cxx:172
 TTableSorter.cxx:173
 TTableSorter.cxx:174
 TTableSorter.cxx:175
 TTableSorter.cxx:176
 TTableSorter.cxx:177
 TTableSorter.cxx:178
 TTableSorter.cxx:179
 TTableSorter.cxx:180
 TTableSorter.cxx:181
 TTableSorter.cxx:182
 TTableSorter.cxx:183
 TTableSorter.cxx:184
 TTableSorter.cxx:185
 TTableSorter.cxx:186
 TTableSorter.cxx:187
 TTableSorter.cxx:188
 TTableSorter.cxx:189
 TTableSorter.cxx:190
 TTableSorter.cxx:191
 TTableSorter.cxx:192
 TTableSorter.cxx:193
 TTableSorter.cxx:194
 TTableSorter.cxx:195
 TTableSorter.cxx:196
 TTableSorter.cxx:197
 TTableSorter.cxx:198
 TTableSorter.cxx:199
 TTableSorter.cxx:200
 TTableSorter.cxx:201
 TTableSorter.cxx:202
 TTableSorter.cxx:203
 TTableSorter.cxx:204
 TTableSorter.cxx:205
 TTableSorter.cxx:206
 TTableSorter.cxx:207
 TTableSorter.cxx:208
 TTableSorter.cxx:209
 TTableSorter.cxx:210
 TTableSorter.cxx:211
 TTableSorter.cxx:212
 TTableSorter.cxx:213
 TTableSorter.cxx:214
 TTableSorter.cxx:215
 TTableSorter.cxx:216
 TTableSorter.cxx:217
 TTableSorter.cxx:218
 TTableSorter.cxx:219
 TTableSorter.cxx:220
 TTableSorter.cxx:221
 TTableSorter.cxx:222
 TTableSorter.cxx:223
 TTableSorter.cxx:224
 TTableSorter.cxx:225
 TTableSorter.cxx:226
 TTableSorter.cxx:227
 TTableSorter.cxx:228
 TTableSorter.cxx:229
 TTableSorter.cxx:230
 TTableSorter.cxx:231
 TTableSorter.cxx:232
 TTableSorter.cxx:233
 TTableSorter.cxx:234
 TTableSorter.cxx:235
 TTableSorter.cxx:236
 TTableSorter.cxx:237
 TTableSorter.cxx:238
 TTableSorter.cxx:239
 TTableSorter.cxx:240
 TTableSorter.cxx:241
 TTableSorter.cxx:242
 TTableSorter.cxx:243
 TTableSorter.cxx:244
 TTableSorter.cxx:245
 TTableSorter.cxx:246
 TTableSorter.cxx:247
 TTableSorter.cxx:248
 TTableSorter.cxx:249
 TTableSorter.cxx:250
 TTableSorter.cxx:251
 TTableSorter.cxx:252
 TTableSorter.cxx:253
 TTableSorter.cxx:254
 TTableSorter.cxx:255
 TTableSorter.cxx:256
 TTableSorter.cxx:257
 TTableSorter.cxx:258
 TTableSorter.cxx:259
 TTableSorter.cxx:260
 TTableSorter.cxx:261
 TTableSorter.cxx:262
 TTableSorter.cxx:263
 TTableSorter.cxx:264
 TTableSorter.cxx:265
 TTableSorter.cxx:266
 TTableSorter.cxx:267
 TTableSorter.cxx:268
 TTableSorter.cxx:269
 TTableSorter.cxx:270
 TTableSorter.cxx:271
 TTableSorter.cxx:272
 TTableSorter.cxx:273
 TTableSorter.cxx:274
 TTableSorter.cxx:275
 TTableSorter.cxx:276
 TTableSorter.cxx:277
 TTableSorter.cxx:278
 TTableSorter.cxx:279
 TTableSorter.cxx:280
 TTableSorter.cxx:281
 TTableSorter.cxx:282
 TTableSorter.cxx:283
 TTableSorter.cxx:284
 TTableSorter.cxx:285
 TTableSorter.cxx:286
 TTableSorter.cxx:287
 TTableSorter.cxx:288
 TTableSorter.cxx:289
 TTableSorter.cxx:290
 TTableSorter.cxx:291
 TTableSorter.cxx:292
 TTableSorter.cxx:293
 TTableSorter.cxx:294
 TTableSorter.cxx:295
 TTableSorter.cxx:296
 TTableSorter.cxx:297
 TTableSorter.cxx:298
 TTableSorter.cxx:299
 TTableSorter.cxx:300
 TTableSorter.cxx:301
 TTableSorter.cxx:302
 TTableSorter.cxx:303
 TTableSorter.cxx:304
 TTableSorter.cxx:305
 TTableSorter.cxx:306
 TTableSorter.cxx:307
 TTableSorter.cxx:308
 TTableSorter.cxx:309
 TTableSorter.cxx:310
 TTableSorter.cxx:311
 TTableSorter.cxx:312
 TTableSorter.cxx:313
 TTableSorter.cxx:314
 TTableSorter.cxx:315
 TTableSorter.cxx:316
 TTableSorter.cxx:317
 TTableSorter.cxx:318
 TTableSorter.cxx:319
 TTableSorter.cxx:320
 TTableSorter.cxx:321
 TTableSorter.cxx:322
 TTableSorter.cxx:323
 TTableSorter.cxx:324
 TTableSorter.cxx:325
 TTableSorter.cxx:326
 TTableSorter.cxx:327
 TTableSorter.cxx:328
 TTableSorter.cxx:329
 TTableSorter.cxx:330
 TTableSorter.cxx:331
 TTableSorter.cxx:332
 TTableSorter.cxx:333
 TTableSorter.cxx:334
 TTableSorter.cxx:335
 TTableSorter.cxx:336
 TTableSorter.cxx:337
 TTableSorter.cxx:338
 TTableSorter.cxx:339
 TTableSorter.cxx:340
 TTableSorter.cxx:341
 TTableSorter.cxx:342
 TTableSorter.cxx:343
 TTableSorter.cxx:344
 TTableSorter.cxx:345
 TTableSorter.cxx:346
 TTableSorter.cxx:347
 TTableSorter.cxx:348
 TTableSorter.cxx:349
 TTableSorter.cxx:350
 TTableSorter.cxx:351
 TTableSorter.cxx:352
 TTableSorter.cxx:353
 TTableSorter.cxx:354
 TTableSorter.cxx:355
 TTableSorter.cxx:356
 TTableSorter.cxx:357
 TTableSorter.cxx:358
 TTableSorter.cxx:359
 TTableSorter.cxx:360
 TTableSorter.cxx:361
 TTableSorter.cxx:362
 TTableSorter.cxx:363
 TTableSorter.cxx:364
 TTableSorter.cxx:365
 TTableSorter.cxx:366
 TTableSorter.cxx:367
 TTableSorter.cxx:368
 TTableSorter.cxx:369
 TTableSorter.cxx:370
 TTableSorter.cxx:371
 TTableSorter.cxx:372
 TTableSorter.cxx:373
 TTableSorter.cxx:374
 TTableSorter.cxx:375
 TTableSorter.cxx:376
 TTableSorter.cxx:377
 TTableSorter.cxx:378
 TTableSorter.cxx:379
 TTableSorter.cxx:380
 TTableSorter.cxx:381
 TTableSorter.cxx:382
 TTableSorter.cxx:383
 TTableSorter.cxx:384
 TTableSorter.cxx:385
 TTableSorter.cxx:386
 TTableSorter.cxx:387
 TTableSorter.cxx:388
 TTableSorter.cxx:389
 TTableSorter.cxx:390
 TTableSorter.cxx:391
 TTableSorter.cxx:392
 TTableSorter.cxx:393
 TTableSorter.cxx:394
 TTableSorter.cxx:395
 TTableSorter.cxx:396
 TTableSorter.cxx:397
 TTableSorter.cxx:398
 TTableSorter.cxx:399
 TTableSorter.cxx:400
 TTableSorter.cxx:401
 TTableSorter.cxx:402
 TTableSorter.cxx:403
 TTableSorter.cxx:404
 TTableSorter.cxx:405
 TTableSorter.cxx:406
 TTableSorter.cxx:407
 TTableSorter.cxx:408
 TTableSorter.cxx:409
 TTableSorter.cxx:410
 TTableSorter.cxx:411
 TTableSorter.cxx:412
 TTableSorter.cxx:413
 TTableSorter.cxx:414
 TTableSorter.cxx:415
 TTableSorter.cxx:416
 TTableSorter.cxx:417
 TTableSorter.cxx:418
 TTableSorter.cxx:419
 TTableSorter.cxx:420
 TTableSorter.cxx:421
 TTableSorter.cxx:422
 TTableSorter.cxx:423
 TTableSorter.cxx:424
 TTableSorter.cxx:425
 TTableSorter.cxx:426
 TTableSorter.cxx:427
 TTableSorter.cxx:428
 TTableSorter.cxx:429
 TTableSorter.cxx:430
 TTableSorter.cxx:431
 TTableSorter.cxx:432
 TTableSorter.cxx:433
 TTableSorter.cxx:434
 TTableSorter.cxx:435
 TTableSorter.cxx:436
 TTableSorter.cxx:437
 TTableSorter.cxx:438
 TTableSorter.cxx:439
 TTableSorter.cxx:440
 TTableSorter.cxx:441
 TTableSorter.cxx:442
 TTableSorter.cxx:443
 TTableSorter.cxx:444
 TTableSorter.cxx:445
 TTableSorter.cxx:446
 TTableSorter.cxx:447
 TTableSorter.cxx:448
 TTableSorter.cxx:449
 TTableSorter.cxx:450
 TTableSorter.cxx:451
 TTableSorter.cxx:452
 TTableSorter.cxx:453
 TTableSorter.cxx:454
 TTableSorter.cxx:455
 TTableSorter.cxx:456
 TTableSorter.cxx:457
 TTableSorter.cxx:458
 TTableSorter.cxx:459
 TTableSorter.cxx:460
 TTableSorter.cxx:461
 TTableSorter.cxx:462
 TTableSorter.cxx:463
 TTableSorter.cxx:464
 TTableSorter.cxx:465
 TTableSorter.cxx:466
 TTableSorter.cxx:467
 TTableSorter.cxx:468
 TTableSorter.cxx:469
 TTableSorter.cxx:470
 TTableSorter.cxx:471
 TTableSorter.cxx:472
 TTableSorter.cxx:473
 TTableSorter.cxx:474
 TTableSorter.cxx:475
 TTableSorter.cxx:476
 TTableSorter.cxx:477
 TTableSorter.cxx:478
 TTableSorter.cxx:479
 TTableSorter.cxx:480
 TTableSorter.cxx:481
 TTableSorter.cxx:482
 TTableSorter.cxx:483
 TTableSorter.cxx:484
 TTableSorter.cxx:485
 TTableSorter.cxx:486
 TTableSorter.cxx:487
 TTableSorter.cxx:488
 TTableSorter.cxx:489
 TTableSorter.cxx:490
 TTableSorter.cxx:491
 TTableSorter.cxx:492
 TTableSorter.cxx:493
 TTableSorter.cxx:494
 TTableSorter.cxx:495
 TTableSorter.cxx:496
 TTableSorter.cxx:497
 TTableSorter.cxx:498
 TTableSorter.cxx:499
 TTableSorter.cxx:500
 TTableSorter.cxx:501
 TTableSorter.cxx:502
 TTableSorter.cxx:503
 TTableSorter.cxx:504
 TTableSorter.cxx:505
 TTableSorter.cxx:506
 TTableSorter.cxx:507
 TTableSorter.cxx:508
 TTableSorter.cxx:509
 TTableSorter.cxx:510
 TTableSorter.cxx:511
 TTableSorter.cxx:512
 TTableSorter.cxx:513
 TTableSorter.cxx:514
 TTableSorter.cxx:515
 TTableSorter.cxx:516
 TTableSorter.cxx:517
 TTableSorter.cxx:518
 TTableSorter.cxx:519
 TTableSorter.cxx:520
 TTableSorter.cxx:521
 TTableSorter.cxx:522
 TTableSorter.cxx:523
 TTableSorter.cxx:524
 TTableSorter.cxx:525
 TTableSorter.cxx:526
 TTableSorter.cxx:527
 TTableSorter.cxx:528
 TTableSorter.cxx:529
 TTableSorter.cxx:530
 TTableSorter.cxx:531
 TTableSorter.cxx:532
 TTableSorter.cxx:533
 TTableSorter.cxx:534
 TTableSorter.cxx:535
 TTableSorter.cxx:536
 TTableSorter.cxx:537
 TTableSorter.cxx:538
 TTableSorter.cxx:539
 TTableSorter.cxx:540
 TTableSorter.cxx:541
 TTableSorter.cxx:542
 TTableSorter.cxx:543
 TTableSorter.cxx:544
 TTableSorter.cxx:545
 TTableSorter.cxx:546
 TTableSorter.cxx:547
 TTableSorter.cxx:548
 TTableSorter.cxx:549
 TTableSorter.cxx:550
 TTableSorter.cxx:551
 TTableSorter.cxx:552
 TTableSorter.cxx:553
 TTableSorter.cxx:554
 TTableSorter.cxx:555
 TTableSorter.cxx:556
 TTableSorter.cxx:557
 TTableSorter.cxx:558
 TTableSorter.cxx:559
 TTableSorter.cxx:560
 TTableSorter.cxx:561
 TTableSorter.cxx:562
 TTableSorter.cxx:563
 TTableSorter.cxx:564
 TTableSorter.cxx:565
 TTableSorter.cxx:566
 TTableSorter.cxx:567
 TTableSorter.cxx:568
 TTableSorter.cxx:569
 TTableSorter.cxx:570
 TTableSorter.cxx:571
 TTableSorter.cxx:572
 TTableSorter.cxx:573
 TTableSorter.cxx:574
 TTableSorter.cxx:575
 TTableSorter.cxx:576
 TTableSorter.cxx:577
 TTableSorter.cxx:578
 TTableSorter.cxx:579
 TTableSorter.cxx:580
 TTableSorter.cxx:581
 TTableSorter.cxx:582
 TTableSorter.cxx:583
 TTableSorter.cxx:584
 TTableSorter.cxx:585
 TTableSorter.cxx:586
 TTableSorter.cxx:587
 TTableSorter.cxx:588
 TTableSorter.cxx:589
 TTableSorter.cxx:590
 TTableSorter.cxx:591
 TTableSorter.cxx:592
 TTableSorter.cxx:593
 TTableSorter.cxx:594
 TTableSorter.cxx:595
 TTableSorter.cxx:596
 TTableSorter.cxx:597
 TTableSorter.cxx:598
 TTableSorter.cxx:599
 TTableSorter.cxx:600
 TTableSorter.cxx:601
 TTableSorter.cxx:602
 TTableSorter.cxx:603
 TTableSorter.cxx:604
 TTableSorter.cxx:605
 TTableSorter.cxx:606
 TTableSorter.cxx:607
 TTableSorter.cxx:608
 TTableSorter.cxx:609
 TTableSorter.cxx:610
 TTableSorter.cxx:611
 TTableSorter.cxx:612
 TTableSorter.cxx:613
 TTableSorter.cxx:614
 TTableSorter.cxx:615
 TTableSorter.cxx:616
 TTableSorter.cxx:617
 TTableSorter.cxx:618
 TTableSorter.cxx:619
 TTableSorter.cxx:620
 TTableSorter.cxx:621
 TTableSorter.cxx:622
 TTableSorter.cxx:623
 TTableSorter.cxx:624
 TTableSorter.cxx:625
 TTableSorter.cxx:626
 TTableSorter.cxx:627
 TTableSorter.cxx:628
 TTableSorter.cxx:629
 TTableSorter.cxx:630
 TTableSorter.cxx:631
 TTableSorter.cxx:632
 TTableSorter.cxx:633
 TTableSorter.cxx:634
 TTableSorter.cxx:635
 TTableSorter.cxx:636
 TTableSorter.cxx:637
 TTableSorter.cxx:638
 TTableSorter.cxx:639
 TTableSorter.cxx:640
 TTableSorter.cxx:641
 TTableSorter.cxx:642
 TTableSorter.cxx:643
 TTableSorter.cxx:644
 TTableSorter.cxx:645
 TTableSorter.cxx:646
 TTableSorter.cxx:647
 TTableSorter.cxx:648
 TTableSorter.cxx:649
 TTableSorter.cxx:650
 TTableSorter.cxx:651
 TTableSorter.cxx:652
 TTableSorter.cxx:653
 TTableSorter.cxx:654
 TTableSorter.cxx:655
 TTableSorter.cxx:656
 TTableSorter.cxx:657
 TTableSorter.cxx:658
 TTableSorter.cxx:659
 TTableSorter.cxx:660
 TTableSorter.cxx:661
 TTableSorter.cxx:662
 TTableSorter.cxx:663
 TTableSorter.cxx:664
 TTableSorter.cxx:665
 TTableSorter.cxx:666
 TTableSorter.cxx:667
 TTableSorter.cxx:668
 TTableSorter.cxx:669
 TTableSorter.cxx:670
 TTableSorter.cxx:671
 TTableSorter.cxx:672
 TTableSorter.cxx:673
 TTableSorter.cxx:674
 TTableSorter.cxx:675
 TTableSorter.cxx:676
 TTableSorter.cxx:677
 TTableSorter.cxx:678
 TTableSorter.cxx:679
 TTableSorter.cxx:680
 TTableSorter.cxx:681
 TTableSorter.cxx:682
 TTableSorter.cxx:683
 TTableSorter.cxx:684
 TTableSorter.cxx:685
 TTableSorter.cxx:686
 TTableSorter.cxx:687
 TTableSorter.cxx:688
 TTableSorter.cxx:689
 TTableSorter.cxx:690
 TTableSorter.cxx:691
 TTableSorter.cxx:692
 TTableSorter.cxx:693
 TTableSorter.cxx:694
 TTableSorter.cxx:695
 TTableSorter.cxx:696
 TTableSorter.cxx:697
 TTableSorter.cxx:698
 TTableSorter.cxx:699
 TTableSorter.cxx:700
 TTableSorter.cxx:701
 TTableSorter.cxx:702
 TTableSorter.cxx:703
 TTableSorter.cxx:704
 TTableSorter.cxx:705
 TTableSorter.cxx:706
 TTableSorter.cxx:707
 TTableSorter.cxx:708
 TTableSorter.cxx:709
 TTableSorter.cxx:710
 TTableSorter.cxx:711
 TTableSorter.cxx:712
 TTableSorter.cxx:713
 TTableSorter.cxx:714
 TTableSorter.cxx:715
 TTableSorter.cxx:716
 TTableSorter.cxx:717
 TTableSorter.cxx:718
 TTableSorter.cxx:719
 TTableSorter.cxx:720
 TTableSorter.cxx:721
 TTableSorter.cxx:722
 TTableSorter.cxx:723
 TTableSorter.cxx:724
 TTableSorter.cxx:725
 TTableSorter.cxx:726
 TTableSorter.cxx:727
 TTableSorter.cxx:728
 TTableSorter.cxx:729
 TTableSorter.cxx:730
 TTableSorter.cxx:731
 TTableSorter.cxx:732
 TTableSorter.cxx:733
 TTableSorter.cxx:734
 TTableSorter.cxx:735
 TTableSorter.cxx:736
 TTableSorter.cxx:737
 TTableSorter.cxx:738
 TTableSorter.cxx:739
 TTableSorter.cxx:740
 TTableSorter.cxx:741
 TTableSorter.cxx:742
 TTableSorter.cxx:743
 TTableSorter.cxx:744
 TTableSorter.cxx:745
 TTableSorter.cxx:746
 TTableSorter.cxx:747
 TTableSorter.cxx:748
 TTableSorter.cxx:749
 TTableSorter.cxx:750
 TTableSorter.cxx:751
 TTableSorter.cxx:752
 TTableSorter.cxx:753
 TTableSorter.cxx:754
 TTableSorter.cxx:755
 TTableSorter.cxx:756
 TTableSorter.cxx:757
 TTableSorter.cxx:758
 TTableSorter.cxx:759
 TTableSorter.cxx:760
 TTableSorter.cxx:761
 TTableSorter.cxx:762
 TTableSorter.cxx:763
 TTableSorter.cxx:764
 TTableSorter.cxx:765
 TTableSorter.cxx:766
 TTableSorter.cxx:767
 TTableSorter.cxx:768
 TTableSorter.cxx:769
 TTableSorter.cxx:770
 TTableSorter.cxx:771
 TTableSorter.cxx:772
 TTableSorter.cxx:773
 TTableSorter.cxx:774
 TTableSorter.cxx:775
 TTableSorter.cxx:776
 TTableSorter.cxx:777
 TTableSorter.cxx:778
 TTableSorter.cxx:779
 TTableSorter.cxx:780
 TTableSorter.cxx:781
 TTableSorter.cxx:782
 TTableSorter.cxx:783
 TTableSorter.cxx:784
 TTableSorter.cxx:785
 TTableSorter.cxx:786
 TTableSorter.cxx:787
 TTableSorter.cxx:788
 TTableSorter.cxx:789
 TTableSorter.cxx:790
 TTableSorter.cxx:791
 TTableSorter.cxx:792
 TTableSorter.cxx:793
 TTableSorter.cxx:794
 TTableSorter.cxx:795
 TTableSorter.cxx:796
 TTableSorter.cxx:797
 TTableSorter.cxx:798
 TTableSorter.cxx:799
 TTableSorter.cxx:800
 TTableSorter.cxx:801
 TTableSorter.cxx:802
 TTableSorter.cxx:803
 TTableSorter.cxx:804
 TTableSorter.cxx:805
 TTableSorter.cxx:806
 TTableSorter.cxx:807
 TTableSorter.cxx:808
 TTableSorter.cxx:809
 TTableSorter.cxx:810
 TTableSorter.cxx:811
 TTableSorter.cxx:812
 TTableSorter.cxx:813
 TTableSorter.cxx:814
 TTableSorter.cxx:815
 TTableSorter.cxx:816
 TTableSorter.cxx:817
 TTableSorter.cxx:818
 TTableSorter.cxx:819
 TTableSorter.cxx:820
 TTableSorter.cxx:821
 TTableSorter.cxx:822
 TTableSorter.cxx:823
 TTableSorter.cxx:824
 TTableSorter.cxx:825
 TTableSorter.cxx:826
 TTableSorter.cxx:827
 TTableSorter.cxx:828
 TTableSorter.cxx:829
 TTableSorter.cxx:830
 TTableSorter.cxx:831
 TTableSorter.cxx:832
 TTableSorter.cxx:833
 TTableSorter.cxx:834
 TTableSorter.cxx:835
 TTableSorter.cxx:836
 TTableSorter.cxx:837
 TTableSorter.cxx:838
 TTableSorter.cxx:839
 TTableSorter.cxx:840
 TTableSorter.cxx:841
 TTableSorter.cxx:842
 TTableSorter.cxx:843
 TTableSorter.cxx:844
 TTableSorter.cxx:845
 TTableSorter.cxx:846
 TTableSorter.cxx:847
 TTableSorter.cxx:848
 TTableSorter.cxx:849
 TTableSorter.cxx:850
 TTableSorter.cxx:851
 TTableSorter.cxx:852
 TTableSorter.cxx:853
 TTableSorter.cxx:854
 TTableSorter.cxx:855
 TTableSorter.cxx:856
 TTableSorter.cxx:857
 TTableSorter.cxx:858
 TTableSorter.cxx:859
 TTableSorter.cxx:860
 TTableSorter.cxx:861
 TTableSorter.cxx:862
 TTableSorter.cxx:863
 TTableSorter.cxx:864
 TTableSorter.cxx:865
 TTableSorter.cxx:866
 TTableSorter.cxx:867
 TTableSorter.cxx:868
 TTableSorter.cxx:869
 TTableSorter.cxx:870
 TTableSorter.cxx:871
 TTableSorter.cxx:872
 TTableSorter.cxx:873
 TTableSorter.cxx:874
 TTableSorter.cxx:875
 TTableSorter.cxx:876
 TTableSorter.cxx:877
 TTableSorter.cxx:878
 TTableSorter.cxx:879
 TTableSorter.cxx:880
 TTableSorter.cxx:881
 TTableSorter.cxx:882
 TTableSorter.cxx:883
 TTableSorter.cxx:884
 TTableSorter.cxx:885
 TTableSorter.cxx:886
 TTableSorter.cxx:887
 TTableSorter.cxx:888
 TTableSorter.cxx:889
 TTableSorter.cxx:890
 TTableSorter.cxx:891
 TTableSorter.cxx:892
 TTableSorter.cxx:893
 TTableSorter.cxx:894
 TTableSorter.cxx:895
 TTableSorter.cxx:896
 TTableSorter.cxx:897
 TTableSorter.cxx:898
 TTableSorter.cxx:899
 TTableSorter.cxx:900
 TTableSorter.cxx:901
 TTableSorter.cxx:902
 TTableSorter.cxx:903
 TTableSorter.cxx:904
 TTableSorter.cxx:905
 TTableSorter.cxx:906
 TTableSorter.cxx:907
 TTableSorter.cxx:908
 TTableSorter.cxx:909
 TTableSorter.cxx:910
 TTableSorter.cxx:911
 TTableSorter.cxx:912
 TTableSorter.cxx:913
 TTableSorter.cxx:914
 TTableSorter.cxx:915
 TTableSorter.cxx:916
 TTableSorter.cxx:917
 TTableSorter.cxx:918
 TTableSorter.cxx:919
 TTableSorter.cxx:920
 TTableSorter.cxx:921
 TTableSorter.cxx:922
 TTableSorter.cxx:923
 TTableSorter.cxx:924
 TTableSorter.cxx:925
 TTableSorter.cxx:926
 TTableSorter.cxx:927
 TTableSorter.cxx:928
 TTableSorter.cxx:929
 TTableSorter.cxx:930
 TTableSorter.cxx:931
 TTableSorter.cxx:932
 TTableSorter.cxx:933
 TTableSorter.cxx:934
 TTableSorter.cxx:935
 TTableSorter.cxx:936
 TTableSorter.cxx:937
 TTableSorter.cxx:938
 TTableSorter.cxx:939
 TTableSorter.cxx:940
 TTableSorter.cxx:941
 TTableSorter.cxx:942
 TTableSorter.cxx:943
 TTableSorter.cxx:944
 TTableSorter.cxx:945
 TTableSorter.cxx:946
 TTableSorter.cxx:947
 TTableSorter.cxx:948
 TTableSorter.cxx:949
 TTableSorter.cxx:950
 TTableSorter.cxx:951
 TTableSorter.cxx:952
 TTableSorter.cxx:953
 TTableSorter.cxx:954