github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/sentinels/partition.go (about)

     1  package sentinels
     2  
     3  // requires -gcflags="-B" to be effective
     4  func PartitionBreak(items []int, pivot int) int {
     5  	items[pivot], items[0] = items[0], items[pivot]
     6  	lo, hi := 1, len(items)-1
     7  loop:
     8  	for ; ; lo, hi = lo+1, hi-1 {
     9  		for ; ; lo++ {
    10  			if lo > hi {
    11  				break loop
    12  			}
    13  			if items[lo] >= items[0] {
    14  				break
    15  			}
    16  		}
    17  		for ; ; hi-- {
    18  			if lo >= hi {
    19  				break loop
    20  			}
    21  			if items[0] >= items[hi] {
    22  				break
    23  			}
    24  		}
    25  		items[hi], items[lo] = items[lo], items[hi]
    26  	}
    27  	lo--
    28  	items[lo], items[0] = items[0], items[lo]
    29  	return lo
    30  }
    31  
    32  // requires -gcflags="-B" to be effective
    33  func PartitionSentinel(items []int, pivot int) int {
    34  	if len(items) <= 1 {
    35  		return 0
    36  	}
    37  	items[pivot], items[0] = items[0], items[pivot]
    38  
    39  	pv, save := items[0], items[0]
    40  	save, items[len(items)-1] = items[len(items)-1], save
    41  
    42  	lo, hi := 0, len(items)-1
    43  	for {
    44  		for {
    45  			lo++
    46  			if items[lo] < pv {
    47  				break
    48  			}
    49  		}
    50  		items[hi] = items[lo]
    51  		for {
    52  			hi--
    53  			if items[hi] >= pv {
    54  				break
    55  			}
    56  		}
    57  		if lo >= hi {
    58  			break
    59  		}
    60  		items[lo] = items[hi]
    61  	}
    62  
    63  	if lo == hi+2 {
    64  		items[lo] = items[hi+1]
    65  		lo--
    66  	}
    67  	items[lo] = save
    68  	if pv < save {
    69  		lo--
    70  	}
    71  	items[lo], items[0] = items[0], items[lo]
    72  	return lo
    73  }