Compare commits

...

2 Commits

Author SHA1 Message Date
cat
0014ce0602 First RC of QueryWithAll, needs its erase logic improved 2026-02-27 09:06:16 +02:00
cat
09b58fe1f5 addded .cache to gitignore 2026-02-27 09:06:04 +02:00
2 changed files with 31 additions and 33 deletions

3
.gitignore vendored
View File

@@ -165,3 +165,6 @@ build-iPhoneSimulator/
# Custom # Custom
# For personal testing cases # For personal testing cases
test/ test/
# clangd
.cache/

View File

@@ -11,6 +11,7 @@
#include "../Concepts.hpp" #include "../Concepts.hpp"
#include "../Systems/Logging.hpp" #include "../Systems/Logging.hpp"
#include <algorithm>
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
@@ -30,11 +31,16 @@ template <Concepts::Hashable AKey, Concepts::Hashable BKey, typename Value,
class DualkeyMap { class DualkeyMap {
public: public:
// Return Types // Return Types
template <typename OppositeKey, std::size_t Count> template <typename OppositeKey, std::size_t keyCount>
requires Concepts::Either<OppositeKey, AKey, BKey> requires Concepts::Either<OppositeKey, AKey, BKey>
using MultiQueryResult = struct MultiQueryResult {
std::pair<const OppositeKey &, // Having to use pointers here over references was not fun
std::array<std::reference_wrapper<Value>, Count>>; // but it was for greater good
const OppositeKey *oppositeKey;
std::size_t howManyFound = 1;
std::array<Value *, keyCount> valueQueryResults;
};
using QueryResult = using QueryResult =
std::pair<std::variant<std::monostate, std::reference_wrapper<const AKey>, std::pair<std::variant<std::monostate, std::reference_wrapper<const AKey>,
std::reference_wrapper<const BKey>>, std::reference_wrapper<const BKey>>,
@@ -201,19 +207,16 @@ public:
std::size_t keyCount> std::size_t keyCount>
requires Concepts::Either<Key, AKey, BKey> requires Concepts::Either<Key, AKey, BKey>
[[nodiscard("Discarding a very expensive query!")]] [[nodiscard("Discarding a very expensive query!")]]
int QueryWithAll(const Key (&keys)[keyCount]) { std::vector<MultiQueryResult<OppositeKey, keyCount>>
std::vector<unprocessedMultiQueryResult<OppositeKey, keyCount>> QueryWithAll(const Key (&keys)[keyCount]) {
queryResults = queryWithMany<Key>(keys); std::vector<MultiQueryResult<OppositeKey, keyCount>> queryResult =
queryWithMany<Key>(keys);
// You could very well use auto here but this helps std::erase_if(
// with LSP hints queryResult,
for (const unprocessedMultiQueryResult<OppositeKey, keyCount> &queryRecord : [](const MultiQueryResult<OppositeKey, keyCount> &queryRecord) {
queryResults) { return queryRecord.howManyFound != keyCount;
if (queryRecord.howManyFound == keyCount) { });
} return queryResult;
}
return 0;
} }
void Scan(std::function<bool(const std::size_t firstKeyHash, void Scan(std::function<bool(const std::size_t firstKeyHash,
@@ -244,13 +247,6 @@ public:
private: private:
// Interal data structures // Interal data structures
template <typename OppositeKey, std::size_t keyCount>
struct unprocessedMultiQueryResult {
OppositeKey *resultKey = nullptr;
std::size_t howManyFound = 1;
std::array<Value *, keyCount> valueQueryResults;
};
struct DualkeyHash { struct DualkeyHash {
DualkeyHash(AKey &&firstKey, BKey &&secondKey, Value &&value) DualkeyHash(AKey &&firstKey, BKey &&secondKey, Value &&value)
: firstKey(std::move(firstKey)), secondKey(std::move(secondKey)), : firstKey(std::move(firstKey)), secondKey(std::move(secondKey)),
@@ -273,7 +269,7 @@ private:
template <typename Key, template <typename Key,
typename OppositeKey = Concepts::OppositeOf<Key, AKey, BKey>, typename OppositeKey = Concepts::OppositeOf<Key, AKey, BKey>,
std::size_t keyCount> std::size_t keyCount>
inline std::vector<unprocessedMultiQueryResult<OppositeKey, keyCount>> inline std::vector<MultiQueryResult<OppositeKey, keyCount>>
queryWithMany(const Key (&keys)[keyCount]) { queryWithMany(const Key (&keys)[keyCount]) {
constexpr bool searchingInFirstKey = std::is_same_v<Key, AKey>; constexpr bool searchingInFirstKey = std::is_same_v<Key, AKey>;
@@ -301,9 +297,9 @@ private:
uint64_t hashToCompare; uint64_t hashToCompare;
Key *keyToCompare; Key *keyToCompare;
OppositeKey *resultKey; OppositeKey *oppositeKey;
std::vector<unprocessedMultiQueryResult<OppositeKey, keyCount>> std::vector<MultiQueryResult<OppositeKey, keyCount>> queryResults;
queryResults; queryResults.reserve(512);
for (DualkeyHash *hash : hashList) { for (DualkeyHash *hash : hashList) {
// The hell of doing 2 conditions with similar logics in // The hell of doing 2 conditions with similar logics in
@@ -311,11 +307,11 @@ private:
if constexpr (searchingInFirstKey) { if constexpr (searchingInFirstKey) {
hashToCompare = hash->firstKeyHash; hashToCompare = hash->firstKeyHash;
keyToCompare = const_cast<AKey *>(&hash->firstKey); keyToCompare = const_cast<AKey *>(&hash->firstKey);
resultKey = const_cast<BKey *>(&hash->secondKey); oppositeKey = const_cast<BKey *>(&hash->secondKey);
} else { } else {
hashToCompare = hash->secondKeyHash; hashToCompare = hash->secondKeyHash;
keyToCompare = const_cast<BKey *>(&hash->secondKey); keyToCompare = const_cast<BKey *>(&hash->secondKey);
resultKey = const_cast<AKey *>(&hash->firstKey); oppositeKey = const_cast<AKey *>(&hash->firstKey);
} }
// The code above was done to make this code more uniform // The code above was done to make this code more uniform
@@ -324,7 +320,7 @@ private:
bool doesExist = false; bool doesExist = false;
for (auto &queryRecord : queryResults) { for (auto &queryRecord : queryResults) {
if (*queryRecord.resultKey == *resultKey) { if (*queryRecord.oppositeKey == *oppositeKey) {
queryRecord.valueQueryResults[index] = &hash->value; queryRecord.valueQueryResults[index] = &hash->value;
++queryRecord.howManyFound; ++queryRecord.howManyFound;
doesExist = true; doesExist = true;
@@ -338,9 +334,8 @@ private:
// Since the result record is not present // Since the result record is not present
// we have to make it // we have to make it
queryResults.emplace_back(); queryResults.emplace_back(oppositeKey);
auto &newRecord = queryResults.back(); auto &newRecord = queryResults.back();
newRecord.resultKey = resultKey;
newRecord.valueQueryResults[index] = &hash->value; newRecord.valueQueryResults[index] = &hash->value;
} }
} }