blob: f4469d71e941d529f20f816fd1e4082df64c5ded [file] [log] [blame]
-module(hyper_array).
-export([new/1, get/2, set/3, fold/3, max_merge/2, bytes/1]).
-export([register_sum/1, zero_count/1, encode_registers/1, decode_registers/2, compact/1]).
-behaviour(hyper_register).
new(P) ->
M = trunc(math:pow(2, P)),
array:new([{size, M}, {fixed, true}, {default, 0}]).
get(Index, A) ->
case array:get(Index, A) of
0 ->
undefined;
Value ->
{ok, Value}
end.
set(Index, Value, A) ->
array:set(Index, Value, A).
fold(F, Acc, A) ->
array:sparse_foldl(F, Acc, A).
max_merge(Left, Right) ->
fold(fun (Index, L, Registers) ->
case get(Index, Registers) of
{ok, R} when R < L ->
set(Index, L, Registers);
{ok, _} ->
Registers;
undefined ->
set(Index, L, Registers)
end
end, Right, Left).
bytes(A) ->
erts_debug:flat_size(A) * 8.
register_sum(A) ->
array:foldl(fun (_, Value, Sum) ->
Sum + math:pow(2, -Value)
end, 0, A).
zero_count(A) ->
array:foldl(fun (_, 0, Sum) -> Sum + 1;
(_, _, Sum) -> Sum
end, 0, A).
compact(A) ->
A.
encode_registers(A) ->
iolist_to_binary(
lists:reverse(
array:foldl(fun (_, V, Acc) -> [<<V:8/integer>> | Acc] end,
[], A))).
decode_registers(Bytes, P) ->
do_decode_registers(Bytes, 0, new(P)).
do_decode_registers(<<>>, _, A) ->
A;
do_decode_registers(<<Value:8/integer, Rest/binary>>, I, A) ->
NewA = case Value of
0 -> A;
N -> array:set(I, N, A)
end,
do_decode_registers(Rest, I+1, NewA).