Commit cea089f6 authored by Yann Boucher's avatar Yann Boucher
Browse files

Improved performance (600ms to 30ms per cycle for 1M cells

parent a829fbcc
#ifndef CONSTANTES_HPP
#define CONSTANTES_HPP
#define MAX_ETATS 32
#if MAX_ETATS > 255
#error MAX_ETATS ne tient pas dans un unsigned char
#endif
#define MAX_VOISINS 256
#endif // CONSTANTES_HPP
......@@ -31,7 +31,7 @@ class Structure;
class Grid{
int nb_rows;
int nb_col;
std::vector<unsigned int> matrix;
std::vector<unsigned char> matrix;
public:
//! \brief Constructeur par défaut, avec le nombre de ligne et de colonne souhaités
Grid(size_t l,size_t c);
......
......@@ -17,9 +17,11 @@ Cette classe représente le voisinage d'une cellule.
#include <utility>
#include <string>
#include <algorithm>
#include <cstring>
#include "coord.hpp"
#include "state.hpp"
#include "constantes.hpp"
using namespace std;
......@@ -38,18 +40,27 @@ public:
//! \brief Classe représentant un voisinage, c'est à dire une liste de cellules dont leur état et leur position.
class Neighborhood {
//! \brief vector de voisins contenant la position relative et l'état du voisin
mutable vector<pair<Coord, unsigned int>> neighborPositions;
//! \brief Contient le nombre de voisins d'état i : counts[i] contient le nb de voisins d'état i, ou 0 si i >= counts.size()
std::vector<unsigned> counts;
//! \brief struct nécéssaire pour éviter l'initalisation par zéro coûteuse d'un std::pair
struct Cell
{
Coord pos;
unsigned char state;
};
//! \brief Contient le nombre de voisins d'état i : counts[i] contient le nb de voisins d'état i, ou 0 si i >= MAX_ETATS
unsigned char counts[MAX_ETATS];
//! \brief Nombre de voisins
unsigned int neighbors;
mutable bool sorted;
//! \brief Tableau contenant la liste des voisins
mutable Cell neighborPositions[MAX_VOISINS];
public:
//! \brief Initialisation du Neighborhood
Neighborhood()
{
neighborPositions.reserve(8);
counts.reserve(8);
memset(counts, 0, MAX_ETATS);
neighbors = 0;
sorted = false;
}
......@@ -58,7 +69,7 @@ public:
//! \return Le nombre de voisin
unsigned int getNb(unsigned int s) const
{
if (s >= counts.size())
if (s >= MAX_ETATS)
return 0;
else
return counts[s];
......@@ -68,12 +79,13 @@ public:
//! \brief Ajoute un voisin au vecteur des voisins. Prend une coordonnée et un état en paramètre
//! \param Coord, State : coordonée relative et état du voisin
//! \pre La coord ne doit pas déjà exister
void addNeighbor(Coord c, unsigned int s) {
void addNeighbor(Coord c, unsigned char s) {
if (s >= MAX_ETATS)
throw NeighborhoodException("Valeur d'état supérieure à l'état maximal");
sorted = false;
neighborPositions.push_back({c,s});
if (s >= counts.size())
counts.resize(s+1, 0);
++counts[s];
neighborPositions[neighbors++] = {c,s};
++counts[s];
}
//! \brief Retourne une copie du voisinage, miroir selon l'axe vertical.
......@@ -85,23 +97,23 @@ public:
//! \brief Retourne le nombre de voisins dans le Neighborhood.
unsigned size() const
{ return neighborPositions.size(); }
{ return neighbors; }
//! \brief Retourne la cellule numéro i (index allant de 0 à size()-1, permettant d'indexer les cellules indépendamment de leur position
pair<Coord, unsigned int> neighbor_at_index(unsigned i) const
pair<Coord, unsigned char> neighbor_at_index(unsigned i) const
{
if (i >= size())
throw NeighborhoodException("Index invalide\n");
if (!sorted)
{
std::sort(neighborPositions.begin(), neighborPositions.end(),
[](const pair<Coord, unsigned int>& lhs, const pair<Coord, unsigned int>& rhs)
std::sort(std::begin(neighborPositions), std::begin(neighborPositions) + neighbors,
[](const Cell& lhs, const Cell& rhs)
{
return lhs.first < rhs.first;
return lhs.pos < rhs.pos;
});
sorted = true;
}
return neighborPositions[i];
return {neighborPositions[i].pos, neighborPositions[i].state};
}
};
......
......@@ -3,9 +3,10 @@
Neighborhood Neighborhood::flip_vertically() const
{
Neighborhood n;
for (const auto& val : neighborPositions)
for (unsigned i = 0; i < size(); ++i)
{
n.addNeighbor(Coord{val.first.x, -val.first.y}, val.second);
const auto& val = neighborPositions[i];
n.addNeighbor(Coord{val.pos.x, -val.pos.y}, val.state);
}
return n;
}
......@@ -13,9 +14,10 @@ Neighborhood Neighborhood::flip_vertically() const
Neighborhood Neighborhood::flip_horizontally() const
{
Neighborhood n;
for (const auto& val : neighborPositions)
for (unsigned i = 0; i < size(); ++i)
{
n.addNeighbor(Coord{-val.first.x, val.first.y}, val.second);
const auto& val = neighborPositions[i];
n.addNeighbor(Coord{-val.pos.x, val.pos.y}, val.state);
}
return n;
}
......@@ -23,9 +25,10 @@ Neighborhood Neighborhood::flip_horizontally() const
Neighborhood Neighborhood::rotate90() const
{
Neighborhood n;
for (const auto& val : neighborPositions)
for (unsigned i = 0; i < size(); ++i)
{
n.addNeighbor(Coord{-val.first.y, val.first.x}, val.second);
const auto& val = neighborPositions[i];
n.addNeighbor(Coord{-val.pos.y, val.pos.x}, val.state);
}
return n;
}
......
......@@ -6,7 +6,7 @@ CONFIG += c++14
TEMPLATE = app
# Optimisations, flag pour garder les infos de debug
QMAKE_CXXFLAGS += -O2 -g
QMAKE_CXXFLAGS += -O3 -g
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
......@@ -69,6 +69,7 @@ HEADERS += \
../include/stateColor.hpp \
../include/state.hpp \
../include/history.h \
../include/constantes.hpp \
../include/structurelibraryview.hpp \
../include/transitionrule.hpp \
../include/transition_rules/circulartransition.hpp \
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment