LibUDB  1.0.1
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 
28 class Algorithm
29 {
30 public:
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
The Algorithm class.
Definition: Algorithm.h:28
static InputIt parallelFindIf(InputIt start, InputIt end, UnaryPred predicate)
Definition: Algorithm.h:85
static void parallelSort(InputIt start, InputIt end, UnaryPred predicate)
Definition: Algorithm.h:120
static InputIt parallelRemove(InputIt start, InputIt end, const T &val)
Definition: Algorithm.h:199
static InputIt parallelRemoveIf(InputIt start, InputIt end, UnaryPred predicate)
Definition: Algorithm.h:243
static InputIt parallelFind(InputIt start, InputIt end, const T &val)
Definition: Algorithm.h:48