From 092d947830408475b65cbc63b2b5a6c733cb3435 Mon Sep 17 00:00:00 2001 From: Kp Date: Sun, 15 Jan 2017 00:03:14 +0000 Subject: [PATCH] Optimize change_light search Use std::equal_range to find the upper and lower bounds in a single binary search, rather than relying on a linear search to find the first sought element. --- common/main/segment.h | 8 ++++++++ similar/main/gamesave.cpp | 9 +-------- similar/main/gameseg.cpp | 18 ++++++------------ 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/common/main/segment.h b/common/main/segment.h index f5297eeb7..6069dcb35 100644 --- a/common/main/segment.h +++ b/common/main/segment.h @@ -279,6 +279,14 @@ struct dl_index { uint8_t sidenum; uint8_t count; uint16_t index; + bool operator<(const dl_index &rhs) const + { + if (segnum < rhs.segnum) + return true; + if (segnum > rhs.segnum) + return false; + return sidenum < rhs.sidenum; + } }; #endif diff --git a/similar/main/gamesave.cpp b/similar/main/gamesave.cpp index 15e817b42..291f19a43 100644 --- a/similar/main/gamesave.cpp +++ b/similar/main/gamesave.cpp @@ -993,14 +993,7 @@ static int load_game_data(PHYSFS_File *LoadFile) const auto &&lr = partial_range(Dl_indices, Num_static_lights); range_for (auto &i, lr) dl_index_read(&i, LoadFile); - const auto predicate = [](const dl_index &a, const dl_index &b) { - if (a.segnum < b.segnum) - return true; - if (a.segnum > b.segnum) - return false; - return a.sidenum < b.sidenum; - }; - std::sort(lr.begin(), lr.end(), predicate); + std::sort(lr.begin(), lr.end()); } // Indicate that no light has been subtracted from any vertices. diff --git a/similar/main/gameseg.cpp b/similar/main/gameseg.cpp index 65566d815..65c9bdbac 100644 --- a/similar/main/gameseg.cpp +++ b/similar/main/gameseg.cpp @@ -1686,18 +1686,15 @@ static void change_segment_light(const vsegptridx_t segp,int sidenum,int dir) // dir = -1 -> subtract light // dir = 17 -> add 17x light // dir = 0 -> you are dumb -static void change_light(const vsegptridx_t segnum, int sidenum, int dir) +static void change_light(const vsegptridx_t segnum, const uint8_t sidenum, const int dir) { const fix ds = dir * DL_SCALE; - range_for (auto &i, partial_const_range(Dl_indices, Num_static_lights)) + const auto &&pr = partial_const_range(Dl_indices, Num_static_lights); + const auto &&er = std::equal_range(pr.begin(), pr.end(), dl_index{segnum, sidenum, 0, 0}); + range_for (auto &i, partial_range_t(er.first, er.second)) { - if (i.segnum == segnum) - { - if (i.sidenum > sidenum) - break; - if (i.sidenum < sidenum) - continue; - range_for (auto &j, partial_const_range(Delta_lights, static_cast(i.index), static_cast(i.count))) + const uint_fast32_t idx = i.index; + range_for (auto &j, partial_const_range(Delta_lights, idx, idx + i.count)) { assert(j.sidenum < MAX_SIDES_PER_SEGMENT); const auto &&segp = vsegptr(j.segnum); @@ -1709,9 +1706,6 @@ static void change_light(const vsegptridx_t segnum, int sidenum, int dir) l = 0; } } - } - else if (i.segnum > segnum) - break; } //recompute static light for segment