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  }