00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
00041 #define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
00042
00043 #include <omp.h>
00044
00045 #include <parallel/settings.h>
00046 #include <parallel/multiseq_selection.h>
00047
00048 namespace __gnu_parallel
00049 {
00050 template<typename InputIterator, typename OutputIterator>
00051 OutputIterator
00052 copy_tail(std::pair<InputIterator, InputIterator> b,
00053 std::pair<InputIterator, InputIterator> e, OutputIterator r)
00054 {
00055 if (b.first != e.first)
00056 {
00057 do
00058 {
00059 *r++ = *b.first++;
00060 }
00061 while (b.first != e.first);
00062 }
00063 else
00064 {
00065 while (b.second != e.second)
00066 *r++ = *b.second++;
00067 }
00068 return r;
00069 }
00070
00071 template<typename InputIterator,
00072 typename OutputIterator,
00073 typename Comparator>
00074 struct symmetric_difference_func
00075 {
00076 typedef std::iterator_traits<InputIterator> traits_type;
00077 typedef typename traits_type::difference_type difference_type;
00078 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
00079
00080 symmetric_difference_func(Comparator c) : comp(c) {}
00081
00082 Comparator comp;
00083
00084 OutputIterator
00085 invoke(InputIterator a, InputIterator b,
00086 InputIterator c, InputIterator d,
00087 OutputIterator r) const
00088 {
00089 while (a != b && c != d)
00090 {
00091 if (comp(*a, *c))
00092 {
00093 *r = *a;
00094 ++a;
00095 ++r;
00096 }
00097 else if (comp(*c, *a))
00098 {
00099 *r = *c;
00100 ++c;
00101 ++r;
00102 }
00103 else
00104 {
00105 ++a;
00106 ++c;
00107 }
00108 }
00109 return std::copy(c, d, std::copy(a, b, r));
00110 }
00111
00112 difference_type
00113 count(InputIterator a, InputIterator b,
00114 InputIterator c, InputIterator d) const
00115 {
00116 difference_type counter = 0;
00117
00118 while (a != b && c != d)
00119 {
00120 if (comp(*a, *c))
00121 {
00122 ++a;
00123 ++counter;
00124 }
00125 else if (comp(*c, *a))
00126 {
00127 ++c;
00128 ++counter;
00129 }
00130 else
00131 {
00132 ++a;
00133 ++c;
00134 }
00135 }
00136
00137 return counter + (b - a) + (d - c);
00138 }
00139
00140 OutputIterator
00141 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
00142 { return std::copy(c, d, out); }
00143
00144 OutputIterator
00145 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
00146 { return std::copy(a, b, out); }
00147 };
00148
00149
00150 template<typename InputIterator,
00151 typename OutputIterator,
00152 typename Comparator>
00153 struct difference_func
00154 {
00155 typedef std::iterator_traits<InputIterator> traits_type;
00156 typedef typename traits_type::difference_type difference_type;
00157 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
00158
00159 difference_func(Comparator c) : comp(c) {}
00160
00161 Comparator comp;
00162
00163 OutputIterator
00164 invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
00165 OutputIterator r) const
00166 {
00167 while (a != b && c != d)
00168 {
00169 if (comp(*a, *c))
00170 {
00171 *r = *a;
00172 ++a;
00173 ++r;
00174 }
00175 else if (comp(*c, *a))
00176 { ++c; }
00177 else
00178 {
00179 ++a;
00180 ++c;
00181 }
00182 }
00183 return std::copy(a, b, r);
00184 }
00185
00186 difference_type
00187 count(InputIterator a, InputIterator b,
00188 InputIterator c, InputIterator d) const
00189 {
00190 difference_type counter = 0;
00191
00192 while (a != b && c != d)
00193 {
00194 if (comp(*a, *c))
00195 {
00196 ++a;
00197 ++counter;
00198 }
00199 else if (comp(*c, *a))
00200 { ++c; }
00201 else
00202 { ++a; ++c; }
00203 }
00204
00205 return counter + (b - a);
00206 }
00207
00208 inline OutputIterator
00209 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
00210 { return out; }
00211
00212 inline OutputIterator
00213 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
00214 { return std::copy(a, b, out); }
00215 };
00216
00217
00218 template<typename InputIterator,
00219 typename OutputIterator,
00220 typename Comparator>
00221 struct intersection_func
00222 {
00223 typedef std::iterator_traits<InputIterator> traits_type;
00224 typedef typename traits_type::difference_type difference_type;
00225 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
00226
00227 intersection_func(Comparator c) : comp(c) {}
00228
00229 Comparator comp;
00230
00231 OutputIterator
00232 invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
00233 OutputIterator r) const
00234 {
00235 while (a != b && c != d)
00236 {
00237 if (comp(*a, *c))
00238 { ++a; }
00239 else if (comp(*c, *a))
00240 { ++c; }
00241 else
00242 {
00243 *r = *a;
00244 ++a;
00245 ++c;
00246 ++r;
00247 }
00248 }
00249
00250 return r;
00251 }
00252
00253 difference_type
00254 count(InputIterator a, InputIterator b,
00255 InputIterator c, InputIterator d) const
00256 {
00257 difference_type counter = 0;
00258
00259 while (a != b && c != d)
00260 {
00261 if (comp(*a, *c))
00262 { ++a; }
00263 else if (comp(*c, *a))
00264 { ++c; }
00265 else
00266 {
00267 ++a;
00268 ++c;
00269 ++counter;
00270 }
00271 }
00272
00273 return counter;
00274 }
00275
00276 inline OutputIterator
00277 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
00278 { return out; }
00279
00280 inline OutputIterator
00281 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
00282 { return out; }
00283 };
00284
00285 template<class InputIterator, class OutputIterator, class Comparator>
00286 struct union_func
00287 {
00288 typedef typename std::iterator_traits<InputIterator>::difference_type
00289 difference_type;
00290
00291 union_func(Comparator c) : comp(c) {}
00292
00293 Comparator comp;
00294
00295 OutputIterator
00296 invoke(InputIterator a, const InputIterator b, InputIterator c,
00297 const InputIterator d, OutputIterator r) const
00298 {
00299 while (a != b && c != d)
00300 {
00301 if (comp(*a, *c))
00302 {
00303 *r = *a;
00304 ++a;
00305 }
00306 else if (comp(*c, *a))
00307 {
00308 *r = *c;
00309 ++c;
00310 }
00311 else
00312 {
00313 *r = *a;
00314 ++a;
00315 ++c;
00316 }
00317 ++r;
00318 }
00319 return std::copy(c, d, std::copy(a, b, r));
00320 }
00321
00322 difference_type
00323 count(InputIterator a, InputIterator b,
00324 InputIterator c, InputIterator d) const
00325 {
00326 difference_type counter = 0;
00327
00328 while (a != b && c != d)
00329 {
00330 if (comp(*a, *c))
00331 { ++a; }
00332 else if (comp(*c, *a))
00333 { ++c; }
00334 else
00335 {
00336 ++a;
00337 ++c;
00338 }
00339 ++counter;
00340 }
00341
00342 counter += (b - a);
00343 counter += (d - c);
00344 return counter;
00345 }
00346
00347 inline OutputIterator
00348 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
00349 { return std::copy(c, d, out); }
00350
00351 inline OutputIterator
00352 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
00353 { return std::copy(a, b, out); }
00354 };
00355
00356 template<typename InputIterator,
00357 typename OutputIterator,
00358 typename Operation>
00359 OutputIterator
00360 parallel_set_operation(InputIterator begin1, InputIterator end1,
00361 InputIterator begin2, InputIterator end2,
00362 OutputIterator result, Operation op)
00363 {
00364 _GLIBCXX_CALL((end1 - begin1) + (end2 - begin2))
00365
00366 typedef std::iterator_traits<InputIterator> traits_type;
00367 typedef typename traits_type::difference_type difference_type;
00368 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
00369
00370 if (begin1 == end1)
00371 return op.first_empty(begin2, end2, result);
00372
00373 if (begin2 == end2)
00374 return op.second_empty(begin1, end1, result);
00375
00376 const difference_type size = (end1 - begin1) + (end2 - begin2);
00377
00378 const iterator_pair sequence[ 2 ] =
00379 { std::make_pair(begin1, end1), std::make_pair(begin2, end2) } ;
00380 OutputIterator return_value = result;
00381 difference_type *borders;
00382 iterator_pair *block_begins;
00383 difference_type* lengths;
00384
00385 thread_index_t num_threads =
00386 std::min<difference_type>(get_max_threads(),
00387 std::min(end1 - begin1, end2 - begin2));
00388
00389 # pragma omp parallel num_threads(num_threads)
00390 {
00391 # pragma omp single
00392 {
00393 num_threads = omp_get_num_threads();
00394
00395 borders = new difference_type[num_threads + 2];
00396 equally_split(size, num_threads + 1, borders);
00397 block_begins = new iterator_pair[num_threads + 1];
00398
00399 block_begins[0] = std::make_pair(begin1, begin2);
00400 lengths = new difference_type[num_threads];
00401 }
00402
00403 thread_index_t iam = omp_get_thread_num();
00404
00405
00406 InputIterator offset[2];
00407 const difference_type rank = borders[iam + 1];
00408
00409 multiseq_partition(sequence, sequence + 2, rank, offset, op.comp);
00410
00411
00412
00413
00414 if (offset[ 0 ] != begin1 && offset[ 1 ] != end2
00415 && !op.comp(*(offset[ 0 ] - 1), *offset[ 1 ])
00416 && !op.comp(*offset[ 1 ], *(offset[ 0 ] - 1)))
00417 {
00418
00419
00420 --offset[ 0 ];
00421 }
00422
00423 iterator_pair block_end = block_begins[ iam + 1 ] =
00424 iterator_pair(offset[ 0 ], offset[ 1 ]);
00425
00426
00427 # pragma omp barrier
00428
00429 iterator_pair block_begin = block_begins[ iam ];
00430
00431
00432
00433 if (iam == 0)
00434 {
00435
00436 lengths[ iam ] = op.invoke(block_begin.first, block_end.first,
00437 block_begin.second, block_end.second,
00438 result)
00439 - result;
00440 }
00441 else
00442 {
00443 lengths[ iam ] = op.count(block_begin.first, block_end.first,
00444 block_begin.second, block_end.second);
00445 }
00446
00447
00448 # pragma omp barrier
00449
00450 OutputIterator r = result;
00451
00452 if (iam == 0)
00453 {
00454
00455 for (int i = 0; i < num_threads; ++i)
00456 r += lengths[i];
00457
00458 block_begin = block_begins[num_threads];
00459
00460
00461 return_value = op.invoke(
00462 block_begin.first, end1, block_begin.second, end2, r);
00463
00464 }
00465 else
00466 {
00467 for (int i = 0; i < iam; ++i)
00468 r += lengths[ i ];
00469
00470
00471 op.invoke(block_begin.first, block_end.first,
00472 block_begin.second, block_end.second, r);
00473 }
00474 }
00475 return return_value;
00476 }
00477
00478
00479 template<typename InputIterator,
00480 typename OutputIterator,
00481 typename Comparator>
00482 inline OutputIterator
00483 parallel_set_union(InputIterator begin1, InputIterator end1,
00484 InputIterator begin2, InputIterator end2,
00485 OutputIterator result, Comparator comp)
00486 {
00487 return parallel_set_operation(begin1, end1, begin2, end2, result,
00488 union_func< InputIterator, OutputIterator, Comparator>(comp));
00489 }
00490
00491 template<typename InputIterator,
00492 typename OutputIterator,
00493 typename Comparator>
00494 inline OutputIterator
00495 parallel_set_intersection(InputIterator begin1, InputIterator end1,
00496 InputIterator begin2, InputIterator end2,
00497 OutputIterator result, Comparator comp)
00498 {
00499 return parallel_set_operation(begin1, end1, begin2, end2, result,
00500 intersection_func<InputIterator, OutputIterator, Comparator>(comp));
00501 }
00502
00503
00504 template<typename InputIterator, typename OutputIterator>
00505 inline OutputIterator
00506 set_intersection(InputIterator begin1, InputIterator end1,
00507 InputIterator begin2, InputIterator end2,
00508 OutputIterator result)
00509 {
00510 typedef std::iterator_traits<InputIterator> traits_type;
00511 typedef typename traits_type::value_type value_type;
00512
00513 return set_intersection(begin1, end1, begin2, end2, result,
00514 std::less<value_type>());
00515 }
00516
00517 template<typename InputIterator,
00518 typename OutputIterator,
00519 typename Comparator>
00520 inline OutputIterator
00521 parallel_set_difference(InputIterator begin1, InputIterator end1,
00522 InputIterator begin2, InputIterator end2,
00523 OutputIterator result, Comparator comp)
00524 {
00525 return parallel_set_operation(begin1, end1, begin2, end2, result,
00526 difference_func<InputIterator, OutputIterator, Comparator>(comp));
00527 }
00528
00529 template<typename InputIterator,
00530 typename OutputIterator,
00531 typename Comparator>
00532 inline OutputIterator
00533 parallel_set_symmetric_difference(InputIterator begin1, InputIterator end1,
00534 InputIterator begin2, InputIterator end2,
00535 OutputIterator result, Comparator comp)
00536 {
00537 return parallel_set_operation(begin1, end1, begin2, end2, result,
00538 symmetric_difference_func<InputIterator, OutputIterator, Comparator>
00539 (comp));
00540 }
00541
00542 }
00543
00544 #endif // _GLIBCXX_SET_ALGORITHM_