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.
This commit is contained in:
Kp 2017-01-15 00:03:14 +00:00
parent 3594e7093f
commit 092d947830
3 changed files with 15 additions and 20 deletions

View file

@ -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

View file

@ -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.

View file

@ -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<const dl_index *>(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<uint_fast32_t>(i.index), static_cast<uint_fast32_t>(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);
@ -1710,9 +1707,6 @@ static void change_light(const vsegptridx_t segnum, int sidenum, int dir)
}
}
}
else if (i.segnum > segnum)
break;
}
//recompute static light for segment
change_segment_light(segnum,sidenum,dir);