github.com/puellanivis/breton@v0.2.16/lib/sort/sort_test.go (about)

     1  package sort
     2  
     3  import (
     4  	"crypto/rand"
     5  	"fmt"
     6  	"sort"
     7  	"sync"
     8  	"testing"
     9  )
    10  
    11  func TestInt32s(t *testing.T) {
    12  	qsortInstead = qsortNever
    13  
    14  	l := []int32{42, 5, 7, 2, 3}
    15  
    16  	if Int32sAreSorted(l) {
    17  		t.Error("unsorted int32 list reports as sorted")
    18  	}
    19  
    20  	Int32s(l)
    21  
    22  	if !Int32sAreSorted(l) {
    23  		t.Error("after sorting int32 list reports as not sorted")
    24  		t.Error("Got:", l)
    25  	}
    26  
    27  	if SearchInt32s(l, 42) != 4 {
    28  		t.Error("binary search failed for int32 list")
    29  	}
    30  }
    31  
    32  func TestReverseInt32s(t *testing.T) {
    33  	qsortInstead = qsortNever
    34  
    35  	a := []int32{42, 5, 7, 2, 3}
    36  	l := Reverse(a)
    37  
    38  	if IsSorted(l) {
    39  		t.Error("unsorted reverse int32 list reports as sorted")
    40  	}
    41  
    42  	Sort(l)
    43  
    44  	if !IsSorted(l) {
    45  		t.Error("after reverse sorting int32 list reports as not sorted")
    46  		t.Error("Got:", l)
    47  	}
    48  
    49  	if got := SearchFor(l, int32(42)); got != 0 {
    50  		t.Errorf("binary search failed for reversed int32 list got %d wanted 0", got)
    51  	}
    52  }
    53  
    54  func TestInt64s(t *testing.T) {
    55  	qsortInstead = qsortNever
    56  
    57  	l := []int64{42, 5, 7, 2, 3}
    58  
    59  	if Int64sAreSorted(l) {
    60  		t.Error("unsorted int64 list reports as sorted")
    61  	}
    62  
    63  	Sort(l)
    64  
    65  	if !Int64sAreSorted(l) {
    66  		t.Error("after sorting int64 list reports as not sorted")
    67  		t.Error("Got:", l)
    68  	}
    69  
    70  	if SearchInt64s(l, 42) != 4 {
    71  		t.Error("binary search failed for int64 list")
    72  	}
    73  }
    74  
    75  var benchIntArray = make([][]int, 5)
    76  var benchIntOnce = make([]sync.Once, len(benchIntArray))
    77  
    78  const (
    79  	//benchSize = 1000
    80  	benchSize = 10000000
    81  )
    82  
    83  func initIntBench(n int) {
    84  	// bit width here is set to ceil(log_2(benchSize)) - n
    85  	// With a larger bit width, there will be more recursions based on radi than for quicksort (i.e. log n).
    86  	// So, the “intelligent” Radix implementation will often switch to using sort.qsort.
    87  	//
    88  	// Quick rundown of pure radix, vs “intelligent” Radix, and sort.Sort:
    89  	// 	n < 1:     pure radix sort is slower; “intelligent” Radix will almost always pick sort.qsort.
    90  	//	n > 3:     pure radix sort is faster; “intelligent” Radix will almost never pick sort.qsort.
    91  	// 	n = 2:     all three run in around the same, and picking one or the other is a wash.
    92  	//      otherwise: “intelligent” Radix will either pick sort.qsort too much or not enough,
    93  	//			so, results end up super non-deterministic, but either n = 1 sucks, or n = 3 does.
    94  	log := (maxDepth(benchSize) / 2) - n
    95  	width := log/8 + 1
    96  	mask := byte(0xff) >> (uint(8 - (log % 8)))
    97  	if width < 2 {
    98  		width = 2
    99  	}
   100  	fmt.Printf("using a slice of len %d\n", benchSize)
   101  	fmt.Printf("n = %d is using %d bits << %d\n", n, log, uintMSB-log)
   102  	b := make([]byte, width)
   103  
   104  	for i := 0; i < benchSize; i++ {
   105  		_, err := rand.Read(b)
   106  		if err != nil {
   107  			panic(err)
   108  		}
   109  
   110  		val := int(b[0] & mask)
   111  
   112  		for j := 1; j < len(b); j++ {
   113  			val <<= 8
   114  			val |= int(b[j])
   115  		}
   116  
   117  		/* if b[0] & 0x80 != 0 {
   118  			val = -val
   119  		} //*/
   120  
   121  		benchIntArray[n] = append(benchIntArray[n], (val<<uint(uintMSB-log))|0x10)
   122  	}
   123  }
   124  
   125  func benchmarkIntAllRadixSort(b *testing.B, n int) {
   126  	b.StopTimer()
   127  	benchIntOnce[n].Do(func() { initIntBench(n) })
   128  
   129  	qsortInstead = qsortNever
   130  
   131  	buf := make([]int, len(benchIntArray[n]))
   132  
   133  	for i := 0; i < b.N; i++ {
   134  		copy(buf, benchIntArray[n])
   135  
   136  		b.StartTimer()
   137  		Ints(buf)
   138  		b.StopTimer()
   139  
   140  		if !IntsAreSorted(buf) {
   141  			b.Fatal("sorting failed!")
   142  		}
   143  	}
   144  }
   145  
   146  func BenchmarkIntAllRadixSort0(b *testing.B) {
   147  	benchmarkIntAllRadixSort(b, 0)
   148  }
   149  func BenchmarkIntAllRadixSort1(b *testing.B) {
   150  	benchmarkIntAllRadixSort(b, 1)
   151  }
   152  func BenchmarkIntAllRadixSort2(b *testing.B) {
   153  	benchmarkIntAllRadixSort(b, 2)
   154  }
   155  func BenchmarkIntAllRadixSort3(b *testing.B) {
   156  	benchmarkIntAllRadixSort(b, 3)
   157  }
   158  func BenchmarkIntAllRadixSort4(b *testing.B) {
   159  	benchmarkIntAllRadixSort(b, 4)
   160  }
   161  
   162  func benchmarkIntRadixSort(b *testing.B, n int) {
   163  	b.StopTimer()
   164  	benchIntOnce[n].Do(func() { initIntBench(n) })
   165  
   166  	qsortInstead = qsortSometimes
   167  
   168  	buf := make([]int, len(benchIntArray[n]))
   169  
   170  	for i := 0; i < b.N; i++ {
   171  		copy(buf, benchIntArray[n])
   172  
   173  		b.StartTimer()
   174  		Ints(buf)
   175  		b.StopTimer()
   176  
   177  		if !IntsAreSorted(buf) {
   178  			b.Fatal("sorting failed!")
   179  		}
   180  	}
   181  }
   182  
   183  func BenchmarkIntRadixSort0(b *testing.B) {
   184  	benchmarkIntRadixSort(b, 0)
   185  }
   186  func BenchmarkIntRadixSort1(b *testing.B) {
   187  	benchmarkIntRadixSort(b, 1)
   188  }
   189  func BenchmarkIntRadixSort2(b *testing.B) {
   190  	benchmarkIntRadixSort(b, 2)
   191  }
   192  func BenchmarkIntRadixSort3(b *testing.B) {
   193  	benchmarkIntRadixSort(b, 3)
   194  }
   195  func BenchmarkIntRadixSort4(b *testing.B) {
   196  	benchmarkIntRadixSort(b, 4)
   197  }
   198  
   199  func benchmarkIntOriginalSort(b *testing.B, n int) {
   200  	b.StopTimer()
   201  	benchIntOnce[n].Do(func() { initIntBench(n) })
   202  
   203  	buf := make(IntSlice, len(benchIntArray[n]))
   204  
   205  	for i := 0; i < b.N; i++ {
   206  		copy(buf, benchIntArray[n])
   207  
   208  		b.StartTimer()
   209  		sort.Sort(buf)
   210  		b.StopTimer()
   211  
   212  		if !IntsAreSorted(buf) {
   213  			b.Fatal("sorting failed!")
   214  		}
   215  	}
   216  }
   217  
   218  func BenchmarkIntOriginalSort0(b *testing.B) {
   219  	benchmarkIntOriginalSort(b, 0)
   220  }
   221  func BenchmarkIntOriginalSort1(b *testing.B) {
   222  	benchmarkIntOriginalSort(b, 1)
   223  }
   224  func BenchmarkIntOriginalSort2(b *testing.B) {
   225  	benchmarkIntOriginalSort(b, 2)
   226  }
   227  func BenchmarkIntOriginalSort3(b *testing.B) {
   228  	benchmarkIntOriginalSort(b, 3)
   229  }
   230  func BenchmarkIntOriginalSort4(b *testing.B) {
   231  	benchmarkIntOriginalSort(b, 4)
   232  }