Performance between std::vector and std::array<std::optional>, n> to store small amount of data?

214 views Asked by At

I have a 2D Environment where I want to get for some cells the Moore neighborhood (east, west, north and east cells). Sometimes a cell can only have 3 or 2 neighbors (if we check from a border or a corner of the grid).

Above this, I'd like to differentiate the case where there is no border (torus world, what goes up reappears down...). In such case, every cells have exactly 4 neighbors.

Hence I made 2 versions of this algorithm, one using a std::vector of coordinates, and another one using std::array of optional coordinates (I refer to coordinates as pair of short ints). See below :

version with a vector of pairs

std::vector<std::pair<uint16_t, uint16_t>>* Environment::getMooreNeighborhood(uint16_t x, uint16_t y) const{
    std::vector<std::pair<uint16_t, uint16_t>>* neighborhood = new std::vector<std::pair<uint16_t, uint16_t>>();
    std::pair<uint16_t, uint16_t> west_cell(x - 1, y);
    std::pair<uint16_t, uint16_t> east_cell(x + 1, y);
    std::pair<uint16_t, uint16_t> north_cell(x, y - 1);
    std::pair<uint16_t, uint16_t> south_cell(x, y + 1);

    if(this->torus){
        if(x == this->width - 1){
            east_cell.first = 0;
        }
        else if(x == 0){
            west_cell.first = this->width - 1;
        }
        if(y == 0){
            north_cell.second = this->height - 1;
        }
        else if(y == this->height - 1){
            south_cell.second = 0;
        }
        neighborhood->push_back(east_cell);
        neighborhood->push_back(west_cell);
        neighborhood->push_back(south_cell);
        neighborhood->push_back(north_cell);
    }else{
        if(x > 0){
            neighborhood->push_back(east_cell);
        }
        if(x < this->width - 1){
            neighborhood->push_back(west_cell);
        }
        if(y > 0){
            neighborhood->push_back(north_cell);
        }
        if(y < this->height - 1){
            neighborhood->push_back(south_cell);
        }
    }
    return neighborhood;
}

version with an array of optional pairs

std::array<std::optional<std::pair<uint16_t,uint16_t>>, 4> Environment::getMooreNeighborhood(uint16_t x, uint16_t y) const {
    std::array<std::optional<std::pair<uint16_t,uint16_t>>, 4> neighborhood;
    std::optional<std::pair<uint16_t, uint16_t>> west_cell;
    std::optional<std::pair<uint16_t, uint16_t>> east_cell;
    std::optional<std::pair<uint16_t, uint16_t>> north_cell;
    std::optional<std::pair<uint16_t, uint16_t>> south_cell;

    if(this->torus){
        if(x == this->width - 1){
            east_cell = std::pair<uint16_t, uint16_t>(0, y);
        }
        else if(x == 0){
            west_cell = std::pair<uint16_t, uint16_t>(this->width - 1, y);
        }
        if(y == 0){
            north_cell = std::pair<uint16_t, uint16_t>(x, this->height - 1);
        }
        else if(y == this->height - 1){
            south_cell = std::pair<uint16_t, uint16_t>(x, 0);
        }
    }else{
        if(x > 0){
            east_cell = std::pair<uint16_t, uint16_t>(x - 1, y);
        }
        if(x < this->width - 1){
            west_cell = std::pair<uint16_t, uint16_t>(x + 1, y);
        }
        if(y > 0){
            north_cell = std::pair<uint16_t, uint16_t>(x, y - 1);
        }
        if(y < this->height - 1){
            north_cell = std::pair<uint16_t, uint16_t>(x, y + 1);
        }
    }
    neighborhood[0] = west_cell;
    neighborhood[1] = east_cell;
    neighborhood[2] = north_cell;
    neighborhood[3] = south_cell;
    return neighborhood;
}

I have to perform this operation a very high number of times, and I don't want to shoot myself in the foot by having a bad implementation. Is one choice over the other better or am I absolutely wrong and there is another way to do efficiently ?

0

There are 0 answers