diff --git a/GPA675Lab1GOL/GOLTeamH.cpp b/GPA675Lab1GOL/GOLTeamH.cpp index 61e14c6..d4626f7 100644 --- a/GPA675Lab1GOL/GOLTeamH.cpp +++ b/GPA675Lab1GOL/GOLTeamH.cpp @@ -1,7 +1,7 @@ #include "GOLTeamH.h" GOLTeamH::GOLTeamH() - : mParsedRule{} + : mParsedRule{}, mDeadColorEncoded{}, mAliveColorEncoded{} { } //! \brief Accesseurs retournant des informations générales sur la @@ -39,11 +39,11 @@ GOL::Statistics GOLTeamH::statistics() const .width = width(), .height = height(), .totalCells = size(), - .iteration = mIteration - //.totalDeadAbs = mData.totalDead(), - //.totalAliveAbs = mData.totalAlive(), - //.totalDeadRel = mData.totalDeadRel(), - //.totalAliveRel = mData.totalAliveRel() + .iteration = mIteration, + .totalDeadAbs = mData.totalDead(), + .totalAliveAbs = mData.totalAlive(), + .totalDeadRel = mData.totalDeadRel(), + .totalAliveRel = mData.totalAliveRel() // .tendencyAbs = ..., // .tendencyRel = ... }); @@ -71,7 +71,8 @@ GOL::ImplementationInformation GOLTeamH::information() const { return std::move(ImplementationInformation{ .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{}, .optionnalComments{} // Réponses aux questions... @@ -210,7 +211,6 @@ bool GOLTeamH::setRule(std::string const& rule) //! **grille**. -// TODO: Changer le tableau intermédiaire aussi. void GOLTeamH::setBorderManagement(BorderManagement borderManagement) { mBorderManagement = borderManagement; @@ -351,10 +351,18 @@ bool GOLTeamH::setFromPattern(std::string const& pattern) //! \param color La nouvelle couleur de l'état. void GOLTeamH::setSolidColor(State state, Color const& color) { - if (state == State::alive) + if (state == State::alive) { mAliveColor = color; - else + mAliveColorEncoded |= mAliveColor.red << 16; + mAliveColorEncoded |= mAliveColor.green << 8; + mAliveColorEncoded |= mAliveColor.blue; + } + else { 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 offset{ mData.width() }; - size_t aliveCount{}; + size_t neighbourAliveCount{}, aliveCount{}; // 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. - auto* ptrGrid{ &(mData.data()[0]) }; // Pointeur qui se promène en mémoire. + // Pointeur du tableau intermédiaire. + auto* ptrGridInt{ reinterpret_cast(&(mData.intData()[0])) + (offset + 1) }; - for (size_t j{}; j < heightNoBorder; ++j) { - for (size_t i{}; i < widthNoBorder; ++i) { + // Pointeur qui se promène en mémoire. + auto* ptrGrid{ reinterpret_cast(&(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 - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; ptrGrid++; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; ptrGrid++; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; // Milieu ptrGrid += offset - 2; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; ptrGrid += 2; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; // Dessous ptrGrid += offset - 2; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; ptrGrid++; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; ptrGrid++; - aliveCount += static_cast (*ptrGrid); + neighbourAliveCount += *ptrGrid; // On retourne à une place plus loin qu'à l'origine. 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 // présent. Voir GOLTeamH.cpp pour plus de détails. - *(ptrGridInt - 1) = static_cast( - static_cast( - (mParsedRule >> static_cast(*(ptrGrid + offset)) * 16) & (1u << aliveCount) - ) + *(ptrGridInt - 1) = static_cast( + (mParsedRule >> static_cast(*(ptrGrid + offset)) * 16) & (1u << neighbourAliveCount) ); + + if (*(ptrGridInt - 1)) + aliveCount++; } // On saute le border @@ -441,6 +453,7 @@ void GOLTeamH::processOneStep() mData.switchToIntermediate(); mIteration.value()++; + mData.setAliveCount(aliveCount); } @@ -483,26 +496,27 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const if (buffer == nullptr) return; - auto* s_ptr = buffer; + auto* s_ptr{ buffer }, * e_ptr{ buffer + buffer_size }; - auto width{ mData.width() }, height{ mData.height() }; - auto* ptrGrid{ &mData.data()[0] }; // Pointeur qui se promène en mémoire. - auto var = static_cast(*ptrGrid); // Variable qui va décoder l'état d'une cellule. + // Pointeur qui se promène en mémoire. + auto* ptrGrid{ reinterpret_cast(&mData.data()[0]) }; + + // 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. - for (size_t j{}; j < height * width; ++j) { - var = static_cast(*ptrGrid); + while (s_ptr < e_ptr) { + var = *ptrGrid; *s_ptr &= 0; // Clear *s_ptr |= MAX_ALPHA << 24; // Alpha = 255 - *s_ptr |= mAliveColor.red * var << 16; - *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); + if (var) { + *s_ptr |= mAliveColorEncoded; + } + else { + *s_ptr |= mDeadColorEncoded; + } s_ptr++; ptrGrid++; diff --git a/GPA675Lab1GOL/GOLTeamH.h b/GPA675Lab1GOL/GOLTeamH.h index b2b77e0..7c406c1 100644 --- a/GPA675Lab1GOL/GOLTeamH.h +++ b/GPA675Lab1GOL/GOLTeamH.h @@ -47,6 +47,9 @@ private: // // Le premier 16 bits (à gauche) est celui de la règle de survie alors // qu'à droite nous avons la règle de réanimation. + // + // Exemple: + // // 0000000111000111 0000000110011001 // ^^^^^^^ ^^^^^^^ // Bits non utilisés @@ -55,6 +58,7 @@ private: GridTeamH mData; Color mDeadColor, mAliveColor; + uint32_t mDeadColorEncoded, mAliveColorEncoded; // Fonctions utilisées à l'interne. std::optional convertCharToNumber(const char c); diff --git a/GPA675Lab1GOL/GridTeamH.cpp b/GPA675Lab1GOL/GridTeamH.cpp index f510943..297aa4f 100644 --- a/GPA675Lab1GOL/GridTeamH.cpp +++ b/GPA675Lab1GOL/GridTeamH.cpp @@ -1,6 +1,7 @@ #include "GridTeamH.h" #include "GOL.h" -#include + +#include // Constructeur Grid par défaut GridTeamH::GridTeamH() @@ -9,7 +10,7 @@ GridTeamH::GridTeamH() } 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); } @@ -28,7 +29,7 @@ void GridTeamH::resize(size_t width, size_t height, CellType initValue) mData.resize(width * height); mIntermediateData.resize(width * height); - fill(initValue, false); + fill(initValue, true); } // 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; } +void GridTeamH::setAliveCount(size_t aliveCount) +{ + mAliveCount = aliveCount; +} + // Accesseur en lecture seule sur le "buffer" de la grille. GridTeamH::DataType const& GridTeamH::data() const @@ -85,11 +91,9 @@ GridTeamH::DataType& GridTeamH::intData() return mIntermediateData; } -// TODO: FIX performance -// https://en.cppreference.com/w/cpp/algorithm/count 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 @@ -97,10 +101,9 @@ float GridTeamH::totalDeadRel() const return static_cast(totalDead()) / static_cast(size()); } -// TODO: FIX 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 @@ -160,8 +163,13 @@ void GridTeamH::randomize(double percentAlive, bool fillBorder) void GridTeamH::fillBorder(CellType value) { - auto* ptr = &mData.front(); - auto* e_ptr = &mData.front() + mWidth; + fillBorderManipulations(&mData.front(), value); + fillBorderManipulations(&mIntermediateData.front(), value); +} + +void GridTeamH::fillBorderManipulations(CellType* ptr, CellType value) const +{ + auto* e_ptr = ptr + (mWidth - 1); // TOP while (ptr < e_ptr) { diff --git a/GPA675Lab1GOL/GridTeamH.h b/GPA675Lab1GOL/GridTeamH.h index eb7315f..c94736e 100644 --- a/GPA675Lab1GOL/GridTeamH.h +++ b/GPA675Lab1GOL/GridTeamH.h @@ -31,6 +31,7 @@ public: size_t width() const { return mWidth; } size_t height() const { return mHeight; } size_t size() const { return mHeight * mWidth; } + size_t aliveCount() const { return mAliveCount; } void resize(size_t width, size_t height, CellType initValue = CellType{}); @@ -41,6 +42,8 @@ public: std::optional at(int column, int row) const; void setAt(int column, int row, CellType value); + void setAliveCount(size_t aliveCount); + // Accesseurs du "buffer" de la grille DataType const& data() const; DataType& data(); @@ -66,10 +69,12 @@ public: private: DataType mData, mIntermediateData; - size_t mWidth, mHeight; + size_t mWidth, mHeight, mAliveCount; // Pour la génération de nombres aléatoires std::random_device mRandomDevice; std::mt19937 mEngine; std::uniform_real_distribution<> mDistribution; + + void fillBorderManipulations(CellType* ptr, CellType value) const; };