LibUDB 1.0
Loading...
Searching...
No Matches
Algorithm.h
1/*
2 * Copyright (C) 2026 Yury Bobylev <bobilev_yury@mail.ru>
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation, version 3.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16#ifndef ALGORITHM_H
17#define ALGORITHM_H
18
19#include <algorithm>
20#include <omp.h>
21#include <vector>
22
28class Algorithm
29{
30public:
31 Algorithm();
32
45 template <class InputIt,
46 class T = typename std::iterator_traits<InputIt>::value_type>
47 static InputIt
48 parallelFind(InputIt start, InputIt end, const T &val)
49 {
50 InputIt result = end;
51#pragma omp parallel
52#pragma omp for
53 for(InputIt i = start; i < end; i++)
54 {
55 if(*i == val)
56 {
57#pragma omp critical
58 {
59 if(i < result)
60 {
61 result = i;
62 }
63 }
64#pragma omp cancel for
65 }
66 }
67
68 return result;
69 }
70
83 template <class InputIt, class UnaryPred>
84 static InputIt
85 parallelFindIf(InputIt start, InputIt end, UnaryPred predicate)
86 {
87 InputIt res = end;
88#pragma omp parallel
89#pragma omp for
90 for(InputIt i = start; i < end; i++)
91 {
92 if(predicate(*i))
93 {
94#pragma omp critical
95 {
96 if(i < res)
97 {
98 res = i;
99 }
100 }
101#pragma omp cancel for
102 }
103 }
104
105 return res;
106 }
107
118 template <class InputIt, class UnaryPred>
119 static void
120 parallelSort(InputIt start, InputIt end, UnaryPred predicate)
121 {
122 if(end - start < 1)
123 {
124 return void();
125 }
126 std::vector<std::tuple<InputIt, InputIt>> parts;
127 parts.push_back(std::make_tuple(start, end));
128
129 omp_lock_t mtx;
130 omp_init_lock(&mtx);
131
132 while(parts.size() > 0)
133 {
134 std::vector<std::tuple<InputIt, InputIt>> l_parts;
135#pragma omp parallel
136#pragma omp masked
137 {
138 for(auto it = parts.begin(); it != parts.end(); it++)
139 {
140#pragma omp task
141 {
142 InputIt i = std::get<0>(*it);
143 InputIt end = std::get<1>(*it);
144 std::ptrdiff_t diff = end - i;
145 while(diff > 1)
146 {
147 if(predicate(*i, *(end - 1)))
148 {
149 i++;
150 }
151 else
152 {
153 if(diff > 2)
154 {
155 std::swap(*(end - 1), *(end - 2));
156 }
157 std::swap(*i, *(end - 1));
158 end--;
159 }
160 diff = end - i;
161 }
162 if(end - 1 - std::get<0>(*it) > 1)
163 {
164 omp_set_lock(&mtx);
165 l_parts.push_back(
166 std::make_tuple(std::get<0>(*it), end - 1));
167 omp_unset_lock(&mtx);
168 }
169 if(std::get<1>(*it) - end > 1)
170 {
171 omp_set_lock(&mtx);
172 l_parts.push_back(std::make_tuple(end, std::get<1>(*it)));
173 omp_unset_lock(&mtx);
174 }
175 }
176 }
177 }
178 parts = std::move(l_parts);
179 }
180
181 omp_destroy_lock(&mtx);
182 }
183
196 template <class InputIt,
197 class T = typename std::iterator_traits<InputIt>::value_type>
198 static InputIt
199 parallelRemove(InputIt start, InputIt end, const T &val)
200 {
201#ifndef OMP_REMOVING
202 return std::remove(start, end, val);
203#else
204 start = parallelFind(start, end, val);
205 if(start < end)
206 {
207 T *s = start.base();
208 T *e = end.base();
209#pragma omp parallel
210#pragma omp for ordered
211 for(T *i = s + 1; i != e; i++)
212 {
213 if((*i) != val)
214 {
215#pragma omp ordered
216 {
217 *s = std::move((*i));
218 s++;
219 }
220 }
221 }
222 start += s - start.base();
223 }
224 return start;
225#endif
226 }
227
240 template <class InputIt, class UnaryPred,
241 class T = typename std::iterator_traits<InputIt>::value_type>
242 static InputIt
243 parallelRemoveIf(InputIt start, InputIt end, UnaryPred predicate)
244 {
245#ifndef OMP_REMOVING
246 return std::remove_if(start, end, predicate);
247#else
248 start = parallelFindIf(start, end, predicate);
249 if(start < end)
250 {
251 T *s = start.base();
252 T *e = end.base();
253#pragma omp parallel
254#pragma omp for ordered
255 for(T *i = s + 1; i != e; i++)
256 {
257 if(!predicate(*i))
258 {
259#pragma omp ordered
260 {
261 *s = std::move(*i);
262 s++;
263 }
264 }
265 }
266 start += s - start.base();
267 }
268 return start;
269#endif
270 }
271};
272
273#endif // ALGORITHM_H
static InputIt parallelFind(InputIt start, InputIt end, const T &val)
Definition Algorithm.h:48
static InputIt parallelRemoveIf(InputIt start, InputIt end, UnaryPred predicate)
Definition Algorithm.h:243
static InputIt parallelFindIf(InputIt start, InputIt end, UnaryPred predicate)
Definition Algorithm.h:85
static InputIt parallelRemove(InputIt start, InputIt end, const T &val)
Definition Algorithm.h:199
static void parallelSort(InputIt start, InputIt end, UnaryPred predicate)
Definition Algorithm.h:120