Make add and clear use indices.
This is the last commit of the workstream and we have a ~10% speed improvement.
This commit is contained in:
44
main.cc
44
main.cc
@@ -26,7 +26,7 @@ namespace {
|
||||
* \param pos Position of closest corner to origin
|
||||
* \param length Side length.
|
||||
*/
|
||||
Square(Pos const &pos, size_t const length) noexcept : pos_(pos), length_(length) {
|
||||
Square(Pos pos, size_t const length) noexcept : pos_(pos), length_(length) {
|
||||
}
|
||||
|
||||
Square(Square const &other) noexcept = default;
|
||||
@@ -57,9 +57,13 @@ namespace {
|
||||
}
|
||||
|
||||
Results(Results const &other) noexcept = delete;
|
||||
|
||||
Results &operator=(Results const &other) noexcept = delete;
|
||||
|
||||
Results &operator=(Results &&other) noexcept = default;
|
||||
|
||||
Results(Results &&other) noexcept = default;
|
||||
|
||||
~Results() noexcept = default;
|
||||
|
||||
auto length() const noexcept -> size_t { return length_; }
|
||||
@@ -144,35 +148,35 @@ namespace {
|
||||
~Grid() noexcept = default;
|
||||
|
||||
/** Get grid length */
|
||||
auto length() const noexcept -> size_t { return length_; }
|
||||
auto end() const noexcept -> size_t { return grid_.size(); }
|
||||
|
||||
auto pos_x(Pos const& pos) const noexcept -> size_t { return pos % length_; }
|
||||
auto pos_y(Pos const& pos) const noexcept -> size_t { return pos / length_; }
|
||||
|
||||
/** Add a square to the grid. */
|
||||
auto add(Square const &sq) noexcept -> void {
|
||||
for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) {
|
||||
for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) {
|
||||
set(i, j, filled);
|
||||
/* One would expect the fastest way to do this would be to have x be the
|
||||
* fastest increasing index so we stores [pos, pos + 1,..., pos+length, ...]
|
||||
* But experimentation tells us this isn't so, and storing
|
||||
* [pos, pos + length, ..., pos + 1, ...] is faster!
|
||||
*/
|
||||
for (auto x = 0; x < sq.length(); ++x) {
|
||||
for (auto y = sq.pos(); y < sq.pos() + sq.length() * length_; y += length_) {
|
||||
grid_[x + y] = filled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear a square from the grid. */
|
||||
auto clear(Square const &sq) noexcept -> void {
|
||||
for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) {
|
||||
for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) {
|
||||
set(i, j, empty);
|
||||
for (auto x = 0; x < sq.length(); ++x) {
|
||||
for (auto y = sq.pos(); y < sq.pos() + sq.length() * length_; y += length_) {
|
||||
grid_[x + y] = empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Get length of the largest square that fits at \a pos in the grid.
|
||||
*/
|
||||
auto largest_square(Pos const &pos, size_t n) const noexcept -> size_t {
|
||||
assert(x(pos) < length_);
|
||||
assert(y(pos) < length_);
|
||||
auto largest_square(Pos pos, size_t n) const noexcept -> size_t {
|
||||
assert(pos < end());
|
||||
|
||||
/* Because of how we walk through the grid (starting at 0,0 then increasing
|
||||
* x followed by y) we can assume that if the position (b, y) is clear
|
||||
@@ -192,15 +196,16 @@ namespace {
|
||||
}
|
||||
// Check that this length fits vertically as well.
|
||||
auto const len = b - pos;
|
||||
auto const ye = std::min((pos / length_) + len, length_);
|
||||
return ye - pos_y(pos);
|
||||
auto const pos_y = pos / length_;
|
||||
auto const ye = std::min(pos_y + len, length_);
|
||||
return ye - pos_y;
|
||||
}
|
||||
|
||||
/** Get the next position to check starting at pos.
|
||||
*
|
||||
* Returns grid_.length() if no more positions avaialble.
|
||||
*/
|
||||
auto next_pos(Pos const &pos) const noexcept -> Pos {
|
||||
auto next_pos(Pos pos) const noexcept -> Pos {
|
||||
auto const b = grid_.begin() + pos;
|
||||
auto const p = std::find(b, grid_.end(), empty);
|
||||
return p - grid_.begin();
|
||||
@@ -287,7 +292,10 @@ namespace {
|
||||
}
|
||||
|
||||
// If there are no squares available of the current size try the next one.
|
||||
if (avail_sqs[idx] == 0) { --idx; continue; }
|
||||
if (avail_sqs[idx] == 0) {
|
||||
--idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Place a square of side length idx at pos, push this onto the stack and
|
||||
* set up to look at the next position.
|
||||
|
||||
Reference in New Issue
Block a user