Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
b
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
b
Commits
84c589d6
Commit
84c589d6
authored
Apr 13, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Plain Diff
.
parents
3bddfd4e
15a07c50
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
146 additions
and
59 deletions
+146
-59
all_test.go
all_test.go
+65
-0
btree.go
btree.go
+19
-28
example/all_test.go
example/all_test.go
+49
-4
example/int.go
example/int.go
+13
-27
No files found.
all_test.go
View file @
84c589d6
...
...
@@ -407,6 +407,71 @@ func TestPrealloc(*testing.T) {
r
.
Close
()
}
func
TestSplitXOnEdge
(
t
*
testing
.
T
)
{
// verify how splitX works when splitting X for k pointing directly at split edge
tr
:=
TreeNew
(
cmp
)
// one index page with 2*kx+2 elements (last has .k=∞ so x.c=2*kx+1)
// which will splitX on next Set
for
i
:=
0
;
i
<=
(
2
*
kx
+
1
)
*
2
*
kd
;
i
++
{
// odd keys are left to be filled in second test
tr
.
Set
(
2
*
i
,
2
*
i
)
}
x0
:=
tr
.
r
.
(
*
x
)
if
x0
.
c
!=
2
*
kx
+
1
{
t
.
Fatalf
(
"x0.c: %v ; expected %v"
,
x0
.
c
,
2
*
kx
+
1
)
}
// set element with k directly at x0[kx].k
kedge
:=
2
*
(
kx
+
1
)
*
(
2
*
kd
)
if
x0
.
x
[
kx
]
.
k
!=
kedge
{
t
.
Fatalf
(
"edge key before splitX: %v ; expected %v"
,
x0
.
x
[
kx
]
.
k
,
kedge
)
}
tr
.
Set
(
kedge
,
777
)
// if splitX was wrong kedge:777 would land into wrong place with Get failing
v
,
ok
:=
tr
.
Get
(
kedge
)
if
!
(
v
==
777
&&
ok
)
{
t
.
Fatalf
(
"after splitX: Get(%v) -> %v, %v ; expected 777, true"
,
v
,
ok
)
}
// now check the same when splitted X has parent
xr
:=
tr
.
r
.
(
*
x
)
if
xr
.
c
!=
1
{
// second x comes with k=∞ with .c index
t
.
Fatalf
(
"after splitX: xr.c: %v ; expected 1"
,
xr
.
c
)
}
if
xr
.
x
[
0
]
.
ch
!=
x0
{
t
.
Fatal
(
"xr[0].ch is not x0"
)
}
for
i
:=
0
;
i
<=
(
2
*
kx
)
*
kd
;
i
++
{
tr
.
Set
(
2
*
i
+
1
,
2
*
i
+
1
)
}
// check x0 is in pre-splitX condition and still at the right place
if
x0
.
c
!=
2
*
kx
+
1
{
t
.
Fatalf
(
"x0.c: %v ; expected %v"
,
x0
.
c
,
2
*
kx
+
1
)
}
if
xr
.
x
[
0
]
.
ch
!=
x0
{
t
.
Fatal
(
"xr[0].ch is not x0"
)
}
// set element with k directly at x0[kx].k
kedge
=
(
kx
+
1
)
*
(
2
*
kd
)
if
x0
.
x
[
kx
]
.
k
!=
kedge
{
t
.
Fatalf
(
"edge key before splitX: %v ; expected %v"
,
x0
.
x
[
kx
]
.
k
,
kedge
)
}
tr
.
Set
(
kedge
,
888
)
// if splitX was wrong kedge:888 would land into wrong place
v
,
ok
=
tr
.
Get
(
kedge
)
if
!
(
v
==
888
&&
ok
)
{
t
.
Fatalf
(
"after splitX: Get(%v) -> %v, %v ; expected 888, true"
,
v
,
ok
)
}
}
func
BenchmarkSetSeq1e3
(
b
*
testing
.
B
)
{
benchmarkSetSeq
(
b
,
1e3
)
}
...
...
btree.go
View file @
84c589d6
...
...
@@ -771,6 +771,9 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
switch
x
:=
q
.
(
type
)
{
case
*
x
:
//hitPKmax = hitKmax
if
ok
{
i
++
}
if
x
.
c
>
2
*
kx
{
//dbg("splitX")
...
...
@@ -798,9 +801,9 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
p
=
x
pi
=
i
if
ok
{
pi
++
}
//
if ok {
//
pi++
//
}
q
=
p
.
x
[
pi
]
.
ch
if
pi
>
0
{
...
...
@@ -879,13 +882,14 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
++
if
x
.
c
>
2
*
kx
{
panic
(
"TODO"
)
x
,
i
,
_
,
_
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
pi
=
i
p
=
x
q
=
x
.
x
[
i
+
1
]
.
ch
q
=
x
.
x
[
i
]
.
ch
continue
case
*
d
:
oldV
=
x
.
d
[
i
]
.
v
...
...
@@ -982,36 +986,23 @@ func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int, *x, int) {
r
.
c
=
kx
if
pi
>=
0
{
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
k
,
r
)
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
,
p
,
pi
case
i
==
kx
:
return
p
,
pi
,
p
,
-
1
default
:
// i > kx
return
r
,
i
-
kx
-
1
,
p
,
pi
+
1
}
}
else
{
p
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
pi
=
0
t
.
r
=
p
}
nr
:=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
t
.
r
=
nr
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
,
nr
,
0
case
i
==
kx
:
return
nr
,
0
,
nr
,
-
1
default
:
// i > kx
return
r
,
i
-
kx
-
1
,
nr
,
1
if
i
>
kx
{
q
=
r
i
-=
kx
+
1
pi
++
}
return
q
,
i
,
p
,
pi
}
func
(
t
*
Tree
)
underflow
(
p
*
x
,
q
*
d
,
pi
int
)
{
...
...
example/all_test.go
View file @
84c589d6
...
...
@@ -620,13 +620,13 @@ func TestEnumeratorPrev(t *testing.T) {
hit
bool
keys
[]
int
}{
{
5
,
false
,
[]
int
{
10
}},
{
5
,
false
,
[]
int
{}},
{
10
,
true
,
[]
int
{
10
}},
{
15
,
false
,
[]
int
{
20
,
10
}},
{
15
,
false
,
[]
int
{
10
}},
{
20
,
true
,
[]
int
{
20
,
10
}},
{
25
,
false
,
[]
int
{
30
,
20
,
10
}},
{
25
,
false
,
[]
int
{
20
,
10
}},
{
30
,
true
,
[]
int
{
30
,
20
,
10
}},
{
35
,
false
,
[]
int
{}},
{
35
,
false
,
[]
int
{
30
,
20
,
10
}},
}
for
i
,
test
:=
range
table
{
...
...
@@ -683,6 +683,51 @@ func TestEnumeratorPrev(t *testing.T) {
}
}
func
TestEnumeratorPrevSanity
(
t
*
testing
.
T
)
{
// seeking within 3 keys: 10, 20, 30
table
:=
[]
struct
{
k
int
hit
bool
kOut
int
vOut
int
errOut
error
}{
{
10
,
true
,
10
,
100
,
nil
},
{
20
,
true
,
20
,
200
,
nil
},
{
30
,
true
,
30
,
300
,
nil
},
{
35
,
false
,
30
,
300
,
nil
},
{
25
,
false
,
20
,
200
,
nil
},
{
15
,
false
,
10
,
100
,
nil
},
{
5
,
false
,
0
,
0
,
io
.
EOF
},
}
for
i
,
test
:=
range
table
{
r
:=
TreeNew
(
cmp
)
r
.
Set
(
10
,
100
)
r
.
Set
(
20
,
200
)
r
.
Set
(
30
,
300
)
en
,
hit
:=
r
.
Seek
(
test
.
k
)
if
g
,
e
:=
hit
,
test
.
hit
;
g
!=
e
{
t
.
Fatal
(
i
,
g
,
e
)
}
k
,
v
,
err
:=
en
.
Prev
()
if
g
,
e
:=
err
,
test
.
errOut
;
g
!=
e
{
t
.
Fatal
(
i
,
g
,
e
)
}
if
g
,
e
:=
k
,
test
.
kOut
;
g
!=
e
{
t
.
Fatal
(
i
,
g
,
e
)
}
if
g
,
e
:=
v
,
test
.
vOut
;
g
!=
e
{
t
.
Fatal
(
i
,
g
,
e
)
}
}
}
func
BenchmarkSeekSeq1e3
(
b
*
testing
.
B
)
{
benchmarkSeekSeq
(
b
,
1e3
)
}
...
...
example/int.go
View file @
84c589d6
...
...
@@ -547,12 +547,13 @@ func (t *Tree) Set(k int, v int) {
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
++
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
pi
=
i
p
=
x
q
=
x
.
x
[
i
+
1
]
.
ch
q
=
x
.
x
[
i
]
.
ch
continue
case
*
d
:
x
.
d
[
i
]
.
v
=
v
...
...
@@ -614,12 +615,13 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
++
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
pi
=
i
p
=
x
q
=
x
.
x
[
i
+
1
]
.
ch
q
=
x
.
x
[
i
]
.
ch
continue
case
*
d
:
oldV
=
x
.
d
[
i
]
.
v
...
...
@@ -701,36 +703,20 @@ func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) {
r
.
c
=
kx
if
pi
>=
0
{
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
k
,
r
)
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
case
i
==
kx
:
return
p
,
pi
default
:
// i > kx
return
r
,
i
-
kx
-
1
}
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
}
nr
:=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
t
.
r
=
nr
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
case
i
==
kx
:
return
nr
,
0
default
:
// i > kx
return
r
,
i
-
kx
-
1
if
i
>
kx
{
q
=
r
i
-=
kx
+
1
}
return
q
,
i
}
func
(
t
*
Tree
)
underflow
(
p
*
x
,
q
*
d
,
pi
int
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment