LCOV - code coverage report
Current view: top level - src/utility - LG_qsort_template.h (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: 3b461aa. Current time (UTC): 2024-01-25T16:04:32Z Lines: 23 23 100.0 %
Date: 2024-01-25 16:05:28 Functions: 6 6 100.0 %

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LG_qsort_template: quicksort of a K-by-n array
       3             : //------------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
       6             : // SPDX-License-Identifier: BSD-2-Clause
       7             : //
       8             : // For additional details (including references to third party source code and
       9             : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See
      10             : // Contributors.txt for a full list of contributors. Created, in part, with
      11             : // funding and support from the U.S. Government (see Acknowledgments.txt file).
      12             : // DM22-0790
      13             : 
      14             : // Contributed by Timothy A. Davis, Texas A&M University
      15             : 
      16             : //------------------------------------------------------------------------------
      17             : 
      18             : // This file is #include'd in LG_qsort*.c to create specific versions for
      19             : // different kinds of sort keys and auxiliary arrays.  Requires an inline or
      20             : // macro definition of the LG_lt function.  The LG_lt function has the form
      21             : // LG_lt (A,i,B,j) and returns true if A[i] < B[j].
      22             : 
      23             : // All of these functions are static; there will be versions of them in each
      24             : // variant of LG_qsort*, and given unique names via #define's in the
      25             : // #include'ing file.
      26             : 
      27             : //------------------------------------------------------------------------------
      28             : // LG_partition: use a pivot to partition an array
      29             : //------------------------------------------------------------------------------
      30             : 
      31             : // C.A.R Hoare partition method, partitions an array in-place via a pivot.
      32             : // k = partition (A, n) partitions A [0:n-1] such that all entries in
      33             : // A [0:k] are <= all entries in A [k+1:n-1].
      34             : 
      35      526786 : static inline int64_t LG_partition
      36             : (
      37             :     LG_args (A),            // array(s) to partition
      38             :     const int64_t n,        // size of the array(s) to partition
      39             :     uint64_t *seed,         // random number seed, modified on output
      40             :     LG_void *tx
      41             : )
      42             : {
      43             : 
      44             :     // select a pivot at random
      45      526786 :     int64_t pivot = ((n < LG_RANDOM15_MAX) ?
      46      526786 :         LG_Random15 (seed) : LG_Random60 (seed)) % n ;
      47             : 
      48             :     // get the Pivot
      49      526786 :     int64_t Pivot_0 [1] ; Pivot_0 [0] = A_0 [pivot] ;
      50             :     #if LG_K > 1
      51      423972 :     int64_t Pivot_1 [1] ; Pivot_1 [0] = A_1 [pivot] ;
      52             :     #endif
      53             :     #if LG_K > 2
      54      112526 :     int64_t Pivot_2 [1] ; Pivot_2 [0] = A_2 [pivot] ;
      55             :     #endif
      56             : 
      57             :     // At the top of the while loop, A [left+1...right-1] is considered, and
      58             :     // entries outside this range are in their proper place and not touched.
      59             :     // Since the input specification of this function is to partition A
      60             :     // [0..n-1], left must start at -1 and right must start at n.
      61      526786 :     int64_t left = -1 ;
      62      526786 :     int64_t right = n ;
      63             : 
      64             :     // keep partitioning until the left and right sides meet
      65    13413610 :     while (true)
      66             :     {
      67             :         // loop invariant:  A [0..left] < pivot and A [right..n-1] > pivot,
      68             :         // so the region to be considered is A [left+1 ... right-1].
      69             : 
      70             :         // increment left until finding an entry A [left] >= pivot
      71    39729138 :         do { left++ ; } while (LG_lt (A, left, Pivot, 0)) ;
      72             : 
      73             :         // decrement right until finding an entry A [right] <= pivot
      74    41263801 :         do { right-- ; } while (LG_lt (Pivot, 0, A, right)) ;
      75             : 
      76             :         // now A [0..left-1] < pivot and A [right+1..n-1] > pivot, but
      77             :         // A [left] > pivot and A [right] < pivot, so these two entries
      78             :         // are out of place and must be swapped.
      79             : 
      80             :         // However, if the two sides have met, the partition is finished.
      81    13940396 :         if (left >= right)
      82             :         {
      83             :             // A has been partitioned into A [0:right] and A [right+1:n-1].
      84             :             // k = right+1, so A is split into A [0:k-1] and A [k:n-1].
      85      526786 :             return (right + 1) ;
      86             :         }
      87             : 
      88             :         // since A [left] > pivot and A [right] < pivot, swap them
      89    13413610 :         LG_swap (A, left, right) ;
      90             : 
      91             :         // after the swap this condition holds:
      92             :         // A [0..left] < pivot and A [right..n-1] > pivot
      93             :     }
      94             : }
      95             : 
      96             : //------------------------------------------------------------------------------
      97             : // LG_quicksort: recursive single-threaded quicksort
      98             : //------------------------------------------------------------------------------
      99             : 
     100     1055716 : static void LG_quicksort    // sort A [0:n-1]
     101             : (
     102             :     LG_args (A),            // array(s) to sort
     103             :     const int64_t n,        // size of the array(s) to sort
     104             :     uint64_t *seed,         // random number seed
     105             :     LG_void *tx
     106             : )
     107             : {
     108             : 
     109     1055716 :     if (n < 20)
     110             :     {
     111             :         // in-place insertion sort on A [0:n-1], where n is small
     112     5852040 :         for (int64_t k = 1 ; k < n ; k++)
     113             :         {
     114    13505041 :             for (int64_t j = k ; j > 0 && LG_lt (A, j, A, j-1) ; j--)
     115             :             {
     116             :                 // swap A [j-1] and A [j]
     117     8181931 :                 LG_swap (A, j-1, j) ;
     118             :             }
     119             :         }
     120             :     }
     121             :     else
     122             :     {
     123             :         // partition A [0:n-1] into A [0:k-1] and A [k:n-1]
     124      526786 :         int64_t k = LG_partition (LG_arg (A), n, seed, tx) ;
     125             : 
     126             :         // sort each partition
     127      526786 :         LG_quicksort (LG_arg (A), k, seed, tx) ;             // sort A [0:k-1]
     128      526786 :         LG_quicksort (LG_arg_offset (A, k), n-k, seed, tx) ; // sort A [k+1:n-1]
     129             :     }
     130     1055716 : }

Generated by: LCOV version 1.14