// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: MIT package integrate import ( "math" "testing" ) // cubHeapPop takes the heap's head the way IntegrateND does: the last // box replaces the root and sifts down. func cubHeapPop(h []*cubBox) ([]*cubBox, *cubBox) { top := h[0] last := len(h) - 1 h[0] = h[last] h[last] = nil h = h[:last] if last > 0 { cubSiftDown(h) } return h, top } // TestCubatureBoxHeapOrder pins the order the box heap pops in, the // substance of the heap replacing the linear scan: the largest finite // estimate first, the earliest insertion among equals, and a // non-finite estimate, which only an overflowed measure produces, // below every finite one. func TestCubatureBoxHeapOrder(t *testing.T) { t.Run("larger estimate first", func(t *testing.T) { h := []*cubBox{{est: 5, seq: 1}, {est: 1, seq: 2}, {est: math.NaN(), seq: 3}, {est: 3, seq: 4}} for i := range h { cubSiftUp(h[:i+1]) } for _, want := range []float64{5, 3, 1} { var top *cubBox h, top = cubHeapPop(h) if top.est != want { t.Fatalf("popped estimate %v, want %v", top.est, want) } } if h[0].est == h[0].est { t.Fatalf("a finite estimate %v survived before the non-finite one", h[0].est) } }) t.Run("earliest insertion among equals", func(t *testing.T) { h := []*cubBox{{est: 2, seq: 2}, {est: 2, seq: 0}, {est: 2, seq: 3}, {est: 2, seq: 1}} for i := range h { cubSiftUp(h[:i+1]) } for _, want := range []int{0, 1, 2, 3} { var top *cubBox h, top = cubHeapPop(h) if top.seq != want { t.Fatalf("popped insertion %d, want %d", top.seq, want) } } }) t.Run("interleaved push and pop", func(t *testing.T) { h := []*cubBox{{est: 5, seq: 0}} for _, b := range []*cubBox{{est: 7, seq: 1}, {est: 6, seq: 2}} { h = append(h, b) cubSiftUp(h) } var top *cubBox h, top = cubHeapPop(h) if top.est != 7 { t.Fatalf("popped estimate %v, want 7", top.est) } h = append(h, &cubBox{est: 4, seq: 3}) cubSiftUp(h) h, top = cubHeapPop(h) if top.est != 6 { t.Fatalf("popped estimate %v, want 6", top.est) } h, top = cubHeapPop(h) if top.est != 5 { t.Fatalf("popped estimate %v, want 5", top.est) } }) t.Run("overflowed estimates sort below every finite one", func(t *testing.T) { // An overflowed measure can carry +Inf, and a corrupted one a // NaN: both belong at the bottom of the heap, and the insertion // order holds between them. h := []*cubBox{ {est: math.Inf(1), seq: 0}, {est: 2, seq: 1}, {est: math.NaN(), seq: 2}, {est: 4, seq: 3}, {est: math.Inf(-1), seq: 4}, {est: 3, seq: 5}, } for i := range h { cubSiftUp(h[:i+1]) } for _, want := range []float64{4, 3, 2} { var top *cubBox h, top = cubHeapPop(h) if top.est != want { t.Fatalf("popped estimate %v, want %v", top.est, want) } } for _, want := range []int{0, 2, 4} { var top *cubBox h, top = cubHeapPop(h) if top.seq != want { t.Fatalf("popped insertion %d, want %d", top.seq, want) } } }) }