@@ -486,13 +486,6 @@ void _merge<E, K>(
486486///
487487/// The sorting algorithm is a Pattern-defeating Quicksort (pdqsort), a
488488/// hybrid of Quicksort, Heapsort, and Insertion Sort.
489- /// It is not stable, but is typically very fast.
490- ///
491- /// This implementation is highly efficient for common data patterns
492- /// (such as sorted, reverse-sorted, or with few unique values) and has a
493- /// guaranteed worst-case time complexity of O(n*log(n)).
494- ///
495- /// For a stable sort, use [mergeSort] .
496489void quickSort <E >(
497490 List <E > elements,
498491 int Function (E a, E b) compare, [
@@ -504,6 +497,36 @@ void quickSort<E>(
504497 _pdqSortImpl (elements, compare, start, end, _log2 (end - start));
505498}
506499
500+ /// Sorts a list between [start] (inclusive) and [end] (exclusive) by key.
501+ ///
502+ /// Elements are ordered by the [compare] function applied to the result of
503+ /// the [keyOf] function.
504+ void quickSortBy <E , K >(
505+ List <E > elements,
506+ K Function (E element) keyOf,
507+ int Function (K a, K b) compare, [
508+ int start = 0 ,
509+ int ? end,
510+ ]) {
511+ end = RangeError .checkValidRange (start, end, elements.length);
512+ if (end - start < 2 ) return ;
513+ _pdqSortByImpl (elements, keyOf, compare, start, end, _log2 (end - start));
514+ }
515+
516+ /// Minimum list size below which pdqsort uses insertion sort.
517+ const int _pdqInsertionSortThreshold = 32 ;
518+
519+ /// Computes the base-2 logarithm of [n] .
520+ /// Computes the base-2 logarithm of [n] .
521+ ///
522+ /// Uses bitLength to compute the floor(log2(n)) efficiently.
523+ /// For n == 0 we return 0.
524+ int _log2 (int n) => n > 0 ? n.bitLength - 1 : 0 ;
525+
526+ // ==========================================
527+ // Implementation: Direct Comparison
528+ // ==========================================
529+
507530void _pdqSortImpl <E >(List <E > elements, int Function (E , E ) compare, int start,
508531 int end, int badAllowed) {
509532 while (true ) {
@@ -560,18 +583,6 @@ void _pdqSortImpl<E>(List<E> elements, int Function(E, E) compare, int start,
560583 }
561584}
562585
563- void _reverseRange <E >(List <E > elements, int start, int end) {
564- var left = start;
565- var right = end - 1 ;
566- while (left < right) {
567- final temp = elements[left];
568- elements[left] = elements[right];
569- elements[right] = temp;
570- left++ ;
571- right-- ;
572- }
573- }
574-
575586bool _handlePresorted <E >(
576587 List <E > elements, int Function (E , E ) compare, int start, int end) {
577588 if (compare (elements[start], elements[start + 1 ]) > 0 ) {
@@ -595,6 +606,18 @@ bool _handlePresorted<E>(
595606 return false ;
596607}
597608
609+ void _reverseRange <E >(List <E > elements, int start, int end) {
610+ var left = start;
611+ var right = end - 1 ;
612+ while (left < right) {
613+ final temp = elements[left];
614+ elements[left] = elements[right];
615+ elements[right] = temp;
616+ left++ ;
617+ right-- ;
618+ }
619+ }
620+
598621void _insertionSort <E >(
599622 List <E > elements, int Function (E , E ) compare, int start, int end) {
600623 for (var i = start + 1 ; i < end; i++ ) {
@@ -680,42 +703,10 @@ void _sort3<E>(
680703 }
681704}
682705
683- /// Sorts a list between [start] (inclusive) and [end] (exclusive) by key.
684- ///
685- /// The sorting algorithm is a Pattern-defeating Quicksort (pdqsort), a
686- /// hybrid of Quicksort, Heapsort, and Insertion Sort.
687- /// It is not stable, but is typically very fast.
688- ///
689- /// This implementation is highly efficient for common data patterns
690- /// (such as sorted, reverse-sorted, or with few unique values) and has a
691- /// guaranteed worst-case time complexity of O(n*log(n)).
692- ///
693- /// Elements are ordered by the [compare] function applied to the result of
694- /// the [keyOf] function. For a stable sort, use [mergeSortBy] .
695- void quickSortBy <E , K >(
696- List <E > elements,
697- K Function (E element) keyOf,
698- int Function (K a, K b) compare, [
699- int start = 0 ,
700- int ? end,
701- ]) {
702- end = RangeError .checkValidRange (start, end, elements.length);
703- if (end - start < 2 ) return ;
704- _pdqSortByImpl (elements, keyOf, compare, start, end, _log2 (end - start));
705- }
706-
707- /// Minimum list size below which pdqsort uses insertion sort.
708- const int _pdqInsertionSortThreshold = 24 ;
706+ // ==========================================
707+ // Implementation: Keyed Comparison (By)
708+ // ==========================================
709709
710- /// Computes the base-2 logarithm of [n] .
711- /// Computes the base-2 logarithm of [n] .
712- ///
713- /// Uses bitLength to compute the floor(log2(n)) efficiently. For n == 0
714- /// we return 0.
715- int _log2 (int n) => n > 0 ? n.bitLength - 1 : 0 ;
716-
717- /// The core implementation of Pattern-defeating Quicksort.
718- ///
719710/// [badAllowed] tracks how many bad pivot selections are allowed before
720711/// falling back to heap sort.
721712void _pdqSortByImpl <E , K >(List <E > elements, K Function (E ) keyOf,
0 commit comments