Répare le warping / mirroir

This commit is contained in:
Timothée Leclaire-Fournier 2024-02-10 16:29:08 -05:00
parent 84ad4a3536
commit bb351157e5
2 changed files with 44 additions and 39 deletions

View File

@ -258,8 +258,7 @@ void GOLTeamH::fill(State state)
mBorderManagement == GOL::BorderManagement::immutableAsIs || mBorderManagement == GOL::BorderManagement::immutableAsIs ||
mBorderManagement == GOL::BorderManagement::warping || mBorderManagement == GOL::BorderManagement::warping ||
mBorderManagement == GOL::BorderManagement::mirror); mBorderManagement == GOL::BorderManagement::mirror);
modifyBorderIfNecessary(reinterpret_cast<uint8_t*>(mData.data()), modifyBorderIfNecessary();
reinterpret_cast<uint8_t*>(mData.intData()));
mIteration = 0; mIteration = 0;
countLifeStatusCells(); countLifeStatusCells();
} }
@ -280,8 +279,7 @@ void GOLTeamH::fillAlternately(State firstCell)
mBorderManagement == GOL::BorderManagement::immutableAsIs || mBorderManagement == GOL::BorderManagement::immutableAsIs ||
mBorderManagement == GOL::BorderManagement::warping || mBorderManagement == GOL::BorderManagement::warping ||
mBorderManagement == GOL::BorderManagement::mirror); mBorderManagement == GOL::BorderManagement::mirror);
modifyBorderIfNecessary(reinterpret_cast<uint8_t*>(mData.data()), modifyBorderIfNecessary();
reinterpret_cast<uint8_t*>(mData.intData()));
mIteration = 0; mIteration = 0;
countLifeStatusCells(); countLifeStatusCells();
} }
@ -303,8 +301,7 @@ void GOLTeamH::randomize(double percentAlive)
mBorderManagement == GOL::BorderManagement::immutableAsIs || mBorderManagement == GOL::BorderManagement::immutableAsIs ||
mBorderManagement == GOL::BorderManagement::warping || mBorderManagement == GOL::BorderManagement::warping ||
mBorderManagement == GOL::BorderManagement::mirror); mBorderManagement == GOL::BorderManagement::mirror);
modifyBorderIfNecessary(reinterpret_cast<uint8_t*>(mData.data()), modifyBorderIfNecessary();
reinterpret_cast<uint8_t*>(mData.intData()));
mIteration = 0; mIteration = 0;
countLifeStatusCells(); countLifeStatusCells();
} }
@ -477,7 +474,7 @@ void GOLTeamH::processOneStep()
ptrGrid = nullptr; ptrGrid = nullptr;
ptrGridInt = nullptr; ptrGridInt = nullptr;
modifyBorderIfNecessary(reinterpret_cast<uint8_t*>(mData.data()), reinterpret_cast<uint8_t*>(mData.intData())); modifyBorderIfNecessary();
mData.switchToIntermediate(); // Mise à jour de la grille mData.switchToIntermediate(); // Mise à jour de la grille
mIteration.value()++; mIteration.value()++;
mData.setAliveCount(aliveCount); mData.setAliveCount(aliveCount);
@ -604,11 +601,14 @@ void GOLTeamH::countLifeStatusCells()
// TODO: combiner avec fillBorder // TODO: combiner avec fillBorder
void GOLTeamH::modifyBorderIfNecessary(uint8_t* ptrGrid, uint8_t* ptrGridInt) void GOLTeamH::modifyBorderIfNecessary()
{ {
auto* ptrGrid{ reinterpret_cast<uint8_t*>(mData.data()) };
auto* ptrGridInt{ reinterpret_cast<uint8_t*>(mData.intData()) };
auto bm = mBorderManagement.value_or(BorderManagement::immutableAsIs); auto bm = mBorderManagement.value_or(BorderManagement::immutableAsIs);
auto width{ mData.width() }, height{ mData.height() }; // Pour éviter des appels de fonctions trop souvent. auto width{ mData.width() }, height{ mData.height() }; // Pour éviter des appels de fonctions trop souvent.
auto rule{ mParsedRule }; // Pour la capture du lambda. auto rule{ mParsedRule }; // Pour la capture du lambda.
int count{};
if (mBorderManagement.value() == GOL::BorderManagement::immutableAsIs || if (mBorderManagement.value() == GOL::BorderManagement::immutableAsIs ||
bm == GOL::BorderManagement::foreverAlive || bm == GOL::BorderManagement::foreverAlive ||
@ -618,22 +618,23 @@ void GOLTeamH::modifyBorderIfNecessary(uint8_t* ptrGrid, uint8_t* ptrGridInt)
auto* e_ptr = ptrGrid + (width - 1); auto* e_ptr = ptrGrid + (width - 1);
// Lambda pour une opération courante. // Lambda pour une opération courante.
auto getFutureStatus = [rule](size_t count, uint8_t* ptrGrid) { auto applyRule = [rule](size_t count, uint8_t* ptrGrid) {
return static_cast<bool>((rule >> *(ptrGrid) * 16) & (1u << count)); return static_cast<bool>((rule >> *(ptrGrid) * 16) & (1u << count));
}; };
// TOP // TOP
while (ptrGrid < e_ptr) { while (ptrGrid < e_ptr) {
*ptrGridInt = getFutureStatus(countNeighbors(ptrGrid, bm), ptrGrid); *ptrGridInt = applyRule(countNeighbors(ptrGrid), ptrGrid);
ptrGrid++; ptrGrid++;
ptrGridInt++; ptrGridInt++;
count++;
} }
// DROITE // DROITE
e_ptr += width * (height - 1); e_ptr += width * (height - 1);
while (ptrGrid < e_ptr) { while (ptrGrid < e_ptr) {
*ptrGridInt = getFutureStatus(countNeighbors(ptrGrid, bm), ptrGrid); *ptrGridInt = applyRule(countNeighbors(ptrGrid), ptrGrid);
ptrGrid += width; ptrGrid += width;
ptrGridInt += width; ptrGridInt += width;
@ -642,7 +643,7 @@ void GOLTeamH::modifyBorderIfNecessary(uint8_t* ptrGrid, uint8_t* ptrGridInt)
// DESSOUS // DESSOUS
e_ptr -= (width - 1); e_ptr -= (width - 1);
while (ptrGrid > e_ptr) { while (ptrGrid > e_ptr) {
*ptrGridInt = getFutureStatus(countNeighbors(ptrGrid, bm), ptrGrid); *ptrGridInt = applyRule(countNeighbors(ptrGrid), ptrGrid);
ptrGrid--; ptrGrid--;
ptrGridInt--; ptrGridInt--;
@ -651,53 +652,57 @@ void GOLTeamH::modifyBorderIfNecessary(uint8_t* ptrGrid, uint8_t* ptrGridInt)
// GAUCHE // GAUCHE
e_ptr -= width * (height - 1); e_ptr -= width * (height - 1);
while (ptrGrid > e_ptr) { while (ptrGrid > e_ptr) {
*ptrGridInt = getFutureStatus(countNeighbors(ptrGrid, bm), ptrGrid); *ptrGridInt = applyRule(countNeighbors(ptrGrid), ptrGrid);
ptrGrid -= width; ptrGrid -= width;
ptrGridInt -= width; ptrGridInt -= width;
} }
} }
size_t GOLTeamH::countNeighbors(uint8_t* ptrGrid, BorderManagement bm) const size_t GOLTeamH::countNeighbors(const uint8_t* cellPtr) const
{ {
auto bm{ mBorderManagement };
auto width{ mData.width() }, height{ mData.height() }; // Pour éviter des appels de fonctions trop souvent. auto width{ mData.width() }, height{ mData.height() }; // Pour éviter des appels de fonctions trop souvent.
size_t neighborsAliveCount{}; size_t neighborsAliveCount{};
auto* tempPtr{ ptrGrid - (width + 1) }; auto* tempPtr{ cellPtr - (width + 1) }; // Pointeur qui se promène en mémoire.
const auto* firstGridPtr{ reinterpret_cast<uint8_t*>(mData.data()) };
const auto* lastGridPtr{ reinterpret_cast<uint8_t*>(mData.data()) + (width * height) - 1 };
// Petit lambda pour simplifier les opérations. // Petit lambda pour simplifier les opérations.
auto putInBounds = [ptrGrid, width, height, bm](uint8_t* ptr, uint8_t const* cellPtr) { auto putInBounds = [width, height, bm, firstGridPtr, lastGridPtr](const uint8_t* ptr) {
if (ptr < ptrGrid) if (ptr < firstGridPtr)
ptr += width * (bm == GOL::BorderManagement::mirror) ? 2 : (height - 1); ptr += width * ((bm == GOL::BorderManagement::mirror) ? 2 : (height - 1));
else if (ptr > ptrGrid + (width * height)) else if (ptr > lastGridPtr)
ptr -= width * (bm == GOL::BorderManagement::mirror) ? 2 : (height - 1); ptr -= width * ((bm == GOL::BorderManagement::mirror) ? 2 : (height - 1));
if ((ptr - firstGridPtr) % width == 0)
ptr -= ((bm == GOL::BorderManagement::mirror) ? 2 : (width - 1));
else if ((ptr - firstGridPtr) % width == width - 1)
ptr += ((bm == GOL::BorderManagement::mirror) ? 2 : (width - 1));
if ((cellPtr - ptrGrid) % width == 0)
ptr += (bm == GOL::BorderManagement::mirror) ? 2 : (width - 1);
else if ((cellPtr - ptrGrid) % width == width - 1)
ptr -= (bm == GOL::BorderManagement::mirror) ? 2 : (width - 1);
return ptr; return ptr;
}; };
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr++; tempPtr++;
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr++; tempPtr++;
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr += (width - 2); tempPtr += (width - 2);
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr += 2; tempPtr += 2;
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr += (width - 2); tempPtr += (width - 2);
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr++; tempPtr++;
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
tempPtr++; tempPtr++;
neighborsAliveCount += *(putInBounds(tempPtr, ptrGrid)); neighborsAliveCount += *(putInBounds(tempPtr));
if (neighborsAliveCount) if (neighborsAliveCount) // TODO: retire
int a = 0; int a = 0;
return neighborsAliveCount; return neighborsAliveCount;

View File

@ -98,8 +98,8 @@ private:
void countLifeStatusCells(); void countLifeStatusCells();
// Fonction qui modifie le border selon la règle // Fonction qui modifie le border selon la règle
void modifyBorderIfNecessary(uint8_t* ptrGrid, uint8_t* ptrGridInt); void modifyBorderIfNecessary();
size_t countNeighbors(uint8_t* ptrGrid, BorderManagement bm) const; size_t countNeighbors(const uint8_t* ptrGrid) const;
}; };
#endif GOLTEAMH_H #endif GOLTEAMH_H