Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
p2p
go-p2p-xor
Commits
8b25ab89
Commit
8b25ab89
authored
Mar 25, 2020
by
Petar Maymounkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make XorTrie fields public.
parent
96a5b4b6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
49 additions
and
48 deletions
+49
-48
trie/add.go
trie/add.go
+10
-10
trie/equal.go
trie/equal.go
+2
-2
trie/intersect.go
trie/intersect.go
+7
-7
trie/xortrie.go
trie/xortrie.go
+30
-29
No files found.
trie/add.go
View file @
8b25ab89
...
@@ -14,24 +14,24 @@ func add(depth int, trie *XorTrie, q key.Key) *XorTrie {
...
@@ -14,24 +14,24 @@ func add(depth int, trie *XorTrie, q key.Key) *XorTrie {
dir
:=
q
.
BitAt
(
depth
)
dir
:=
q
.
BitAt
(
depth
)
if
!
trie
.
isLeaf
()
{
if
!
trie
.
isLeaf
()
{
s
:=
&
XorTrie
{}
s
:=
&
XorTrie
{}
s
.
b
ranch
[
dir
]
=
add
(
depth
+
1
,
trie
.
b
ranch
[
dir
],
q
)
s
.
B
ranch
[
dir
]
=
add
(
depth
+
1
,
trie
.
B
ranch
[
dir
],
q
)
s
.
b
ranch
[
1
-
dir
]
=
trie
.
b
ranch
[
1
-
dir
]
s
.
B
ranch
[
1
-
dir
]
=
trie
.
B
ranch
[
1
-
dir
]
return
s
return
s
}
else
{
}
else
{
if
trie
.
k
ey
==
nil
{
if
trie
.
K
ey
==
nil
{
return
&
XorTrie
{
k
ey
:
q
}
return
&
XorTrie
{
K
ey
:
q
}
}
else
{
}
else
{
if
key
.
Equal
(
trie
.
k
ey
,
q
)
{
if
key
.
Equal
(
trie
.
K
ey
,
q
)
{
return
trie
return
trie
}
else
{
}
else
{
s
:=
&
XorTrie
{}
s
:=
&
XorTrie
{}
if
q
.
BitAt
(
depth
)
==
trie
.
k
ey
.
BitAt
(
depth
)
{
if
q
.
BitAt
(
depth
)
==
trie
.
K
ey
.
BitAt
(
depth
)
{
s
.
b
ranch
[
dir
]
=
add
(
depth
+
1
,
&
XorTrie
{
k
ey
:
trie
.
k
ey
},
q
)
s
.
B
ranch
[
dir
]
=
add
(
depth
+
1
,
&
XorTrie
{
K
ey
:
trie
.
K
ey
},
q
)
s
.
b
ranch
[
1
-
dir
]
=
&
XorTrie
{}
s
.
B
ranch
[
1
-
dir
]
=
&
XorTrie
{}
return
s
return
s
}
else
{
}
else
{
s
.
b
ranch
[
dir
]
=
add
(
depth
+
1
,
&
XorTrie
{
k
ey
:
trie
.
k
ey
},
q
)
s
.
B
ranch
[
dir
]
=
add
(
depth
+
1
,
&
XorTrie
{
K
ey
:
trie
.
K
ey
},
q
)
s
.
b
ranch
[
1
-
dir
]
=
&
XorTrie
{}
s
.
B
ranch
[
1
-
dir
]
=
&
XorTrie
{}
}
}
return
s
return
s
}
}
...
...
trie/equal.go
View file @
8b25ab89
...
@@ -7,9 +7,9 @@ import (
...
@@ -7,9 +7,9 @@ import (
func
Equal
(
p
,
q
*
XorTrie
)
bool
{
func
Equal
(
p
,
q
*
XorTrie
)
bool
{
switch
{
switch
{
case
p
.
isLeaf
()
&&
q
.
isLeaf
()
:
case
p
.
isLeaf
()
&&
q
.
isLeaf
()
:
return
key
.
Equal
(
p
.
k
ey
,
q
.
k
ey
)
return
key
.
Equal
(
p
.
K
ey
,
q
.
K
ey
)
case
!
p
.
isLeaf
()
&&
!
q
.
isLeaf
()
:
case
!
p
.
isLeaf
()
&&
!
q
.
isLeaf
()
:
return
Equal
(
p
.
b
ranch
[
0
],
q
.
b
ranch
[
0
])
&&
Equal
(
p
.
b
ranch
[
1
],
q
.
b
ranch
[
1
])
return
Equal
(
p
.
B
ranch
[
0
],
q
.
B
ranch
[
0
])
&&
Equal
(
p
.
B
ranch
[
1
],
q
.
B
ranch
[
1
])
}
}
return
false
return
false
}
}
trie/intersect.go
View file @
8b25ab89
...
@@ -16,8 +16,8 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
...
@@ -16,8 +16,8 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
if
p
.
isEmpty
()
||
q
.
isEmpty
()
{
if
p
.
isEmpty
()
||
q
.
isEmpty
()
{
return
&
XorTrie
{}
// empty set
return
&
XorTrie
{}
// empty set
}
else
{
}
else
{
if
key
.
Equal
(
p
.
k
ey
,
q
.
k
ey
)
{
if
key
.
Equal
(
p
.
K
ey
,
q
.
K
ey
)
{
return
&
XorTrie
{
k
ey
:
p
.
k
ey
}
// singleton
return
&
XorTrie
{
K
ey
:
p
.
K
ey
}
// singleton
}
else
{
}
else
{
return
&
XorTrie
{}
// empty set
return
&
XorTrie
{}
// empty set
}
}
...
@@ -26,8 +26,8 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
...
@@ -26,8 +26,8 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
if
p
.
isEmpty
()
{
if
p
.
isEmpty
()
{
return
&
XorTrie
{}
// empty set
return
&
XorTrie
{}
// empty set
}
else
{
}
else
{
if
_
,
found
:=
q
.
find
(
depth
,
p
.
k
ey
);
found
{
if
_
,
found
:=
q
.
find
(
depth
,
p
.
K
ey
);
found
{
return
&
XorTrie
{
k
ey
:
p
.
k
ey
}
return
&
XorTrie
{
K
ey
:
p
.
K
ey
}
}
else
{
}
else
{
return
&
XorTrie
{}
// empty set
return
&
XorTrie
{}
// empty set
}
}
...
@@ -36,9 +36,9 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
...
@@ -36,9 +36,9 @@ func intersect(depth int, p, q *XorTrie) *XorTrie {
return
Intersect
(
q
,
p
)
return
Intersect
(
q
,
p
)
case
!
p
.
isLeaf
()
&&
!
q
.
isLeaf
()
:
case
!
p
.
isLeaf
()
&&
!
q
.
isLeaf
()
:
disjointUnion
:=
&
XorTrie
{
disjointUnion
:=
&
XorTrie
{
b
ranch
:
[
2
]
*
XorTrie
{
B
ranch
:
[
2
]
*
XorTrie
{
intersect
(
depth
+
1
,
p
.
b
ranch
[
0
],
q
.
b
ranch
[
0
]),
intersect
(
depth
+
1
,
p
.
B
ranch
[
0
],
q
.
B
ranch
[
0
]),
intersect
(
depth
+
1
,
p
.
b
ranch
[
1
],
q
.
b
ranch
[
1
]),
intersect
(
depth
+
1
,
p
.
B
ranch
[
1
],
q
.
B
ranch
[
1
]),
},
},
}
}
disjointUnion
.
shrink
()
disjointUnion
.
shrink
()
...
...
trie/xortrie.go
View file @
8b25ab89
...
@@ -7,10 +7,11 @@ import (
...
@@ -7,10 +7,11 @@ import (
// XorTrie is a trie for equal-length bit vectors, which stores values only in the leaves.
// XorTrie is a trie for equal-length bit vectors, which stores values only in the leaves.
// XorTrie node invariants:
// XorTrie node invariants:
// (1) Either both branches are nil, or both are non-nil.
// (1) Either both branches are nil, or both are non-nil.
// (2) If both branches are leaves, then they are both non-empty (have keys).
// (2) If branches are non-nil, key must be nil.
// (3) If both branches are leaves, then they are both non-empty (have keys).
type
XorTrie
struct
{
type
XorTrie
struct
{
b
ranch
[
2
]
*
XorTrie
B
ranch
[
2
]
*
XorTrie
k
ey
key
.
Key
K
ey
key
.
Key
}
}
func
New
()
*
XorTrie
{
func
New
()
*
XorTrie
{
...
@@ -22,10 +23,10 @@ func (trie *XorTrie) Depth() int {
...
@@ -22,10 +23,10 @@ func (trie *XorTrie) Depth() int {
}
}
func
(
trie
*
XorTrie
)
depth
(
depth
int
)
int
{
func
(
trie
*
XorTrie
)
depth
(
depth
int
)
int
{
if
trie
.
b
ranch
[
0
]
==
nil
&&
trie
.
b
ranch
[
1
]
==
nil
{
if
trie
.
B
ranch
[
0
]
==
nil
&&
trie
.
B
ranch
[
1
]
==
nil
{
return
depth
return
depth
}
else
{
}
else
{
return
max
(
trie
.
b
ranch
[
0
]
.
depth
(
depth
+
1
),
trie
.
b
ranch
[
1
]
.
depth
(
depth
+
1
))
return
max
(
trie
.
B
ranch
[
0
]
.
depth
(
depth
+
1
),
trie
.
B
ranch
[
1
]
.
depth
(
depth
+
1
))
}
}
}
}
...
@@ -41,13 +42,13 @@ func (trie *XorTrie) Find(q key.Key) (reachedDepth int, found bool) {
...
@@ -41,13 +42,13 @@ func (trie *XorTrie) Find(q key.Key) (reachedDepth int, found bool) {
}
}
func
(
trie
*
XorTrie
)
find
(
depth
int
,
q
key
.
Key
)
(
reachedDepth
int
,
found
bool
)
{
func
(
trie
*
XorTrie
)
find
(
depth
int
,
q
key
.
Key
)
(
reachedDepth
int
,
found
bool
)
{
if
qb
:=
trie
.
b
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
if
qb
:=
trie
.
B
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
return
qb
.
find
(
depth
+
1
,
q
)
return
qb
.
find
(
depth
+
1
,
q
)
}
else
{
}
else
{
if
trie
.
k
ey
==
nil
{
if
trie
.
K
ey
==
nil
{
return
depth
,
false
return
depth
,
false
}
else
{
}
else
{
return
depth
,
key
.
Equal
(
trie
.
k
ey
,
q
)
return
depth
,
key
.
Equal
(
trie
.
K
ey
,
q
)
}
}
}
}
}
}
...
@@ -59,22 +60,22 @@ func (trie *XorTrie) Add(q key.Key) (insertedDepth int, insertedOK bool) {
...
@@ -59,22 +60,22 @@ func (trie *XorTrie) Add(q key.Key) (insertedDepth int, insertedOK bool) {
}
}
func
(
trie
*
XorTrie
)
add
(
depth
int
,
q
key
.
Key
)
(
insertedDepth
int
,
insertedOK
bool
)
{
func
(
trie
*
XorTrie
)
add
(
depth
int
,
q
key
.
Key
)
(
insertedDepth
int
,
insertedOK
bool
)
{
if
qb
:=
trie
.
b
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
if
qb
:=
trie
.
B
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
return
qb
.
add
(
depth
+
1
,
q
)
return
qb
.
add
(
depth
+
1
,
q
)
}
else
{
}
else
{
if
trie
.
k
ey
==
nil
{
if
trie
.
K
ey
==
nil
{
trie
.
k
ey
=
q
trie
.
K
ey
=
q
return
depth
,
true
return
depth
,
true
}
else
{
}
else
{
if
key
.
Equal
(
trie
.
k
ey
,
q
)
{
if
key
.
Equal
(
trie
.
K
ey
,
q
)
{
return
depth
,
false
return
depth
,
false
}
else
{
}
else
{
p
:=
trie
.
k
ey
p
:=
trie
.
K
ey
trie
.
k
ey
=
nil
trie
.
K
ey
=
nil
// both
b
ranches are nil
// both
B
ranches are nil
trie
.
b
ranch
[
0
],
trie
.
b
ranch
[
1
]
=
&
XorTrie
{},
&
XorTrie
{}
trie
.
B
ranch
[
0
],
trie
.
B
ranch
[
1
]
=
&
XorTrie
{},
&
XorTrie
{}
trie
.
b
ranch
[
p
.
BitAt
(
depth
)]
.
add
(
depth
+
1
,
p
)
trie
.
B
ranch
[
p
.
BitAt
(
depth
)]
.
add
(
depth
+
1
,
p
)
return
trie
.
b
ranch
[
q
.
BitAt
(
depth
)]
.
add
(
depth
+
1
,
q
)
return
trie
.
B
ranch
[
q
.
BitAt
(
depth
)]
.
add
(
depth
+
1
,
q
)
}
}
}
}
}
}
...
@@ -87,7 +88,7 @@ func (trie *XorTrie) Remove(q key.Key) (removedDepth int, removed bool) {
...
@@ -87,7 +88,7 @@ func (trie *XorTrie) Remove(q key.Key) (removedDepth int, removed bool) {
}
}
func
(
trie
*
XorTrie
)
remove
(
depth
int
,
q
key
.
Key
)
(
reachedDepth
int
,
removed
bool
)
{
func
(
trie
*
XorTrie
)
remove
(
depth
int
,
q
key
.
Key
)
(
reachedDepth
int
,
removed
bool
)
{
if
qb
:=
trie
.
b
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
if
qb
:=
trie
.
B
ranch
[
q
.
BitAt
(
depth
)];
qb
!=
nil
{
if
d
,
ok
:=
qb
.
remove
(
depth
+
1
,
q
);
ok
{
if
d
,
ok
:=
qb
.
remove
(
depth
+
1
,
q
);
ok
{
trie
.
shrink
()
trie
.
shrink
()
return
d
,
true
return
d
,
true
...
@@ -95,8 +96,8 @@ func (trie *XorTrie) remove(depth int, q key.Key) (reachedDepth int, removed boo
...
@@ -95,8 +96,8 @@ func (trie *XorTrie) remove(depth int, q key.Key) (reachedDepth int, removed boo
return
d
,
false
return
d
,
false
}
}
}
else
{
}
else
{
if
trie
.
k
ey
!=
nil
&&
key
.
Equal
(
q
,
trie
.
k
ey
)
{
if
trie
.
K
ey
!=
nil
&&
key
.
Equal
(
q
,
trie
.
K
ey
)
{
trie
.
k
ey
=
nil
trie
.
K
ey
=
nil
return
depth
,
true
return
depth
,
true
}
else
{
}
else
{
return
depth
,
false
return
depth
,
false
...
@@ -105,11 +106,11 @@ func (trie *XorTrie) remove(depth int, q key.Key) (reachedDepth int, removed boo
...
@@ -105,11 +106,11 @@ func (trie *XorTrie) remove(depth int, q key.Key) (reachedDepth int, removed boo
}
}
func
(
trie
*
XorTrie
)
isEmpty
()
bool
{
func
(
trie
*
XorTrie
)
isEmpty
()
bool
{
return
trie
.
k
ey
==
nil
return
trie
.
K
ey
==
nil
}
}
func
(
trie
*
XorTrie
)
isLeaf
()
bool
{
func
(
trie
*
XorTrie
)
isLeaf
()
bool
{
return
trie
.
b
ranch
[
0
]
==
nil
&&
trie
.
b
ranch
[
1
]
==
nil
return
trie
.
B
ranch
[
0
]
==
nil
&&
trie
.
B
ranch
[
1
]
==
nil
}
}
func
(
trie
*
XorTrie
)
isEmptyLeaf
()
bool
{
func
(
trie
*
XorTrie
)
isEmptyLeaf
()
bool
{
...
@@ -121,15 +122,15 @@ func (trie *XorTrie) isNonEmptyLeaf() bool {
...
@@ -121,15 +122,15 @@ func (trie *XorTrie) isNonEmptyLeaf() bool {
}
}
func
(
trie
*
XorTrie
)
shrink
()
{
func
(
trie
*
XorTrie
)
shrink
()
{
b0
,
b1
:=
trie
.
b
ranch
[
0
],
trie
.
b
ranch
[
1
]
b0
,
b1
:=
trie
.
B
ranch
[
0
],
trie
.
B
ranch
[
1
]
switch
{
switch
{
case
b0
.
isEmptyLeaf
()
&&
b1
.
isEmptyLeaf
()
:
case
b0
.
isEmptyLeaf
()
&&
b1
.
isEmptyLeaf
()
:
trie
.
b
ranch
[
0
],
trie
.
b
ranch
[
1
]
=
nil
,
nil
trie
.
B
ranch
[
0
],
trie
.
B
ranch
[
1
]
=
nil
,
nil
case
b0
.
isEmptyLeaf
()
&&
b1
.
isNonEmptyLeaf
()
:
case
b0
.
isEmptyLeaf
()
&&
b1
.
isNonEmptyLeaf
()
:
trie
.
k
ey
=
b1
.
k
ey
trie
.
K
ey
=
b1
.
K
ey
trie
.
b
ranch
[
0
],
trie
.
b
ranch
[
1
]
=
nil
,
nil
trie
.
B
ranch
[
0
],
trie
.
B
ranch
[
1
]
=
nil
,
nil
case
b0
.
isNonEmptyLeaf
()
&&
b1
.
isEmptyLeaf
()
:
case
b0
.
isNonEmptyLeaf
()
&&
b1
.
isEmptyLeaf
()
:
trie
.
k
ey
=
b0
.
k
ey
trie
.
K
ey
=
b0
.
K
ey
trie
.
b
ranch
[
0
],
trie
.
b
ranch
[
1
]
=
nil
,
nil
trie
.
B
ranch
[
0
],
trie
.
B
ranch
[
1
]
=
nil
,
nil
}
}
}
}
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