go-hep.org/x/hep@v0.38.1/fastjet/internal/heap/heap_test.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package heap 6 7 import ( 8 "container/heap" 9 "math/rand" 10 "testing" 11 ) 12 13 // FIXME B/op is higher here, than for PQ 14 func BenchmarkHeap(b *testing.B) { 15 var items []*pair 16 for range 5000 { 17 jeti := rand.Int() 18 jetj := rand.Int() 19 dij := rand.Float64() 20 items = append(items, &pair{jeti: jeti, jetj: jetj, dij: dij}) 21 } 22 b.ResetTimer() 23 b.ReportAllocs() 24 for i := 0; i < b.N; i++ { 25 h := New() 26 for _, item := range items { 27 h.Push(item.jeti, item.jetj, item.dij) 28 } 29 for !h.IsEmpty() { 30 h.Pop() 31 } 32 } 33 } 34 35 func BenchmarkPQ(b *testing.B) { 36 var items []*pair 37 for range 5000 { 38 jeti := rand.Int() 39 jetj := rand.Int() 40 dij := rand.Float64() 41 items = append(items, &pair{jeti: jeti, jetj: jetj, dij: dij}) 42 } 43 b.ResetTimer() 44 b.ReportAllocs() 45 for i := 0; i < b.N; i++ { 46 var pq PQ 47 heap.Init(&pq) 48 for _, item := range items { 49 heap.Push(&pq, item) 50 } 51 for pq.Len() > 0 { 52 heap.Pop(&pq) 53 } 54 } 55 } 56 57 func TestHeapPush(t *testing.T) { 58 h := New() 59 h.Push(0, 1, 10) 60 h.Push(2, 3, 5) 61 h.Push(4, 5, 8) 62 h.Push(6, 7, 2) 63 want := []struct { 64 jeti, jetj int 65 dij float64 66 }{ 67 {-1, -1, 0}, 68 {6, 7, 2}, 69 {2, 3, 5}, 70 {4, 5, 8}, 71 {0, 1, 10}, 72 } 73 got := h.items 74 if len(got) != len(want) { 75 t.Errorf("got = %d items, want = %d", len(got), len(want)) 76 } 77 for i, pair := range got { 78 if i == 0 { 79 continue 80 } 81 if pair.jeti != want[i].jeti { 82 t.Errorf("h.items[%d].jeti: got = %d, want = %d", i, pair.jeti, want[i].jeti) 83 } 84 if pair.jetj != want[i].jetj { 85 t.Errorf("h.items[%d].jetj: got = %d, want = %d", i, pair.jetj, want[i].jetj) 86 } 87 if pair.dij != want[i].dij { 88 t.Errorf("h.items[%d].dij: got = %f, want = %f", i, pair.dij, want[i].dij) 89 } 90 } 91 } 92 93 func TestHeapPop(t *testing.T) { 94 pairs := []pair{{}, {jeti: 6, jetj: 7, dij: 2}, {jeti: 2, jetj: 3, dij: 5}, {jeti: 4, jetj: 5, dij: 8}, 95 {jeti: 0, jetj: 1, dij: 10}, {jeti: 8, jetj: 9, dij: 6}, 96 } 97 h := &Heap{items: pairs, n: 5} 98 want := []struct { 99 jeti, jetj int 100 dij float64 101 }{ 102 {6, 7, 2}, 103 {2, 3, 5}, 104 {8, 9, 6}, 105 {4, 5, 8}, 106 {0, 1, 10}, 107 } 108 got := make([]struct { 109 jeti, jetj int 110 dij float64 111 }, len(pairs)-1) 112 for i := 0; !h.IsEmpty(); i++ { 113 if i >= len(got) { 114 t.Fatalf("Heap with n = %d should be empty", h.n) 115 } 116 jeti, jetj, dij := h.Pop() 117 got[i].jeti = jeti 118 got[i].jetj = jetj 119 got[i].dij = dij 120 } 121 if len(got) != len(want) { 122 t.Errorf("got = %d items, want = %d", len(got), len(want)) 123 } 124 for i := range got { 125 if want[i].jeti != got[i].jeti { 126 t.Errorf("got[%d].jeti = %d, want[%d].jeti = %d", i, got[i].jeti, i, want[i].jeti) 127 } 128 if want[i].jetj != got[i].jetj { 129 t.Errorf("got[%d].jetj = %d, want[%d].jetj = %d", i, got[i].jetj, i, want[i].jetj) 130 } 131 if want[i].dij != got[i].dij { 132 t.Errorf("got[%d] = %f, want[%d] = %f", i, got[i].dij, i, want[i].dij) 133 } 134 } 135 } 136 137 // PQ is a priority queue of pairs. It is implemented using the 138 // container/heap interface. 139 type PQ []*pair 140 141 func (pq PQ) Len() int { return len(pq) } 142 143 func (pq PQ) Less(i, j int) bool { 144 return pq[i].dij < pq[j].dij 145 } 146 147 func (pq PQ) Swap(i, j int) { 148 pq[i], pq[j] = pq[j], pq[i] 149 } 150 151 func (pq *PQ) Push(x any) { 152 item := x.(*pair) 153 *pq = append(*pq, item) 154 } 155 156 func (pq *PQ) Pop() any { 157 old := *pq 158 n := len(old) 159 item := old[n-1] 160 *pq = old[0 : n-1] 161 return item 162 }