@@ -1435,13 +1435,14 @@ namespace // anonymous
14351435{
14361436struct GPUTPCGMMerger_CompareClusterIds {
14371437 const GPUTPCGMMerger::trackCluster* const mCmp ;
1438- GPUd () GPUTPCGMMerger_CompareClusterIds(const GPUTPCGMMerger::trackCluster* cmp) : mCmp (cmp) {}
1438+ const bool revert;
1439+ GPUd () GPUTPCGMMerger_CompareClusterIds(const GPUTPCGMMerger::trackCluster* cmp, bool r) : mCmp (cmp), revert(r) {}
14391440 GPUd () bool operator ()(const int16_t aa, const int16_t bb)
14401441 {
14411442 const GPUTPCGMMerger::trackCluster& a = mCmp [aa];
14421443 const GPUTPCGMMerger::trackCluster& b = mCmp [bb];
14431444 if (a.row != b.row ) {
1444- return (a.row > b.row );
1445+ return (a.row > b.row ) ^ revert ;
14451446 }
14461447 return GPUCA_DETERMINISTIC_CODE ((a.id != b.id ) ? (a.id > b.id ) : (aa > bb), a.id > b.id );
14471448 }
@@ -1460,6 +1461,8 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
14601461 GPUTPCGMSectorTrack* trbase = nullptr ;
14611462 int32_t leg = 0 ;
14621463 int32_t lastMergedSegment = -1 ;
1464+ bool revertSegments = false ;
1465+ bool revertInSegment = false ;
14631466 while (true ) {
14641467 if (trbase && !Param ().rec .tpc .dropLoopers ) {
14651468 int32_t jtr = trbase->NextNeighbour ();
@@ -1469,7 +1472,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
14691472 trbase = nullptr ;
14701473 } else {
14711474 trbase->SetPrevSegmentNeighbour (1000000001 );
1472- leg-- ;
1475+ leg += revertSegments ? 1 : - 1 ;
14731476 }
14741477 } else {
14751478 trbase = nullptr ;
@@ -1488,15 +1491,68 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
14881491 if (itr >= SectorTrackInfoLocalTotal ()) {
14891492 break ;
14901493 }
1491- itr += nThreads * nBlocks;
1494+ revertSegments = false ;
1495+ revertInSegment = false ;
14921496 trbase->SetPrevSegmentNeighbour (1000000000 );
14931497 int32_t jtr = trbase->NextNeighbour ();
14941498 leg = 0 ;
1495- while (jtr >= 0 ) {
1496- leg++;
1497- jtr = mSectorTrackInfos [jtr].NextNeighbour ();
1499+ if (jtr >= 0 ) {
1500+ int32_t lasttr = itr;
1501+ while (jtr >= 0 ) { // --------------- count segments ---------------
1502+ if (&mSectorTrackInfos [jtr] == trbase) {
1503+ break ; // Break cyclic graph
1504+ }
1505+ lasttr = jtr;
1506+ leg++;
1507+ jtr = mSectorTrackInfos [jtr].NextNeighbour ();
1508+ }
1509+
1510+ float mainZT = 1e9 ;
1511+ revertSegments = true ;
1512+ for (uint32_t k = 0 ; k < 2 ; k++) { // --------------- check if first or last segment is primary ---------------
1513+ int32_t ichk = k ? lasttr : itr;
1514+ const GPUTPCGMSectorTrack* trchk = &mSectorTrackInfos [ichk];
1515+ while (true ) {
1516+ float zt = Param ().par .earlyTpcTransform ? CAMath::Min (CAMath::Abs (trchk->ClusterZT0 ()), CAMath::Abs (trchk->ClusterZTN ())) : -trchk->MinClusterZT (); // Negative time ~ smallest z, behaves the same way
1517+ if (zt < mainZT) {
1518+ if (k) {
1519+ revertSegments = false ;
1520+ break ;
1521+ }
1522+ mainZT = zt;
1523+ }
1524+ int32_t next = trchk->NextSegmentNeighbour ();
1525+ if (next < 0 || next == ichk) {
1526+ break ; // Breaks also cycles
1527+ }
1528+ trchk = &mSectorTrackInfos [next];
1529+ }
1530+ }
1531+ if (revertSegments) {
1532+ leg = 0 ;
1533+ }
1534+
1535+ { // --------------- find longest sector track of main segment ---------------
1536+ int32_t length = 0 ;
1537+ int32_t ichk = revertSegments ? itr : lasttr;
1538+ const GPUTPCGMSectorTrack* trchk = &mSectorTrackInfos [ichk];
1539+ const GPUTPCGMSectorTrack* longest = trchk;
1540+ while (true ) {
1541+ if (trchk->OrigTrack ()->NHits () > length) {
1542+ longest = trchk;
1543+ length = trchk->OrigTrack ()->NHits ();
1544+ }
1545+ int32_t next = trchk->NextSegmentNeighbour ();
1546+ if (next < 0 || next == ichk) {
1547+ break ; // Breaks also cycles
1548+ }
1549+ trchk = &mSectorTrackInfos [next];
1550+ }
1551+ revertInSegment = (longest->ClusterZT0 () < longest->ClusterZTN ()) ^ (Param ().par .earlyTpcTransform ? !longest->CSide () : false );
1552+ }
14981553 }
14991554 lastMergedSegment = -1 ;
1555+ itr += nThreads * nBlocks;
15001556 }
15011557
15021558 do {
@@ -1513,7 +1569,6 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
15131569 }
15141570 nHits += tr->NClusters ();
15151571
1516- tr->SetLeg (leg);
15171572 trackParts[nParts++] = tr;
15181573 for (int32_t i = 0 ; i < 2 ; i++) {
15191574 if (tr->ExtrapolatedTrackId (i) != -1 ) {
@@ -1523,8 +1578,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
15231578 if (nHits + mSectorTrackInfos [tr->ExtrapolatedTrackId (i)].NClusters () > kMaxClusters ) {
15241579 break ;
15251580 }
1526- trackParts[nParts] = &mSectorTrackInfos [tr->ExtrapolatedTrackId (i)];
1527- trackParts[nParts++]->SetLeg (leg);
1581+ trackParts[nParts++] = &mSectorTrackInfos [tr->ExtrapolatedTrackId (i)];
15281582 nHits += mSectorTrackInfos [tr->ExtrapolatedTrackId (i)].NClusters ();
15291583 }
15301584 }
@@ -1538,7 +1592,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
15381592 }
15391593
15401594 // unpack and sort clusters
1541- if (nParts > 1 ) {
1595+ if (nParts > 1 && (!revertInSegment ^ (leg & 1 )) ) {
15421596 GPUCommonAlgorithm::sort (trackParts, trackParts + nParts, [](const GPUTPCGMSectorTrack* a, const GPUTPCGMSectorTrack* b) {
15431597 GPUCA_DETERMINISTIC_CODE ( // clang-format off
15441598 if (a->X () != b->X ()) {
@@ -1576,11 +1630,14 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
15761630 break ;
15771631 }
15781632
1579- bool ordered = true ;
1580- for (int32_t i = 1 ; i < nHits; i++) {
1581- if (trackClusters[i].row > trackClusters[i - 1 ].row || trackClusters[i].id == trackClusters[i - 1 ].id ) {
1582- ordered = false ;
1583- break ;
1633+ const bool mustReverse = revertInSegment ^ (leg & 1 );
1634+ bool ordered = !mustReverse;
1635+ if (ordered) {
1636+ for (int32_t i = 1 ; i < nHits; i++) {
1637+ if ((trackClusters[i].row > trackClusters[i - 1 ].row ) ^ mustReverse || trackClusters[i].id == trackClusters[i - 1 ].id ) {
1638+ ordered = false ;
1639+ break ;
1640+ }
15841641 }
15851642 }
15861643 int32_t firstTrackIndex = 0 ;
@@ -1594,7 +1651,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
15941651 clusterIndices[i] = i;
15951652 }
15961653
1597- GPUCommonAlgorithm::sort (clusterIndices, clusterIndices + nHits, GPUTPCGMMerger_CompareClusterIds (trackClusters));
1654+ GPUCommonAlgorithm::sort (clusterIndices, clusterIndices + nHits, GPUTPCGMMerger_CompareClusterIds (trackClusters, mustReverse ));
15981655
15991656 nTmpHits = 0 ;
16001657 firstTrackIndex = lastTrackIndex = -1 ;
@@ -1659,16 +1716,24 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread
16591716 }
16601717
16611718 GPUTPCGMMergedTrack& mergedTrack = mMergedTracks [iOutputTrack];
1719+ GPUTPCGMTrackParam& p1 = mergedTrack.Param ();
1720+ const GPUTPCGMSectorTrack& p2 = *trackParts[firstTrackIndex];
16621721 mergedTrack.SetFlags (0 );
16631722 mergedTrack.SetOK (true );
1664- mergedTrack.SetLooper (leg > 0 || lastMergedSegment >= 0 );
1723+ mergedTrack.SetLeg (leg);
1724+ mergedTrack.SetLooper (leg > 0 || lastMergedSegment >= 0 || revertSegments);
16651725 mergedTrack.SetNClusters (nHits);
16661726 mergedTrack.SetFirstClusterRef (iMergedTrackFirstCluster);
1667- GPUTPCGMTrackParam& p1 = mergedTrack.Param ();
1668- const GPUTPCGMSectorTrack& p2 = *trackParts[firstTrackIndex];
16691727 mergedTrack.SetCSide (p2.CSide ());
16701728 mergedTrack.SetMergedLooperConnected (leg > 0 );
1671- mergedTrack.SetPrevSegment (lastMergedSegment);
1729+ if (revertSegments) {
1730+ mergedTrack.SetPrevSegment (-1 );
1731+ if (lastMergedSegment >= 0 ) {
1732+ mMergedTracks [lastMergedSegment].SetPrevSegment (iOutputTrack);
1733+ }
1734+ } else {
1735+ mergedTrack.SetPrevSegment (lastMergedSegment);
1736+ }
16721737 lastMergedSegment = iOutputTrack;
16731738
16741739 GPUTPCGMBorderTrack b;
0 commit comments