CastleProto: track mapping of reports to tops

This allows us to speed up report-based queries, like dedupe checking.
This commit is contained in:
Justin Viiret 2015-12-02 11:31:09 +11:00 committed by Matthew Barr
parent da23e8306a
commit 8427d83780
2 changed files with 35 additions and 16 deletions

View File

@ -58,6 +58,7 @@
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
using namespace std; using namespace std;
using boost::adaptors::map_keys;
using boost::adaptors::map_values; using boost::adaptors::map_values;
namespace ue2 { namespace ue2 {
@ -686,8 +687,8 @@ buildCastle(const CastleProto &proto,
set<ReportID> all_reports(const CastleProto &proto) { set<ReportID> all_reports(const CastleProto &proto) {
set<ReportID> reports; set<ReportID> reports;
for (const PureRepeat &pr : proto.repeats | map_values) { for (const ReportID &report : proto.report_map | map_keys) {
reports.insert(pr.reports.begin(), pr.reports.end()); reports.insert(report);
} }
return reports; return reports;
} }
@ -727,7 +728,11 @@ depth findMaxWidth(const CastleProto &proto, u32 top) {
CastleProto::CastleProto(const PureRepeat &pr) { CastleProto::CastleProto(const PureRepeat &pr) {
assert(pr.reach.any()); assert(pr.reach.any());
assert(pr.reports.size() == 1); assert(pr.reports.size() == 1);
repeats.insert(make_pair(0, pr)); u32 top = 0;
repeats.emplace(top, pr);
for (const auto &report : pr.reports) {
report_map[report].insert(top);
}
} }
const CharReach &CastleProto::reach() const { const CharReach &CastleProto::reach() const {
@ -749,6 +754,9 @@ u32 CastleProto::add(const PureRepeat &pr) {
u32 top = find_next_top(repeats); u32 top = find_next_top(repeats);
DEBUG_PRINTF("selected unused top %u\n", top); DEBUG_PRINTF("selected unused top %u\n", top);
repeats.emplace(top, pr); repeats.emplace(top, pr);
for (const auto &report : pr.reports) {
report_map[report].insert(top);
}
return top; return top;
} }
@ -796,8 +804,7 @@ bool mergeCastle(CastleProto &c1, const CastleProto &c2,
const u32 top = m.first; const u32 top = m.first;
const PureRepeat &pr = m.second; const PureRepeat &pr = m.second;
DEBUG_PRINTF("top %u\n", top); DEBUG_PRINTF("top %u\n", top);
u32 new_top = find_next_top(c1.repeats); u32 new_top = c1.add(pr);
c1.repeats.emplace(new_top, pr);
top_map[top] = new_top; top_map[top] = new_top;
DEBUG_PRINTF("adding repeat: map %u->%u\n", top, new_top); DEBUG_PRINTF("adding repeat: map %u->%u\n", top, new_top);
} }
@ -819,6 +826,17 @@ void remapCastleTops(CastleProto &proto, map<u32, u32> &top_map) {
} }
proto.repeats.swap(out); proto.repeats.swap(out);
// Remap report map.
proto.report_map.clear();
for (const auto &m : proto.repeats) {
const u32 top = m.first;
const PureRepeat &pr = m.second;
for (const auto &report : pr.reports) {
proto.report_map[report].insert(top);
}
}
assert(proto.repeats.size() <= proto.max_occupancy); assert(proto.repeats.size() <= proto.max_occupancy);
} }
@ -896,18 +914,16 @@ bool is_equal(const CastleProto &c1, const CastleProto &c2) {
bool requiresDedupe(const CastleProto &proto, bool requiresDedupe(const CastleProto &proto,
const ue2::flat_set<ReportID> &reports) { const ue2::flat_set<ReportID> &reports) {
ue2::unordered_set<ReportID> seen; for (const auto &report : reports) {
for (const PureRepeat &pr : proto.repeats | map_values) { auto it = proto.report_map.find(report);
for (const ReportID &report : pr.reports) { if (it == end(proto.report_map)) {
if (contains(reports, report)) { continue;
if (contains(seen, report)) { }
if (it->second.size() > 1) {
DEBUG_PRINTF("castle proto %p has dupe report %u\n", &proto, DEBUG_PRINTF("castle proto %p has dupe report %u\n", &proto,
report); report);
return true; return true;
} }
seen.insert(report);
}
}
} }
return false; return false;
} }

View File

@ -81,6 +81,9 @@ struct CastleProto {
/** \brief Mapping from unique top id to repeat. */ /** \brief Mapping from unique top id to repeat. */
std::map<u32, PureRepeat> repeats; std::map<u32, PureRepeat> repeats;
/** \brief Mapping from report to associated tops. */
ue2::unordered_map<ReportID, flat_set<u32>> report_map;
}; };
std::set<ReportID> all_reports(const CastleProto &proto); std::set<ReportID> all_reports(const CastleProto &proto);