Current section

Files

Jump to
gchess src bitboard.erl
Raw

src/bitboard.erl

-module(bitboard).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-export([new_bitboard/1, empty_bitboard/0, full_bitboard/0, 'and'/2, exclusive_or/2, 'or'/2, 'not'/1, shift_left/2, shift_right/2, bitscan_forward_inner/2, bitscan_forward/1, bitscan_backward_inner/2, bitscan_backward/1]).
-export_type([bitboard/0]).
-type bitboard() :: {bitboard, integer()}.
-spec new_bitboard(integer()) -> bitboard().
new_bitboard(Bitboard) ->
{bitboard, Bitboard}.
-spec empty_bitboard() -> bitboard().
empty_bitboard() ->
{bitboard, 0}.
-spec full_bitboard() -> bitboard().
full_bitboard() ->
{bitboard, 16#ffffffffffffffff}.
-spec 'and'(bitboard(), bitboard()) -> bitboard().
'and'(Bitboard1, Bitboard2) ->
{bitboard,
gleam@bitwise:'and'(
erlang:element(2, Bitboard1),
erlang:element(2, Bitboard2)
)}.
-spec exclusive_or(bitboard(), bitboard()) -> bitboard().
exclusive_or(Bitboard1, Bitboard2) ->
{bitboard,
gleam@bitwise:exclusive_or(
erlang:element(2, Bitboard1),
erlang:element(2, Bitboard2)
)}.
-spec 'or'(bitboard(), bitboard()) -> bitboard().
'or'(Bitboard1, Bitboard2) ->
{bitboard,
gleam@bitwise:'or'(
erlang:element(2, Bitboard1),
erlang:element(2, Bitboard2)
)}.
-spec 'not'(bitboard()) -> bitboard().
'not'(Bitboard) ->
{bitboard, gleam@bitwise:'not'(erlang:element(2, Bitboard))}.
-spec shift_left(bitboard(), integer()) -> bitboard().
shift_left(Bitboard, Shift) ->
{bitboard, gleam@bitwise:shift_left(erlang:element(2, Bitboard), Shift)}.
-spec shift_right(bitboard(), integer()) -> bitboard().
shift_right(Bitboard, Shift) ->
{bitboard, gleam@bitwise:shift_right(erlang:element(2, Bitboard), Shift)}.
-spec bitscan_forward_inner(bitboard(), integer()) -> integer().
bitscan_forward_inner(Bitboard, Index) ->
case (erlang:element(2, Bitboard) =:= 0) orelse (Index > 63) of
true ->
-1;
false ->
Lsb_digit = 2#0000000000000000000000000000000000000000000000000000000000000001,
First_digit_bitboard = 'and'(Bitboard, new_bitboard(Lsb_digit)),
case erlang:element(2, First_digit_bitboard) of
0 ->
bitscan_forward_inner(shift_right(Bitboard, 1), Index + 1);
_ ->
Index
end
end.
-spec bitscan_forward(bitboard()) -> integer().
bitscan_forward(Bitboard) ->
bitscan_forward_inner(Bitboard, 0).
-spec bitscan_backward_inner(bitboard(), integer()) -> integer().
bitscan_backward_inner(Bitboard, Index) ->
case (erlang:element(2, Bitboard) =:= 0) orelse (Index < 0) of
true ->
-1;
false ->
Msb_digit = 2#1000000000000000000000000000000000000000000000000000000000000000,
First_digit_bitboard = 'and'(Bitboard, new_bitboard(Msb_digit)),
case erlang:element(2, First_digit_bitboard) of
0 ->
bitscan_backward_inner(shift_left(Bitboard, 1), Index - 1);
_ ->
Index
end
end.
-spec bitscan_backward(bitboard()) -> integer().
bitscan_backward(Bitboard) ->
bitscan_backward_inner(Bitboard, 63).