Browse files

Make Crit-bit trees work. Insertion is currently slow.

  • Loading branch information...
1 parent af1fdd5 commit 4dcfbf833e2a24832282158202d68dc74c4e2c23 @jlouis committed Feb 17, 2011
Showing with 90 additions and 72 deletions.
  1. +68 −52 src/bench_map.erl
  2. +22 −20 src/patricia.erl
View
120 src/bench_map.erl
@@ -1,33 +1,34 @@
-module(bench_map).
--export([run/0]).
+-export([run/0, runs/1]).
-ifdef(TEST).
-include_lib("eqc/include/eqc.hrl").
-include_lib("eunit/include/eunit.hrl").
-endif.
run() ->
- [{sets, runs(
- fun () ->
- timer:tc(fun() -> set_test(), ok end, [])
- end)},
- {dict, timer:tc(fun() -> dict_test(), ok end, [])},
- {gb_sets, runs(
- fun () ->
- timer:tc(fun() -> gb_sets_test(), ok end, [])
- end)},
- {gb_trees, timer:tc(fun() -> gb_trees_test(), ok end, [])},
- {h_rb_sets, timer:tc(fun() -> h_rb_set_test(), ok end, [])},
- {rb_sets, timer:tc(fun() -> rb_sets_test(), ok end, [])}].
+ [
+ {patricia, timer:tc(fun() -> patricia_test(), ok end, [])}
+ %% {sets, timer:tc(fun() -> set_test(), ok end, [])},
+ %% {dict, timer:tc(fun() -> dict_test(), ok end, [])},
+ %% {gb_sets, timer:tc(fun() -> gb_sets_test(), ok end, [])},
+ %% {gb_trees, timer:tc(fun() -> gb_trees_test(), ok end, [])},
+ %% {h_rb_sets, timer:tc(fun() -> h_rb_set_test(), ok end, [])},
+ %% {rb_sets, timer:tc(fun() -> rb_sets_test(), ok end, [])}
+ ].
runs(F) ->
[F() || _ <- lists:seq(1, 10)].
words() ->
Words = "/usr/share/dict/words",
{ok, Content} = file:read_file(Words),
- [binary_to_list(W) || W <- binary:split(Content, <<"\n">>, [global])].
+ {Taken, _} = lists:split(500,
+ [binary_to_list(W)
+ || W <- binary:split(Content, <<"\n">>, [global])]),
+ Taken.
+
list_shuffle(L) ->
random:seed(), %% Reset Random function
@@ -63,6 +64,15 @@ test_gb_sets_words(Words, Set) ->
end,
Words).
+test_patricia_words(Words, Tree) ->
+ lists:foreach(
+ fun(Word) ->
+ true = patricia:is_element(Word, Tree)
+ end,
+ Words),
+ false = patricia:is_element(notthere, Tree).
+
+
test_dict_words(Words, Dict) ->
lists:foreach(
fun(W) ->
@@ -84,46 +94,52 @@ test_map(Generator, TestFun) ->
TestFun(lists:reverse(Ws), S),
TestFun(list_shuffle(Ws), S).
-h_rb_set_test() ->
- test_map(fun(Ws) ->
- h_rb_set:from_list(Ws)
- end,
- fun test_h_rb_set_words/2).
-
-set_test() ->
- test_map(fun(Ws) ->
- sets:from_list(Ws)
- end,
- fun test_sets_words/2).
-
-dict_test() ->
- test_map(fun(Ws) ->
- dict:from_list([{K, true} || K <- Ws])
- end,
- fun test_dict_words/2).
-
-gb_sets_test() ->
- test_map(fun(Ws) ->
- gb_sets:from_list(Ws)
- end,
- fun test_gb_sets_words/2).
-
-gb_trees_test() ->
- test_map(fun(Ws) ->
- lists:foldl(
- fun(K, Tree) ->
- gb_trees:enter(K, true, Tree)
- end,
- gb_trees:empty(),
- Ws)
- end,
- fun test_gb_trees_words/2).
-
-rb_sets_test() ->
+%% h_rb_set_test() ->
+%% test_map(fun(Ws) ->
+%% h_rb_set:from_list(Ws)
+%% end,
+%% fun test_h_rb_set_words/2).
+
+%% set_test() ->
+%% test_map(fun(Ws) ->
+%% sets:from_list(Ws)
+%% end,
+%% fun test_sets_words/2).
+
+%% dict_test() ->
+%% test_map(fun(Ws) ->
+%% dict:from_list([{K, true} || K <- Ws])
+%% end,
+%% fun test_dict_words/2).
+
+%% gb_sets_test() ->
+%% test_map(fun(Ws) ->
+%% gb_sets:from_list(Ws)
+%% end,
+%% fun test_gb_sets_words/2).
+
+%% gb_trees_test() ->
+%% test_map(fun(Ws) ->
+%% lists:foldl(
+%% fun(K, Tree) ->
+%% gb_trees:enter(K, true, Tree)
+%% end,
+%% gb_trees:empty(),
+%% Ws)
+%% end,
+%% fun test_gb_trees_words/2).
+
+%% rb_sets_test() ->
+%% test_map(fun(Ws) ->
+%% rbsets:from_list(Ws)
+%% end,
+%% fun test_rb_sets_words/2).
+
+patricia_test() ->
test_map(fun(Ws) ->
- rbsets:from_list(Ws)
+ patricia:from_list(Ws)
end,
- fun test_rb_sets_words/2).
+ fun test_patricia_words/2).
-ifdef(EUNIT).
-ifdef(EQC).
View
42 src/patricia.erl
@@ -6,7 +6,7 @@
-define(BIT_MAX, 27). % Set by virtue of erlang:phash2
-type ptree(A) :: empty | {leaf, [A]} | {node, pos_integer(), ptree(A), ptree(A)}.
--spec insert(A, ptree(A)) -> ptree(A) | already.
+
hash(X) ->
erlang:phash2(X).
@@ -20,13 +20,15 @@ from_list(L) ->
new() ->
empty.
+-spec insert(A, ptree(A)) -> ptree(A) | already.
insert(E, empty) ->
{leaf, [E]};
insert(E, Tree) ->
H = hash(E),
{Bit, Lt} = find_bit(H, Tree),
insert(H, E, Bit, Lt, Tree).
+-spec find_bit(integer(), ptree(_)) -> {pos_integer(), boolean()}.
find_bit(H, {leaf, [A | _]}) ->
H1 = hash(A),
crit_bit(H, H1);
@@ -39,21 +41,23 @@ find_bit(H, {node, Bit, Left, Right}) ->
crit_bit(I1, I2) ->
crit_bit(I1, I2, ?BIT_MAX).
-cmp_lt_bit(I1, I2, N) ->
- Bit = (1 bsr N),
- (Bit band I1) < (Bit band I2).
-
crit_bit(I1, I2, N) ->
- Bit = (1 bsr N),
+ Bit = (1 bsl N),
case (Bit band I1) bxor (Bit band I2) of
0 ->
crit_bit(I1, I2, N-1);
_ ->
{N, cmp_lt_bit(I1, I2, N)}
end.
+-spec cmp_lt_bit(integer(), integer(), pos_integer()) -> boolean().
+cmp_lt_bit(I1, I2, N) ->
+ Bit = (1 bsl N),
+ (Bit band I1) < (Bit band I2).
+
+
inspect_bit(H, Bit) ->
- case H band (1 bsr Bit) of
+ case H band (1 bsl Bit) of
0 -> left;
_ -> right
end.
@@ -74,9 +78,9 @@ insert(_H, E, Bit, Lt, {leaf, Es} = Lf) ->
insert(H, E, Bit, Lt, {node, CBit, Left, Right}) when Bit < CBit ->
case inspect_bit(H, CBit) of
left ->
- {node, CBit, insert(H, E, Lt, Bit, Left), Right};
+ {node, CBit, insert(H, E, Bit, Lt, Left), Right};
right ->
- {node, CBit, Left, insert(H, E, Lt, Bit, Right)}
+ {node, CBit, Left, insert(H, E, Bit, Lt, Right)}
end;
insert(_H, E, Bit, Lt, {node, CBit, _Left, _Right} = N) when Bit > CBit ->
case Lt of
@@ -88,23 +92,21 @@ insert(_H, E, Bit, Lt, {node, CBit, _Left, _Right} = N) when Bit > CBit ->
is_element(Key, Tree) ->
H = hash(Key),
- is_element1(H, Key, 0, Tree).
+ is_element(H, Key, Tree).
-is_element1(_, _, _, empty) -> false;
-is_element1(_H, Key, _Cnt, {leaf, Elems}) ->
+is_element(_, _, empty) -> false;
+is_element(_H, Key, {leaf, Elems}) ->
lists:member(Key, Elems);
-is_element1(H, Key, Cnt, {node, Bit, L, R}) ->
- case H band (1 bsr (Cnt + Bit)) of
- 0 -> is_element1(H, Key, Cnt+Bit, L);
- 1 -> is_element1(H, Key, Cnt+Bit, R)
+is_element(H, Key, {node, Bit, L, R}) ->
+ case inspect_bit(H, Bit) of
+ left ->
+ is_element(H, Key, L);
+ right ->
+ is_element(H, Key, R)
end.
-
-
-
-

0 comments on commit 4dcfbf8

Please sign in to comment.