#include <cstring>
#include <mutex>
#include <lookup_tables/lookup_tables.hpp>
#include <utility/constants.h>
namespace
{
static int highest_rank_storage[8192];
static int lowest_rank_storage[8192];
static int count_table_storage[8192];
static char rel_rank_storage[8192][15];
static unsigned short win_ranks_storage[8192][14];
static MoveGroupType group_data_storage[8192];
static std::once_flag lookup_tables_init_flag;
}
static auto init_lookup_tables_impl() -> void
{
highest_rank_storage[0] = 0;
lowest_rank_storage[0] = 0;
for (int aggregate = 1; aggregate < 8192; aggregate++)
{
for (int rank = 14; rank >= 2; rank--)
{
if (aggregate & bit_map_rank[rank])
{
highest_rank_storage[aggregate] = rank;
break;
}
}
for (int rank = 2; rank <= 14; rank++)
{
if (aggregate & bit_map_rank[rank])
{
lowest_rank_storage[aggregate] = rank;
break;
}
}
}
for (int aggregate = 0; aggregate < 8192; aggregate++)
{
count_table_storage[aggregate] = 0;
for (int rank = 0; rank < 13; rank++)
{
if (aggregate & (1 << rank))
{
count_table_storage[aggregate]++;
}
}
}
memset(rel_rank_storage[0], 0, 15);
for (int aggregate = 1; aggregate < 8192; aggregate++)
{
char ordinal = 0;
for (int rank = 14; rank >= 2; rank--)
{
if (aggregate & bit_map_rank[rank])
{
ordinal++;
rel_rank_storage[aggregate][rank] = ordinal;
}
}
}
for (int aggregate = 0; aggregate < 8192; aggregate++)
{
win_ranks_storage[aggregate][0] = 0;
for (int least_win = 1; least_win < 14; least_win++)
{
int result = 0;
int next_bit_position = 1;
for (int rank = 14; rank >= 2; rank--)
{
if (aggregate & bit_map_rank[rank])
{
if (next_bit_position <= least_win)
{
result |= bit_map_rank[rank];
next_bit_position++;
}
else
break;
}
}
win_ranks_storage[aggregate][least_win] = static_cast<unsigned short>(result);
}
}
static const int topside[15] =
{
0x0000, 0x0000, 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff };
static const int botside[15] =
{
0xffff, 0xffff, 0x1ffe, 0x1ffc, 0x1ff8, 0x1ff0, 0x1fe0, 0x1fc0, 0x1f80, 0x1f00, 0x1e00, 0x1c00, 0x1800, 0x1000, 0x0000 };
group_data_storage[0].last_group_ = -1;
group_data_storage[1].last_group_ = 0;
group_data_storage[1].rank_[0] = 2;
group_data_storage[1].sequence_[0] = 0;
group_data_storage[1].fullseq_[0] = 1;
group_data_storage[1].gap_[0] = 0;
int topBitRank = 1;
int nextBitRank = 0;
int topBitNo = 2;
int g;
for (int ris = 2; ris < 8192; ris++)
{
if (ris >= (topBitRank << 1))
{
nextBitRank = topBitRank;
topBitRank <<= 1;
topBitNo++;
}
group_data_storage[ris] = group_data_storage[ris ^ topBitRank];
if (ris & nextBitRank) {
g = group_data_storage[ris].last_group_;
group_data_storage[ris].rank_[g]++;
group_data_storage[ris].sequence_[g] |= nextBitRank;
group_data_storage[ris].fullseq_[g] |= topBitRank;
}
else {
g = ++group_data_storage[ris].last_group_;
group_data_storage[ris].rank_[g] = topBitNo;
group_data_storage[ris].sequence_[g] = 0;
group_data_storage[ris].fullseq_[g] = topBitRank;
group_data_storage[ris].gap_[g] =
topside[topBitNo] & botside[ group_data_storage[ris].rank_[g - 1] ];
}
}
}
auto init_lookup_tables() -> void
{
std::call_once(lookup_tables_init_flag, init_lookup_tables_impl);
}
namespace
{
struct DdsLutInitGuard
{
DdsLutInitGuard() noexcept
{
init_lookup_tables();
}
};
static const DdsLutInitGuard dds_lut_init_guard;
}
const MoveGroupType (&group_data)[8192] = group_data_storage;
const int (&highest_rank)[8192] = highest_rank_storage;
const int (&lowest_rank)[8192] = lowest_rank_storage;
const int (&count_table)[8192] = count_table_storage;
const char (&rel_rank)[8192][15] = rel_rank_storage;
const unsigned short (&win_ranks)[8192][14] = win_ranks_storage;