Repository navigation
Expand file tree
/
Copy pathutils.hpp
More file actions
95 lines (82 loc) 路 2.55 KB
/
Copy pathutils.hpp
File metadata and controls
95 lines (82 loc) 路 2.55 KB
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
#ifndef UTILS_H
#define UTILS_H
#include <vector>
#include <deque>
#include <algorithm>
#include <random>
#include <iostream>
#include <thread>
#include <functional>
#define RELEASE_SAFELY(__POINTER) { if (__POINTER != nullptr) { delete __POINTER; __POINTER = nullptr; } }
template <typename T>
class InfiniteRandomIterator
{
using VecType = std::vector<T>;
public:
InfiniteRandomIterator(const VecType &v) : v(v), engine(42) {
shuffleV();
}
void shuffleV(){
std::shuffle(std::begin(v), std::end(v), engine);
i = 0;
}
T next(){
T ret = v[i++];
if (i >= v.size()){
if (upcoming.empty()){
shuffleV();
}else{
v = std::move(upcoming.front());
upcoming.pop_front();
i = 0;
}
}
return ret;
}
// Element that next() will return k calls from now (k = 0 is the next one).
// Looking ahead does not change the sequence
T peek(size_t k){
size_t idx = i + k;
size_t available = v.size();
for (const VecType &p : upcoming) available += p.size();
while (idx >= available){
VecType p = upcoming.empty() ? v : upcoming.back();
std::shuffle(std::begin(p), std::end(p), engine);
available += p.size();
upcoming.push_back(std::move(p));
}
if (idx < v.size()) return v[idx];
idx -= v.size();
for (const VecType &p : upcoming){
if (idx < p.size()) return p[idx];
idx -= p.size();
}
return v[0];
}
private:
VecType v;
std::deque<VecType> upcoming; // permutations generated ahead by peek()
size_t i;
std::default_random_engine engine;
};
template <typename IndexType, typename FuncType>
void parallel_for(IndexType begin, IndexType end, FuncType func) {
size_t range = end - begin;
if (range <= 0) return;
size_t numThreads = (std::min)(static_cast<size_t>(std::thread::hardware_concurrency()), range);
size_t chunkSize = (range + numThreads - 1) / numThreads;
std::vector<std::thread> threads;
for (unsigned int i = 0; i < numThreads; i++) {
IndexType chunkBegin = begin + i * chunkSize;
IndexType chunkEnd = (std::min)(chunkBegin + chunkSize, end);
threads.emplace_back([chunkBegin, chunkEnd, &func]() {
for (IndexType item = chunkBegin; item < chunkEnd; item++) {
func(*item);
}
});
}
for (std::thread& t : threads) {
t.join();
}
}
#endif