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
2d6fbbb4
Commit
2d6fbbb4
authored
Jun 20, 2014
by
Jan Mercl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make index page embed separator keys directly, not data page refs.
parent
5a1179fd
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
296 additions
and
223 deletions
+296
-223
all_test.go
all_test.go
+39
-24
btree.go
btree.go
+104
-99
example/int.go
example/int.go
+153
-100
No files found.
all_test.go
View file @
2d6fbbb4
...
...
@@ -5,6 +5,7 @@
package
b
import
(
"bytes"
"fmt"
"io"
"math"
...
...
@@ -14,11 +15,16 @@ import (
"strings"
"testing"
"github.com/cznic/fileutil"
"github.com/cznic/mathutil"
"github.com/cznic/strutil"
)
func
use
(
...
interface
{})
{}
var
caller
=
func
(
s
string
,
va
...
interface
{})
{
_
,
fn
,
fl
,
_
:=
runtime
.
Caller
(
2
)
fmt
.
Printf
(
"%s:%d: "
,
path
.
Base
(
fn
),
fl
)
fmt
.
Printf
(
s
,
va
...
)
fmt
.
Println
()
}
func
dbg
(
s
string
,
va
...
interface
{})
{
if
s
==
""
{
...
...
@@ -30,13 +36,15 @@ func dbg(s string, va ...interface{}) {
fmt
.
Println
()
}
var
caller
=
func
(
s
string
,
va
...
interface
{})
{
_
,
fn
,
fl
,
_
:=
runtime
.
Caller
(
2
)
fmt
.
Printf
(
"%s:%d: "
,
path
.
Base
(
fn
),
fl
)
fmt
.
Printf
(
s
,
va
...
)
fmt
.
Println
()
func
TODO
(
...
interface
{})
string
{
_
,
fn
,
fl
,
_
:=
runtime
.
Caller
(
1
)
return
fmt
.
Sprintf
(
"TODO: %s:%d:
\n
"
,
path
.
Base
(
fn
),
fl
)
}
func
use
(
...
interface
{})
{}
// ============================================================================
func
isNil
(
p
interface
{})
bool
{
switch
x
:=
p
.
(
type
)
{
case
*
x
:
...
...
@@ -52,6 +60,9 @@ func isNil(p interface{}) bool {
}
func
(
t
*
Tree
)
dump
()
string
{
var
buf
bytes
.
Buffer
f
:=
strutil
.
IndentFormatter
(
&
buf
,
"
\t
"
)
num
:=
map
[
interface
{}]
int
{}
visited
:=
map
[
interface
{}]
bool
{}
...
...
@@ -81,20 +92,20 @@ func (t *Tree) dump() string {
h
:=
handle
(
p
)
n
:=
0
for
i
,
v
:=
range
x
.
x
{
if
v
.
ch
!=
nil
||
v
.
sep
!=
nil
{
if
v
.
ch
!=
nil
||
v
.
k
!=
nil
{
n
=
i
+
1
}
}
f
mt
.
Printf
(
"%sX#%d n %d:%d {"
,
pref
,
h
,
x
.
c
,
n
)
f
.
Format
(
"%sX#%d n %d:%d {"
,
pref
,
h
,
x
.
c
,
n
)
a
:=
[]
interface
{}{}
for
i
,
v
:=
range
x
.
x
[
:
n
]
{
a
=
append
(
a
,
v
.
ch
,
v
.
sep
)
a
=
append
(
a
,
v
.
ch
)
if
i
!=
0
{
f
mt
.
Printf
(
" "
)
f
.
Format
(
" "
)
}
f
mt
.
Printf
(
"(C#%d D#%d)"
,
handle
(
v
.
ch
),
handle
(
v
.
sep
)
)
f
.
Format
(
"(C#%d K %v)"
,
handle
(
v
.
ch
),
v
.
k
)
}
f
mt
.
Printf
(
"}
\n
"
)
f
.
Format
(
"}
\n
"
)
for
_
,
p
:=
range
a
{
pagedump
(
p
,
pref
+
". "
)
}
...
...
@@ -106,19 +117,23 @@ func (t *Tree) dump() string {
n
=
i
+
1
}
}
f
mt
.
Printf
(
"%sD#%d P#%d N#%d n %d:%d {"
,
pref
,
h
,
handle
(
x
.
p
),
handle
(
x
.
n
),
x
.
c
,
n
)
f
.
Format
(
"%sD#%d P#%d N#%d n %d:%d {"
,
pref
,
h
,
handle
(
x
.
p
),
handle
(
x
.
n
),
x
.
c
,
n
)
for
i
,
v
:=
range
x
.
d
[
:
n
]
{
if
i
!=
0
{
f
mt
.
Printf
(
" "
)
f
.
Format
(
" "
)
}
f
mt
.
Printf
(
"%v:%v"
,
v
.
k
,
v
.
v
)
f
.
Format
(
"%v:%v"
,
v
.
k
,
v
.
v
)
}
f
mt
.
Printf
(
"}
\n
"
)
f
.
Format
(
"}
\n
"
)
}
}
pagedump
(
t
.
r
,
""
)
return
""
s
:=
buf
.
String
()
if
s
!=
""
{
s
=
s
[
:
len
(
s
)
-
1
]
}
return
s
}
func
rng
()
*
mathutil
.
FC32
{
...
...
@@ -203,7 +218,7 @@ func TestSetGet0(t *testing.T) {
}
func
TestSetGet1
(
t
*
testing
.
T
)
{
const
N
=
9
0000
const
N
=
5
0000
for
_
,
x
:=
range
[]
int
{
0
,
-
1
,
0x555555
,
0xaaaaaa
,
0x314259
}
{
r
:=
TreeNew
(
cmp
)
set
:=
r
.
Set
...
...
@@ -387,7 +402,7 @@ func benchmarkGetRnd(b *testing.B, n int) {
}
func
TestSetGet2
(
t
*
testing
.
T
)
{
const
N
=
7
0000
const
N
=
5
0000
for
_
,
x
:=
range
[]
int
{
0
,
-
1
,
0x555555
,
0xaaaaaa
,
0x314259
}
{
r
:=
TreeNew
(
cmp
)
set
:=
r
.
Set
...
...
@@ -533,7 +548,7 @@ func TestDelete0(t *testing.T) {
}
func
TestDelete1
(
t
*
testing
.
T
)
{
const
N
=
10
0000
const
N
=
6
0000
for
_
,
x
:=
range
[]
int
{
0
,
-
1
,
0x555555
,
0xaaaaaa
,
0x314259
}
{
r
:=
TreeNew
(
cmp
)
set
:=
r
.
Set
...
...
@@ -638,7 +653,7 @@ func benchmarkDelRnd(b *testing.B, n int) {
}
func
TestDelete2
(
t
*
testing
.
T
)
{
const
N
=
8
0000
const
N
=
5
0000
for
_
,
x
:=
range
[]
int
{
0
,
-
1
,
0x555555
,
0xaaaaaa
,
0x314259
}
{
r
:=
TreeNew
(
cmp
)
set
:=
r
.
Set
...
...
@@ -703,7 +718,7 @@ func TestEnumeratorNext(t *testing.T) {
k
,
v
,
err
:=
en
.
Next
()
if
err
!=
nil
{
if
!
fileutil
.
IsEOF
(
err
)
{
if
err
!=
io
.
EOF
{
t
.
Fatal
(
i
,
err
)
}
...
...
@@ -773,7 +788,7 @@ func TestEnumeratorPrev(t *testing.T) {
k
,
v
,
err
:=
en
.
Prev
()
if
err
!=
nil
{
if
!
fileutil
.
IsEOF
(
err
)
{
if
err
!=
io
.
EOF
{
t
.
Fatal
(
i
,
err
)
}
...
...
btree.go
View file @
2d6fbbb4
...
...
@@ -60,8 +60,8 @@ import (
//TODO check vs orig initialize/finalize
const
(
kx
=
128
//TODO benchmark tune this number if using custom key/value type(s).
kd
=
64
//TODO benchmark tune this number if using custom key/value type(s).
kx
=
128
//
min 2 //
TODO benchmark tune this number if using custom key/value type(s).
kd
=
64
//
min 1 //
TODO benchmark tune this number if using custom key/value type(s).
)
type
(
...
...
@@ -115,7 +115,7 @@ type (
xe
struct
{
// x element
ch
interface
{}
sep
*
d
k
interface
{}
/*K*/
}
x
struct
{
// index page
...
...
@@ -129,6 +129,7 @@ var ( // R/O zero values
zde
de
zx
x
zxe
xe
zk
interface
{}
/*K*/
)
func
clr
(
q
interface
{})
{
...
...
@@ -156,21 +157,21 @@ func (q *x) extract(i int) {
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
]
.
sep
=
nil
// GC
q
.
x
[
q
.
c
]
.
k
=
zk
// GC
q
.
x
[
q
.
c
+
1
]
=
zxe
// GC
}
}
func
(
q
*
x
)
insert
(
i
int
,
d
*
d
,
ch
interface
{})
*
x
{
func
(
q
*
x
)
insert
(
i
int
,
k
interface
{}
/*K*/
,
ch
interface
{})
*
x
{
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
]
.
sep
=
q
.
x
[
i
]
.
sep
q
.
x
[
i
+
1
]
.
k
=
q
.
x
[
i
]
.
k
}
c
++
q
.
c
=
c
q
.
x
[
i
]
.
sep
=
d
q
.
x
[
i
]
.
k
=
k
q
.
x
[
i
+
1
]
.
ch
=
ch
return
q
}
...
...
@@ -241,7 +242,7 @@ func (t *Tree) cat(p *x, q, r *d, pi int) {
func
(
t
*
Tree
)
catX
(
p
,
q
,
r
*
x
,
pi
int
)
{
t
.
ver
++
q
.
x
[
q
.
c
]
.
sep
=
p
.
x
[
pi
]
.
sep
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
//TODO recycle r
...
...
@@ -249,10 +250,10 @@ func (t *Tree) catX(p, q, r *x, pi int) {
p
.
c
--
pc
:=
p
.
c
if
pi
<
pc
{
p
.
x
[
pi
]
.
sep
=
p
.
x
[
pi
+
1
]
.
sep
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
]
.
sep
=
nil
// GC
p
.
x
[
pc
]
.
k
=
zk
// GC
p
.
x
[
pc
+
1
]
.
ch
=
nil
// GC
}
return
...
...
@@ -268,7 +269,7 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
var
p
*
x
q
:=
t
.
r
if
q
==
nil
{
return
return
false
}
for
{
...
...
@@ -277,11 +278,6 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
dp
:=
x
.
x
[
i
]
.
sep
switch
{
case
dp
.
c
>
kd
:
t
.
extract
(
dp
,
0
)
default
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
t
.
underflowX
(
p
,
&
x
,
pi
,
&
i
)
}
...
...
@@ -290,11 +286,10 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
q
=
x
.
x
[
pi
]
.
ch
ok
=
false
continue
}
case
*
d
:
t
.
extract
(
x
,
i
)
if
x
.
c
>=
kd
{
return
return
true
}
if
q
!=
t
.
r
{
...
...
@@ -302,8 +297,8 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
}
else
if
t
.
c
==
0
{
t
.
Clear
()
}
return
true
}
return
}
switch
x
:=
q
.
(
type
)
{
...
...
@@ -315,7 +310,7 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
return
false
}
}
}
...
...
@@ -340,7 +335,7 @@ func (t *Tree) find(q interface{}, k interface{} /*K*/) (i int, ok bool) {
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
mk
=
x
.
x
[
m
]
.
sep
.
d
[
0
]
.
k
mk
=
x
.
x
[
m
]
.
k
switch
cmp
:=
t
.
cmp
(
k
,
mk
);
{
case
cmp
>
0
:
l
=
m
+
1
...
...
@@ -368,15 +363,15 @@ func (t *Tree) find(q interface{}, k interface{} /*K*/) (i int, ok bool) {
return
l
,
false
}
// First returns the first item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
First
()
(
k
interface
{}
/*K*/
,
v
interface
{}
/*V*/
)
{
if
q
:=
t
.
first
;
q
!=
nil
{
q
:=
&
q
.
d
[
0
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
//
A //
First returns the first item of the tree in the key collating order, or
//
A //
(zero-value, zero-value) if the tree is empty.
//A
func (t *Tree) First() (k interface{} /*K*/, v interface{} /*V*/) {
//A
if q := t.first; q != nil {
//A
q := &q.d[0]
//A
k, v = q.k, q.v
//A
}
//A
return
//A
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (zero-value, false).
...
...
@@ -391,7 +386,8 @@ func (t *Tree) Get(k interface{} /*K*/) (v interface{} /*V*/, ok bool) {
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
return
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
,
true
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
return
x
.
d
[
i
]
.
v
,
true
}
...
...
@@ -418,15 +414,15 @@ func (t *Tree) insert(q *d, i int, k interface{} /*K*/, v interface{} /*V*/) *d
return
q
}
// Last returns the last item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
Last
()
(
k
interface
{}
/*K*/
,
v
interface
{}
/*V*/
)
{
if
q
:=
t
.
last
;
q
!=
nil
{
q
:=
&
q
.
d
[
q
.
c
-
1
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
//
A //
Last returns the last item of the tree in the key collating order, or
//
A //
(zero-value, zero-value) if the tree is empty.
//A
func (t *Tree) Last() (k interface{} /*K*/, v interface{} /*V*/) {
//A
if q := t.last; q != nil {
//A
q := &q.d[q.c-1]
//A
k, v = q.k, q.v
//A
}
//A
return
//A
}
// Len returns the number of items in the tree.
func
(
t
*
Tree
)
Len
()
int
{
...
...
@@ -440,6 +436,7 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{
if
l
!=
nil
&&
l
.
c
<
2
*
kd
{
l
.
mvL
(
q
,
1
)
t
.
insert
(
q
,
i
-
1
,
k
,
v
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
return
}
...
...
@@ -447,8 +444,10 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{
if
i
<
2
*
kd
{
q
.
mvR
(
r
,
1
)
t
.
insert
(
q
,
i
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
}
else
{
t
.
insert
(
r
,
0
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
k
}
return
}
...
...
@@ -471,8 +470,8 @@ func (t *Tree) Seek(k interface{} /*K*/) (e *Enumerator, ok bool) {
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
e
=
&
Enumerator
{
nil
,
ok
,
0
,
k
,
x
.
x
[
i
]
.
sep
,
t
,
t
.
ver
}
return
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
e
=
&
Enumerator
{
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
}
return
...
...
@@ -512,16 +511,26 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
// Set sets the value associated with k.
func
(
t
*
Tree
)
Set
(
k
interface
{}
/*K*/
,
v
interface
{}
/*V*/
)
{
//dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump())
//defer func() {
// dbg("--- POST\n%s\n====\n", t.dump())
//}()
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
if
q
!=
nil
{
if
q
==
nil
{
z
:=
t
.
insert
(
&
d
{},
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
for
{
i
,
ok
:=
t
.
find
(
q
,
k
)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
=
v
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
x
.
d
[
i
]
.
v
=
v
}
...
...
@@ -546,11 +555,6 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
return
}
}
}
z
:=
t
.
insert
(
&
d
{},
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
// Put combines Get and Set in a more efficient way where the tree is walked
...
...
@@ -576,13 +580,8 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
oldV
=
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
if
!
written
{
return
}
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
=
newV
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
oldV
=
x
.
d
[
i
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
...
...
@@ -649,13 +648,17 @@ func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /
}
q
.
c
=
kd
r
.
c
=
kd
var
done
bool
if
i
>
kd
{
done
=
true
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
}
if
pi
>=
0
{
p
.
insert
(
pi
,
r
,
r
)
p
.
insert
(
pi
,
r
.
d
[
0
]
.
k
,
r
)
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
r
,
r
)
t
.
r
=
newX
(
q
)
.
insert
(
0
,
r
.
d
[
0
]
.
k
,
r
)
}
if
i
>
kd
{
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
if
done
{
return
}
...
...
@@ -670,11 +673,11 @@ func (t *Tree) splitX(p *x, pp **x, pi int, i *int) {
q
.
c
=
kx
r
.
c
=
kx
if
pi
>=
0
{
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
sep
,
r
)
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
k
,
r
)
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
sep
,
r
)
t
.
r
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
}
q
.
x
[
kx
]
.
sep
=
nil
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
...
...
@@ -690,8 +693,10 @@ func (t *Tree) underflow(p *x, q *d, pi int) {
if
l
!=
nil
&&
l
.
c
+
q
.
c
>=
2
*
kd
{
l
.
mvR
(
q
,
1
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
}
else
if
r
!=
nil
&&
q
.
c
+
r
.
c
>=
2
*
kd
{
q
.
mvL
(
r
,
1
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
r
.
d
[
r
.
c
]
=
zde
// GC
}
else
if
l
!=
nil
{
t
.
cat
(
p
,
l
,
q
,
pi
-
1
)
...
...
@@ -718,24 +723,24 @@ func (t *Tree) underflowX(p *x, pp **x, pi int, i *int) {
q
.
x
[
q
.
c
+
1
]
.
ch
=
q
.
x
[
q
.
c
]
.
ch
copy
(
q
.
x
[
1
:
],
q
.
x
[
:
q
.
c
])
q
.
x
[
0
]
.
ch
=
l
.
x
[
l
.
c
]
.
ch
q
.
x
[
0
]
.
sep
=
p
.
x
[
pi
-
1
]
.
sep
q
.
x
[
0
]
.
k
=
p
.
x
[
pi
-
1
]
.
k
q
.
c
++
*
i
++
l
.
c
--
p
.
x
[
pi
-
1
]
.
sep
=
l
.
x
[
l
.
c
]
.
sep
p
.
x
[
pi
-
1
]
.
k
=
l
.
x
[
l
.
c
]
.
k
return
}
if
r
!=
nil
&&
r
.
c
>
kx
{
q
.
x
[
q
.
c
]
.
sep
=
p
.
x
[
pi
]
.
sep
q
.
x
[
q
.
c
]
.
k
=
p
.
x
[
pi
]
.
k
q
.
c
++
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
0
]
.
ch
p
.
x
[
pi
]
.
sep
=
r
.
x
[
0
]
.
sep
p
.
x
[
pi
]
.
k
=
r
.
x
[
0
]
.
k
copy
(
r
.
x
[
:
],
r
.
x
[
1
:
r
.
c
])
r
.
c
--
rc
:=
r
.
c
r
.
x
[
rc
]
.
ch
=
r
.
x
[
rc
+
1
]
.
ch
r
.
x
[
rc
]
.
sep
=
nil
r
.
x
[
rc
]
.
k
=
zk
r
.
x
[
rc
+
1
]
.
ch
=
nil
return
}
...
...
example/int.go
View file @
2d6fbbb4
...
...
@@ -2,7 +2,55 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package b implements an int->int B+tree.
// Package b implements a B+tree.
//
// Changelog
//
// 2014-04-18: Added new method Put.
//
// Generic types
//
// Keys and their associated values are interface{} typed, similar to all of
// the containers in the standard library.
//
// Semiautomatic production of a type specific variant of this package is
// supported via
//
// $ make generic
//
// This command will write to stdout a version of the btree.go file where
// every key type occurrence is replaced by the word 'key' (written in all
// CAPS) and every value type occurrence is replaced by the word 'value'
// (written in all CAPS). Then you have to replace these tokens with your
// desired type(s), using any technique you're comfortable with.
//
// This is how, for example, 'example/int.go' was created:
//
// $ mkdir example
// $
// $ # Note: the command bellow must be actually written using the words
// $ # 'key' and 'value' in all CAPS. The proper form is avoided in this
// $ # documentation to not confuse any text replacement mechanism.
// $
// $ make generic | sed -e 's/key/int/g' -e 's/value/int/g' > example/int.go
//
// No other changes to int.go are (strictly) necessary, it compiles just fine.
//
// Running the benchmarks for 1000 keys on a machine with Intel X5450 CPU @ 3
// GHz, Go release 1.3.
//
// $ go test -bench 1e3 example/all_test.go example/int.go
// PASS
// BenchmarkSetSeq1e3 10000 263951 ns/op
// BenchmarkGetSeq1e3 10000 154410 ns/op
// BenchmarkSetRnd1e3 5000 392690 ns/op
// BenchmarkGetRnd1e3 10000 181776 ns/op
// BenchmarkDelRnd1e3 5000 323795 ns/op
// BenchmarkSeekSeq1e3 10000 235939 ns/op
// BenchmarkSeekRnd1e3 5000 299997 ns/op
// BenchmarkNext1e3 200000 14202 ns/op
// BenchmarkPrev1e3 200000 13842 ns/op
// ok command-line-arguments 30.620s
package
b
import
(
...
...
@@ -12,8 +60,8 @@ import (
//TODO check vs orig initialize/finalize
const
(
kx
=
128
//TODO benchmark tune this number if using custom key/value type(s).
kd
=
64
//TODO benchmark tune this number if using custom key/value type(s).
kx
=
128
//
min 2 //
TODO benchmark tune this number if using custom key/value type(s).
kd
=
64
//
min 1 //
TODO benchmark tune this number if using custom key/value type(s).
)
type
(
...
...
@@ -67,7 +115,7 @@ type (
xe
struct
{
// x element
ch
interface
{}
sep
*
d
k
int
}
x
struct
{
// index page
...
...
@@ -81,6 +129,7 @@ var ( // R/O zero values
zde
de
zx
x
zxe
xe
zk
int
)
func
clr
(
q
interface
{})
{
...
...
@@ -108,21 +157,21 @@ func (q *x) extract(i int) {
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
]
.
sep
=
nil
// GC
q
.
x
[
q
.
c
]
.
k
=
zk
// GC
q
.
x
[
q
.
c
+
1
]
=
zxe
// GC
}
}
func
(
q
*
x
)
insert
(
i
int
,
d
*
d
,
ch
interface
{})
*
x
{
func
(
q
*
x
)
insert
(
i
int
,
k
int
,
ch
interface
{})
*
x
{
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
]
.
sep
=
q
.
x
[
i
]
.
sep
q
.
x
[
i
+
1
]
.
k
=
q
.
x
[
i
]
.
k
}
c
++
q
.
c
=
c
q
.
x
[
i
]
.
sep
=
d
q
.
x
[
i
]
.
k
=
k
q
.
x
[
i
+
1
]
.
ch
=
ch
return
q
}
...
...
@@ -193,7 +242,7 @@ func (t *Tree) cat(p *x, q, r *d, pi int) {
func
(
t
*
Tree
)
catX
(
p
,
q
,
r
*
x
,
pi
int
)
{
t
.
ver
++
q
.
x
[
q
.
c
]
.
sep
=
p
.
x
[
pi
]
.
sep
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
//TODO recycle r
...
...
@@ -201,10 +250,10 @@ func (t *Tree) catX(p, q, r *x, pi int) {
p
.
c
--
pc
:=
p
.
c
if
pi
<
pc
{
p
.
x
[
pi
]
.
sep
=
p
.
x
[
pi
+
1
]
.
sep
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
]
.
sep
=
nil
// GC
p
.
x
[
pc
]
.
k
=
zk
// GC
p
.
x
[
pc
+
1
]
.
ch
=
nil
// GC
}
return
...
...
@@ -220,7 +269,7 @@ func (t *Tree) Delete(k int) (ok bool) {
var
p
*
x
q
:=
t
.
r
if
q
==
nil
{
return
return
false
}
for
{
...
...
@@ -229,11 +278,6 @@ func (t *Tree) Delete(k int) (ok bool) {
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
dp
:=
x
.
x
[
i
]
.
sep
switch
{
case
dp
.
c
>
kd
:
t
.
extract
(
dp
,
0
)
default
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
t
.
underflowX
(
p
,
&
x
,
pi
,
&
i
)
}
...
...
@@ -242,11 +286,10 @@ func (t *Tree) Delete(k int) (ok bool) {
q
=
x
.
x
[
pi
]
.
ch
ok
=
false
continue
}
case
*
d
:
t
.
extract
(
x
,
i
)
if
x
.
c
>=
kd
{
return
return
true
}
if
q
!=
t
.
r
{
...
...
@@ -254,8 +297,8 @@ func (t *Tree) Delete(k int) (ok bool) {
}
else
if
t
.
c
==
0
{
t
.
Clear
()
}
return
true
}
return
}
switch
x
:=
q
.
(
type
)
{
...
...
@@ -267,7 +310,7 @@ func (t *Tree) Delete(k int) (ok bool) {
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
return
false
}
}
}
...
...
@@ -292,7 +335,7 @@ func (t *Tree) find(q interface{}, k int) (i int, ok bool) {
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
mk
=
x
.
x
[
m
]
.
sep
.
d
[
0
]
.
k
mk
=
x
.
x
[
m
]
.
k
switch
cmp
:=
t
.
cmp
(
k
,
mk
);
{
case
cmp
>
0
:
l
=
m
+
1
...
...
@@ -320,15 +363,15 @@ func (t *Tree) find(q interface{}, k int) (i int, ok bool) {
return
l
,
false
}
// First returns the first item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
First
()
(
k
int
,
v
int
)
{
if
q
:=
t
.
first
;
q
!=
nil
{
q
:=
&
q
.
d
[
0
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
//
A //
First returns the first item of the tree in the key collating order, or
//
A //
(zero-value, zero-value) if the tree is empty.
//A
func (t *Tree) First() (k int, v int) {
//A
if q := t.first; q != nil {
//A
q := &q.d[0]
//A
k, v = q.k, q.v
//A
}
//A
return
//A
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (zero-value, false).
...
...
@@ -343,7 +386,8 @@ func (t *Tree) Get(k int) (v int, ok bool) {
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
return
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
,
true
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
return
x
.
d
[
i
]
.
v
,
true
}
...
...
@@ -370,15 +414,15 @@ func (t *Tree) insert(q *d, i int, k int, v int) *d {
return
q
}
// Last returns the last item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
Last
()
(
k
int
,
v
int
)
{
if
q
:=
t
.
last
;
q
!=
nil
{
q
:=
&
q
.
d
[
q
.
c
-
1
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
//
A //
Last returns the last item of the tree in the key collating order, or
//
A //
(zero-value, zero-value) if the tree is empty.
//A
func (t *Tree) Last() (k int, v int) {
//A
if q := t.last; q != nil {
//A
q := &q.d[q.c-1]
//A
k, v = q.k, q.v
//A
}
//A
return
//A
}
// Len returns the number of items in the tree.
func
(
t
*
Tree
)
Len
()
int
{
...
...
@@ -392,6 +436,7 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) {
if
l
!=
nil
&&
l
.
c
<
2
*
kd
{
l
.
mvL
(
q
,
1
)
t
.
insert
(
q
,
i
-
1
,
k
,
v
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
return
}
...
...
@@ -399,8 +444,10 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) {
if
i
<
2
*
kd
{
q
.
mvR
(
r
,
1
)
t
.
insert
(
q
,
i
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
}
else
{
t
.
insert
(
r
,
0
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
k
}
return
}
...
...
@@ -423,8 +470,8 @@ func (t *Tree) Seek(k int) (e *Enumerator, ok bool) {
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
e
=
&
Enumerator
{
nil
,
ok
,
0
,
k
,
x
.
x
[
i
]
.
sep
,
t
,
t
.
ver
}
return
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
e
=
&
Enumerator
{
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
}
return
...
...
@@ -464,16 +511,26 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
// Set sets the value associated with k.
func
(
t
*
Tree
)
Set
(
k
int
,
v
int
)
{
//dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump())
//defer func() {
// dbg("--- POST\n%s\n====\n", t.dump())
//}()
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
if
q
!=
nil
{
if
q
==
nil
{
z
:=
t
.
insert
(
&
d
{},
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
for
{
i
,
ok
:=
t
.
find
(
q
,
k
)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
=
v
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
x
.
d
[
i
]
.
v
=
v
}
...
...
@@ -498,11 +555,6 @@ func (t *Tree) Set(k int, v int) {
return
}
}
}
z
:=
t
.
insert
(
&
d
{},
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
// Put combines Get and Set in a more efficient way where the tree is walked
...
...
@@ -528,13 +580,8 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
oldV
=
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
if
!
written
{
return
}
x
.
x
[
i
]
.
sep
.
d
[
0
]
.
v
=
newV
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
oldV
=
x
.
d
[
i
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
...
...
@@ -601,13 +648,17 @@ func (t *Tree) split(p *x, q *d, pi, i int, k int, v int) {
}
q
.
c
=
kd
r
.
c
=
kd
var
done
bool
if
i
>
kd
{
done
=
true
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
}
if
pi
>=
0
{
p
.
insert
(
pi
,
r
,
r
)
p
.
insert
(
pi
,
r
.
d
[
0
]
.
k
,
r
)
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
r
,
r
)
t
.
r
=
newX
(
q
)
.
insert
(
0
,
r
.
d
[
0
]
.
k
,
r
)
}
if
i
>
kd
{
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
if
done
{
return
}
...
...
@@ -622,11 +673,11 @@ func (t *Tree) splitX(p *x, pp **x, pi int, i *int) {
q
.
c
=
kx
r
.
c
=
kx
if
pi
>=
0
{
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
sep
,
r
)
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
k
,
r
)
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
sep
,
r
)
t
.
r
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
}
q
.
x
[
kx
]
.
sep
=
nil
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
...
...
@@ -642,8 +693,10 @@ func (t *Tree) underflow(p *x, q *d, pi int) {
if
l
!=
nil
&&
l
.
c
+
q
.
c
>=
2
*
kd
{
l
.
mvR
(
q
,
1
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
}
else
if
r
!=
nil
&&
q
.
c
+
r
.
c
>=
2
*
kd
{
q
.
mvL
(
r
,
1
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
r
.
d
[
r
.
c
]
=
zde
// GC
}
else
if
l
!=
nil
{
t
.
cat
(
p
,
l
,
q
,
pi
-
1
)
...
...
@@ -670,24 +723,24 @@ func (t *Tree) underflowX(p *x, pp **x, pi int, i *int) {
q
.
x
[
q
.
c
+
1
]
.
ch
=
q
.
x
[
q
.
c
]
.
ch
copy
(
q
.
x
[
1
:
],
q
.
x
[
:
q
.
c
])
q
.
x
[
0
]
.
ch
=
l
.
x
[
l
.
c
]
.
ch
q
.
x
[
0
]
.
sep
=
p
.
x
[
pi
-
1
]
.
sep
q
.
x
[
0
]
.
k
=
p
.
x
[
pi
-
1
]
.
k
q
.
c
++
*
i
++
l
.
c
--
p
.
x
[
pi
-
1
]
.
sep
=
l
.
x
[
l
.
c
]
.
sep
p
.
x
[
pi
-
1
]
.
k
=
l
.
x
[
l
.
c
]
.
k
return
}
if
r
!=
nil
&&
r
.
c
>
kx
{
q
.
x
[
q
.
c
]
.
sep
=
p
.
x
[
pi
]
.
sep
q
.
x
[
q
.
c
]
.
k
=
p
.
x
[
pi
]
.
k
q
.
c
++
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
0
]
.
ch
p
.
x
[
pi
]
.
sep
=
r
.
x
[
0
]
.
sep
p
.
x
[
pi
]
.
k
=
r
.
x
[
0
]
.
k
copy
(
r
.
x
[
:
],
r
.
x
[
1
:
r
.
c
])
r
.
c
--
rc
:=
r
.
c
r
.
x
[
rc
]
.
ch
=
r
.
x
[
rc
+
1
]
.
ch
r
.
x
[
rc
]
.
sep
=
nil
r
.
x
[
rc
]
.
k
=
zk
r
.
x
[
rc
+
1
]
.
ch
=
nil
return
}
...
...
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