All sorts of things.

This commit is contained in:
Gregory Burd 2013-11-15 13:43:54 -05:00
parent 146bb62380
commit fece77ec72
7 changed files with 138 additions and 56 deletions

146
Makefile
View file

@ -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 # Source: https://gist.github.com/ericbmerritt/5706091
ERL= /usr/bin/env erl
DIALYZER= /usr/bin/env dialyzer
REBAR= /usr/bin/env rebar ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/deps/*/ebin
ifdef suites
SUITE_OPTION := suites=$(suites) 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 endif
ifdef tests
TESTS_OPTION := tests=$(tests) REBAR=$(shell which rebar)
ifeq ($(REBAR),)
$(error "Rebar not available on this system")
endif 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: deps:
$(REBAR) get-deps $(REBAR) get-deps
compile: deps
$(REBAR) compile $(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: 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 distclean: clean
$(REBAR) delete-deps - rm -rf $(DEPS_PLT)
- rm -rvf $(CURDIR)/deps
eunit: test rebuild: distclean deps compile escript dialyzer 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").'

View file

@ -1,6 +1,6 @@
%%% -*- mode: erlang -*- %%% -*- mode: erlang -*-
{require_otp_vsn, "R15"}. {require_otp_vsn, "R1[56]"}.
{cover_enabled, true}. {cover_enabled, true}.
@ -21,7 +21,8 @@
warn_obsolete_guard, warn_obsolete_guard,
warn_export_vars, warn_export_vars,
warn_exported_vars, warn_exported_vars,
warn_untyped_record warn_untyped_record,
inline, native, {hipe, [o2]}
%warn_missing_spec, %warn_missing_spec,
%strict_validation %strict_validation
%{parse_transform, lager_transform}, %{parse_transform, lager_transform},

View file

@ -33,6 +33,11 @@ count(X, Acc) -> count((X band (X - 1)), (Acc + 1)).
-endif. -endif.
%-ifdef(WORKING_METHOD_2). % Works well enough %-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(0) -> 0;
count(X) count(X)
when is_integer(X), X > 0, X < 16#FFFFFFFF -> when is_integer(X), X > 0, X < 16#FFFFFFFF ->

View file

@ -4,16 +4,15 @@
%% %%
%% Copyright (C) 2013 Gregory Burd. All Rights Reserved. %% Copyright (C) 2013 Gregory Burd. All Rights Reserved.
%% %%
%% The contents of this file are subject to the Mozilla Public License, %% The contents of this file are subject to the Mozilla Public License, Version
%% Version 2, (the "License"); you may not use this file except in %% 2, (the "License"); you may not use this file except in compliance with the
%% compliance with the License. You should have received a copy of the %% License. You should have received a copy of the Mozilla Public License along
%% Mozilla Public License along with this software. If not, it can be %% with this software. If not, it can be retrieved online at
%% retrieved online at http://www.mozilla.org/MPL/ %% http://www.mozilla.org/MPL/
%% %%
%% Software distributed under the License is distributed on an "AS IS" %% Software distributed under the License is distributed on an "AS IS" basis,
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
%% the License for the specific language governing rights and limitations %% the specific language governing rights and limitations under the License.
%% under the License.
%% %%
%% %CopyrightEnd% %% %CopyrightEnd%
%% %%
@ -81,6 +80,7 @@
-ifdef(EQC). -ifdef(EQC).
-include_lib("eqc/include/eqc.hrl"). -include_lib("eqc/include/eqc.hrl").
-include_lib("eqc/include/eqc_fsm.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. -endif.
-compile(export_all). -compile(export_all).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@ -165,6 +165,7 @@ get(Key, {hamt, HashSize, {cnode, _Bitmap, _Nodes}=CN}) ->
{error, not_found} {error, not_found}
end. 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 -> get_1(Hash, {cnode, Bitmap, Nodes}, L, M) when L =< M ->
Bit = bitpos(Hash, L), Bit = bitpos(Hash, L),
case exists(Bit, Bitmap) of case exists(Bit, Bitmap) of
@ -181,6 +182,7 @@ get_1(_Hash, {lnode, List}, _L, _M)
when is_list(List) -> when is_list(List) ->
{list, List}. {list, List}.
-spec get_2(_,maybe_improper_list()) -> 'none' | {_,_}.
get_2(_Key, []) -> get_2(_Key, []) ->
none; none;
get_2(Key, [{Key, Value} | _Rest]) -> get_2(Key, [{Key, Value} | _Rest]) ->
@ -215,6 +217,7 @@ put(Key, Value, {hamt, HashSize, nil}) ->
put(Key, Value, {hamt, HashSize, Node}) -> put(Key, Value, {hamt, HashSize, Node}) ->
{hamt, HashSize, put_1(hash(HashSize, Key), Key, Value, Node, 0, max_depth(HashSize))}. {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) put_1(Hash, Key, Value, {cnode, Bitmap, Nodes}, L, M)
when L =< M -> when L =< M ->
Bit = bitpos(Hash, L), Bit = bitpos(Hash, L),
@ -230,7 +233,7 @@ put_1(_Hash, Key, Value, {snode, Key, _}, _L, _M) ->
{snode, Key, Value}; {snode, Key, Value};
put_1(Hash, Key, Value, {snode, SNKey, SNValue}, L, M) put_1(Hash, Key, Value, {snode, SNKey, SNValue}, L, M)
when 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, Key, Value, CN, L, M);
put_1(_Hash, Key1, Value1, {snode, Key2, Value2}, L, M) put_1(_Hash, Key1, Value1, {snode, Key2, Value2}, L, M)
when L > M -> when L > M ->

View file

@ -9,8 +9,10 @@
%% Application callbacks %% Application callbacks
%% =================================================================== %% ===================================================================
-spec start(_,_) -> 'ignore' | {'error',_} | {'ok',pid()}.
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
hamt_sup:start_link(). hamt_sup:start_link().
-spec stop(_) -> 'ok'.
stop(_State) -> stop(_State) ->
ok. ok.

View file

@ -16,6 +16,7 @@
%% API functions %% API functions
%% =================================================================== %% ===================================================================
-spec start_link() -> 'ignore' | {'error',_} | {'ok',pid()}.
start_link() -> start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
@ -23,5 +24,6 @@ start_link() ->
%% Supervisor callbacks %% Supervisor callbacks
%% =================================================================== %% ===================================================================
-spec init([]) -> {'ok', term()}.
init([]) -> init([]) ->
{ok, { {one_for_one, 5, 10}, []} }. {ok, { {one_for_one, 5, 10}, []} }.

View file

@ -26,22 +26,27 @@
-define(MASK32, 16#FFFFFFFF). -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. 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) -> hash32_mmix(K1) ->
K2 = (K1 * 16#CC9E2D51) band ?MASK32, K2 = (K1 * 16#CC9E2D51) band ?MASK32,
K3 = rotl32(K2, 15), K3 = rotl32(K2, 15),
(K3 * 16#1B873593) band ?MASK32. (K3 * 16#1B873593) band ?MASK32.
-spec hash32_fmix(integer()) -> non_neg_integer().
hash32_fmix(H) -> hash32_fmix(H) ->
H2 = ((H bxor (H bsr 16)) * 16#85EBCA6B) band ?MASK32, H2 = ((H bxor (H bsr 16)) * 16#85EBCA6B) band ?MASK32,
H3 = ((H2 bxor (H2 bsr 13)) * 16#C2B2AE35) band ?MASK32, H3 = ((H2 bxor (H2 bsr 13)) * 16#C2B2AE35) band ?MASK32,
H3 bxor (H3 bsr 16). H3 bxor (H3 bsr 16).
-spec hash32_tail_mix(non_neg_integer(),integer()) -> integer().
hash32_tail_mix(K1, Hash) -> hash32_tail_mix(K1, Hash) ->
Hash bxor hash32_mmix(K1). Hash bxor hash32_mmix(K1).
% 4-byte blocks % 4-byte blocks
-spec hash32_body(binary(),_) -> non_neg_integer().
hash32_body(<<K1:32/little, Rest/binary>>, Hash) -> hash32_body(<<K1:32/little, Rest/binary>>, Hash) ->
K2 = hash32_mmix(K1), K2 = hash32_mmix(K1),
Hash2 = Hash bxor K2, 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(<<K1:24/little>>, Hash) -> hash32_tail_mix(K1, Hash);
hash32_body(<<>>, Hash) -> Hash. hash32_body(<<>>, Hash) -> Hash.
-spec hash32_impl(binary(),_) -> non_neg_integer().
hash32_impl(Data, Seed) -> hash32_impl(Data, Seed) ->
Len = byte_size(Data), Len = byte_size(Data),
hash32_fmix(hash32_body(Data, Seed) bxor Len). 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) when is_binary(Data) -> hash32_impl(Data, Seed);
hash32(Data, Seed) -> hash32(term_to_binary(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. hash32(Data) -> hash32(Data, 16#9E3779B9). % Seed is "golden ratio" FWIW.
-spec hash(_) -> non_neg_integer().
hash(Data) -> hash32(Data). hash(Data) -> hash32(Data).
-spec hash(32,_) -> non_neg_integer().
hash(32, Data) -> hash32(Data). hash(32, Data) -> hash32(Data).
-spec hash(32,_,_) -> non_neg_integer().
hash(32, Data, Seed) -> hash32(Data, Seed). hash(32, Data, Seed) -> hash32(Data, Seed).