]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/TPCLib/tracking-ca/AliHLTTPCCATracker.cxx
OpenCL version of the HLT tracker added (the new code is not used in standard compila...
[u/mrichter/AliRoot.git] / HLT / TPCLib / tracking-ca / AliHLTTPCCATracker.cxx
index 868620b4e5413aa5583e463895e9f253cde9255e..387d76f8f2589d91a8dded42480216b52441dc2a 100644 (file)
 //***************************************************************************
 
 #include "AliHLTTPCCATracker.h"
-#include "AliHLTTPCCAOutTrack.h"
-#include "AliHLTTPCCAGrid.h"
 #include "AliHLTTPCCARow.h"
 #include "AliHLTTPCCATrack.h"
 #include "AliHLTTPCCATracklet.h"
 #include "AliHLTTPCCAMath.h"
-#include "AliHLTTPCCAHit.h"
 #include "MemoryAssignmentHelpers.h"
 
 #include "TStopwatch.h"
 #include "AliHLTTPCCATrackletConstructor.h"
 #include "AliHLTTPCCATrackletSelector.h"
 #include "AliHLTTPCCAProcess.h"
-#include "AliHLTTPCCASliceTrack.h"
-#include "AliHLTTPCCASliceOutput.h"
-#include "AliHLTTPCCADataCompressor.h"
 #include "AliHLTTPCCAClusterData.h"
 
 #include "AliHLTTPCCATrackParam.h"
 
+#include "AliHLTTPCCAGPUConfig.h"
+
 #if !defined(HLTCA_GPUCODE)
 #include <iostream>
+#include <iomanip>
+#include <string.h>
+#include <cmath>
 #endif
 
 //#define DRAW1
 
 #ifdef DRAW1
 #include "AliHLTTPCCADisplay.h"
-#endif //DRAW
+#endif //DRAW1
 
 #ifdef HLTCA_INTERNAL_PERFORMANCE
-#include "AliHLTTPCCAPerformance.h"
+//#include "AliHLTTPCCAPerformance.h"
 #endif
 
-
 ClassImp( AliHLTTPCCATracker )
 
+#if !defined(__OPENCL__) || defined(HLTCA_HOSTCODE)
+
 #if !defined(HLTCA_GPUCODE)
 
-AliHLTTPCCATracker::AliHLTTPCCATracker()
-    :
-    fParam(),
-    fClusterData( 0 ),
-    fData(),
-    fCommonMemory( 0 ),
-    fCommonMemorySize( 0 ),
-    fHitMemory( 0 ),
-    fHitMemorySize( 0 ),
-    fTrackMemory( 0 ),
-    fTrackMemorySize( 0 ),
-    fNTracklets( 0 ),
-    fTrackletStartHits( 0 ),
-    fTracklets( 0 ),
-    fNTracks( 0 ),
-    fTracks( 0 ),
-    fNTrackHits( 0 ),
-    fTrackHits( 0 ),
-    fOutput( 0 ),
-    fNOutTracks( 0 ),
-    fOutTracks( 0 ),
-    fNOutTrackHits( 0 ),
-    fOutTrackHits( 0 )
-{
-  // constructor
-}
-
-GPUd() AliHLTTPCCATracker::~AliHLTTPCCATracker()
-{
-  // destructor
-  delete[] fCommonMemory;
-  delete[] fHitMemory;
-  delete[] fTrackMemory;
-}
+AliHLTTPCCATracker::~AliHLTTPCCATracker()
+{
+       // destructor
+       if (!fIsGPUTracker)
+       {
+               if (fCommonMem) delete fCommonMem;
+               if (fHitMemory) delete[] fHitMemory;
+               if (fTrackletMemory) delete[] fTrackletMemory;
+               if (fTrackMemory) delete[] fTrackMemory;
+               fCommonMem = NULL;
+               fHitMemory = fTrackMemory = NULL;
+       }
+#ifdef HLTCA_STANDALONE
+       if (fLinkTmpMemory) delete[] fLinkTmpMemory;
 #endif
-
-
+}
 
 // ----------------------------------------------------------------------------------
-GPUd() void AliHLTTPCCATracker::Initialize( const AliHLTTPCCAParam &param )
+void AliHLTTPCCATracker::Initialize( const AliHLTTPCCAParam &param )
 {
-  // initialisation
-  fParam = param;
-  fParam.Update();
-  fData.InitializeRows( fParam );
+       // initialisation
+       fParam = param;
+       fParam.Update();
+       fData.InitializeRows( fParam );
 
-  StartEvent();
+       StartEvent();
 }
 
-GPUd() void AliHLTTPCCATracker::StartEvent()
+void AliHLTTPCCATracker::StartEvent()
 {
-  // start new event and fresh the memory
+       // start new event and fresh the memory
 
-  SetupCommonMemory();
-  *fNTrackHits = 0;
+       SetupCommonMemory();
 }
 
-void  AliHLTTPCCATracker::SetupCommonMemory()
+void AliHLTTPCCATracker::SetGPUTracker()
 {
-  // set up common memory
+       //Make this a GPU Tracker
+       fIsGPUTracker = true;
+       fData.SetGpuSliceData();
+}
 
-  if ( !fCommonMemory ) {
-    SetPointersCommon(); // just to calculate the size
-    // the 1600 extra bytes are not used unless fCommonMemorySize increases with a later event
-    fCommonMemory = reinterpret_cast<char*> ( new uint4 [ fCommonMemorySize/sizeof( uint4 ) + 100] );
-    SetPointersCommon();// set pointers
-  }
+char* AliHLTTPCCATracker::SetGPUTrackerCommonMemory(char* const pGPUMemory)
+{
+       //Set up common Memory Pointer for GPU Tracker
+       fCommonMem = (commonMemoryStruct*) pGPUMemory;
+       return(pGPUMemory + sizeof(commonMemoryStruct));
+}
 
-  delete[] fHitMemory;
-  fHitMemory = 0;
-  delete[] fTrackMemory;
-  fTrackMemory = 0;
 
-  fData.Clear();
-  *fNTracklets = 0;
-  *fNTracks = 0 ;
-  *fNTrackHits = 0;
-  *fNOutTracks = 0;
-  *fNOutTrackHits = 0;
+char* AliHLTTPCCATracker::SetGPUTrackerHitsMemory(char* pGPUMemory, int MaxNHits)
+{
+       //Set up Hits Memory Pointers for GPU Tracker
+       fHitMemory = (char*) pGPUMemory;
+       SetPointersHits(MaxNHits);
+       pGPUMemory += fHitMemorySize;
+       AssignMemory(fTrackletTmpStartHits, pGPUMemory, NHitsTotal());
+       AssignMemory(fRowStartHitCountOffset, pGPUMemory, Param().NRows());
+
+       return(pGPUMemory);
 }
 
-GPUhd() void  AliHLTTPCCATracker::SetPointersCommon()
+char* AliHLTTPCCATracker::SetGPUTrackerTrackletsMemory(char* pGPUMemory, int MaxNTracks, int 
+#ifndef HLTCA_GPU_ALTERNATIVE_SCHEDULER
+constructorBlockCount
+#endif
+)
 {
-  // set all pointers to the event memory
+       //Set up Tracklet Memory Pointers for GPU Tracker
+       fTrackletMemory = (char*) pGPUMemory;
+       SetPointersTracklets(MaxNTracks);
+       pGPUMemory += fTrackletMemorySize;
+#ifndef HLTCA_GPU_ALTERNATIVE_SCHEDULER
+       AssignMemory(fGPUTrackletTemp, pGPUMemory, MaxNTracks);
+       AssignMemory(fRowBlockTracklets, pGPUMemory, MaxNTracks * 2 * (Param().NRows() / HLTCA_GPU_SCHED_ROW_STEP + 1));
+       AssignMemory(fRowBlockPos, pGPUMemory, 2 * (Param().NRows() / HLTCA_GPU_SCHED_ROW_STEP + 1));
+       AssignMemory(fBlockStartingTracklet, pGPUMemory, constructorBlockCount);
+#endif
 
-  char *mem = fCommonMemory;
-  AssignMemory( fNTracklets, mem, 1 );
-  AssignMemory( fNTracks, mem, 1 );
-  AssignMemory( fNTrackHits, mem, 1 );
-  AssignMemory( fNOutTracks, mem, 1 );
-  AssignMemory( fNOutTrackHits, mem, 1 );
+       return(pGPUMemory);
+}
 
-  // calculate the size
+char* AliHLTTPCCATracker::SetGPUTrackerTracksMemory(char* pGPUMemory, int MaxNTracks, int MaxNHits )
+{
+       //Set up Tracks Memory Pointer for GPU Tracker
+       fTrackMemory = (char*) pGPUMemory;
+       SetPointersTracks(MaxNTracks, MaxNHits);
+       pGPUMemory += fTrackMemorySize;
 
-  fCommonMemorySize = mem - fCommonMemory;
+       return(pGPUMemory);
 }
 
-
-GPUhd() void  AliHLTTPCCATracker::SetPointersHits( int MaxNHits )
+void AliHLTTPCCATracker::DumpOutput(FILE* out)
 {
-  // set all pointers to the event memory
+       fprintf(out, "Slice %d\n", fParam.ISlice());
+       const AliHLTTPCCASliceOutTrack* track = (*(Output()))->GetFirstTrack();
+       for (int j = 0;j < (*(Output()))->NTracks();j++)
+       {
+               fprintf(out, "Track %d (%d): ", j, track->NClusters());
+               for (int k = 0;k < track->NClusters();k++)
+               {
+                       fprintf(out, "(%2.3f,%2.3f,%2.4f) ", track->Cluster(k).GetX(), track->Cluster(k).GetY(), track->Cluster(k).GetZ());
+               }
+               fprintf(out, " - (%8.5f %8.5f %8.5f %8.5f %8.5f)", track->Param().Y(), track->Param().Z(), track->Param().SinPhi(), track->Param().DzDs(), track->Param().QPt());
+               fprintf(out, "\n");
+               track = track->GetNextTrack();
+       }
+}
 
-  char *mem = fHitMemory;
+void AliHLTTPCCATracker::DumpSliceData(std::ostream &out)
+{
+       //Dump Slice Input Data to File
+       out << "Slice Data (Slice" << Param().ISlice() << "):" << std::endl;
+       for (int i = 0;i < Param().NRows();i++)
+       {
+               if (Row(i).NHits() == 0) continue;
+               out << "Row: " << i << std::endl;
+               for (int j = 0;j < Row(i).NHits();j++)
+               {
+                       if (j && j % 16 == 0) out << std::endl;
+                       out << j << '-' << Data().HitDataY(Row(i), j) << '-' << Data().HitDataZ(Row(i), j) << ", ";
+               }
+               out << std::endl;
+       }
+}
 
-  // extra arrays for tpc clusters
+void AliHLTTPCCATracker::DumpLinks(std::ostream &out)
+{
+       //Dump Links (after Neighbours Finder / Cleaner) to file
+       out << "Hit Links(Slice" << Param().ISlice() << "):" << std::endl;
+       for (int i = 0;i < Param().NRows();i++)
+       {
+               if (Row(i).NHits() == 0) continue;
+               out << "Row: " << i << std::endl;
+               for (int j = 0;j < Row(i).NHits();j++)
+               {
+                       if (j && j % 32 == 0) out << std::endl;
+                       out << HitLinkUpData(Row(i), j) << "/" << HitLinkDownData(Row(i), j) << ", ";
+               }
+               out << std::endl;
+       }
+}
 
-  AssignMemory( fTrackletStartHits, mem, MaxNHits );
+void AliHLTTPCCATracker::DumpHitWeights(std::ostream &out)
+{
+       //dump hit weights to file
+       out << "Hit Weights(Slice" << Param().ISlice() << "):" << std::endl;
+       for (int i = 0;i < Param().NRows();i++)
+       {
+               if (Row(i).NHits() == 0) continue;
+               out << "Row: " << i << ":" << std::endl;
+               for (int j = 0;j < Row(i).NHits();j++)
+               {
+                       if (j && j % 32 == 0) out << std::endl;
+                       out << HitWeight(Row(i), j) << ", ";
+               }
+               out << std::endl;
+       }
+}
 
-  // arrays for track hits
+int AliHLTTPCCATracker::StarthitSortComparison(const void*a, const void* b)
+{
+       //qsort helper function to sort start hits
+       AliHLTTPCCAHitId* aa = (AliHLTTPCCAHitId*) a;
+       AliHLTTPCCAHitId* bb = (AliHLTTPCCAHitId*) b;
 
-  AssignMemory( fTrackHits, mem, 10 * MaxNHits );
+       if (aa->RowIndex() != bb->RowIndex()) return(aa->RowIndex() - bb->RowIndex());
+       return(aa->HitIndex() - bb->HitIndex());
+}
 
-  AssignMemory( fOutTrackHits, mem, 10 * MaxNHits );
+void AliHLTTPCCATracker::DumpStartHits(std::ostream &out)
+{
+       //sort start hits and dump to file
+       out << "Start Hits: (Slice" << Param().ISlice() << ") (" << *NTracklets() << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       qsort(TrackletStartHits(), *NTracklets(), sizeof(AliHLTTPCCAHitId), StarthitSortComparison);
+#endif
+       for (int i = 0;i < *NTracklets();i++)
+       {
+               out << TrackletStartHit(i).RowIndex() << "-" << TrackletStartHit(i).HitIndex() << std::endl;
+       }
+       out << std::endl;
+}
 
-  // calculate the size
+void AliHLTTPCCATracker::DumpTrackHits(std::ostream &out)
+{
+       //dump tracks to file
+       out << "Tracks: (Slice" << Param().ISlice() << ") (" << *NTracks() << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       for (int k = 0;k < Param().NRows();k++)
+       {
+               for (int l = 0;l < Row(k).NHits();l++)
+               {
+#endif
+                       for (int j = 0;j < *NTracks();j++)
+                       {
+                               if (Tracks()[j].NHits() == 0 || !Tracks()[j].Alive()) continue;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+                               if (TrackHits()[Tracks()[j].FirstHitID()].RowIndex() == k && TrackHits()[Tracks()[j].FirstHitID()].HitIndex() == l)
+                               {
+#endif
+                                       for (int i = 0;i < Tracks()[j].NHits();i++)
+                                       {
+                                               out << TrackHits()[Tracks()[j].FirstHitID() + i].RowIndex() << "-" << TrackHits()[Tracks()[j].FirstHitID() + i].HitIndex() << ", ";
+                                       }
+#ifndef BITWISE_COMPATIBLE_DEBUG_OUTPUT
+                                       out << "(Track: " << j << ")";
+#endif
+                                       out << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+                               }
+                       }       
+#endif
+               }       
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       }
+#endif
+}
 
-  fHitMemorySize = mem - fHitMemory;
+void AliHLTTPCCATracker::DumpTrackletHits(std::ostream &out)
+{
+       //dump tracklets to file
+       int nTracklets = *NTracklets();
+       if( nTracklets<0 ) nTracklets = 0;
+       if( nTracklets>HLTCA_GPU_MAX_TRACKLETS ) nTracklets = HLTCA_GPU_MAX_TRACKLETS;
+       out << "Tracklets: (Slice" << Param().ISlice() << ") (" << nTracklets << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       AliHLTTPCCAHitId* tmpIds = new AliHLTTPCCAHitId[nTracklets];
+       AliHLTTPCCATracklet* tmpTracklets = new AliHLTTPCCATracklet[nTracklets];
+       memcpy(tmpIds, TrackletStartHits(), nTracklets * sizeof(AliHLTTPCCAHitId));
+       memcpy(tmpTracklets, Tracklets(), nTracklets * sizeof(AliHLTTPCCATracklet));
+#ifdef EXTERN_ROW_HITS
+       int* tmpHits = new int[nTracklets * Param().NRows()];
+       memcpy(tmpHits, TrackletRowHits(), nTracklets * Param().NRows() * sizeof(int));
+#endif
+       qsort(TrackletStartHits(), nTracklets, sizeof(AliHLTTPCCAHitId), StarthitSortComparison);
+       for (int i = 0;i < nTracklets; i++ ){
+               for (int j = 0;j < nTracklets; j++ ){
+                       if (tmpIds[i].RowIndex() == TrackletStartHit(j).RowIndex() && tmpIds[i].HitIndex() == TrackletStartHit(j).HitIndex() ){
+                               memcpy(&Tracklets()[j], &tmpTracklets[i], sizeof(AliHLTTPCCATracklet));
+#ifdef EXTERN_ROW_HITS
+                               if (tmpTracklets[i].NHits() ){
+                                       for (int k = tmpTracklets[i].FirstRow();k <= tmpTracklets[i].LastRow();k++){
+                                               const int pos = k * nTracklets + j;
+                                               if (pos < 0 || pos >= HLTCA_GPU_MAX_TRACKLETS * fParam.NRows()){
+                                                       printf("internal error\n");           
+                                               } else {
+                                                       fTrackletRowHits[pos] = tmpHits[k * nTracklets + i];
+                                               }
+                                       }
+                               }
+#endif
+                               break;
+                       }
+               }
+       }
+       delete[] tmpIds;
+       delete[] tmpTracklets;
+#ifdef EXTERN_ROW_HITS
+       delete[] tmpHits;
+#endif
+#endif
+       for (int j = 0;j < nTracklets; j++ )
+       {
+               out << "Tracklet " << std::setw(4) << j << " (Hits: " << std::setw(3) << Tracklets()[j].NHits() << ", Start: " << std::setw(3) << TrackletStartHit(j).RowIndex() << "-" << std::setw(3) << TrackletStartHit(j).HitIndex() << ", Rows: " << (Tracklets()[j].NHits() ? Tracklets()[j].FirstRow() : -1) << " - " << (Tracklets()[j].NHits() ? Tracklets()[j].LastRow() : -1) << ") ";
+               if (Tracklets()[j].NHits() == 0);
+               else if (Tracklets()[j].LastRow() > Tracklets()[j].FirstRow() && (Tracklets()[j].FirstRow() >= Param().NRows() || Tracklets()[j].LastRow() >= Param().NRows()))
+               {
+#ifdef HLTCA_STANDALONE
+                       printf("\nError: Tracklet %d First %d Last %d Hits %d", j, Tracklets()[j].FirstRow(), Tracklets()[j].LastRow(), Tracklets()[j].NHits());
+                       out << " (Error: Tracklet " << j << " First " << Tracklets()[j].FirstRow() << " Last " << Tracklets()[j].LastRow() << " Hits " << Tracklets()[j].NHits() << ") ";
+                       for (int i = 0;i < Param().NRows();i++)
+                       {
+                               //if (Tracklets()[j].RowHit(i) != -1)
+#ifdef EXTERN_ROW_HITS
+                               out << i << "-" << fTrackletRowHits[i * fCommonMem->fNTracklets + j] << ", ";
+#else
+                               out << i << "-" << Tracklets()[j].RowHit(i) << ", ";
+#endif
+                       }
+#endif
+               }
+               else if (Tracklets()[j].NHits() && Tracklets()[j].LastRow() > Tracklets()[j].FirstRow())
+               {
+                       int nHits = 0;;
+                       for (int i = Tracklets()[j].FirstRow();i <= Tracklets()[j].LastRow();i++)
+                       {
+#ifdef EXTERN_ROW_HITS
+                               if (fTrackletRowHits[i * fCommonMem->fNTracklets + j] != -1)
+#else
+                               if (Tracklets()[j].RowHit(i) != -1)
+#endif
+                               {
+                                       nHits++;
+                               }
+#ifdef EXTERN_ROW_HITS
+                               out << i << "-" << fTrackletRowHits[i * fCommonMem->fNTracklets + j] << ", ";
+#else
+                               out << i << "-" << Tracklets()[j].RowHit(i) << ", ";
+#endif
+                       }
+                       if (nHits != Tracklets()[j].NHits())
+                       {
+                               out << std::endl << "Wrong NHits!: Expected " << Tracklets()[j].NHits() << ", fount " << nHits;
+                       }
+               }
+               out << std::endl;
+       }
 }
 
 
-GPUhd() void  AliHLTTPCCATracker::SetPointersTracks( int MaxNTracks, int MaxNHits )
+void AliHLTTPCCATracker::SetupCommonMemory()
 {
-  // set all pointers to the tracks memory
+       // set up common memory
+
+       if (!fIsGPUTracker)
+       {
+               if ( !fCommonMem ) {
+                       // the 1600 extra bytes are not used unless fCommonMemorySize increases with a later event
+                       //fCommonMemory = reinterpret_cast<char*> ( new uint4 [ fCommonMemorySize/sizeof( uint4 ) + 100] );
+                       fCommonMem = new commonMemoryStruct;
+               }
+
+               if (fHitMemory) delete[] fHitMemory;
+               if (fTrackletMemory) delete[] fTrackletMemory;
+               if (fTrackMemory) delete[] fTrackMemory;
+       }
+
+       fHitMemory = fTrackletMemory = fTrackMemory = 0;
+
+       fData.Clear();
+       fCommonMem->fNTracklets = 0;
+       fCommonMem->fNTracks = 0 ;
+       fCommonMem->fNTrackHits = 0;
+}
 
-  char *mem = fTrackMemory;
+void AliHLTTPCCATracker::ReadEvent( AliHLTTPCCAClusterData *clusterData )
+{
+       // read event
+
+       fClusterData = clusterData;
+
+       StartEvent();
+
+       //* Convert input hits, create grids, etc.
+       fData.InitFromClusterData( *clusterData );
+       {
+               if (!fIsGPUTracker)
+               {
+                       SetPointersHits( fData.NumberOfHits() ); // to calculate the size
+                       fHitMemory = reinterpret_cast<char*> ( new uint4 [ fHitMemorySize/sizeof( uint4 ) + 100] );
+               }
+               SetPointersHits( fData.NumberOfHits() ); // set pointers for hits
+       }
+}
 
-  // memory for tracklets
+GPUhd() void  AliHLTTPCCATracker::SetPointersHits( int MaxNHits )
+{
+       // set all pointers to the event memory
 
-  AssignMemory( fTracklets, mem, MaxNTracks );
+       char *mem = fHitMemory;
 
-  // memory for selected tracks
+       // extra arrays for tpc clusters
 
-  AssignMemory( fTracks, mem, MaxNTracks );
+#ifdef HLTCA_GPU_SORT_STARTHITS_2
+       AssignMemory( fTrackletStartHits, mem, MaxNHits + 32);
+#else
+       AssignMemory( fTrackletStartHits, mem, MaxNHits);
+#endif
 
-  // memory for output
+       // calculate the size
 
-  AlignTo < sizeof( void * ) > ( mem );
-  fOutput = reinterpret_cast<AliHLTTPCCASliceOutput *>( mem );
-  mem += AliHLTTPCCASliceOutput::EstimateSize( MaxNTracks, MaxNHits );
+       fHitMemorySize = mem - fHitMemory;
+}
 
-  // memory for output tracks
+GPUhd() void  AliHLTTPCCATracker::SetPointersTracklets( int MaxNTracklets )
+{
+       // set all pointers to the tracklets memory
+       char *mem = fTrackletMemory;
 
-  AssignMemory( fOutTracks, mem, MaxNTracks );
+       // memory for tracklets
 
-  // calculate the size
+       AssignMemory( fTracklets, mem, MaxNTracklets );
+#ifdef EXTERN_ROW_HITS
+       AssignMemory( fTrackletRowHits, mem, MaxNTracklets * Param().NRows());
+#endif
 
-  fTrackMemorySize = mem - fTrackMemory;
+       fTrackletMemorySize = mem - fTrackletMemory;
 }
 
 
-void AliHLTTPCCATracker::ReadEvent( AliHLTTPCCAClusterData *clusterData )
+GPUhd() void  AliHLTTPCCATracker::SetPointersTracks( int MaxNTracks, int MaxNHits )
 {
-  // read event
+       // set all pointers to the tracks memory
+       char *mem = fTrackMemory;
 
-  fClusterData = clusterData;
+       // memory for selected tracks
 
-  StartEvent();
+       AssignMemory( fTracks, mem, MaxNTracks );
+       AssignMemory( fTrackHits, mem, 2 * MaxNHits );
 
-  //* Convert input hits, create grids, etc.
-  fData.InitFromClusterData( *clusterData );
+       // calculate the size
 
-  {
-    SetPointersHits( fData.NumberOfHits() ); // to calculate the size
-    fHitMemory = reinterpret_cast<char*> ( new uint4 [ fHitMemorySize/sizeof( uint4 ) + 100] );
-    SetPointersHits( fData.NumberOfHits() ); // set pointers for hits
-    *fNTracklets = 0;
-    *fNTracks = 0 ;
-    *fNOutTracks = 0;
-    *fNOutTrackHits = 0;
-  }
+       fTrackMemorySize = mem - fTrackMemory;
 }
 
-GPUh() void AliHLTTPCCATracker::Reconstruct()
+GPUh() int AliHLTTPCCATracker::CheckEmptySlice() const
 {
-  //* reconstruction of event
-  //std::cout<<"Reconstruct slice "<<fParam.ISlice()<<", nHits="<<NHitsTotal()<<std::endl;
-
-  fTimers[0] = 0; // find neighbours
-  fTimers[1] = 0; // construct tracklets
-  fTimers[2] = 0; // fit tracklets
-  fTimers[3] = 0; // prolongation of tracklets
-  fTimers[4] = 0; // selection
-  fTimers[5] = 0; // write output
-  fTimers[6] = 0;
-  fTimers[7] = 0;
-
-  //if( fParam.ISlice()<1 ) return; //SG!!!
-
-  TStopwatch timer0;
-
-  if ( NHitsTotal() < 1 ) {
-    {
-      SetPointersTracks( 1, 1 ); // to calculate the size
-      fTrackMemory = reinterpret_cast<char*> ( new uint4 [ fTrackMemorySize/sizeof( uint4 ) + 100] );
-      SetPointersTracks( 1, 1 ); // set pointers for tracks
-      fOutput->SetNTracks( 0 );
-      fOutput->SetNTrackClusters( 0 );
-    }
-
-    return;
-  }
-#ifdef DRAW1
-  //if( fParam.ISlice()==15){
-  AliHLTTPCCADisplay::Instance().ClearView();
-  AliHLTTPCCADisplay::Instance().SetSliceView();
-  AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
-  AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
-  if ( NHitsTotal() > 0 ) {
-    AliHLTTPCCADisplay::Instance().DrawSliceHits( kRed, .5 );
-    AliHLTTPCCADisplay::Instance().Ask();
-  }
-  //}
-#endif
+       //Check if the Slice is empty, if so set the output apropriate and tell the reconstuct procesdure to terminate
+       if ( NHitsTotal() < 1 ) {
+               {
+                       AliHLTTPCCASliceOutput::Allocate(*fOutput, 0, 0, fOutputControl);
+                       AliHLTTPCCASliceOutput* useOutput = *fOutput;
+                       if (useOutput == NULL) return(1);
+                       useOutput->SetNTracks( 0 );
+                       useOutput->SetNTrackClusters( 0 );
+               }
+
+               return 1;
+       }
+       return 0;
+}
 
-  *fNTracks = 0;
-  *fNTracklets = 0;
+void AliHLTTPCCATracker::RunNeighboursFinder()
+{
+       //Run the CPU Neighbours Finder
+       AliHLTTPCCAProcess<AliHLTTPCCANeighboursFinder>( Param().NRows(), 1, *this );
+}
 
-#if !defined(HLTCA_GPUCODE)
+void AliHLTTPCCATracker::RunNeighboursCleaner()
+{
+       //Run the CPU Neighbours Cleaner
+       AliHLTTPCCAProcess<AliHLTTPCCANeighboursCleaner>( Param().NRows() - 2, 1, *this );
+}
 
-  AliHLTTPCCAProcess<AliHLTTPCCANeighboursFinder>( Param().NRows(), 1, *this );
+void AliHLTTPCCATracker::RunStartHitsFinder()
+{
+       //Run the CPU Start Hits Finder
+       AliHLTTPCCAProcess<AliHLTTPCCAStartHitsFinder>( Param().NRows() - 4, 1, *this );
+}
 
-#ifdef HLTCA_INTERNAL_PERFORMANCE
-  //if( Param().ISlice()<=2 )
-  //AliHLTTPCCAPerformance::Instance().LinkPerformance( Param().ISlice() );
-#endif
+void AliHLTTPCCATracker::RunTrackletConstructor()
+{
+       //Run CPU Tracklet Constructor
+       AliHLTTPCCATrackletConstructor::AliHLTTPCCATrackletConstructorCPU(*this);
+}
 
+void AliHLTTPCCATracker::RunTrackletSelector()
+{
+       //Run CPU Tracklet Selector
+       AliHLTTPCCAProcess<AliHLTTPCCATrackletSelector>( 1, fCommonMem->fNTracklets, *this );
+}
 
-#ifdef DRAW
-  if ( NHitsTotal() > 0 ) {
-    AliHLTTPCCADisplay::Instance().DrawSliceLinks( -1, -1, 1 );
-    AliHLTTPCCADisplay::Instance().Ask();
-  }
+#ifdef HLTCA_STANDALONE
+void AliHLTTPCCATracker::StandalonePerfTime(int i)
+{
+       //Query Performance Timer for Standalone Version of Tracker
+       if (fGPUDebugLevel >= 1)
+       {
+               StandaloneQueryTime(&fPerfTimers[i]);
+       }
+}
+#else
+void AliHLTTPCCATracker::StandalonePerfTime(int /*i*/) {}
 #endif
 
+GPUh() void AliHLTTPCCATracker::DoTracking()
+{
+       fCommonMem->fNTracklets = fCommonMem->fNTracks = fCommonMem->fNTrackHits = 0;
 
-  AliHLTTPCCAProcess<AliHLTTPCCANeighboursCleaner>( Param().NRows() - 2, 1, *this );
-  AliHLTTPCCAProcess<AliHLTTPCCAStartHitsFinder>( Param().NRows() - 4, 1, *this );
+       if (fGPUDebugLevel >= 6)
+       {
+#ifndef BITWISE_COMPATIBLE_DEBUG_OUTPUT
+               *fGPUDebugOut << std::endl << std::endl << "Slice: " << Param().ISlice() << std::endl;
+               *fGPUDebugOut << "Slice Data:" << std::endl;
+#endif
+               DumpSliceData(*fGPUDebugOut);
+       }
 
-  int nStartHits = *fNTracklets;
+       StandalonePerfTime(1);
 
-  int nThreads = 128;
-  int nBlocks = NHitsTotal() / nThreads + 1;
-  if ( nBlocks < 12 ) {
-    nBlocks = 12;
-    nThreads = NHitsTotal() / 12 + 1;
-    if ( nThreads % 32 ) nThreads = ( nThreads / 32 + 1 ) * 32;
-  }
+       RunNeighboursFinder();
 
-  nThreads = NHitsTotal();
-  nBlocks = 1;
+       StandalonePerfTime(2);
 
-  fData.ClearHitWeights();
-  //AliHLTTPCCAProcess<AliHLTTPCCAUsedHitsInitialiser>( nBlocks, nThreads, *this );
+#ifdef TRACKER_KEEP_TEMPDATA
+       if (fLinkTmpMemory) delete[] fLinkTmpMemory;
+       fLinkTmpMemory = new char[fData.MemorySize()];
+       memcpy(fLinkTmpMemory, fData.Memory(), fData.MemorySize());
+#endif
 
+       if (fGPUDebugLevel >= 6) DumpLinks(*fGPUDebugOut);
 
-  {
-    SetPointersTracks( nStartHits, NHitsTotal() ); // to calculate the size
-    fTrackMemory = reinterpret_cast<char*> ( new uint4 [ fTrackMemorySize/sizeof( uint4 ) + 100] );
-    SetPointersTracks( nStartHits, NHitsTotal() ); // set pointers for hits
-  }
+#ifdef HLTCA_INTERNAL_PERFORMANCE
+       //if( Param().ISlice()<=2 )
+       //AliHLTTPCCAPerformance::Instance().LinkPerformance( Param().ISlice() );
+#endif
 
-  int nMemThreads = AliHLTTPCCATrackletConstructor::NMemThreads();
-  nThreads = 256;//96;
-  nBlocks = nStartHits / nThreads + 1;
-  if ( nBlocks < 30 ) {
-    nBlocks = 30;
-    nThreads = ( nStartHits ) / 30 + 1;
-    if ( nThreads % 32 ) nThreads = ( nThreads / 32 + 1 ) * 32;
-  }
 
-  nThreads = nStartHits;
-  nBlocks = 1;
+#ifdef DRAW1
+       if ( NHitsTotal() > 0 ) {
+               AliHLTTPCCADisplay::Instance().DrawSliceLinks( -1, -1, 1 );
+               AliHLTTPCCADisplay::Instance().Ask();
+       }
+#endif //DRAW1
 
-  AliHLTTPCCAProcess1<AliHLTTPCCATrackletConstructor>( nBlocks, nMemThreads + nThreads, *this );
+       RunNeighboursCleaner();
 
-  //std::cout<<"Slice "<<Param().ISlice()<<": NHits="<<NHitsTotal()<<", NTracklets="<<*NTracklets()<<std::endl;
+       StandalonePerfTime(3);
 
-  {
-    nThreads = 128;
-    nBlocks = nStartHits / nThreads + 1;
-    if ( nBlocks < 12 ) {
-      nBlocks = 12;
-      nThreads = nStartHits / 12 + 1;
-      nThreads = ( nThreads / 32 + 1 ) * 32;
-    }
+       if (fGPUDebugLevel >= 6) DumpLinks(*fGPUDebugOut);
 
-    *fNTrackHits = 0;
+       RunStartHitsFinder();
 
-    nThreads = nStartHits;
-    nBlocks = 1;
+       StandalonePerfTime(4);
+       StandalonePerfTime(5);
 
+       if (fGPUDebugLevel >= 6) DumpStartHits(*fGPUDebugOut);
 
-    AliHLTTPCCAProcess<AliHLTTPCCATrackletSelector>( nBlocks, nThreads, *this );
+       fData.ClearHitWeights();
 
-    //std::cout<<"Slice "<<Param().ISlice()<<": N start hits/tracklets/tracks = "<<nStartHits<<" "<<nStartHits<<" "<<*fNTracks<<std::endl;
-  }
+       if (!fIsGPUTracker)
+       {
+               SetPointersTracklets( fCommonMem->fNTracklets * 2 ); // to calculate the size
+               fTrackletMemory = reinterpret_cast<char*> ( new uint4 [ fTrackletMemorySize/sizeof( uint4 ) + 100] );
+               SetPointersTracks( fCommonMem->fNTracklets * 2, NHitsTotal() ); // to calculate the size
+               fTrackMemory = reinterpret_cast<char*> ( new uint4 [ fTrackMemorySize/sizeof( uint4 ) + 100] );
+       }
 
-  //std::cout<<"Memory used for slice "<<fParam.ISlice()<<" : "<<fCommonMemorySize/1024./1024.<<" + "<<fHitMemorySize/1024./1024.<<" + "<<fTrackMemorySize/1024./1024.<<" = "<<( fCommonMemorySize+fHitMemorySize+fTrackMemorySize )/1024./1024.<<" Mb "<<std::endl;
+       SetPointersTracklets( fCommonMem->fNTracklets * 2 ); // set pointers for hits
+       SetPointersTracks( fCommonMem->fNTracklets * 2, NHitsTotal() ); // set pointers for hits
 
+       StandalonePerfTime(6);
+       StandalonePerfTime(7);
 
-  WriteOutput();
+       RunTrackletConstructor();
 
+       StandalonePerfTime(8);
 
+       if (fGPUDebugLevel >= 6) DumpTrackletHits(*fGPUDebugOut);
+#ifndef BITWISE_COMPATIBLE_DEBUG_OUTPUT
+       if (fGPUDebugLevel >= 6) DumpHitWeights(*fGPUDebugOut);
 #endif
 
-#ifdef DRAW
-  {
-    AliHLTTPCCADisplay &disp = AliHLTTPCCADisplay::Instance();
-    AliHLTTPCCATracker &slice = *this;
-    std::cout << "N out tracks = " << *slice.NOutTracks() << std::endl;
-    //disp.Ask();
-    AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
-    AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
-    disp.DrawSliceHits( -1, .5 );
-    for ( int itr = 0; itr < *slice.NOutTracks(); itr++ ) {
-      std::cout << "track N " << itr << ", nhits=" << slice.OutTracks()[itr].NHits() << std::endl;
-      disp.DrawSliceOutTrack( itr, kBlue );
-      //disp.Ask();
-      //int id = slice.OutTracks()[itr].OrigTrackID();
-      //AliHLTTPCCATrack &tr = Tracks()[id];
-      //for( int ih=0; ih<tr.NHits(); ih++ ){
-      //int ic = (fTrackHits[tr.FirstHitID()+ih]);
-      //std::cout<<ih<<" "<<ID2IRow(ic)<<" "<<ID2IHit(ic)<<std::endl;
-      //}
-      //disp.DrawSliceTrack( id, kBlue );
-      //disp.Ask();
-    }
-    disp.Ask();
-  }
-#endif
+       //std::cout<<"Slice "<<Param().ISlice()<<": NHits="<<NHitsTotal()<<", NTracklets="<<*NTracklets()<<std::endl;
 
-  timer0.Stop();
-  fTimers[0] = timer0.CpuTime() / 100.;
+       RunTrackletSelector();
 
-}
+       StandalonePerfTime(9);
 
+       //std::cout<<"Slice "<<Param().ISlice()<<": N start hits/tracklets/tracks = "<<nStartHits<<" "<<nStartHits<<" "<<*fNTracks<<std::endl;
 
+       if (fGPUDebugLevel >= 6) DumpTrackHits(*fGPUDebugOut);
 
+       //std::cout<<"Memory used for slice "<<fParam.ISlice()<<" : "<<fCommonMemorySize/1024./1024.<<" + "<<fHitMemorySize/1024./1024.<<" + "<<fTrackMemorySize/1024./1024.<<" = "<<( fCommonMemorySize+fHitMemorySize+fTrackMemorySize )/1024./1024.<<" Mb "<<std::endl;
+}
 
-GPUh() void AliHLTTPCCATracker::WriteOutput()
+GPUh() void AliHLTTPCCATracker::Reconstruct()
 {
-  // write output
-
-  TStopwatch timer;
-
-  //cout<<"output: nTracks = "<<*fNTracks<<", nHitsTotal="<<NHitsTotal()<<std::endl;
-
-  fOutput->SetNTracks( *fNTracks );
-  fOutput->SetNTrackClusters( *fNTrackHits );
-  fOutput->SetPointers();
-
-  int nStoredHits = 0;
+       //* reconstruction of event
+       //std::cout<<"Reconstruct slice "<<fParam.ISlice()<<", nHits="<<NHitsTotal()<<std::endl;
 
-  for ( int iTr = 0; iTr < *fNTracks; iTr++ ) {
-    AliHLTTPCCATrack &iTrack = fTracks[iTr];
+       fTimers[0] = 0; // find neighbours
+       fTimers[1] = 0; // construct tracklets
+       fTimers[2] = 0; // fit tracklets
+       fTimers[3] = 0; // prolongation of tracklets
+       fTimers[4] = 0; // selection
+       fTimers[5] = 0; // write output
+       fTimers[6] = 0;
+       fTimers[7] = 0;
 
-    AliHLTTPCCASliceTrack out;
-    out.SetFirstClusterRef( nStoredHits );
-    out.SetNClusters( iTrack.NHits() );
-    out.SetParam( iTrack.Param() );
-
-    fOutput->SetTrack( iTr, out );
-
-    int iID = iTrack.FirstHitID();
-    for ( int ith = 0; ith < iTrack.NHits(); ith++ ) {
-      const AliHLTTPCCAHitId &ic = fTrackHits[iID + ith];
-      int iRow = ic.RowIndex();
-      int ih = ic.HitIndex();
-
-      const AliHLTTPCCARow &row = fData.Row( iRow );
-
-      //float y0 = row.Grid().YMin();
-      //float z0 = row.Grid().ZMin();
-      //float stepY = row.HstepY();
-      //float stepZ = row.HstepZ();
-      //float x = row.X();
+       //if( fParam.ISlice()<1 ) return; //SG!!!
 
-      //const uint4 *tmpint4 = RowData() + row.FullOffset();
-      //const ushort2 *hits = reinterpret_cast<const ushort2*>(tmpint4);
-      //ushort2 hh = hits[ih];
-      //float y = y0 + hh.x*stepY;
-      //float z = z0 + hh.y*stepZ;
+       TStopwatch timer0;
 
-      int clusterIndex = fData.ClusterDataIndex( row, ih );
-      int clusterRowIndex = clusterIndex - fClusterData->RowOffset( iRow );
+       if (CheckEmptySlice()) return;
 
-      if ( clusterIndex < 0 || clusterIndex >= fClusterData->NumberOfClusters() ) {
-        //std::cout << inpIDtot << ", " << fClusterData->NumberOfClusters()
-        //<< "; " << inpID << ", " << fClusterData->NumberOfClusters( iRow ) << std::endl;
-        //abort();
-        continue;
-      }
-      if ( clusterRowIndex < 0 || clusterRowIndex >= fClusterData->NumberOfClusters( iRow ) ) {
-        //std::cout << inpIDtot << ", " << fClusterData->NumberOfClusters()
-        //<< "; " << inpID << ", " << fClusterData->NumberOfClusters( iRow ) << std::endl;
-        //abort();
-        continue;
-      }
-
-      float origX = fClusterData->X( clusterIndex );
-      float origY = fClusterData->Y( clusterIndex );
-      float origZ = fClusterData->Z( clusterIndex );
-
-
-      int id = fClusterData->Id( clusterIndex );
-
-      unsigned short hPackedYZ = 0;
-      UChar_t hPackedAmp = 0;
-      float2 hUnpackedYZ;
-      hUnpackedYZ.x = origY;
-      hUnpackedYZ.y = origZ;
-      float hUnpackedX = origX;
-
-      fOutput->SetClusterId( nStoredHits, id  );
-      fOutput->SetClusterRow( nStoredHits, (unsigned char) iRow  );
-      fOutput->SetClusterPackedYZ( nStoredHits, hPackedYZ );
-      fOutput->SetClusterPackedAmp( nStoredHits, hPackedAmp );
-      fOutput->SetClusterUnpackedYZ( nStoredHits, hUnpackedYZ );
-      fOutput->SetClusterUnpackedX( nStoredHits, hUnpackedX );
-      nStoredHits++;
-    }
-  }
+#ifdef DRAW1
+       //if( fParam.ISlice()==2 || fParam.ISlice()==3)
+       {
+               AliHLTTPCCADisplay::Instance().ClearView();
+               AliHLTTPCCADisplay::Instance().SetSliceView();
+               AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
+               AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
+               if ( NHitsTotal() > 0 ) {
+                       AliHLTTPCCADisplay::Instance().DrawSliceHits( kRed, .5 );
+                       AliHLTTPCCADisplay::Instance().Ask();
+               }
+       }
+#endif //DRAW1
+
+       DoTracking();
+       fTimers[0] = timer0.CpuTime() / 100.;
+}
 
+GPUh() void AliHLTTPCCATracker::ReconstructOutput()
+{
+       TStopwatch timer0;
+       WriteOutputPrepare();
+       WriteOutput();
 
-  // old stuff
+       StandalonePerfTime(10);
 
-  *fNOutTrackHits = 0;
-  *fNOutTracks = 0;
+#ifdef DRAW1
+       {
+               AliHLTTPCCADisplay &disp = AliHLTTPCCADisplay::Instance();
+               AliHLTTPCCATracker &slice = *this;
+               std::cout << "N out tracks = " << slice.NOutTracks() << std::endl;
+               AliHLTTPCCADisplay::Instance().SetSliceView();
+               AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
+               AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
+               disp.DrawSliceHits( kRed, .5 );
+               disp.Ask();
+               for ( int itr = 0; itr < slice.NOutTracks(); itr++ ) {
+                       std::cout << "track N " << itr << ", nhits=" << slice.OutTracks()[itr].NHits() << std::endl;
+                       disp.DrawSliceOutTrack( itr, kBlue );      
+                       //disp.Ask();
+                       //int id = slice.OutTracks()[itr].OrigTrackID();
+                       //AliHLTTPCCATrack &tr = Tracks()[id];
+                       //for( int ih=0; ih<tr.NHits(); ih++ ){
+                       //int ic = (fTrackHits[tr.FirstHitID()+ih]);
+                       //std::cout<<ih<<" "<<ID2IRow(ic)<<" "<<ID2IHit(ic)<<std::endl;
+                       //}
+                       //disp.DrawSliceTrack( id, kBlue );
+                       //disp.Ask();
+               }
+               disp.Ask();
+       }
+#endif //DRAW1
+
+       timer0.Stop();
+       fTimers[0] += timer0.CpuTime() / 100.;
+}
 
+GPUh() void AliHLTTPCCATracker::WriteOutputPrepare()
+{
+       if (fOutputControl == NULL) fOutputControl = new AliHLTTPCCASliceOutput::outputControlStruct;
+       AliHLTTPCCASliceOutput::Allocate(*fOutput, fCommonMem->fNTracks, fCommonMem->fNTrackHits, fOutputControl);
+}
 
-  for ( int iTr = 0; iTr < *fNTracks; iTr++ ) {
+GPUh() int AliHLTTPCCATracker::SortComparison(const void* a, const void* b)
+{
+       return(((trackSortData*) a)->fSortVal < ((trackSortData*) b)->fSortVal ? 1 : -1);
+}
 
-    const AliHLTTPCCATrack &iTrack = fTracks[iTr];
+GPUh() void AliHLTTPCCATracker::WriteOutput()
+{
+       // write output
+       AliHLTTPCCASliceOutput* useOutput = *fOutput;
+
+       TStopwatch timer;
+
+       //cout<<"output: nTracks = "<<*fNTracks<<", nHitsTotal="<<NHitsTotal()<<std::endl;
+
+       if (useOutput == NULL) return;
+
+       useOutput->SetNTracks( 0 );
+       useOutput->SetNTrackClusters( 0 );
+
+       int nStoredHits = 0;
+       int nStoredTracks = 0;
+       int nStoredLocalTracks = 0;
+
+       AliHLTTPCCASliceOutTrack *out = useOutput->FirstTrack();
+
+       trackSortData* trackOrder = new trackSortData[fCommonMem->fNTracks];
+       for (int i = 0;i < fCommonMem->fNTracks;i++)
+       {
+               trackOrder[i].fTtrack = i;
+               trackOrder[i].fSortVal = fTracks[trackOrder[i].fTtrack].NHits() / 1000.f + fTracks[trackOrder[i].fTtrack].Param().GetZ() * 100.f + fTracks[trackOrder[i].fTtrack].Param().GetY();
+       }
+       qsort(trackOrder, fCommonMem->fNLocalTracks, sizeof(trackSortData), SortComparison);
+       qsort(trackOrder + fCommonMem->fNLocalTracks, fCommonMem->fNTracks - fCommonMem->fNLocalTracks, sizeof(trackSortData), SortComparison);
+
+       for ( int iTrTmp = 0; iTrTmp < fCommonMem->fNTracks; iTrTmp++ ) {
+               int iTr = trackOrder[iTrTmp].fTtrack;
+               AliHLTTPCCATrack &iTrack = fTracks[iTr];    
+
+               if( iTr < fCommonMem->fNLocalTracks && iTrack.NHits() < fParam.MinNTrackClusters() ) continue;
+               if( CAMath::Abs(iTrack.Param().GetQPt())> fParam.MaxTrackQPt() ) continue;
+
+               out->SetParam( iTrack.Param() );
+               out->SetLocalTrackId( iTrack.LocalTrackId() );
+               int nClu = 0;
+               int iID = iTrack.FirstHitID();
+
+               for ( int ith = 0; ith < iTrack.NHits(); ith++ ) {
+                       const AliHLTTPCCAHitId &ic = fTrackHits[iID + ith];
+                       int iRow = ic.RowIndex();
+                       int ih = ic.HitIndex();
+
+                       const AliHLTTPCCARow &row = fData.Row( iRow );
+
+                       int clusterIndex = fData.ClusterDataIndex( row, ih );
+
+                       float origX = fClusterData->X( clusterIndex );
+                       float origY = fClusterData->Y( clusterIndex );
+                       float origZ = fClusterData->Z( clusterIndex );      
+                       int id = fClusterData->Id( clusterIndex );
+                       AliHLTTPCCASliceOutCluster c;
+                       c.Set( id, iRow, origX, origY, origZ );
+                       out->SetCluster( nClu, c );
+                       nClu++;
+               }
+
+               nStoredTracks++;
+               if (iTr < fCommonMem->fNLocalTracks) nStoredLocalTracks++;
+               nStoredHits+=nClu; 
+               out->SetNClusters( nClu );
+               out = out->NextTrack();    
+       }
+       delete[] trackOrder;
+
+       useOutput->SetNTracks( nStoredTracks );
+       useOutput->SetNLocalTracks( nStoredLocalTracks );
+       useOutput->SetNTrackClusters( nStoredHits );
+
+       timer.Stop();
+       fTimers[5] += timer.CpuTime();
+}
 
-    //std::cout<<"iTr = "<<iTr<<", nHits="<<iTrack.NHits()<<std::endl;
+#endif
 
-    //if( !iTrack.Alive() ) continue;
-    if ( iTrack.NHits() < 3 ) continue;
-    AliHLTTPCCAOutTrack &out = fOutTracks[*fNOutTracks];
-    out.SetFirstHitRef( *fNOutTrackHits );
-    out.SetNHits( 0 );
-    out.SetOrigTrackID( iTr );
-    out.SetStartPoint( iTrack.Param() );
-    out.SetEndPoint( iTrack.Param() );
-
-    int iID = iTrack.FirstHitID();
-    int nOutTrackHitsOld = *fNOutTrackHits;
-
-    for ( int ith = 0; ith < iTrack.NHits(); ith++ ) {
-      const AliHLTTPCCAHitId &ic = fTrackHits[iID + ith];
-      const AliHLTTPCCARow &row = Row( ic );
-      int ih = ic.HitIndex();
-      fOutTrackHits[*fNOutTrackHits] = HitInputID( row, ih );
-      ( *fNOutTrackHits )++;
-      //std::cout<<"write i,row,hit,id="<<ith<<", "<<ID2IRow(ic)<<", "<<ih<<", "<<HitInputID( row, ih )<<std::endl;
-      if ( *fNOutTrackHits >= 10*NHitsTotal() ) {
-        std::cout << "fNOutTrackHits>NHitsTotal()" << std::endl;
-        //exit(0);
-        return;//SG!!!
-      }
-      out.SetNHits( out.NHits() + 1 );
-    }
-    if ( out.NHits() >= 2 ) {
-      ( *fNOutTracks )++;
-    } else {
-      ( *fNOutTrackHits ) = nOutTrackHitsOld;
-    }
-  }
-
-
-  timer.Stop();
-  fTimers[5] += timer.CpuTime();
-}
-
-GPUh() void AliHLTTPCCATracker::FitTrackFull( const AliHLTTPCCATrack &/**/, float * /**/ ) const
-{
-  // fit track with material
+GPUh() void AliHLTTPCCATracker::FitTrackFull( const MEM_LG2(AliHLTTPCCATrack) &/**/, float * /**/ ) const
+{
+       // fit track with material
 #ifdef XXX
-  //* Fit the track
-  FitTrack( iTrack, tt0 );
-  if ( iTrack.NHits() <= 3 ) return;
-
-  AliHLTTPCCATrackParam &t = iTrack.Param();
-  AliHLTTPCCATrackParam t0 = t;
-
-  t.Chi2() = 0;
-  t.NDF() = -5;
-  bool first = 1;
-
-  int iID = iTrack.FirstHitID();
-  for ( int ih = 0; ih < iTrack.NHits(); ih++, iID++ ) {
-    const AliHLTTPCCAHitId &ic = fTrackHits[iID];
-    int iRow = ic.rowIndex();
-    const AliHLTTPCCARow &row = fData.Row( iRow );
-    if ( !t0.TransportToX( row.X() ) ) continue;
-    float dy, dz;
-    const AliHLTTPCCAHit &h = ic.hitIndex();
-
-    // check for wrong hits
-    if ( 0 ) {
-      dy = t0.GetY() - h.Y();
-      dz = t0.GetZ() - h.Z();
-
-      //if( dy*dy > 3.5*3.5*(/*t0.GetErr2Y() + */h.ErrY()*h.ErrY() ) ) continue;//SG!!!
-      //if( dz*dz > 3.5*3.5*(/*t0.GetErr2Z() + */h.ErrZ()*h.ErrZ() ) ) continue;
-    }
-
-    if ( !t.TransportToX( row.X() ) ) continue;
-
-    //* Update the track
-
-    if ( first ) {
-      t.Cov()[ 0] = .5 * .5;
-      t.Cov()[ 1] = 0;
-      t.Cov()[ 2] = .5 * .5;
-      t.Cov()[ 3] = 0;
-      t.Cov()[ 4] = 0;
-      t.Cov()[ 5] = .2 * .2;
-      t.Cov()[ 6] = 0;
-      t.Cov()[ 7] = 0;
-      t.Cov()[ 8] = 0;
-      t.Cov()[ 9] = .2 * .2;
-      t.Cov()[10] = 0;
-      t.Cov()[11] = 0;
-      t.Cov()[12] = 0;
-      t.Cov()[13] = 0;
-      t.Cov()[14] = .2 * .2;
-      t.Chi2() = 0;
-      t.NDF() = -5;
-    }
-    float err2Y, err2Z;
-    GetErrors2( iRow, t, err2Y, err2Z );
-
-    if ( !t.Filter2( h.Y(), h.Z(), err2Y, err2Z ) ) continue;
-
-    first = 0;
-  }
-  /*
-  float cosPhi = iTrack.Param().GetCosPhi();
-  p0.Param().TransportToX(ID2Row( iTrack.PointID()[0] ).X());
-  p2.Param().TransportToX(ID2Row( iTrack.PointID()[1] ).X());
-  if( p0.Param().GetCosPhi()*cosPhi<0 ){ // change direction
-  float *par = p0.Param().Par();
-  float *cov = p0.Param().Cov();
-  par[2] = -par[2]; // sin phi
-  par[3] = -par[3]; // DzDs
-    par[4] = -par[4]; // kappa
-    cov[3] = -cov[3];
-    cov[4] = -cov[4];
-    cov[6] = -cov[6];
-    cov[7] = -cov[7];
-    cov[10] = -cov[10];
-    cov[11] = -cov[11];
-    p0.Param().CosPhi() = -p0.Param().GetCosPhi();
-  }
-  */
+       //* Fit the track
+       FitTrack( iTrack, tt0 );
+       if ( iTrack.NHits() <= 3 ) return;
+
+       AliHLTTPCCATrackParam &t = iTrack.Param();
+       AliHLTTPCCATrackParam t0 = t;
+
+       t.Chi2() = 0;
+       t.NDF() = -5;
+       bool first = 1;
+
+       int iID = iTrack.FirstHitID();
+       for ( int ih = 0; ih < iTrack.NHits(); ih++, iID++ ) {
+               const AliHLTTPCCAHitId &ic = fTrackHits[iID];
+               int iRow = ic.rowIndex();
+               const AliHLTTPCCARow &row = fData.Row( iRow );
+               if ( !t0.TransportToX( row.X() ) ) continue;
+               float dy, dz;
+               const AliHLTTPCCAHit &h = ic.hitIndex();
+
+               // check for wrong hits
+               if ( 0 ) {
+                       dy = t0.GetY() - h.Y();
+                       dz = t0.GetZ() - h.Z();
+
+                       //if( dy*dy > 3.5*3.5*(/*t0.GetErr2Y() + */h.ErrY()*h.ErrY() ) ) continue;//SG!!!
+                       //if( dz*dz > 3.5*3.5*(/*t0.GetErr2Z() + */h.ErrZ()*h.ErrZ() ) ) continue;
+               }
+
+               if ( !t.TransportToX( row.X() ) ) continue;
+
+               //* Update the track
+
+               if ( first ) {
+                       t.Cov()[ 0] = .5 * .5;
+                       t.Cov()[ 1] = 0;
+                       t.Cov()[ 2] = .5 * .5;
+                       t.Cov()[ 3] = 0;
+                       t.Cov()[ 4] = 0;
+                       t.Cov()[ 5] = .2 * .2;
+                       t.Cov()[ 6] = 0;
+                       t.Cov()[ 7] = 0;
+                       t.Cov()[ 8] = 0;
+                       t.Cov()[ 9] = .2 * .2;
+                       t.Cov()[10] = 0;
+                       t.Cov()[11] = 0;
+                       t.Cov()[12] = 0;
+                       t.Cov()[13] = 0;
+                       t.Cov()[14] = .2 * .2;
+                       t.Chi2() = 0;
+                       t.NDF() = -5;
+               }
+               float err2Y, err2Z;
+               GetErrors2( iRow, t, err2Y, err2Z );
+
+               if ( !t.Filter2( h.Y(), h.Z(), err2Y, err2Z ) ) continue;
+
+               first = 0;
+       }
+       /*
+       float cosPhi = iTrack.Param().GetCosPhi();
+       p0.Param().TransportToX(ID2Row( iTrack.PointID()[0] ).X());
+       p2.Param().TransportToX(ID2Row( iTrack.PointID()[1] ).X());
+       if( p0.Param().GetCosPhi()*cosPhi<0 ){ // change direction
+       float *par = p0.Param().Par();
+       float *cov = p0.Param().Cov();
+       par[2] = -par[2]; // sin phi
+       par[3] = -par[3]; // DzDs
+       par[4] = -par[4]; // kappa
+       cov[3] = -cov[3];
+       cov[4] = -cov[4];
+       cov[6] = -cov[6];
+       cov[7] = -cov[7];
+       cov[10] = -cov[10];
+       cov[11] = -cov[11];
+       p0.Param().CosPhi() = -p0.Param().GetCosPhi();
+       }
+       */
 #endif
 }
 
 GPUh() void AliHLTTPCCATracker::FitTrack( const AliHLTTPCCATrack &/*track*/, float * /*t0[]*/ ) const
 {
-  //* Fit the track
+       //* Fit the track
 #ifdef XXX
-  AliHLTTPCCAEndPoint &p2 = ID2Point( track.PointID()[1] );
-  const AliHLTTPCCAHit &c0 = ID2Hit( fTrackHits[p0.TrackHitID()].HitID() );
-  const AliHLTTPCCAHit &c1 = ID2Hit( fTrackHits[track.HitID()[1]].HitID() );
-  const AliHLTTPCCAHit &c2 = ID2Hit( fTrackHits[p2.TrackHitID()].HitID() );
-  const AliHLTTPCCARow &row0 = ID2Row( fTrackHits[p0.TrackHitID()].HitID() );
-  const AliHLTTPCCARow &row1 = ID2Row( fTrackHits[track.HitID()[1]].HitID() );
-  const AliHLTTPCCARow &row2 = ID2Row( fTrackHits[p2.TrackHitID()].HitID() );
-  float sp0[5] = {row0.X(), c0.Y(), c0.Z(), c0.ErrY(), c0.ErrZ() };
-  float sp1[5] = {row1.X(), c1.Y(), c1.Z(), c1.ErrY(), c1.ErrZ() };
-  float sp2[5] = {row2.X(), c2.Y(), c2.Z(), c2.ErrY(), c2.ErrZ() };
-  //std::cout<<"Fit track, points ="<<sp0[0]<<" "<<sp0[1]<<" / "<<sp1[0]<<" "<<sp1[1]<<" / "<<sp2[0]<<" "<<sp2[1]<<std::endl;
-  if ( track.NHits() >= 3 ) {
-    p0.Param().ConstructXYZ3( sp0, sp1, sp2, p0.Param().CosPhi(), t0 );
-    p2.Param().ConstructXYZ3( sp2, sp1, sp0, p2.Param().CosPhi(), t0 );
-    //p2.Param() = p0.Param();
-    //p2.Param().TransportToX(row2.X());
-    //p2.Param().Par()[1] = -p2.Param().Par()[1];
-    //p2.Param().Par()[4] = -p2.Param().Par()[4];
-  } else {
-    p0.Param().X() = row0.X();
-    p0.Param().Y() = c0.Y();
-    p0.Param().Z() = c0.Z();
-    p0.Param().Err2Y() = c0.ErrY() * c0.ErrY();
-    p0.Param().Err2Z() = c0.ErrZ() * c0.ErrZ();
-    p2.Param().X() = row2.X();
-    p2.Param().Y() = c2.Y();
-    p2.Param().Z() = c2.Z();
-    p2.Param().Err2Y() = c2.ErrY() * c2.ErrY();
-    p2.Param().Err2Z() = c2.ErrZ() * c2.ErrZ();
-  }
+       AliHLTTPCCAEndPoint &p2 = ID2Point( track.PointID()[1] );
+       const AliHLTTPCCAHit &c0 = ID2Hit( fTrackHits[p0.TrackHitID()].HitID() );
+       const AliHLTTPCCAHit &c1 = ID2Hit( fTrackHits[track.HitID()[1]].HitID() );
+       const AliHLTTPCCAHit &c2 = ID2Hit( fTrackHits[p2.TrackHitID()].HitID() );
+       const AliHLTTPCCARow &row0 = ID2Row( fTrackHits[p0.TrackHitID()].HitID() );
+       const AliHLTTPCCARow &row1 = ID2Row( fTrackHits[track.HitID()[1]].HitID() );
+       const AliHLTTPCCARow &row2 = ID2Row( fTrackHits[p2.TrackHitID()].HitID() );
+       float sp0[5] = {row0.X(), c0.Y(), c0.Z(), c0.ErrY(), c0.ErrZ() };
+       float sp1[5] = {row1.X(), c1.Y(), c1.Z(), c1.ErrY(), c1.ErrZ() };
+       float sp2[5] = {row2.X(), c2.Y(), c2.Z(), c2.ErrY(), c2.ErrZ() };
+       //std::cout<<"Fit track, points ="<<sp0[0]<<" "<<sp0[1]<<" / "<<sp1[0]<<" "<<sp1[1]<<" / "<<sp2[0]<<" "<<sp2[1]<<std::endl;
+       if ( track.NHits() >= 3 ) {
+               p0.Param().ConstructXYZ3( sp0, sp1, sp2, p0.Param().CosPhi(), t0 );
+               p2.Param().ConstructXYZ3( sp2, sp1, sp0, p2.Param().CosPhi(), t0 );
+               //p2.Param() = p0.Param();
+               //p2.Param().TransportToX(row2.X());
+               //p2.Param().Par()[1] = -p2.Param().Par()[1];
+               //p2.Param().Par()[4] = -p2.Param().Par()[4];
+       } else {
+               p0.Param().X() = row0.X();
+               p0.Param().Y() = c0.Y();
+               p0.Param().Z() = c0.Z();
+               p0.Param().Err2Y() = c0.ErrY() * c0.ErrY();
+               p0.Param().Err2Z() = c0.ErrZ() * c0.ErrZ();
+               p2.Param().X() = row2.X();
+               p2.Param().Y() = c2.Y();
+               p2.Param().Z() = c2.Z();
+               p2.Param().Err2Y() = c2.ErrY() * c2.ErrY();
+               p2.Param().Err2Z() = c2.ErrZ() * c2.ErrZ();
+       }
 #endif
 }
 
+#if !defined(HLTCA_GPUCODE)
 
-GPUd() void AliHLTTPCCATracker::GetErrors2( int iRow, float z, float sinPhi, float cosPhi, float DzDs, float &Err2Y, float &Err2Z ) const
+GPUh() void AliHLTTPCCATracker::WriteEvent( std::ostream &out )
 {
-  //
-  // Use calibrated cluster error from OCDB
-  //
-
-  fParam.GetClusterErrors2( iRow, z, sinPhi, cosPhi, DzDs, Err2Y, Err2Z );
+       // write event to the file
+       for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
+               out << fData.Row( iRow ).HitNumberOffset() << " " << fData.Row( iRow ).NHits() << std::endl;
+       }
+       out << NHitsTotal() << std::endl;
+
+       AliHLTResizableArray<float> y( NHitsTotal() ), z( NHitsTotal() );
+
+       for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
+               const AliHLTTPCCARow &row = Row( iRow );
+               float y0 = row.Grid().YMin();
+               float z0 = row.Grid().ZMin();
+               float stepY = row.HstepY();
+               float stepZ = row.HstepZ();
+               for ( int ih = 0; ih < fData.Row( iRow ).NHits(); ih++ ) {
+                       int id = HitInputID( row, ih );
+                       y[id] = y0 + HitDataY( row, ih ) * stepY;
+                       z[id] = z0 + HitDataZ( row, ih ) * stepZ;
+               }
+       }
+       for ( int ih = 0; ih < NHitsTotal(); ih++ ) {
+               out << y[ih] << " " << z[ih] << std::endl;
+       }
 }
 
-GPUd() void AliHLTTPCCATracker::GetErrors2( int iRow, const AliHLTTPCCATrackParam &t, float &Err2Y, float &Err2Z ) const
+GPUh() void AliHLTTPCCATracker::WriteTracks( std::ostream &/*out*/ )
 {
-  //
-  // Use calibrated cluster error from OCDB
-  //
-
-  fParam.GetClusterErrors2( iRow, t.GetZ(), t.SinPhi(), t.GetCosPhi(), t.DzDs(), Err2Y, Err2Z );
+       //* Write tracks to file --- dummy
 }
 
+GPUh() void AliHLTTPCCATracker::ReadTracks( std::istream &/*in*/ )
+{
+       //* Read tracks  from file -- dummy
+}
 
-#if !defined(HLTCA_GPUCODE)
+GPUh() int AliHLTTPCCATracker::PerformGlobalTrackingRun(AliHLTTPCCATracker& sliceNeighbour, int iTrack, int rowIndex, float angle, int direction)
+{
+       /*for (int j = 0;j < fTracks[j].NHits();j++)
+       {
+               printf("Hit %3d: Row %3d: X %3.7lf Y %3.7lf\n", j, fTrackHits[fTracks[iTrack].FirstHitID() + j].RowIndex(), Row(fTrackHits[fTracks[iTrack].FirstHitID() + j].RowIndex()).X(),
+               (float) Data().HitDataY(Row(fTrackHits[fTracks[iTrack].FirstHitID() + j].RowIndex()), fTrackHits[fTracks[iTrack].FirstHitID() + j].HitIndex()) * Row(fTrackHits[fTracks[iTrack].FirstHitID() + j].RowIndex()).HstepY() + Row(fTrackHits[fTracks[iTrack].FirstHitID() + j].RowIndex()).Grid().YMin());
+               }*/
+
+       if (sliceNeighbour.fCommonMem->fNTracklets == 0) return(0);
+
+       AliHLTTPCCATrackParam tParam;
+       tParam.InitParam();
+       tParam.SetCov( 0, 0.05 );
+       tParam.SetCov( 2, 0.05 );
+       tParam.SetCov( 5, 0.001 );
+       tParam.SetCov( 9, 0.001 );
+       tParam.SetCov( 14, 0.05 );
+       tParam.SetParam(fTracks[iTrack].Param());
+
+       //printf("Parameters X %f Y %f Z %f SinPhi %f DzDs %f QPt %f SignCosPhi %f\n", tParam.X(), tParam.Y(), tParam.Z(), tParam.SinPhi(), tParam.DzDs(), tParam.QPt(), tParam.SignCosPhi());
+       if (!tParam.Rotate(angle, .999)) return(0);
+       //printf("Rotated X %f Y %f Z %f SinPhi %f DzDs %f QPt %f SignCosPhi %f\n", tParam.X(), tParam.Y(), tParam.Z(), tParam.SinPhi(), tParam.DzDs(), tParam.QPt(), tParam.SignCosPhi());
+
+       int maxRowGap = 6;
+       do
+       {
+               rowIndex += direction;
+               if (!tParam.TransportToX(sliceNeighbour.Row(rowIndex).X(), fParam.ConstBz(), .999)) {maxRowGap = 0;break;}
+               //printf("Transported X %f Y %f Z %f SinPhi %f DzDs %f QPt %f SignCosPhi %f (MaxY %f)\n", tParam.X(), tParam.Y(), tParam.Z(), tParam.SinPhi(), tParam.DzDs(), tParam.QPt(), tParam.SignCosPhi(), sliceNeighbour.Row(rowIndex).MaxY());
+       } while (fabs(tParam.Y()) > sliceNeighbour.Row(rowIndex).MaxY() && --maxRowGap);
+       if (maxRowGap == 0) return(0);
+
+       int nHits = AliHLTTPCCATrackletConstructor::AliHLTTPCCATrackletConstructorGlobalTracking(sliceNeighbour, tParam, rowIndex, direction);
+       if (nHits >= GLOBAL_TRACKING_MIN_HITS)
+       {
+               //printf("%d hits found\n", nHits);
+               AliHLTTPCCATrack& track = sliceNeighbour.fTracks[sliceNeighbour.fCommonMem->fNTracks];
+               if (direction == 1)
+               {
+                       int i = 0;
+                       while (i < nHits)
+                       {
+                               if (sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets] != -1)
+                               {
+                                       //printf("New track: entry %d, row %d, hitindex %d\n", i, rowIndex, sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets]);
+                                       sliceNeighbour.fTrackHits[sliceNeighbour.fCommonMem->fNTrackHits + i].Set(rowIndex, sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets]);
+                                       if (i == 0) tParam.TransportToX(sliceNeighbour.Row(rowIndex).X(), fParam.ConstBz(), .999);
+                                       i++;
+                               }
+                               rowIndex ++;
+                       }
+               }
+               else
+               {
+                       int i = nHits - 1;
+                       while (i >= 0)
+                       {
+                               if (sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets] != -1)
+                               {
+                                       //printf("New track: entry %d, row %d, hitindex %d\n", i, rowIndex, sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets]);
+                                       sliceNeighbour.fTrackHits[sliceNeighbour.fCommonMem->fNTrackHits + i].Set(rowIndex, sliceNeighbour.fTrackletRowHits[rowIndex * sliceNeighbour.fCommonMem->fNTracklets]);
+                                       i--;
+                               }
+                               rowIndex--;
+                       }
+               }
+               track.SetAlive(1);
+               track.SetParam(tParam.GetParam());
+               track.SetNHits(nHits);
+               track.SetFirstHitID(sliceNeighbour.fCommonMem->fNTrackHits);
+               const int kMaxTrackIdInSlice = AliHLTTPCCASliceOutTrack::MaxTrackId();
+               track.SetLocalTrackId(fParam.ISlice() * kMaxTrackIdInSlice + fTracks[iTrack].LocalTrackId());
+               sliceNeighbour.fCommonMem->fNTracks++;
+               sliceNeighbour.fCommonMem->fNTrackHits += nHits;
+               return(1);
+       }
+       return(0);
+}
 
-GPUh() void AliHLTTPCCATracker::WriteEvent( std::ostream &out )
+GPUh() void AliHLTTPCCATracker::PerformGlobalTracking(AliHLTTPCCATracker& sliceLeft, AliHLTTPCCATracker& sliceRight, int MaxTracks)
 {
-  // write event to the file
-  for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
-    out << fData.Row( iRow ).HitNumberOffset() << " " << fData.Row( iRow ).NHits() << std::endl;
-  }
-  out << NHitsTotal() << std::endl;
-
-  AliHLTResizableArray<float> y( NHitsTotal() ), z( NHitsTotal() );
-
-  for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
-    const AliHLTTPCCARow &row = Row( iRow );
-    float y0 = row.Grid().YMin();
-    float z0 = row.Grid().ZMin();
-    float stepY = row.HstepY();
-    float stepZ = row.HstepZ();
-    for ( int ih = 0; ih < fData.Row( iRow ).NHits(); ih++ ) {
-      int id = HitInputID( row, ih );
-      y[id] = y0 + HitDataY( row, ih ) * stepY;
-      z[id] = z0 + HitDataZ( row, ih ) * stepZ;
-    }
-  }
-  for ( int ih = 0; ih < NHitsTotal(); ih++ ) {
-    out << y[ih] << " " << z[ih] << std::endl;
-  }
-}
-
-GPUh() void AliHLTTPCCATracker::WriteTracks( std::ostream &out )
-{
-  //* Write tracks to file
-
-  out << fTimers[0] << std::endl;
-  out << *fNOutTrackHits << std::endl;
-  for ( int ih = 0; ih < *fNOutTrackHits; ih++ ) {
-    out << fOutTrackHits[ih] << " ";
-  }
-  out << std::endl;
-
-  out << *fNOutTracks << std::endl;
-
-  for ( int itr = 0; itr < *fNOutTracks; itr++ ) {
-    AliHLTTPCCAOutTrack &t = fOutTracks[itr];
-    AliHLTTPCCATrackParam p1 = t.StartPoint();
-    AliHLTTPCCATrackParam p2 = t.EndPoint();
-    out << t.NHits() << " ";
-    out << t.FirstHitRef() << " ";
-    out << t.OrigTrackID() << " ";
-    out << std::endl;
-    out << p1.X() << " ";
-    out << p1.SignCosPhi() << " ";
-    out << p1.Chi2() << " ";
-    out << p1.NDF() << std::endl;
-    for ( int i = 0; i < 5; i++ ) out << p1.Par()[i] << " ";
-    out << std::endl;
-    for ( int i = 0; i < 15; i++ ) out << p1.Cov()[i] << " ";
-    out << std::endl;
-    out << p2.X() << " ";
-    out << p2.SignCosPhi() << " ";
-    out << p2.Chi2() << " ";
-    out << p2.NDF() << std::endl;
-    for ( int i = 0; i < 5; i++ ) out << p2.Par()[i] << " ";
-    out << std::endl;
-    for ( int i = 0; i < 15; i++ ) out << p2.Cov()[i] << " ";
-    out << std::endl;
-  }
-}
-
-GPUh() void AliHLTTPCCATracker::ReadTracks( std::istream &in )
-{
-  //* Read tracks  from file
-  in >> fTimers[0];
-  in >> *fNOutTrackHits;
-
-  for ( int ih = 0; ih < *fNOutTrackHits; ih++ ) {
-    in >> fOutTrackHits[ih];
-  }
-  in >> *fNOutTracks;
-
-  for ( int itr = 0; itr < *fNOutTracks; itr++ ) {
-    AliHLTTPCCAOutTrack &t = fOutTracks[itr];
-    AliHLTTPCCATrackParam p1, p2;
-    int i;
-    float f;
-    in >> i; t.SetNHits( i );
-    in >> i; t.SetFirstHitRef( i );
-    in >> i; t.SetOrigTrackID( i );
-    in >> f; p1.SetX( f );
-    in >> f; p1.SetSignCosPhi( f );
-    in >> f; p1.SetChi2( f );
-    in >> i; p1.SetNDF( i );
-    for ( int j = 0; j < 5; j++ ) { in >> f; p1.SetPar( j, f ); }
-    for ( int j = 0; j < 15; j++ ) { in >> f; p1.SetCov( j, f ); }
-    in >> f; p2.SetX( f );
-    in >> f; p2.SetSignCosPhi( f );
-    in >> f; p2.SetChi2( f );
-    in >> i; p2.SetNDF( i );
-    for ( int j = 0; j < 5; j++ ) { in >> f; p2.SetPar( j, f ); }
-    for ( int j = 0; j < 15; j++ ) { in >> f; p2.SetCov( j, f ); }
-    t.SetStartPoint( p1 );
-    t.SetEndPoint( p2 );
-  }
+       int ul = 0, ur = 0, ll = 0, lr = 0;
+       for (int i = 0;i < fCommonMem->fNLocalTracks;i++)
+       {
+               if (sliceLeft.fCommonMem->fNTracks >= MaxTracks || sliceRight.fCommonMem->fNTracks >= MaxTracks) return;
+
+               {
+                       const int tmpHit = fTracks[i].FirstHitID();
+                       if (fTrackHits[tmpHit].RowIndex() >= GLOBAL_TRACKING_MIN_ROWS && fTrackHits[tmpHit].RowIndex() < GLOBAL_TRACKING_RANGE)
+                       {
+                               int rowIndex = fTrackHits[tmpHit].RowIndex();
+                               const AliHLTTPCCARow& row = Row(rowIndex);
+                               float Y = (float) Data().HitDataY(row, fTrackHits[tmpHit].HitIndex()) * row.HstepY() + row.Grid().YMin();
+                               if (Y < -row.MaxY() * GLOBAL_TRACKING_Y_RANGE_LOWER_LEFT)
+                               {
+                                       //printf("Track %d, lower row %d, left border (%f of %f)\n", i, fTrackHits[tmpHit].RowIndex(), Y, -row.MaxY());
+                                       ll += PerformGlobalTrackingRun(sliceLeft, i, rowIndex, -fParam.DAlpha(), -1);
+                               }
+                               if (Y > row.MaxY() * GLOBAL_TRACKING_Y_RANGE_LOWER_RIGHT)
+                               {
+                                       //printf("Track %d, lower row %d, right border (%f of %f)\n", i, fTrackHits[tmpHit].RowIndex(), Y, row.MaxY());
+                                       lr += PerformGlobalTrackingRun(sliceRight, i, rowIndex, fParam.DAlpha(), -1);
+                               }
+                       }
+               }
+               
+               {
+                       const int tmpHit = fTracks[i].FirstHitID() + fTracks[i].NHits() - 1;
+                       if (fTrackHits[tmpHit].RowIndex() < HLTCA_ROW_COUNT - GLOBAL_TRACKING_MIN_ROWS && fTrackHits[tmpHit].RowIndex() >= HLTCA_ROW_COUNT - GLOBAL_TRACKING_RANGE)
+                       {
+                               int rowIndex = fTrackHits[tmpHit].RowIndex();
+                               const AliHLTTPCCARow& row = Row(rowIndex);
+                               float Y = (float) Data().HitDataY(row, fTrackHits[tmpHit].HitIndex()) * row.HstepY() + row.Grid().YMin();
+                               if (Y < -row.MaxY() * GLOBAL_TRACKING_Y_RANGE_UPPER_LEFT)
+                               {
+                                       //printf("Track %d, upper row %d, left border (%f of %f)\n", i, fTrackHits[tmpHit].RowIndex(), Y, -row.MaxY());
+                                       ul += PerformGlobalTrackingRun(sliceLeft, i, rowIndex, -fParam.DAlpha(), 1);
+                               }
+                               if (Y > row.MaxY() * GLOBAL_TRACKING_Y_RANGE_UPPER_RIGHT)
+                               {
+                                       //printf("Track %d, upper row %d, right border (%f of %f)\n", i, fTrackHits[tmpHit].RowIndex(), Y, row.MaxY());
+                                       ur += PerformGlobalTrackingRun(sliceRight, i, rowIndex, fParam.DAlpha(), 1);
+                               }
+                       }
+               }
+       }
+       //printf("Global Tracking Result: Slide %2d: LL %3d LR %3d UL %3d UR %3d\n", fParam.ISlice(), ll, lr, ul, ur);
 }
+
 #endif
+#endif
\ No newline at end of file