All sorts of things.
This commit is contained in:
parent
146bb62380
commit
fece77ec72
7 changed files with 138 additions and 56 deletions
146
Makefile
146
Makefile
|
@ -1,58 +1,116 @@
|
|||
TARGET= hamt
|
||||
# Copyright 2012 Erlware, LLC. All Rights Reserved.
|
||||
#
|
||||
# This file is provided to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
|
||||
REBAR= /usr/bin/env rebar
|
||||
ERL= /usr/bin/env erl
|
||||
DIALYZER= /usr/bin/env dialyzer
|
||||
REBAR= /usr/bin/env rebar
|
||||
ifdef suites
|
||||
SUITE_OPTION := suites=$(suites)
|
||||
# Source: https://gist.github.com/ericbmerritt/5706091
|
||||
|
||||
|
||||
ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/deps/*/ebin
|
||||
|
||||
DEPS_PLT=$(CURDIR)/.deps_plt
|
||||
DEPS=erts kernel stdlib
|
||||
|
||||
# =============================================================================
|
||||
# Verify that the programs we need to run are installed on this system
|
||||
# =============================================================================
|
||||
ERL = $(shell which erl)
|
||||
|
||||
ifeq ($(ERL),)
|
||||
$(error "Erlang not available on this system")
|
||||
endif
|
||||
ifdef tests
|
||||
TESTS_OPTION := tests=$(tests)
|
||||
|
||||
REBAR=$(shell which rebar)
|
||||
|
||||
ifeq ($(REBAR),)
|
||||
$(error "Rebar not available on this system")
|
||||
endif
|
||||
EUNIT_OPTIONS := $(SUITE_OPTION) $(TESTS_OPTION)
|
||||
|
||||
.PHONY: deps test
|
||||
DIALYZER=$(shell which dialyzer)
|
||||
|
||||
all: deps compile
|
||||
ifeq ($(DIALYZER),)
|
||||
$(error "Dialyzer not available on this system")
|
||||
endif
|
||||
|
||||
TYPER=$(shell which typer)
|
||||
|
||||
ifeq ($(TYPER),)
|
||||
$(error "Typer not available on this system")
|
||||
endif
|
||||
|
||||
.PHONY: all compile doc clean test dialyzer typer shell distclean pdf \
|
||||
update-deps clean-common-test-data rebuild
|
||||
|
||||
all: deps compile dialyzer test
|
||||
|
||||
# =============================================================================
|
||||
# Rules to build the system
|
||||
# =============================================================================
|
||||
|
||||
deps:
|
||||
$(REBAR) get-deps
|
||||
|
||||
compile: deps
|
||||
$(REBAR) compile
|
||||
|
||||
update-deps:
|
||||
$(REBAR) update-deps
|
||||
$(REBAR) compile
|
||||
|
||||
compile:
|
||||
$(REBAR) skip_deps=true compile
|
||||
|
||||
doc:
|
||||
$(REBAR) skip_deps=true doc
|
||||
|
||||
eunit: compile clean-common-test-data
|
||||
$(REBAR) skip_deps=true eunit
|
||||
|
||||
test: compile eunit
|
||||
|
||||
$(DEPS_PLT):
|
||||
@echo Building local plt at $(DEPS_PLT)
|
||||
@echo
|
||||
$(DIALYZER) --output_plt $(DEPS_PLT) --build_plt \
|
||||
--apps $(DEPS) -r deps
|
||||
|
||||
dialyzer: $(DEPS_PLT)
|
||||
$(DIALYZER) --fullpath --plt $(DEPS_PLT) -Wrace_conditions -r ./ebin
|
||||
|
||||
typer:
|
||||
$(TYPER) --plt $(DEPS_PLT) -r ./src
|
||||
|
||||
xref:
|
||||
$(REBAR) xref skip_deps=true
|
||||
|
||||
# You often want *rebuilt* rebar tests to be available to the shell you have to
|
||||
# call eunit (to get the tests rebuilt). However, eunit runs the tests, which
|
||||
# probably fails (thats probably why You want them in the shell). This
|
||||
# (prefixing the command with "-") runs eunit but tells make to ignore the
|
||||
# result.
|
||||
shell: deps compile
|
||||
- @$(REBAR) skip_deps=true eunit
|
||||
@$(ERL) $(ERLFLAGS)
|
||||
|
||||
pdf:
|
||||
pandoc README.md -o README.pdf
|
||||
|
||||
clean:
|
||||
$(REBAR) clean
|
||||
- c_src/build_deps.sh clean
|
||||
- rm -rf $(CURDIR)/test/*.beam
|
||||
- rm -rf $(CURDIR)/logs
|
||||
- rm -rf $(CURDIR)/ebin
|
||||
$(REBAR) skip_deps=true clean
|
||||
|
||||
distclean: clean
|
||||
$(REBAR) delete-deps
|
||||
- rm -rf $(DEPS_PLT)
|
||||
- rm -rvf $(CURDIR)/deps
|
||||
|
||||
eunit: test
|
||||
|
||||
test: compile
|
||||
$(REBAR) skip_deps=true $(EUNIT_OPTIONS) eunit
|
||||
|
||||
console: compile
|
||||
erl -pa ebin deps/*/ebin
|
||||
|
||||
plt: compile
|
||||
@$(DIALYZER) --build_plt --output_plt .$(TARGET).plt \
|
||||
-pa deps/plain_fsm/ebin \
|
||||
deps/plain_fsm/ebin \
|
||||
--apps kernel stdlib
|
||||
|
||||
analyze: compile
|
||||
$(DIALYZER) --plt .$(TARGET).plt \
|
||||
-pa deps/plain_fsm/ebin \
|
||||
-pa deps/ebloom/ebin \
|
||||
ebin
|
||||
|
||||
repl:
|
||||
$(ERL) -pz deps/*/ebin -pa ebin
|
||||
|
||||
eunit-repl:
|
||||
erl -pa .eunit -pz deps/*/ebin -pz ebin -exec 'cd(".eunit").'
|
||||
|
||||
gdb-eunit-repl:
|
||||
USE_GDB=1 erl -pa .eunit -pz deps/*/ebin -pz ebin -exec 'cd(".eunit").'
|
||||
rebuild: distclean deps compile escript dialyzer test
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%%% -*- mode: erlang -*-
|
||||
|
||||
{require_otp_vsn, "R15"}.
|
||||
{require_otp_vsn, "R1[56]"}.
|
||||
|
||||
{cover_enabled, true}.
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
|||
warn_obsolete_guard,
|
||||
warn_export_vars,
|
||||
warn_exported_vars,
|
||||
warn_untyped_record
|
||||
warn_untyped_record,
|
||||
inline, native, {hipe, [o2]}
|
||||
%warn_missing_spec,
|
||||
%strict_validation
|
||||
%{parse_transform, lager_transform},
|
||||
|
|
|
@ -33,6 +33,11 @@ count(X, Acc) -> count((X band (X - 1)), (Acc + 1)).
|
|||
-endif.
|
||||
|
||||
%-ifdef(WORKING_METHOD_2). % Works well enough
|
||||
-spec count(non_neg_integer()) -> char().
|
||||
-spec c1(pos_integer()) -> integer().
|
||||
-spec c2(pos_integer()) -> non_neg_integer().
|
||||
-spec c3(pos_integer()) -> non_neg_integer().
|
||||
-spec c4(pos_integer()) -> non_neg_integer().
|
||||
count(0) -> 0;
|
||||
count(X)
|
||||
when is_integer(X), X > 0, X < 16#FFFFFFFF ->
|
||||
|
|
23
src/hamt.erl
23
src/hamt.erl
|
@ -4,16 +4,15 @@
|
|||
%%
|
||||
%% Copyright (C) 2013 Gregory Burd. All Rights Reserved.
|
||||
%%
|
||||
%% The contents of this file are subject to the Mozilla Public License,
|
||||
%% Version 2, (the "License"); you may not use this file except in
|
||||
%% compliance with the License. You should have received a copy of the
|
||||
%% Mozilla Public License along with this software. If not, it can be
|
||||
%% retrieved online at http://www.mozilla.org/MPL/
|
||||
%% The contents of this file are subject to the Mozilla Public License, Version
|
||||
%% 2, (the "License"); you may not use this file except in compliance with the
|
||||
%% License. You should have received a copy of the Mozilla Public License along
|
||||
%% with this software. If not, it can be retrieved online at
|
||||
%% http://www.mozilla.org/MPL/
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and limitations
|
||||
%% under the License.
|
||||
%% Software distributed under the License is distributed on an "AS IS" basis,
|
||||
%% WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
%% the specific language governing rights and limitations under the License.
|
||||
%%
|
||||
%% %CopyrightEnd%
|
||||
%%
|
||||
|
@ -81,6 +80,7 @@
|
|||
-ifdef(EQC).
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
-include_lib("eqc/include/eqc_fsm.hrl").
|
||||
-define(QC_OUT(P), eqc:on_output(fun(Str, Args) -> io:format(user, Str, Args) end, P)).
|
||||
-endif.
|
||||
-compile(export_all).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
@ -165,6 +165,7 @@ get(Key, {hamt, HashSize, {cnode, _Bitmap, _Nodes}=CN}) ->
|
|||
{error, not_found}
|
||||
end.
|
||||
|
||||
-spec get_1(non_neg_integer(),_,non_neg_integer(),30 | 125 | 160) -> 'none' | {_,_}.
|
||||
get_1(Hash, {cnode, Bitmap, Nodes}, L, M) when L =< M ->
|
||||
Bit = bitpos(Hash, L),
|
||||
case exists(Bit, Bitmap) of
|
||||
|
@ -181,6 +182,7 @@ get_1(_Hash, {lnode, List}, _L, _M)
|
|||
when is_list(List) ->
|
||||
{list, List}.
|
||||
|
||||
-spec get_2(_,maybe_improper_list()) -> 'none' | {_,_}.
|
||||
get_2(_Key, []) ->
|
||||
none;
|
||||
get_2(Key, [{Key, Value} | _Rest]) ->
|
||||
|
@ -215,6 +217,7 @@ put(Key, Value, {hamt, HashSize, nil}) ->
|
|||
put(Key, Value, {hamt, HashSize, Node}) ->
|
||||
{hamt, HashSize, put_1(hash(HashSize, Key), Key, Value, Node, 0, max_depth(HashSize))}.
|
||||
|
||||
-spec put_1(non_neg_integer(),_,_,{'lnode',maybe_improper_list()} | {'cnode',integer(),[any()]} | {'snode',_,_},non_neg_integer(),30 | 125 | 160) -> {'lnode',nonempty_maybe_improper_list()} | {'cnode',integer(),[any(),...]} | {'snode',_,_}.
|
||||
put_1(Hash, Key, Value, {cnode, Bitmap, Nodes}, L, M)
|
||||
when L =< M ->
|
||||
Bit = bitpos(Hash, L),
|
||||
|
@ -230,7 +233,7 @@ put_1(_Hash, Key, Value, {snode, Key, _}, _L, _M) ->
|
|||
{snode, Key, Value};
|
||||
put_1(Hash, Key, Value, {snode, SNKey, SNValue}, L, M)
|
||||
when L =< M ->
|
||||
CN = {cnode, bitpos(Hash, L), [{snode, SNKey, SNValue}]},
|
||||
CN = {cnode, bitpos(Hash, L), [{snode, SNKey, SNValue}]}, %% TODO: wrong hash XXX
|
||||
put_1(Hash, Key, Value, CN, L, M);
|
||||
put_1(_Hash, Key1, Value1, {snode, Key2, Value2}, L, M)
|
||||
when L > M ->
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
%% Application callbacks
|
||||
%% ===================================================================
|
||||
|
||||
-spec start(_,_) -> 'ignore' | {'error',_} | {'ok',pid()}.
|
||||
start(_StartType, _StartArgs) ->
|
||||
hamt_sup:start_link().
|
||||
|
||||
-spec stop(_) -> 'ok'.
|
||||
stop(_State) ->
|
||||
ok.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
%% API functions
|
||||
%% ===================================================================
|
||||
|
||||
-spec start_link() -> 'ignore' | {'error',_} | {'ok',pid()}.
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
|
@ -23,5 +24,6 @@ start_link() ->
|
|||
%% Supervisor callbacks
|
||||
%% ===================================================================
|
||||
|
||||
-spec init([]) -> {'ok', term()}.
|
||||
init([]) ->
|
||||
{ok, { {one_for_one, 5, 10}, []} }.
|
||||
|
|
|
@ -26,22 +26,27 @@
|
|||
|
||||
-define(MASK32, 16#FFFFFFFF).
|
||||
|
||||
-spec rotl32(integer(),13 | 15) -> non_neg_integer().
|
||||
rotl32(Num, R) -> ((Num bsl R) bor (Num bsr (32 - R))) band ?MASK32.
|
||||
|
||||
-spec hash32_mmix(non_neg_integer()) -> non_neg_integer().
|
||||
hash32_mmix(K1) ->
|
||||
K2 = (K1 * 16#CC9E2D51) band ?MASK32,
|
||||
K3 = rotl32(K2, 15),
|
||||
(K3 * 16#1B873593) band ?MASK32.
|
||||
|
||||
-spec hash32_fmix(integer()) -> non_neg_integer().
|
||||
hash32_fmix(H) ->
|
||||
H2 = ((H bxor (H bsr 16)) * 16#85EBCA6B) band ?MASK32,
|
||||
H3 = ((H2 bxor (H2 bsr 13)) * 16#C2B2AE35) band ?MASK32,
|
||||
H3 bxor (H3 bsr 16).
|
||||
|
||||
-spec hash32_tail_mix(non_neg_integer(),integer()) -> integer().
|
||||
hash32_tail_mix(K1, Hash) ->
|
||||
Hash bxor hash32_mmix(K1).
|
||||
|
||||
% 4-byte blocks
|
||||
-spec hash32_body(binary(),_) -> non_neg_integer().
|
||||
hash32_body(<<K1:32/little, Rest/binary>>, Hash) ->
|
||||
K2 = hash32_mmix(K1),
|
||||
Hash2 = Hash bxor K2,
|
||||
|
@ -54,15 +59,21 @@ hash32_body(<<K1:16/little>>, Hash) -> hash32_tail_mix(K1, Hash);
|
|||
hash32_body(<<K1:24/little>>, Hash) -> hash32_tail_mix(K1, Hash);
|
||||
hash32_body(<<>>, Hash) -> Hash.
|
||||
|
||||
-spec hash32_impl(binary(),_) -> non_neg_integer().
|
||||
hash32_impl(Data, Seed) ->
|
||||
Len = byte_size(Data),
|
||||
hash32_fmix(hash32_body(Data, Seed) bxor Len).
|
||||
|
||||
-spec hash32(_,_) -> non_neg_integer().
|
||||
hash32(Data, Seed) when is_binary(Data) -> hash32_impl(Data, Seed);
|
||||
hash32(Data, Seed) -> hash32(term_to_binary(Data), Seed).
|
||||
|
||||
-spec hash32(_) -> non_neg_integer().
|
||||
hash32(Data) -> hash32(Data, 16#9E3779B9). % Seed is "golden ratio" FWIW.
|
||||
|
||||
-spec hash(_) -> non_neg_integer().
|
||||
hash(Data) -> hash32(Data).
|
||||
-spec hash(32,_) -> non_neg_integer().
|
||||
hash(32, Data) -> hash32(Data).
|
||||
-spec hash(32,_,_) -> non_neg_integer().
|
||||
hash(32, Data, Seed) -> hash32(Data, Seed).
|
||||
|
|
Loading…
Reference in a new issue