diff --git a/.gitignore b/.gitignore index 2eddf61..457a738 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ erl_crash.dump # Ignore package tarball (built via "mix hex.build"). blex-*.tar +.elixir_ls diff --git a/lib/blex.ex b/lib/blex.ex index 13b98f5..5c654b1 100644 --- a/lib/blex.ex +++ b/lib/blex.ex @@ -164,6 +164,8 @@ defmodule Blex do @range 1 <<< 32 + @spec get_hash_fn(hash_id()) :: hash_function() + # for b <= 16, it requires one :erlang.phash2 call defp get_hash_fn(201) do fn @@ -172,7 +174,7 @@ defmodule Blex do <> = <> {h1, {m, h1, h2}} - i, {m, h1, h2} = acc -> + i, {m, h1, h2} = acc when is_integer(h1) and is_integer(h2) -> {rem(h1 + i * h2, m), acc} end end @@ -184,11 +186,11 @@ defmodule Blex do h1 = :erlang.phash2(item, m) {h1, {item, m, h1}} - 1, {item, m, h1} -> + 1, {item, m, h1} when is_integer(h1) -> h2 = :erlang.phash2([item], m) {rem(h1 + h2, m), {h1, h2, m}} - i, {h1, h2, m} = acc -> + i, {h1, h2, m} = acc when is_integer(h1) and is_integer(h2) -> {rem(h1 + i * h2, m), acc} end end @@ -207,7 +209,7 @@ defmodule Blex do <> = <> {rem(h1 + h2, m), {h1, h2, m}} - i, {h1, h2, m} = acc -> + i, {h1, h2, m} = acc when is_integer(h1) and is_integer(h2) -> {rem(h1 + i * h2, m), acc} end end @@ -327,6 +329,16 @@ defmodule Blex do set_all(0, k, a, {item, b, m}, hash_fn, 64, m) end + @spec set_all( + integer(), + integer(), + :atomics.atomics_ref(), + {any(), integer(), integer()}, + hash_function(), + integer(), + integer() + ) :: :ok + defp set_all(k, k, _, _, _, _, _), do: :ok defp set_all(i, k, a, acc, f, base, m) do @@ -337,6 +349,8 @@ defmodule Blex do set_all(i + 1, k, a, new_acc, f, base + m, m) end + @spec set(:atomics.atomics_ref(), integer(), integer(), integer()) :: :ok + defp set(a, index, bits, origin) do case origin ||| bits do ^origin -> @@ -386,6 +400,16 @@ defmodule Blex do check_member_for_binary(0, k, bin, {item, b, m}, f, max, m) end + @spec check_member( + integer(), + integer(), + :atomics.atomics_ref(), + {any(), integer(), integer()}, + hash_function(), + integer(), + integer() + ) :: boolean() + defp check_member(k, k, _, _, _, _, _), do: true defp check_member(i, k, a, acc, f, base, m) do @@ -402,6 +426,16 @@ defmodule Blex do end end + @spec check_member_for_binary( + integer(), + integer(), + binary(), + {any(), integer(), integer()}, + hash_function(), + integer(), + integer() + ) :: boolean() + defp check_member_for_binary(k, k, _, _, _, _, _), do: true defp check_member_for_binary(i, k, bin, acc, f, max, m) do @@ -471,6 +505,8 @@ defmodule Blex do round(-m * :math.log(1 / m)) end + @spec count_bits_for_bin(binary(), integer()) :: integer() + defp count_bits_for_bin(<>, acc) do count_bits_for_bin(rest, acc + count_64_bits(x)) end @@ -509,6 +545,8 @@ defmodule Blex do """ + @spec estimate_memory(t() | binary()) :: non_neg_integer() + def estimate_memory(%__MODULE__{a: a} = _blex) do :atomics.info(a).memory end @@ -538,6 +576,8 @@ defmodule Blex do """ + @spec estimate_capacity(t() | binary()) :: non_neg_integer() + def estimate_capacity(%__MODULE__{m: m}) do compute_estimated_capacity(m) end @@ -606,6 +646,8 @@ defmodule Blex do blex end + @spec copy_data(binary(), :atomics.atomics_ref(), integer()) :: :ok + defp copy_data(<>, a, i) do :atomics.put(a, i, x) copy_data(rest, a, i - 1) @@ -647,9 +689,9 @@ defmodule Blex do {hash_id, k, b, f_first} = transform(first) f_rest = - Enum.reduce(rest, [], fn it, acc -> + Enum.map(rest, fn it -> {^hash_id, ^k, ^b, f} = transform(it) - [f | acc] + f end) dest = create_instance(hash_id, k, b) @@ -727,9 +769,9 @@ defmodule Blex do {hash_id, k, b, f_first} = transform(first) f_rest = - Enum.reduce(rest, [], fn it, acc -> + Enum.map(rest, fn it -> {^hash_id, ^k, ^b, f} = transform(it) - [f | acc] + f end) size = div((1 <<< b) * k, 64) diff --git a/mix.exs b/mix.exs index 8f4ced2..9c470cb 100644 --- a/mix.exs +++ b/mix.exs @@ -30,6 +30,7 @@ defmodule Blex.MixProject do {:murmur, "~> 1.0", only: [:dev, :test]}, {:stream_data, "~> 0.4", only: [:dev, :test]}, {:ex_doc, "~> 0.19", only: :dev, runtime: false}, + {:ex_type, "~> 0.4.0", only: :dev, runtime: true}, {:dialyxir, "~> 1.0.0-rc.4", only: :dev, runtime: false} ] end diff --git a/mix.lock b/mix.lock index cce475b..10ca2e8 100644 --- a/mix.lock +++ b/mix.lock @@ -6,6 +6,8 @@ "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"}, "erlex": {:hex, :erlex, "0.1.6", "c01c889363168d3fdd23f4211647d8a34c0f9a21ec726762312e08e083f3d47e", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.19.2", "6f4081ccd9ed081b6dc0bd5af97a41e87f5554de469e7d76025fba535180565f", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_type": {:hex, :ex_type, "0.4.0", "7c93a0e64956192d0a7319ad7431471331b33377c7476b4ce61d173d474b1fa0", [:mix], [{:ex_type_runtime, "~> 0.1.0", [hex: :ex_type_runtime, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_type_runtime": {:hex, :ex_type_runtime, "0.1.0", "c7557490c969aacaaada89b30213d3572b615b5ef29c6617f1b588b1213a5127", [:mix], [], "hexpm"}, "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "murmur": {:hex, :murmur, "1.0.1", "a6e6bced2dd0d666090a9cf3e73699f3b9176bbcf32d35b0f022f137667608e3", [:mix], [], "hexpm"},