github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/sorts/rdxsort/uint64.go (about)

     1  package rdxsort
     2  
     3  func Uint64(arr, buf []uint64) {
     4  	if int64(len(arr)) >= int64(1<<32) {
     5  		panic("slice too large")
     6  	}
     7  	if len(arr) != len(buf) {
     8  		panic("len(arr) != len(buf)")
     9  	}
    10  
    11  	var count [8][256]uint32
    12  	for _, v := range arr {
    13  		count[0][byte(v>>(0*8))]++
    14  		count[1][byte(v>>(1*8))]++
    15  		count[2][byte(v>>(2*8))]++
    16  		count[3][byte(v>>(3*8))]++
    17  		count[4][byte(v>>(4*8))]++
    18  		count[5][byte(v>>(5*8))]++
    19  		count[6][byte(v>>(6*8))]++
    20  		count[7][byte(v>>(7*8))]++
    21  	}
    22  
    23  	var offset [8][256]uint32
    24  	for k := 1; k < 256; k++ {
    25  		offset[0][k] = offset[0][k-1] + count[0][k-1]
    26  		offset[1][k] = offset[1][k-1] + count[1][k-1]
    27  		offset[2][k] = offset[2][k-1] + count[2][k-1]
    28  		offset[3][k] = offset[3][k-1] + count[3][k-1]
    29  		offset[4][k] = offset[4][k-1] + count[4][k-1]
    30  		offset[5][k] = offset[5][k-1] + count[5][k-1]
    31  		offset[6][k] = offset[6][k-1] + count[6][k-1]
    32  		offset[7][k] = offset[7][k-1] + count[7][k-1]
    33  	}
    34  
    35  	var nonZero [8]byte
    36  	for k := range nonZero {
    37  		nz := byte(0)
    38  		for _, v := range count[k] {
    39  			if v != 0 {
    40  				nz++
    41  			}
    42  		}
    43  		nonZero[k] = nz
    44  	}
    45  
    46  	swaps := 0
    47  	src, dst := arr, buf
    48  	for k := uint8(0); k < 8; k++ {
    49  		if nonZero[k] == 1 {
    50  			continue
    51  		}
    52  		swaps++
    53  
    54  		off := &offset[k]
    55  
    56  		p := k * 8
    57  		for _, v := range src {
    58  			key := uint8(v >> p)
    59  			dst[off[key]] = v
    60  			off[key]++
    61  		}
    62  
    63  		dst, src = src, dst
    64  	}
    65  
    66  	if swaps&1 == 1 {
    67  		copy(arr, src)
    68  	}
    69  }
    70  
    71  func Uint32(arr, buf []uint32) {
    72  	if int64(len(arr)) >= int64(1<<32) {
    73  		panic("slice too large")
    74  	}
    75  	if len(arr) != len(buf) {
    76  		panic("len(arr) != len(buf)")
    77  	}
    78  
    79  	var count [4][256]uint32
    80  	for _, v := range arr {
    81  		count[0][byte(v>>(0*8))]++
    82  		count[1][byte(v>>(1*8))]++
    83  		count[2][byte(v>>(2*8))]++
    84  		count[3][byte(v>>(3*8))]++
    85  	}
    86  
    87  	var offset [4][256]uint32
    88  	for k := 1; k < 256; k++ {
    89  		offset[0][k] = offset[0][k-1] + count[0][k-1]
    90  		offset[1][k] = offset[1][k-1] + count[1][k-1]
    91  		offset[2][k] = offset[2][k-1] + count[2][k-1]
    92  		offset[3][k] = offset[3][k-1] + count[3][k-1]
    93  	}
    94  
    95  	var nonZero [4]byte
    96  	for k := range nonZero {
    97  		nz := byte(0)
    98  		for _, v := range count[k] {
    99  			if v != 0 {
   100  				nz++
   101  			}
   102  		}
   103  		nonZero[k] = nz
   104  	}
   105  
   106  	swaps := 0
   107  	src, dst := arr, buf
   108  	for k := uint8(0); k < 4; k++ {
   109  		if nonZero[k] == 1 {
   110  			continue
   111  		}
   112  		swaps++
   113  
   114  		off := &offset[k]
   115  		p := k * 8
   116  		for _, v := range src {
   117  			key := uint8(v >> p)
   118  			dst[off[key]] = v
   119  			off[key]++
   120  		}
   121  
   122  		dst, src = src, dst
   123  	}
   124  
   125  	if swaps&1 == 1 {
   126  		copy(arr, src)
   127  	}
   128  }