-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVisitedSet.hpp
148 lines (129 loc) · 3.93 KB
/
VisitedSet.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#pragma once
#include <type_traits>
#include "DistanceFunction.hpp"
#include "Neighbors.hpp"
namespace chm {
/**
* Výsledek pokusu o navštívení prvního nenavštíveného prvku ze seznamu sousedů.
*/
struct VisitResult {
/**
* Pozice prvního nenavštíveného prvku v seznamu sousedů.
*/
size_t idx;
/**
* Identita prvního nenavštíveného prvku.
*/
uint neighborID;
/**
* Pravda, pokud byl nalezen nenavštívený prvek.
*/
bool success;
/**
* Vrátí objekt, který reprezentuje neúspěšný pokus o navštívení.
* @return Objekt reprezentující neúspěšný pokus o navštívení.
*/
static VisitResult fail();
/**
* Konstruktor.
* @param[in] idx @ref idx
* @param[in] neighborID @ref neighborID
* @param[in] success @ref success
*/
VisitResult(const size_t idx, const uint neighborID, const bool success);
};
/**
* Seznam navštívených prvků.
* @tparam T Určuje typ informace o návštěvě prvku.
*/
template<typename T>
class VisitedSet {
/**
* Pole informací o návštěvě prvků.
*/
std::vector<T> v;
/**
* Vrátí pravdu, pokud je @ref v bitovým polem.
* @return Pravda, pokud je @ref v bitovým polem.
*/
static constexpr bool isBitArray();
public:
/**
* Pokusí se navštívit daný prvek.
* @param[in] id Identita prvku.
* @return Pravda, pokud byl prvek před zavoláním této metody nenavštíven.
*/
bool insert(const uint id);
/**
* Pokusí se navštívit první nenavštívený prvek ze seznamu sousedů.
* @param[in] N Seznam sousedů.
* @param[in] startIdx Pozice prvního prvku v seznamu sousedů, který dosud nebyl zkontrolován.
* @return Objekt reprezentující pokus o navštívení prvního nenavštíveného prvku ze seznamu sousedů.
*/
VisitResult insertNext(const Neighbors& N, const size_t startIdx);
/**
* Asynchronně načte informace o návštěvách prvků do paměti.
* @param[in] id Pozice v poli @ref v, odkud budou data načteny.
*/
void prefetch(const uint id) const;
/**
* Vynuluje seznam navštívených prvků a navštíví počáteční prvek.
* @param[in] count Počet prvků v indexu, které mohou být navštíveny.
* @param[in] epID Identita počátečního prvku.
*/
void prepare(const uint count, const uint epID);
/**
* Konstruktor.
* @param[in] maxCount Maximální počet prvků v indexu.
*/
VisitedSet(const uint maxCount);
};
template<typename T>
inline constexpr bool VisitedSet<T>::isBitArray() {
return std::is_same<T, bool>::value;
}
template<typename T>
inline bool VisitedSet<T>::insert(const uint id) {
if(this->v[id])
return false;
this->v[id] = true;
return true;
}
template<typename T>
inline VisitResult VisitedSet<T>::insertNext(const Neighbors& N, const size_t startIdx) {
const size_t len(N.len());
if constexpr(VisitedSet<T>::isBitArray())
for(size_t idx = startIdx; idx < len; idx++) {
const auto id = N.get(idx);
if(this->insert(id))
return VisitResult(idx, id, true);
}
else {
const auto lastIdx = len - 1;
for(size_t idx = startIdx; idx < lastIdx; idx++) {
this->prefetch(N.get(idx + 1));
const auto id = N.get(idx);
if(this->insert(id))
return VisitResult(idx, id, true);
}
const auto id = N.get(lastIdx);
if(this->insert(id))
return VisitResult(lastIdx, id, true);
}
return VisitResult::fail();
}
template<typename T>
inline void VisitedSet<T>::prefetch(const uint id) const {
#if defined(SIMD_CAPABLE)
if constexpr(!VisitedSet<T>::isBitArray())
_mm_prefetch(reinterpret_cast<const char*>(this->v.data() + size_t(id)), _MM_HINT_T0);
#endif
}
template<typename T>
inline void VisitedSet<T>::prepare(const uint count, const uint epID) {
std::fill(this->v.begin(), this->v.begin() + count, false);
this->v[epID] = true;
}
template<typename T>
inline VisitedSet<T>::VisitedSet(const uint maxCount) : v(maxCount, false) {}
}