diff --git a/tests/Makefile b/tests/Makefile index 1c2427e..37f582b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -9,6 +9,8 @@ test: test.cpp ../fsgrid.hpp $(CXX) $(CXXFLAGS) -o $@ $< ddtest: ddtest.cpp $(CXX) $(CXXFLAGS) -o $@ $< +gol: gol.cpp + $(CXX) $(CXXFLAGS) -o $@ $< clean: -rm test diff --git a/tests/gol.cpp b/tests/gol.cpp new file mode 100644 index 0000000..046078c --- /dev/null +++ b/tests/gol.cpp @@ -0,0 +1,134 @@ +/* +Conway's Game of Life test for fsgrid. + +Copyright 2017 Ilja Honkonen + +This file is part of fsgrid + +fsgrid is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +fsgrid is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with fsgrid. If not, see . +*/ + +#include +#include +#include "../fsgrid.hpp" + +int main(int argc, char** argv) try { + MPI_Init(&argc,&argv); + + int rank,size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + FsGrid, 1> grid({10, 10, 1}, MPI_COMM_WORLD, {true, true, false}); + const std::array localSize = grid.getLocalSize(); + + for (int z = 0; z < localSize[2]; z++) { + for (int y = 0; y < localSize[1]; y++) { + for (int x = 0; x < localSize[0]; x++) { + auto* const cell = grid.get(x, y, z); + if (cell == nullptr) { + std::cout << __FILE__ "(" << __LINE__ << ")" << std::endl; + abort(); + } + + *cell = {0, 0}; + // create glider in upper left + const auto index = grid.getGlobalIndices(x, y, z); + if ( + (index[0] == 1 and index[1] == 2) + or (index[0] == 2 and index[1] == 3) + or (index[0] == 3 and index[1] == 3) + or (index[0] == 3 and index[1] == 2) + or (index[0] == 3 and index[1] == 1) + ) { + (*cell)[0] = 1; + } + }}} + + for (size_t turn = 0; turn < 10; turn++) { + grid.updateGhostCells(); + + // get number of live neighbors + for (int z = 0; z < localSize[2]; z++) { + for (int y = 0; y < localSize[1]; y++) { + for (int x = 0; x < localSize[0]; x++) { + auto* const cell = grid.get(x, y, z); + if (cell == nullptr) { + std::cout << __FILE__ "(" << __LINE__ << ")" << std::endl; + abort(); + } + for (auto x_offset: {-1, 0, +1}) { + for (auto y_offset: {-1, 0, +1}) { + for (auto z_offset: {0}) { + if (x_offset == 0 and y_offset == 0 and z_offset == 0) { + continue; + } + + const auto* const neighbor = grid.get(x + x_offset, y + y_offset, z + z_offset); + if (neighbor == nullptr) { + std::cout << __FILE__ "(" << __LINE__ << ")" << std::endl; + abort(); + } + if ((*neighbor)[0] > 0) { + (*cell)[1]++; + } + }}} + }}} + + // set new state + for (int z = 0; z < localSize[2]; z++) { + for (int y = 0; y < localSize[1]; y++) { + for (int x = 0; x < localSize[0]; x++) { + auto* const cell = grid.get(x, y, z); + if (cell == nullptr) { + std::cout << __FILE__ "(" << __LINE__ << ")" << std::endl; + abort(); + } + if ((*cell)[1] == 3) { + (*cell)[0] = 1; + } else if ((*cell)[1] != 2) { + (*cell)[0] = 0; + } + (*cell)[1] = 0; + }}} + + // check result + int local_alive = 0, global_alive = 0; + for (int z = 0; z < localSize[2]; z++) { + for (int y = 0; y < localSize[1]; y++) { + for (int x = 0; x < localSize[0]; x++) { + const auto* const cell = grid.get(x, y, z); + if (cell == nullptr) { + std::cout << __FILE__ "(" << __LINE__ << ")" << std::endl; + abort(); + } + if ((*cell)[0] > 0) { + local_alive++; + } + }}} + MPI_Reduce(&local_alive, &global_alive, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + if (rank == 0 and global_alive != 5) { + std::cout << global_alive << std::endl; + abort(); + } + } + + MPI_Finalize(); + return EXIT_SUCCESS; + +} catch(...) { + + std::cout << "Failed!" << std::endl; + return EXIT_FAILURE; +}