Gros round de résolution de bogues.

This commit is contained in:
Timothée Leclaire-Fournier 2024-01-22 21:38:04 -05:00
parent 3451a57bcf
commit 8d3f741fcc
4 changed files with 83 additions and 52 deletions

View File

@ -1,7 +1,7 @@
#include "GOLTeamH.h" #include "GOLTeamH.h"
GOLTeamH::GOLTeamH() GOLTeamH::GOLTeamH()
: mParsedRule{} : mParsedRule{}, mDeadColorEncoded{}, mAliveColorEncoded{}
{ {
} }
//! \brief Accesseurs retournant des informations générales sur la //! \brief Accesseurs retournant des informations générales sur la
@ -39,11 +39,11 @@ GOL::Statistics GOLTeamH::statistics() const
.width = width(), .width = width(),
.height = height(), .height = height(),
.totalCells = size(), .totalCells = size(),
.iteration = mIteration .iteration = mIteration,
//.totalDeadAbs = mData.totalDead(), .totalDeadAbs = mData.totalDead(),
//.totalAliveAbs = mData.totalAlive(), .totalAliveAbs = mData.totalAlive(),
//.totalDeadRel = mData.totalDeadRel(), .totalDeadRel = mData.totalDeadRel(),
//.totalAliveRel = mData.totalAliveRel() .totalAliveRel = mData.totalAliveRel()
// .tendencyAbs = ..., // .tendencyAbs = ...,
// .tendencyRel = ... // .tendencyRel = ...
}); });
@ -71,7 +71,8 @@ GOL::ImplementationInformation GOLTeamH::information() const
{ {
return std::move(ImplementationInformation{ return std::move(ImplementationInformation{
.title{"Laboratoire 1"}, .title{"Laboratoire 1"},
.authors{{"Timothée Leclaire-Fournier"}, {"Martin Euzenat martin.euzenat.1@ens.etsmtl.ca"}}, .authors{{"Timothée Leclaire-Fournier timothee.leclaire-fournier.1@ens.etsmtl.ca"},
{"Martin Euzenat martin.euzenat.1@ens.etsmtl.ca"}},
.answers{}, .answers{},
.optionnalComments{} .optionnalComments{}
// Réponses aux questions... // Réponses aux questions...
@ -210,7 +211,6 @@ bool GOLTeamH::setRule(std::string const& rule)
//! **grille**. //! **grille**.
// TODO: Changer le tableau intermédiaire aussi.
void GOLTeamH::setBorderManagement(BorderManagement borderManagement) void GOLTeamH::setBorderManagement(BorderManagement borderManagement)
{ {
mBorderManagement = borderManagement; mBorderManagement = borderManagement;
@ -351,10 +351,18 @@ bool GOLTeamH::setFromPattern(std::string const& pattern)
//! \param color La nouvelle couleur de l'état. //! \param color La nouvelle couleur de l'état.
void GOLTeamH::setSolidColor(State state, Color const& color) void GOLTeamH::setSolidColor(State state, Color const& color)
{ {
if (state == State::alive) if (state == State::alive) {
mAliveColor = color; mAliveColor = color;
else mAliveColorEncoded |= mAliveColor.red << 16;
mAliveColorEncoded |= mAliveColor.green << 8;
mAliveColorEncoded |= mAliveColor.blue;
}
else {
mDeadColor = color; mDeadColor = color;
mDeadColorEncoded |= mDeadColor.red << 16;
mDeadColorEncoded |= mDeadColor.green << 8;
mDeadColorEncoded |= mDeadColor.blue;
}
} }
@ -381,38 +389,41 @@ void GOLTeamH::processOneStep()
auto const widthNoBorder{ mData.width() - 2 }, heightNoBorder{ mData.height() - 2 }; auto const widthNoBorder{ mData.width() - 2 }, heightNoBorder{ mData.height() - 2 };
auto const offset{ mData.width() }; auto const offset{ mData.width() };
size_t aliveCount{}; size_t neighbourAliveCount{}, aliveCount{};
// On commence à la première case qui n'est pas dans le border // On commence à la première case qui n'est pas dans le border
auto* ptrGridInt{ (&(mData.intData()[0])) + (offset + 1) }; // Pointeur du tableau intermédiaire. // Pointeur du tableau intermédiaire.
auto* ptrGrid{ &(mData.data()[0]) }; // Pointeur qui se promène en mémoire. auto* ptrGridInt{ reinterpret_cast<uint8_t*>(&(mData.intData()[0])) + (offset + 1) };
for (size_t j{}; j < heightNoBorder; ++j) { // Pointeur qui se promène en mémoire.
for (size_t i{}; i < widthNoBorder; ++i) { auto* ptrGrid{ reinterpret_cast<uint8_t*>(&(mData.data()[0])) };
aliveCount = 0; for (size_t j{ 1 }; j < heightNoBorder + 1; ++j) {
for (size_t i{ 1 }; i < widthNoBorder + 1; ++i) {
neighbourAliveCount = 0;
// Top // Top
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
ptrGrid++; ptrGrid++;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
ptrGrid++; ptrGrid++;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
// Milieu // Milieu
ptrGrid += offset - 2; ptrGrid += offset - 2;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
ptrGrid += 2; ptrGrid += 2;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
// Dessous // Dessous
ptrGrid += offset - 2; ptrGrid += offset - 2;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
ptrGrid++; ptrGrid++;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
ptrGrid++; ptrGrid++;
aliveCount += static_cast<uint8_t> (*ptrGrid); neighbourAliveCount += *ptrGrid;
// On retourne à une place plus loin qu'à l'origine. // On retourne à une place plus loin qu'à l'origine.
ptrGrid -= (2 * offset) + 1; ptrGrid -= (2 * offset) + 1;
@ -425,11 +436,12 @@ void GOLTeamH::processOneStep()
// //
// On accède à la bonne partie des bits et on compare si le bit de survie/réanimation est // On accède à la bonne partie des bits et on compare si le bit de survie/réanimation est
// présent. Voir GOLTeamH.cpp pour plus de détails. // présent. Voir GOLTeamH.cpp pour plus de détails.
*(ptrGridInt - 1) = static_cast<GOL::State>( *(ptrGridInt - 1) = static_cast<bool>(
static_cast<bool>( (mParsedRule >> static_cast<bool>(*(ptrGrid + offset)) * 16) & (1u << neighbourAliveCount)
(mParsedRule >> static_cast<bool>(*(ptrGrid + offset)) * 16) & (1u << aliveCount)
)
); );
if (*(ptrGridInt - 1))
aliveCount++;
} }
// On saute le border // On saute le border
@ -441,6 +453,7 @@ void GOLTeamH::processOneStep()
mData.switchToIntermediate(); mData.switchToIntermediate();
mIteration.value()++; mIteration.value()++;
mData.setAliveCount(aliveCount);
} }
@ -483,26 +496,27 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const
if (buffer == nullptr) if (buffer == nullptr)
return; return;
auto* s_ptr = buffer; auto* s_ptr{ buffer }, * e_ptr{ buffer + buffer_size };
auto width{ mData.width() }, height{ mData.height() }; // Pointeur qui se promène en mémoire.
auto* ptrGrid{ &mData.data()[0] }; // Pointeur qui se promène en mémoire. auto* ptrGrid{ reinterpret_cast<const uint8_t*>(&mData.data()[0]) };
auto var = static_cast<uint8_t>(*ptrGrid); // Variable qui va décoder l'état d'une cellule.
// Variable qui va décoder l'état d'une cellule.
auto var{ *ptrGrid };
// 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 (size_t j{}; j < height * width; ++j) { while (s_ptr < e_ptr) {
var = static_cast<uint8_t>(*ptrGrid); var = *ptrGrid;
*s_ptr &= 0; // Clear *s_ptr &= 0; // Clear
*s_ptr |= MAX_ALPHA << 24; // Alpha = 255 *s_ptr |= MAX_ALPHA << 24; // Alpha = 255
*s_ptr |= mAliveColor.red * var << 16; if (var) {
*s_ptr |= mAliveColor.green * var << 8; *s_ptr |= mAliveColorEncoded;
*s_ptr |= mAliveColor.blue * var; }
else {
*s_ptr |= mDeadColor.red * (1 - var) << 16; *s_ptr |= mDeadColorEncoded;
*s_ptr |= mDeadColor.green * (1 - var) << 8; }
*s_ptr |= mDeadColor.blue * (1 - var);
s_ptr++; s_ptr++;
ptrGrid++; ptrGrid++;

View File

@ -47,6 +47,9 @@ private:
// //
// Le premier 16 bits (à gauche) est celui de la règle de survie alors // Le premier 16 bits (à gauche) est celui de la règle de survie alors
// qu'à droite nous avons la règle de réanimation. // qu'à droite nous avons la règle de réanimation.
//
// Exemple:
//
// 0000000111000111 0000000110011001 // 0000000111000111 0000000110011001
// ^^^^^^^ ^^^^^^^ // ^^^^^^^ ^^^^^^^
// Bits non utilisés // Bits non utilisés
@ -55,6 +58,7 @@ private:
GridTeamH mData; GridTeamH mData;
Color mDeadColor, mAliveColor; Color mDeadColor, mAliveColor;
uint32_t mDeadColorEncoded, mAliveColorEncoded;
// Fonctions utilisées à l'interne. // Fonctions utilisées à l'interne.
std::optional<unsigned char> convertCharToNumber(const char c); std::optional<unsigned char> convertCharToNumber(const char c);

View File

@ -1,6 +1,7 @@
#include "GridTeamH.h" #include "GridTeamH.h"
#include "GOL.h" #include "GOL.h"
#include <algorithm>
#include <optional>
// Constructeur Grid par défaut // Constructeur Grid par défaut
GridTeamH::GridTeamH() GridTeamH::GridTeamH()
@ -9,7 +10,7 @@ GridTeamH::GridTeamH()
} }
GridTeamH::GridTeamH(size_t width, size_t height, CellType initValue) GridTeamH::GridTeamH(size_t width, size_t height, CellType initValue)
:mWidth{ width }, mHeight{ height }, mEngine(mRandomDevice()), mDistribution(0.0, 1.0) :mWidth{ width }, mHeight{ height }, mEngine(mRandomDevice()), mDistribution(0.0, 1.0), mAliveCount{}
{ {
resize(width, height, initValue); resize(width, height, initValue);
} }
@ -28,7 +29,7 @@ void GridTeamH::resize(size_t width, size_t height, CellType initValue)
mData.resize(width * height); mData.resize(width * height);
mIntermediateData.resize(width * height); mIntermediateData.resize(width * height);
fill(initValue, false); fill(initValue, true);
} }
// Accesseur retournant la valeur d'une cellule à une certaine coordonnée. // Accesseur retournant la valeur d'une cellule à une certaine coordonnée.
@ -62,6 +63,11 @@ void GridTeamH::setAt(int column, int row, CellType value)
mData[(row - 1) * mWidth + (column - 1)] = value; mData[(row - 1) * mWidth + (column - 1)] = value;
} }
void GridTeamH::setAliveCount(size_t aliveCount)
{
mAliveCount = aliveCount;
}
// 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
@ -85,11 +91,9 @@ GridTeamH::DataType& GridTeamH::intData()
return mIntermediateData; return mIntermediateData;
} }
// TODO: FIX performance
// https://en.cppreference.com/w/cpp/algorithm/count
size_t GridTeamH::totalDead() const size_t GridTeamH::totalDead() const
{ {
return std::count_if(mData.begin(), mData.end(), [](auto& i) { return i == CellType::dead; }); return mAliveCount;
} }
float GridTeamH::totalDeadRel() const float GridTeamH::totalDeadRel() const
@ -97,10 +101,9 @@ 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 (mWidth * mHeight) - mAliveCount;
} }
float GridTeamH::totalAliveRel() const float GridTeamH::totalAliveRel() const
@ -160,8 +163,13 @@ void GridTeamH::randomize(double percentAlive, bool fillBorder)
void GridTeamH::fillBorder(CellType value) void GridTeamH::fillBorder(CellType value)
{ {
auto* ptr = &mData.front(); fillBorderManipulations(&mData.front(), value);
auto* e_ptr = &mData.front() + mWidth; fillBorderManipulations(&mIntermediateData.front(), value);
}
void GridTeamH::fillBorderManipulations(CellType* ptr, CellType value) const
{
auto* e_ptr = ptr + (mWidth - 1);
// TOP // TOP
while (ptr < e_ptr) { while (ptr < e_ptr) {

View File

@ -31,6 +31,7 @@ public:
size_t width() const { return mWidth; } size_t width() const { return mWidth; }
size_t height() const { return mHeight; } size_t height() const { return mHeight; }
size_t size() const { return mHeight * mWidth; } size_t size() const { return mHeight * mWidth; }
size_t aliveCount() const { return mAliveCount; }
void resize(size_t width, size_t height, CellType initValue = CellType{}); void resize(size_t width, size_t height, CellType initValue = CellType{});
@ -41,6 +42,8 @@ public:
std::optional<CellType> at(int column, int row) const; std::optional<CellType> at(int column, int row) const;
void setAt(int column, int row, CellType value); void setAt(int column, int row, CellType value);
void setAliveCount(size_t aliveCount);
// Accesseurs du "buffer" de la grille // Accesseurs du "buffer" de la grille
DataType const& data() const; DataType const& data() const;
DataType& data(); DataType& data();
@ -66,10 +69,12 @@ public:
private: private:
DataType mData, mIntermediateData; DataType mData, mIntermediateData;
size_t mWidth, mHeight; size_t mWidth, mHeight, mAliveCount;
// 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;
void fillBorderManipulations(CellType* ptr, CellType value) const;
}; };