Ajoute première implémentation
This commit is contained in:
parent
42a4f5dfba
commit
212ed985ea
@ -121,6 +121,21 @@ void GOLTeamH::setBorderManagement(GOL::BorderManagement borderManagement)
|
|||||||
{
|
{
|
||||||
mBorderManagement = borderManagement;
|
mBorderManagement = borderManagement;
|
||||||
mIteration = 0;
|
mIteration = 0;
|
||||||
|
|
||||||
|
switch (borderManagement) {
|
||||||
|
case GOL::BorderManagement::foreverDead:
|
||||||
|
mData.fillBorder(GridTeamH::CellType::dead);
|
||||||
|
break;
|
||||||
|
case GOL::BorderManagement::foreverAlive:
|
||||||
|
mData.fillBorder(GridTeamH::CellType::alive);
|
||||||
|
break;
|
||||||
|
case GOL::BorderManagement::warping:
|
||||||
|
mData.fillBorderWarped();
|
||||||
|
break;
|
||||||
|
case GOL::BorderManagement::mirror:
|
||||||
|
mData.fillBorderWarped();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GOLTeamH::setState(int x, int y, State state)
|
void GOLTeamH::setState(int x, int y, State state)
|
||||||
@ -131,19 +146,31 @@ void GOLTeamH::setState(int x, int y, State state)
|
|||||||
|
|
||||||
void GOLTeamH::fill(State state)
|
void GOLTeamH::fill(State state)
|
||||||
{
|
{
|
||||||
mData.fill(state);
|
if (mBorderManagement == GOL::BorderManagement::immutableAsIs)
|
||||||
|
mData.fill(state, true);
|
||||||
|
else
|
||||||
|
mData.fill(state, false);
|
||||||
|
|
||||||
mIteration = 0;
|
mIteration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GOLTeamH::fillAlternately(State firstCell)
|
void GOLTeamH::fillAlternately(State firstCell)
|
||||||
{
|
{
|
||||||
mData.fillAternately(firstCell);
|
if (mBorderManagement == GOL::BorderManagement::immutableAsIs)
|
||||||
|
mData.fillAternately(firstCell, true);
|
||||||
|
else
|
||||||
|
mData.fillAternately(firstCell, false);
|
||||||
|
|
||||||
mIteration = 0;
|
mIteration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GOLTeamH::randomize(double percentAlive)
|
void GOLTeamH::randomize(double percentAlive)
|
||||||
{
|
{
|
||||||
mData.randomize(percentAlive);
|
if (mBorderManagement == GOL::BorderManagement::immutableAsIs)
|
||||||
|
mData.randomize(percentAlive, true);
|
||||||
|
else
|
||||||
|
mData.randomize(percentAlive, false);
|
||||||
|
|
||||||
mIteration = 0;
|
mIteration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,14 +196,68 @@ void GOLTeamH::setSolidColor(State state, Color const& color)
|
|||||||
mAliveColor = color;
|
mAliveColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: performance
|
|
||||||
void GOLTeamH::processOneStep()
|
void GOLTeamH::processOneStep()
|
||||||
{
|
{
|
||||||
// On commence à itérer sur les côtés. En règlant ces cas particuliers, on
|
auto& grid{ mData.data() };
|
||||||
// peut éviter des branches dans la boucle principale. Le branch predictor
|
auto& intGrid{ mData.intData() };
|
||||||
// aime cela.
|
|
||||||
for (size_t i{}; i < mData.width(); ++i) {
|
if (mBorderManagement == GOL::BorderManagement::foreverDead) {
|
||||||
|
size_t aliveCount{};
|
||||||
|
size_t offset{ width() + 2 };
|
||||||
|
auto* ptr{ &grid[0]};
|
||||||
|
|
||||||
|
for (size_t i{}; i < mData.realSize() - offset - 1; ++i) {
|
||||||
|
|
||||||
|
if (mData.isInBorder(i)) {
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
aliveCount = 0;
|
||||||
|
|
||||||
|
// Top
|
||||||
|
ptr -= offset + 1;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
|
||||||
|
// Milieu
|
||||||
|
ptr += offset - 2;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
ptr += 2;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
|
||||||
|
|
||||||
|
// Dessous
|
||||||
|
ptr += offset - 2;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == GOL::State::alive)
|
||||||
|
aliveCount++;
|
||||||
|
|
||||||
|
if (grid[i] == GOL::State::alive)
|
||||||
|
intGrid[i] = (mParsedRuleSurvive.test(aliveCount)) ? GOL::State::alive : GOL::State::dead;
|
||||||
|
else
|
||||||
|
intGrid[i] = (mParsedRuleRevive.test(aliveCount)) ? GOL::State::alive : GOL::State::dead;
|
||||||
|
|
||||||
|
// On retourne à une place plus loin qu'à l'origine.
|
||||||
|
ptr -= offset;
|
||||||
|
}
|
||||||
|
ptr = nullptr;
|
||||||
|
|
||||||
|
mData.switchToIntermediate();
|
||||||
|
mIteration.value()++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,29 +268,30 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const
|
|||||||
|
|
||||||
auto s_ptr = buffer;
|
auto s_ptr = buffer;
|
||||||
auto e_ptr = &buffer[buffer_size];
|
auto e_ptr = &buffer[buffer_size];
|
||||||
|
auto& grid = mData.data();
|
||||||
|
|
||||||
// On itère sur chaque éléments du tableau et on associe la couleur.
|
// On itère sur chaque éléments du tableau et on associe la couleur.
|
||||||
for (const auto& i : mData.data()) {
|
for (size_t index{ width() + 2 };
|
||||||
if (i == GridTeamH::CellType::alive) {
|
index < (width() + 2) * (height() + 1);
|
||||||
*s_ptr &= 0; // Clear
|
index++) {
|
||||||
*s_ptr |= MAX_ALPHA << 24; // Alpha = 255
|
|
||||||
*s_ptr |= mAliveColor.red << 16;
|
if (mData.isInBorder(index))
|
||||||
*s_ptr |= mAliveColor.green << 8;
|
continue;
|
||||||
*s_ptr |= mAliveColor.blue;
|
|
||||||
}
|
auto var = static_cast<uint8_t>(grid[index]);
|
||||||
else {
|
|
||||||
*s_ptr &= 0;
|
*s_ptr &= 0; // Clear
|
||||||
*s_ptr |= MAX_ALPHA << 24;
|
*s_ptr |= MAX_ALPHA << 24; // Alpha = 255
|
||||||
*s_ptr |= mDeadColor.red << 16;
|
|
||||||
*s_ptr |= mDeadColor.green << 8;
|
*s_ptr |= mAliveColor.red * var << 16;
|
||||||
*s_ptr |= mDeadColor.blue;
|
*s_ptr |= mAliveColor.green * var << 8;
|
||||||
}
|
*s_ptr |= mAliveColor.blue * var;
|
||||||
|
|
||||||
|
*s_ptr |= mDeadColor.red * (1 - var) << 16;
|
||||||
|
*s_ptr |= mDeadColor.green * (1 - var) << 8;
|
||||||
|
*s_ptr |= mDeadColor.blue * (1 - var);
|
||||||
|
|
||||||
s_ptr++;
|
s_ptr++;
|
||||||
|
|
||||||
// Sanity check, pour éviter des problèmes
|
|
||||||
if (s_ptr >= e_ptr)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,4 +301,4 @@ std::optional<unsigned char> GOLTeamH::convertCharToNumber(const char c)
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return (c - 48);
|
return (c - 48);
|
||||||
}
|
}
|
@ -45,6 +45,6 @@ private:
|
|||||||
GridTeamH mData;
|
GridTeamH mData;
|
||||||
Color mDeadColor, mAliveColor;
|
Color mDeadColor, mAliveColor;
|
||||||
|
|
||||||
// Fonction utilisée à l'interne.
|
// Fonctions utilisées à l'interne.
|
||||||
std::optional<unsigned char> convertCharToNumber(const char c);
|
std::optional<unsigned char> convertCharToNumber(const char c);
|
||||||
};
|
};
|
@ -35,37 +35,44 @@ size_t GridTeamH::size() const
|
|||||||
return mWidth * mHeight;
|
return mWidth * mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GridTeamH::realSize() const
|
||||||
|
{
|
||||||
|
return (mWidth + 2) * (mHeight + 2);
|
||||||
|
}
|
||||||
|
|
||||||
// Mutateur modifiant la taille de la grille et initialise le contenu par la valeur spécifiée.
|
// Mutateur modifiant la taille de la grille et initialise le contenu par la valeur spécifiée.
|
||||||
void GridTeamH::resize(size_t width, size_t height, CellType initValue)
|
void GridTeamH::resize(size_t width, size_t height, CellType initValue)
|
||||||
{
|
{
|
||||||
// TODO: Performance de resize avec beaucoup d'appel?
|
mData.resize((width + 2) * (height + 2));
|
||||||
// Investiguer reserve + resize
|
mIntermediateData.resize((width + 2) * (width + 2));
|
||||||
mData.resize(width * height);
|
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
|
|
||||||
fill(initValue);
|
fill(initValue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accesseur retournant la valeur d'une cellule à une certaine coordonnée.
|
// Accesseur retournant la valeur d'une cellule à une certaine coordonnée.
|
||||||
GridTeamH::CellType GridTeamH::value(int column, int row) const
|
GridTeamH::CellType GridTeamH::value(int column, int row) const
|
||||||
{
|
{
|
||||||
return mData[(column - 1) * (row - 1)];
|
size_t offset{ mWidth + 2 };
|
||||||
|
return mData[offset * row + (column - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutateur modifiant la valeur d'une cellule à une certaine coordonnée.
|
// Mutateur modifiant la valeur d'une cellule à une certaine coordonnée.
|
||||||
void GridTeamH::setValue(int column, int row, CellType value)
|
void GridTeamH::setValue(int column, int row, CellType value)
|
||||||
{
|
{
|
||||||
mData[(column - 1) * (row - 1)] = value;
|
size_t offset{ mWidth + 2 };
|
||||||
|
mData[offset * row + (column - 1)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accesseur retournant la valeur d'une cellule à une certaine coordonnée.
|
// Accesseur retournant la valeur d'une cellule à une certaine coordonnée.
|
||||||
std::optional<GridTeamH::CellType> GridTeamH::at(int column, int row) const
|
std::optional<GridTeamH::CellType> GridTeamH::at(int column, int row) const
|
||||||
{
|
{
|
||||||
if (column > mWidth || row > mHeight)
|
if (column >= mWidth || row >= mHeight)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return mData[(column - 1) * (row - 1)];
|
size_t offset{ mWidth + 2 };
|
||||||
|
return mData[offset * row + (column - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutateur modifiant la valeur d'une cellule à une certaine coordonn<6E>e.
|
// Mutateur modifiant la valeur d'une cellule à une certaine coordonn<6E>e.
|
||||||
@ -74,19 +81,33 @@ void GridTeamH::setAt(int column, int row, CellType value)
|
|||||||
if (column > mWidth || row > mHeight)
|
if (column > mWidth || row > mHeight)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mData[(column - 1) * (row - 1)] = value;
|
size_t offset{ mWidth + 2 };
|
||||||
|
mData[offset * row + (column - 1)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accesseur en lecture seule sur le "buffer" de la grille.
|
// Accesseur en lecture seule sur le "buffer" de la grille.
|
||||||
GridTeamH::DataType const& GridTeamH::data() const
|
GridTeamH::DataType const& GridTeamH::data() const
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accesseur en lecture/écriture sur le "buffer" de la grille.
|
// Accesseur en lecture/écriture sur le "buffer" de la grille.
|
||||||
GridTeamH::DataType& GridTeamH::data()
|
GridTeamH::DataType& GridTeamH::data()
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GridTeamH::DataType const& GridTeamH::intData() const
|
||||||
|
{
|
||||||
|
return mIntermediateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
GridTeamH::DataType& GridTeamH::intData()
|
||||||
|
{
|
||||||
|
return mIntermediateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: FIX
|
||||||
// https://en.cppreference.com/w/cpp/algorithm/count
|
// https://en.cppreference.com/w/cpp/algorithm/count
|
||||||
size_t GridTeamH::totalDead() const
|
size_t GridTeamH::totalDead() const
|
||||||
{
|
{
|
||||||
@ -98,6 +119,7 @@ float GridTeamH::totalDeadRel() const
|
|||||||
return static_cast<float>(totalDead()) / static_cast<float>(size());
|
return static_cast<float>(totalDead()) / static_cast<float>(size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: FIX
|
||||||
size_t GridTeamH::totalAlive() const
|
size_t GridTeamH::totalAlive() const
|
||||||
{
|
{
|
||||||
return std::count_if(mData.begin(), mData.end(), [](auto& i) { return i == CellType::alive; });
|
return std::count_if(mData.begin(), mData.end(), [](auto& i) { return i == CellType::alive; });
|
||||||
@ -108,26 +130,85 @@ float GridTeamH::totalAliveRel() const
|
|||||||
return static_cast<float>(totalAlive()) / static_cast<float>(size());
|
return static_cast<float>(totalAlive()) / static_cast<float>(size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridTeamH::fill(CellType value)
|
void GridTeamH::fill(CellType value, bool fillBorder)
|
||||||
{
|
{
|
||||||
for (auto& i : mData)
|
if (fillBorder) {
|
||||||
i = value;
|
for (auto& i : mData)
|
||||||
|
i = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t index{}; index < mData.size(); index++) {
|
||||||
|
if (isInBorder(index))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mData[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridTeamH::fillAternately(CellType initValue)
|
void GridTeamH::fillAternately(CellType initValue, bool fillBorder)
|
||||||
{
|
{
|
||||||
auto otherValue = (initValue == CellType::alive) ? CellType::dead : CellType::alive;
|
auto otherValue = (initValue == CellType::alive) ? CellType::dead : CellType::alive;
|
||||||
|
|
||||||
for (size_t i{}; i < mData.size(); i++)
|
if (fillBorder) {
|
||||||
mData[i] = !(i % 2) ? initValue : otherValue;
|
for (size_t i{}; i < mData.size(); i++)
|
||||||
}
|
mData[i] = !(i % 2) ? initValue : otherValue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t index{}; index < mData.size(); index++) {
|
||||||
|
if (isInBorder(index))
|
||||||
|
continue;
|
||||||
|
|
||||||
void GridTeamH::randomize(double percentAlive)
|
mData[index] = !(index % 2) ? initValue : otherValue;
|
||||||
{
|
}
|
||||||
for (auto& i : mData) {
|
|
||||||
if (mDistribution(mEngine) < percentAlive)
|
|
||||||
i = CellType::alive;
|
|
||||||
else
|
|
||||||
i = CellType::dead;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GridTeamH::randomize(double percentAlive, bool fillBorder)
|
||||||
|
{
|
||||||
|
if (fillBorder) {
|
||||||
|
for (auto& i : mData) {
|
||||||
|
if (mDistribution(mEngine) < percentAlive)
|
||||||
|
i = CellType::alive;
|
||||||
|
else
|
||||||
|
i = CellType::dead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t index{}; index < mData.size() - 1; index++) {
|
||||||
|
if (isInBorder(index))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mDistribution(mEngine) < percentAlive)
|
||||||
|
mData[index] = CellType::alive;
|
||||||
|
else
|
||||||
|
mData[index] = CellType::dead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTeamH::fillBorder(CellType value)
|
||||||
|
{
|
||||||
|
for (size_t index{}; index < mData.size(); index++) {
|
||||||
|
if (isInBorder(index))
|
||||||
|
mData[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTeamH::fillBorderWarped()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTeamH::fillBorderMirror()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTeamH::switchToIntermediate()
|
||||||
|
{
|
||||||
|
// Swap pour la performance.
|
||||||
|
mData.swap(mIntermediateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
size_t width() const;
|
size_t width() const;
|
||||||
size_t height() const;
|
size_t height() const;
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
size_t realSize() const;
|
||||||
|
|
||||||
void resize(size_t width, size_t height, CellType initValue = CellType{});
|
void resize(size_t width, size_t height, CellType initValue = CellType{});
|
||||||
|
|
||||||
@ -39,6 +40,9 @@ public:
|
|||||||
// Accesseurs du "buffer" de la grille
|
// Accesseurs du "buffer" de la grille
|
||||||
DataType const& data() const;
|
DataType const& data() const;
|
||||||
DataType& data();
|
DataType& data();
|
||||||
|
|
||||||
|
DataType const& intData() const;
|
||||||
|
DataType& intData();
|
||||||
|
|
||||||
size_t totalDead() const;
|
size_t totalDead() const;
|
||||||
float totalDeadRel() const;
|
float totalDeadRel() const;
|
||||||
@ -46,16 +50,31 @@ public:
|
|||||||
size_t totalAlive() const;
|
size_t totalAlive() const;
|
||||||
float totalAliveRel() const;
|
float totalAliveRel() const;
|
||||||
|
|
||||||
void fill(CellType value);
|
void fill(CellType value, bool fillBorder);
|
||||||
void fillAternately(CellType initValue);
|
void fillAternately(CellType initValue, bool fillBorder);
|
||||||
void randomize(double percentAlive);
|
void randomize(double percentAlive, bool fillBorder);
|
||||||
|
|
||||||
|
void fillBorder(CellType value);
|
||||||
|
void fillBorderWarped();
|
||||||
|
void fillBorderMirror();
|
||||||
|
|
||||||
|
void switchToIntermediate();
|
||||||
|
bool isInBorder(size_t index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataType mData;
|
DataType mData, mIntermediateData;
|
||||||
size_t mWidth, mHeight;
|
size_t mWidth, mHeight;
|
||||||
|
|
||||||
// Pour la génération de nombres aléatoires
|
// Pour la génération de nombres aléatoires
|
||||||
std::random_device mRandomDevice;
|
std::random_device mRandomDevice;
|
||||||
std::mt19937 mEngine;
|
std::mt19937 mEngine;
|
||||||
std::uniform_real_distribution<> mDistribution;
|
std::uniform_real_distribution<> mDistribution;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool GridTeamH::isInBorder(size_t index) const
|
||||||
|
{
|
||||||
|
return(index % (mWidth + 2) < 1
|
||||||
|
|| index % (mWidth + 2) > mWidth
|
||||||
|
|| index < mWidth + 2
|
||||||
|
|| index > (mWidth + 2) * (mHeight + 1));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user