@@ -436,6 +436,10 @@ protected override void OnRecursionEntrance(Provider provider)
436436
437437 private static List < int > Merge ( IEnumerable < int > left , IEnumerable < int > right )
438438 {
439+ if ( TryMergeFast ( left , right , out var result ) )
440+ return result ;
441+
442+ // slow
439443 var hs = new HashSet < int > ( left ) ;
440444 foreach ( var r in right ) {
441445 _ = hs . Add ( r ) ;
@@ -445,18 +449,50 @@ private static List<int> Merge(IEnumerable<int> left, IEnumerable<int> right)
445449 return resultList ;
446450 }
447451
448- private static List < int > Merge ( List < int > leftMap , IEnumerable < int > rightMap )
452+ private static bool TryMergeFast ( IEnumerable < int > leftMap , IEnumerable < int > rightMap , out List < int > result )
449453 {
450- var preReturn = leftMap . Union ( rightMap ) . ToList ( leftMap . Count * 2 ) ;
451- preReturn . Sort ( ) ;
452- return preReturn ;
453- }
454+ Span < bool > usageMap = stackalloc bool [ 512 ] ;
455+ usageMap . Fill ( false ) ;
456+ var uniqueCount = 0 ;
457+ var biggestIndex = 0 ;
454458
455- private static List < int > Merge ( List < int > leftMap , IList < int > rightMap )
456- {
457- var preReturn = leftMap . Union ( rightMap ) . ToList ( leftMap . Count + rightMap . Count ) ;
458- preReturn . Sort ( ) ;
459- return preReturn ;
459+ // leftMap.Concat(rightMap) is slower!
460+ foreach ( var idx in leftMap ) {
461+ if ( idx >= usageMap . Length ) {
462+ result = null ;
463+ return false ;
464+ }
465+ if ( ! usageMap [ idx ] ) {
466+ uniqueCount ++ ;
467+ usageMap [ idx ] = true ;
468+ }
469+ if ( biggestIndex < idx )
470+ biggestIndex = idx ;
471+ }
472+ foreach ( var idx in rightMap ) {
473+ if ( idx >= usageMap . Length ) {
474+ result = null ;
475+ return false ;
476+ }
477+ if ( ! usageMap [ idx ] ) {
478+ uniqueCount ++ ;
479+ usageMap [ idx ] = true ;
480+ }
481+ if ( biggestIndex < idx )
482+ biggestIndex = idx ;
483+ }
484+ var resultList = new List < int > ( uniqueCount ) ;
485+ for ( int i = 0 ; i < biggestIndex + 1 ; i ++ ) {
486+ if ( usageMap [ i ] )
487+ resultList . Add ( i ) ;
488+ }
489+ if ( resultList . Count != uniqueCount ) {
490+ //
491+ result = null ;
492+ return false ;
493+ }
494+ result = resultList ;
495+ return true ;
460496 }
461497
462498 private static List < int > MergeMappings ( Provider originalLeft , List < int > leftMap , List < int > rightMap )
0 commit comments