diff --git a/infinite_sparce_cube.hpp b/infinite_sparce_cube.hpp new file mode 100644 index 0000000..fe2db00 --- /dev/null +++ b/infinite_sparce_cube.hpp @@ -0,0 +1,96 @@ +#pragma once +#include +#include + +template +struct cube { + struct chunk_elem_t { + size_t coord; + T elem; + }; + + struct chunk_t { + std::array, chunk_size>, chunk_size> data; + }; + + struct row_t { + size_t coord; + std::shared_ptr value; + }; + + struct column_t { + size_t coord; + std::vector value; + }; + + std::vector chunks; + + std::optional at(size_t x, size_t y, size_t z) { + auto column = std::ranges::find_if(chunks, [&](const column_t& col) { + return col.coord == y/chunk_size; + }); + if(column == chunks.end()) return std::nullopt; + auto row = std::ranges::find_if(column->value, [&](const row_t& row) { + return row.coord == x/chunk_size; + }); + if(column->value.end() == row) return std::nullopt; + auto& chunk_segment = row->value->data.at(x%chunk_size).at(y%chunk_size); + auto position = std::ranges::find_if(chunk_segment, [&](const chunk_elem_t& item) { + return item.coord == z; + }); + if(position == chunk_segment.end()) return std::nullopt; + return position->elem; + } + + void set(size_t x, size_t y, size_t z, T&& value) { + auto column = std::ranges::find_if(chunks, [&](const column_t& col) { + return col.coord == y/chunk_size; + }); + if(column == chunks.end()) { + auto chunk = std::make_shared(); + chunks.push_back(column_t{ + .coord = y / chunk_size, + .value = { + row_t{ + .coord = x/chunk_size, + .value = chunk + } + } + }); + chunk->data.at(x%chunk_size).at(y%chunk_size).push_back(chunk_elem_t{ + .coord = z, + .elem = std::move(value) + }); + return; + } + auto row = std::ranges::find_if(column->value, [&](const row_t& row) { + return row.coord == x/chunk_size; + }); + if(column->value.end() == row) { + auto chunk = std::make_shared(); + column->value.push_back( + row_t{ + .coord = x/chunk_size, + .value = chunk + } + ); + chunk->data.at(x%chunk_size).at(y%chunk_size).push_back(chunk_elem_t{ + .coord = z, + .elem = std::move(value) + }); + return; + } + auto& chunk_segment = row->value->data.at(x%chunk_size).at(y%chunk_size); + auto position = std::ranges::find_if(chunk_segment, [&](const chunk_elem_t& item) { + return item.coord == z; + }); + if(position == chunk_segment.end()) { + chunk_segment.push_back(chunk_elem_t{ + .coord = z, + .elem = std::move(value) + }); + return; + } + position->elem = std::move(value); + } +};