Packages
fixpoint
0.8.5
0.22.1
0.21.5
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.6
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.18.2
0.18.1
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.13.5
0.13.4
0.13.2
0.13.1
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.2
0.12.1
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.46
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.28
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.1.3
0.1.2
0.1.1
0.1.0
Constraint Programming Solver
Current section
Files
Jump to
Current section
Files
src/bitset.erl.save
-module(bitset).
-export([new/0, new/1, from_list/1, insert/2,
intersect/1, union/1, difference/2,
contains/2, foldl/3, foldr/3,
pmap/2]).
%% Create a new bitset, with no bits set.
%% return A new bitset
new() ->
{ ?MODULE, { 1, 0 }}.
%% Create a new bitset from the entries in the given list of numbers
%% Elems A list of integers that should be set in this new bitset
new(Elems) when is_list(Elems) ->
from_list(Elems, new()).
from_list(Elems) when is_list(Elems) ->
from_list(Elems, new()).
%% Put a given Key (non-negative integer) into the bitset
%% Key Non-negative integer to be stored in the set
%% Set The set in which to store the key
%% return A new bitset, with the desired key set
insert(Key, { ?MODULE, Tree = { Depth, _}}) when is_integer(Key), Key >= 0 ->
{ ToMake, Path } = split_key(Depth, Key),
LargeEnough = grow(ToMake, Tree),
{ ?MODULE, set(Path, LargeEnough) }.
%% Determine the intersection of the given list of bitsets. The resulting
%% bitset will have bits set where all given sets had them set, and nowhere
%% else.
%% List A list of bitsets
%% return A new bitset that is the intersection of the given bitsets
intersect([]) -> bitset:new();
intersect([Final]) -> Final;
intersect([{ ?MODULE, First }, { ?MODULE, Second } | Rest]) ->
intersect([{ ?MODULE, imerge(First, Second)} | Rest]).
%% Determine the union of the given list of bitsets. The resulting bitset will
%% have bits set where any of the given sets had them set, and nowhere else.
%% List A list of bitsets to union together
%% return A new bitset which is the union of the given bitsets
union([]) -> bitset:new();
union([Final]) -> Final;
union([{ ?MODULE, First }, { ?MODULE, Second } | Rest]) ->
union([{ ?MODULE, umerge(First, Second)} | Rest]).
difference({ ?MODULE, Left = { LD, _ }}, { ?MODULE, Right = { RD, _ }}) ->
{ SLeft, SRight } = if
LD < RD ->
{ grow(RD-LD, Left), Right };
LD > RD ->
{ Left, grow(LD-RD, Right) };
LD =:= RD ->
{ Left, Right }
end,
{ ?MODULE, diff_eq(SLeft, SRight) }.
%% Test whether a bit is set in the given bitset.
%% Key The key to test
%% Set The bitset to test against
%% return true of that bit is set, false otherwise
contains(Key, { ?MODULE, { Depth, _ } = Tree })
when is_integer(Key), Key >= 0 ->
case split_key(Depth, Key) of
{ 0, Path } ->
%io:format("Path is ~w~n", [Path]),
contains2(Path, Tree);
{ _ToMake, _Exists } ->
%io:format("Key is too large for this set~n"),
false
end.
foldl(Fun, Accum0, { ?MODULE, Tree }) -> fold(left, Fun, Accum0, 0, Tree).
foldr(Fun, Accum0, { ?MODULE, Tree }) -> fold(right, Fun, Accum0, 0, Tree).
pmap(Fun, { ?MODULE, Tree }) ->
pmap(Fun, Tree, 0, 2).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helper for new/1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
from_list([], Bs) -> Bs;
from_list([Head | Tail ], Bs) when is_integer(Head) ->
from_list(Tail, insert(Head, Bs)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helper for insert/2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% empty entry at the bottom becomes a number with the correct bit set
set([Final], empty) when is_integer(Final), Final >= 0 ->
{ 1, 1 bsl Final };
%% good node at the bottom gets a new bit set
set([Final], { 1, Number })
when is_integer(Final), Final >= 0 ->
{ 1, Number bor (1 bsl Final) };
%% non-bottom node gets a new child
set([Pos0 | Rest], { Depth, Children })
when is_integer(Pos0), Pos0 >= 0 ->
Pos = Pos0+1,
New = set(Rest, element(Pos, Children)),
{ Depth, setelement(Pos, Children, New) };
%% non-bottom empty becomes a child container, and gets a child
set([Pos0 | Rest], empty)
when is_integer(Pos0), Pos0 >= 0 ->
Pos = Pos0 + 1,
Children = erlang:make_tuple(27, empty),
Depth = length(Rest)+1,
{ Depth, setelement(Pos, Children, set(Rest, empty)) }.
%% Function used to make the tree deeper, so it can hold elements that are too
%% large for its current size
grow(0, Tree) -> Tree;
grow(Levels, { ChildDepth, _ } = Tree)
when is_integer(Levels), Levels > 0 ->
%io:format("Growing, Levels is ~p~n", [Levels]),
Children = erlang:make_tuple(27, empty),
grow(Levels-1, { ChildDepth+1, setelement(1, Children, Tree) }).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers for intersect/1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
imerge(First = { FDepth, FTree }, Second = { SDepth, STree }) ->
if
FDepth > SDepth ->
imerge(element(1, FTree), Second);
FDepth < SDepth ->
imerge(First, element(1, STree));
FDepth =:= SDepth ->
imerge_equal(First, Second)
end.
imerge_equal(_, empty) -> empty;
imerge_equal(empty, _) -> empty;
imerge_equal({ 1, FNumber }, { 1, SNumber }) ->
{ 1, FNumber band SNumber };
imerge_equal({ Depth, FTree }, { Depth, STree }) ->
NewTree = lists:zipwith(fun imerge_equal/2,
tuple_to_list(FTree), tuple_to_list(STree)),
{ Depth, list_to_tuple(NewTree) }.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers for union/1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
umerge(First = { FDepth, _ }, Second = { SDepth, _ }) ->
if
FDepth > SDepth ->
umerge_equal(First, grow(FDepth-SDepth, Second));
FDepth < SDepth ->
umerge_equal(grow(SDepth-FDepth, First), Second);
FDepth =:= SDepth ->
umerge_equal(First, Second)
end.
umerge_equal(empty, empty) -> empty;
umerge_equal(First, empty) -> First;
umerge_equal(empty, Second) -> Second;
umerge_equal({ 1, FNumber }, { 1, SNumber }) ->
{ 1, FNumber bor SNumber };
umerge_equal({ Depth, FTree }, { Depth, STree }) ->
NewTree = lists:zipwith(fun umerge_equal/2,
tuple_to_list(FTree), tuple_to_list(STree)),
{ Depth, list_to_tuple(NewTree) }.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers for difference/2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff_eq(empty, _) -> empty;
diff_eq(Left, empty) -> Left;
diff_eq({ 1, LNumber }, { 1, RNumber }) ->
RInvert = ((1 bsl 27 - 1) bxor RNumber),
{ 1, LNumber band RInvert };
diff_eq({ Depth, Left }, { Depth, Right }) ->
NewTree = lists:zipwith(fun diff_eq/2,
tuple_to_list(Left), tuple_to_list(Right)),
{ Depth, list_to_tuple(NewTree) }.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers for fold[lr]/3
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fold(_Dir, _Fun, Accum, _Pre, empty) -> Accum;
fold(Dir, Fun, Accum, Pre, { 1, Number }) ->
%io:format("Iterating on leaf, pre is ~p, Number is ~p~n", [ Pre, Number ]),
lists:foldl(
fun(Bit, AccumI) ->
case Number band (1 bsl Bit) of
0 -> AccumI;
_ -> Fun(Pre * 27 + Bit, AccumI)
end
end,
Accum,
case Dir of
left -> lists:seq(0, 26);
right -> lists:reverse(lists:seq(0, 26))
end);
fold(Dir, Fun, Accum, Pre, { _Depth, Children }) ->
%io:format("Pre is ~p, Tree is ~p~n", [ Pre, { Depth, Children }]),
Offset = Pre*27,
lists:foldl(
fun(Element, AccumI) ->
Child = element(Element+1, Children),
fold(Dir, Fun, AccumI, Offset+Element, Child)
end,
Accum,
case Dir of
left -> lists:seq(0,26);
right -> lists:reverse(lists:seq(0, 26))
end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helper for pmap/2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pmap(Fun, Tree, Pre, 0) ->
pmap_fold(Fun, Tree, Pre);
pmap(_Fun, empty, _, _) ->
[];
pmap(Fun, Tree = { Depth, _Children }, Pre, _Levels) when Depth =< 3 ->
pmap_fold(Fun, Tree, Pre);
pmap(Fun, { _Depth, Children }, Pre, Levels) ->
Offset = Pre*27,
Root = self(),
Pids = [
spawn(fun() ->
Root ! { self(), pmap(Fun, Child, Offset+Element, Levels-1) }
end)
|| { Element, Child }
<- lists:zip(lists:seq(0,26), tuple_to_list(Children)) ],
lists:foldl(
fun(Pid, Accum) ->
receive { Pid, Result } ->
Result ++ Accum
end
end,
[],
Pids).
pmap_fold(Fun, Tree, Pre) ->
fold(
left,
fun(Bit, Accum) ->
case Fun(Bit) of
{ ok, Value } ->
[ Value | Accum ];
nil ->
Accum
end
end,
[],
Pre,
Tree).
%% Helper function for split_key, generates X and Y where X*27+Y = Key; used for
%% converting the key to base-27, which is how our values are stored.
%% Key Non-negative integer to divmod to our satisfaction
%% return { Next, Diff } where Diff < 27 and Next * 27 + Diff = Key
next_diff(Key) when is_integer(Key), Key >= 0 ->
Next = Key div 27,
Diff = Key - ( Next * 27 ),
{ Next, Diff }.
%% Determine the base-27 form of the given non-negative integer. This will be
%% returned as a list of numbers in the range [0, 26]; each number is a
%% coefficient in the base-27 form of the given key, with the most significant
%% at the head of the list.
%% Also given to this function is the current depth of the tree; this function
%% will return how much larger the tree would have to be to hold this key, or 0
%% if the tree is already large enough.
%% Depth The size of the tree we are generating a key address for
%% Key The key we want to find in the tree
%% return { NewLevels, Path }
split_key(Depth, Key) when is_integer(Key), Key >= 0 ->
split_key(Depth, Key, 0, []).
%% Helper functions for split_key/2, with some accumulators added.
split_key(0, 0, New, Path) ->
{ New, Path };
split_key(0, Key, New, Path) when is_integer(Key), Key >= 0 ->
{ Next, Diff } = next_diff(Key),
split_key(0, Next, New + 1,[ Diff | Path ]);
split_key(Depth, 0, New, Path) ->
split_key(Depth-1, 0, New, [ 0 | Path ]);
split_key(Depth, Key, New, Path) when is_integer(Key), Key >= 0 ->
{ Next, Diff } = next_diff(Key),
split_key(Depth-1, Next, New, [ Diff | Path ]).
contains2(_, empty) ->
%io:format("Empty is false~n"),
false;
contains2([ Final ], { 1, Number })
when is_integer(Final), Final >= 0 ->
%io:format("Final is ~p, Number is ~p~n", [Final, Number]),
(Number band (1 bsl Final)) =/= 0;
contains2([ Pos0 | Rest ], { _Depth, Children })
when is_integer(Pos0), Pos0 >= 0 ->
Pos = Pos0+1,
%io:format("Children are ~p, Pos is ~p~n", [Children, Pos]),
contains2(Rest, element(Pos, Children)).