func (t *SecondaryTree) Delete(k generic.U) (ok bool) {
	pi := -1
	var p *x2
	q := t.r
	if q == nil {
		return false
	}
	for {
		var i int
		i, ok = t.find(q, k)
		if ok {
			switch x := q.(type) {
			case *x2:
				if x.c < kx2 && q != t.r {
					x, i = t.underflowX(p, x, pi, i)
				}
				pi = i + 1
				p = x
				q = x.x[pi].ch
				ok = false
				continue
			case *d2:
				t.extract(x, i)
				if x.c >= kd2 {
					return true
				}
				if q != t.r {
					t.underflow(p, x, pi)
				} else if t.c == 0 {
					t.Clear()
				}
				return true
			}
		}
		switch x := q.(type) {
		case *x2:
			if x.c < kx2 && q != t.r {
				x, i = t.underflowX(p, x, pi, i)
			}
			pi = i
			p = x
			q = x.x[i].ch
		case *d2:
			return false
		}
	}
}
Delete removes the k's KV pair, if it exists, in which case Delete returns
true.
package btree2d
import (
	"fmt"
	"io"
	"sync"
	"sync/atomic"
	"github.com/joeshaw/gengen/generic"
)
const (
	kx2 = 64  
	kd2 = 64  
)
func init() {
	if kd2 < 1 {
		panic(fmt.Errorf("kd2 %d: out of range", kd2))
	}
	if kx2 < 2 {
		panic(fmt.Errorf("kx2 %d: out of range", kx2))
	}
}
var (
	btDPool2 = sync.Pool{New: func() interface{} { return &d2{} }}
	btEPool2 = btEpool2{sync.Pool{New: func() interface{} { return &SecondaryEnumerator{} }}}
	btTPool2 = btTpool2{sync.Pool{New: func() interface{} { return &SecondaryTree{} }}}
	btXPool2 = sync.Pool{New: func() interface{} { return &x2{} }}
)
type btTpool2 struct{ sync.Pool }
func (p *btTpool2) get(cmp SecondaryCmpFunc) *SecondaryTree {
	x := p.Get().(*SecondaryTree)
	x.cmp = cmp
	return x
}
type btEpool2 struct{ sync.Pool }
func (p *btEpool2) get(err error, hit bool, i int, k generic.U, q *d2, t *SecondaryTree, ver uint64) *SecondaryEnumerator {
	x := p.Get().(*SecondaryEnumerator)
	x.err, x.hit, x.i, x.k, x.q, x.t, x.ver = err, hit, i, k, q, t, ver
	return x
}
type (
	d2 struct {  
		c int
		d [2*kd2 + 1]de2
		n *d2
		p *d2
	}
	de2 struct {  
		k generic.U
		v *FinalizerList
	}
	SecondaryEnumerator struct {
		err error
		hit bool
		i   int
		k   generic.U
		q   *d2
		t   *SecondaryTree
		ver uint64
	}
	SecondaryTree struct {
		c     int
		cmp   SecondaryCmpFunc
		first *d2
		last  *d2
		r     interface{}
		ver   uint64
	}
	xe2 struct {  
		ch interface{}
		k  generic.U
	}
	x2 struct {  
		c int
		x [2*kx2 + 2]xe2
	}
)
var (  
	zd2  d2
	zde2 de2
	ze2  SecondaryEnumerator
	zk2  generic.U
	zt2  SecondaryTree
	zx2  x2
	zxe2 xe2
)
func clr2(q interface{}) {
	switch x := q.(type) {
	case *x2:
		for i := 0; i <= x.c; i++ {  
			clr2(x.x[i].ch)
		}
		*x = zx2
		btXPool2.Put(x)
	case *d2:
		*x = zd2
		btDPool2.Put(x)
	}
}
func newX2(ch0 interface{}) *x2 {
	r := btXPool2.Get().(*x2)
	r.x[0].ch = ch0
	return r
}
func (q *x2) extract(i int) {
	q.c--
	if i < q.c {
		copy(q.x[i:], q.x[i+1:q.c+1])
		q.x[q.c].ch = q.x[q.c+1].ch
		q.x[q.c].k = zk2   
		q.x[q.c+1] = zxe2  
	}
}
func (q *x2) insert(i int, k generic.U, ch interface{}) *x2 {
	c := q.c
	if i < c {
		q.x[c+1].ch = q.x[c].ch
		copy(q.x[i+2:], q.x[i+1:c])
		q.x[i+1].k = q.x[i].k
	}
	c++
	q.c = c
	q.x[i].k = k
	q.x[i+1].ch = ch
	return q
}
func (q *x2) siblings(i int) (l, r *d2) {
	if i >= 0 {
		if i > 0 {
			l = q.x[i-1].ch.(*d2)
		}
		if i < q.c {
			r = q.x[i+1].ch.(*d2)
		}
	}
	return
}
func (l *d2) mvL(r *d2, c int) {
	copy(l.d[l.c:], r.d[:c])
	copy(r.d[:], r.d[c:r.c])
	l.c += c
	r.c -= c
}
func (l *d2) mvR(r *d2, c int) {
	copy(r.d[c:], r.d[:r.c])
	copy(r.d[:c], l.d[l.c-c:])
	r.c += c
	l.c -= c
}
func NewSecondaryTree(cmp SecondaryCmpFunc) *SecondaryTree {
	return btTPool2.get(cmp)
}
func (t *SecondaryTree) Clear() {
	if t.r == nil {
		return
	}
	clr2(t.r)
	t.c, t.first, t.last, t.r = 0, nil, nil, nil
	atomic.AddUint64(&t.ver, 1)
}
func (t *SecondaryTree) Close() {
	t.Clear()
	*t = zt2
	btTPool2.Put(t)
}
func (t *SecondaryTree) cat(p *x2, q, r *d2, pi int) {
	atomic.AddUint64(&t.ver, 1)
	q.mvL(r, r.c)
	if r.n != nil {
		r.n.p = q
	} else {
		t.last = q
	}
	q.n = r.n
	*r = zd2
	btDPool2.Put(r)
	if p.c > 1 {
		p.extract(pi)
		p.x[pi].ch = q
		return
	}
	switch x := t.r.(type) {
	case *x2:
		*x = zx2
		btXPool2.Put(x)
	case *d2:
		*x = zd2
		btDPool2.Put(x)
	}
	t.r = q
}
func (t *SecondaryTree) catX(p, q, r *x2, pi int) {
	atomic.AddUint64(&t.ver, 1)
	q.x[q.c].k = p.x[pi].k
	copy(q.x[q.c+1:], r.x[:r.c])
	q.c += r.c + 1
	q.x[q.c].ch = r.x[r.c].ch
	*r = zx2
	btXPool2.Put(r)
	if p.c > 1 {
		p.c--
		pc := p.c
		if pi < pc {
			p.x[pi].k = p.x[pi+1].k
			copy(p.x[pi+1:], p.x[pi+2:pc+1])
			p.x[pc].ch = p.x[pc+1].ch
			p.x[pc].k = zk2     
			p.x[pc+1].ch = nil  
		}
		return
	}
	switch x := t.r.(type) {
	case *x2:
		*x = zx2
		btXPool2.Put(x)
	case *d2:
		*x = zd2
		btDPool2.Put(x)
	}
	t.r = q
}