Commit dc6556cd authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent e81232be
...@@ -222,14 +222,19 @@ func TestSetGet0(t *testing.T) { ...@@ -222,14 +222,19 @@ func TestSetGet0(t *testing.T) {
} }
func TestSetGet1(t *testing.T) { func TestSetGet1(t *testing.T) {
const N = 40000 //const N = 40000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} { //const N = 21
const N = 41
//for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} {
//for _, x := range []int{0x314159} {
for _, x := range []int{0} {
r := TreeNew(cmp) r := TreeNew(cmp)
set := r.Set set := r.Set
a := make([]int, N) a := make([]int, N)
for i := range a { for i := range a {
a[i] = (i ^ x) << 1 a[i] = (i ^ x) << 1
} }
dbg("", a)
for i, k := range a { for i, k := range a {
set(k, k^x) set(k, k^x)
if g, e := r.Len(), i+1; g != e { if g, e := r.Len(), i+1; g != e {
...@@ -266,7 +271,7 @@ func TestSetGet1(t *testing.T) { ...@@ -266,7 +271,7 @@ func TestSetGet1(t *testing.T) {
} }
if g, e := v.(int), k^x+42; g != e { if g, e := v.(int), k^x+42; g != e {
t.Fatal(i, g, e) t.Fatal(i, g, e) // XXX bug here
} }
k |= 1 k |= 1
......
...@@ -41,6 +41,7 @@ func (p *btTpool) get(cmp Cmp) *Tree { ...@@ -41,6 +41,7 @@ func (p *btTpool) get(cmp Cmp) *Tree {
x.cmp = cmp x.cmp = cmp
x.hitIdx = -1 x.hitIdx = -1
x.hitPi = -1 x.hitPi = -1
x.hitMaxKInf = true
return x return x
} }
...@@ -106,6 +107,9 @@ type ( ...@@ -106,6 +107,9 @@ type (
hitIdx int hitIdx int
hitP *x hitP *x
hitPi int hitPi int
hitMaxK interface{} /*K*/
hitMaxKInf bool // whether hitMaxK = ∞
} }
xe struct { // x element xe struct { // x element
...@@ -435,8 +439,12 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) { ...@@ -435,8 +439,12 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) {
switch cmp := t.cmp(k, hit.d[i].k); { switch cmp := t.cmp(k, hit.d[i].k); {
case cmp > 0: case cmp > 0:
// in hit range: < p.k (which is ∞ when pi == p.c) // // in hit range: < p.k (which is ∞ when pi == p.c)
if p != nil && pi < p.c && t.cmp(k, p.x[pi].k) >= 0 { // if p != nil && pi < p.c && t.cmp(k, p.x[pi].k) >= 0 {
// return -1, false
// }
if !(t.hitMaxKInf || t.cmp(k, t.hitMaxK) < 0) {
return -1, false return -1, false
} }
...@@ -626,36 +634,37 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) { ...@@ -626,36 +634,37 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
// Set sets the value associated with k. // Set sets the value associated with k.
func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
//dbg("--- PRE Set(%v, %v)\t(%v @%d, %v @%d)\n%s", k, v, t.hit, t.hitIdx, t.hitP, t.hitPi, t.dump()) dbg("--- PRE Set(%v, %v)\t(%v @%d, %v/%v, %v @%d)\n%s", k, v, t.hit, t.hitIdx, t.hitMaxKInf, t.hitMaxK, t.hitP, t.hitPi, t.dump())
//defer func() { defer func() {
// //if r := recover(); r != nil { //if r := recover(); r != nil {
// // panic(r) // panic(r)
// //} //}
// dbg("--- POST\n%s\n====\n", t.dump()) dbg("--- POST\n%s\n====\n", t.dump())
//}() }()
// check if we can do the update nearby previous change // check if we can do the update nearby previous change
i, ok := t.hitFind(k) i, ok := t.hitFind(k)
if i >= 0 { if i >= 0 {
//dbg("hit found\t-> %d, %v", i, ok) //dbg("hit found\t-> %d, %v", i, ok)
dd, p, pi := t.hit, t.hitP, t.hitPi //dd, p, pi := t.hit, t.hitP, t.hitPi
dd := t.hit
switch { switch {
case ok: case ok:
//dbg("ok'") dbg("ok'")
dd.d[i].v = v dd.d[i].v = v
t.hitIdx = i t.hitIdx = i
return return
case dd.c < 2*kd: case dd.c < 2*kd:
//dbg("insert'") dbg("insert'")
t.insert(dd, i, k, v) t.insert(dd, i, k, v)
return return
case p == nil || p.c <= 2*kx: //case p == nil || p.c <= 2*kx:
//dbg("overflow'") // dbg("overflow'")
t.overflow(p, dd, pi, i, k, v) // t.overflow(p, dd, pi, i, k, v)
return // return
default: default:
// here: need to overflow but p.c > 2*kx -> need to do // here: need to overflow but p.c > 2*kx -> need to do
...@@ -669,12 +678,15 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { ...@@ -669,12 +678,15 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
q := t.r q := t.r
if q == nil { if q == nil {
//dbg("empty") dbg("empty")
z := t.insert(btDPool.Get().(*d), 0, k, v) // XXX update hit z := t.insert(btDPool.Get().(*d), 0, k, v) // XXX update hit
t.r, t.first, t.last = z, z, z t.r, t.first, t.last = z, z, z
return return
} }
var maxK interface{} /*K*/ // XXX max key limiting found hit range
maxKInf := true // if there will be no limiting factors ... XXX
for { for {
i, ok = t.find(q, k) i, ok = t.find(q, k)
switch x := q.(type) { switch x := q.(type) {
...@@ -682,32 +694,47 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { ...@@ -682,32 +694,47 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
if x.c > 2*kx { if x.c > 2*kx {
x, i = t.splitX(p, x, pi, i) x, i = t.splitX(p, x, pi, i)
} }
p = x
if ok { if ok {
pi = i + 1 pi = i + 1
q = x.x[i+1].ch
} else { } else {
pi = i pi = i
q = x.x[i].ch }
p = x
q = p.x[pi].ch
if pi < p.c {
maxK = p.x[pi].k
maxKInf = false
}
if maxK != nil && maxKInf {
dbg("", pi, maxK)
panic(maxK)
} }
case *d: case *d:
// data page found - perform the update // data page found - perform the update
switch { switch {
case ok: case ok:
//dbg("ok") dbg("ok")
x.d[i].v = v x.d[i].v = v
t.hit, t.hitIdx = x, i t.hit, t.hitIdx = x, i
t.hitP, t.hitPi = p, pi t.hitP, t.hitPi = p, pi
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
case x.c < 2*kd: case x.c < 2*kd:
//dbg("insert") dbg("insert")
t.insert(x, i, k, v) t.insert(x, i, k, v)
t.hitP, t.hitPi = p, pi t.hitP, t.hitPi = p, pi
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
default: default:
//dbg("overflow") dbg("overflow")
t.overflow(p, x, pi, i, k, v) t.overflow(p, x, pi, i, k, v)
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
} }
return return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment