You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
6.0KB

  1. // -*- C++ -*-
  2. // Copyright (C) 2007-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the terms
  6. // of the GNU General Public License as published by the Free Software
  7. // Foundation; either version 3, or (at your option) any later
  8. // version.
  9. // This library is distributed in the hope that it will be useful, but
  10. // WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file parallel/unique_copy.h
  21. * @brief Parallel implementations of std::unique_copy().
  22. * This file is a GNU parallel extension to the Standard C++ Library.
  23. */
  24. // Written by Robert Geisberger and Robin Dapp.
  25. #ifndef _GLIBCXX_PARALLEL_UNIQUE_COPY_H
  26. #define _GLIBCXX_PARALLEL_UNIQUE_COPY_H 1
  27. #include <parallel/parallel.h>
  28. #include <parallel/multiseq_selection.h>
  29. namespace __gnu_parallel
  30. {
  31. /** @brief Parallel std::unique_copy(), w/__o explicit equality predicate.
  32. * @param __first Begin iterator of input sequence.
  33. * @param __last End iterator of input sequence.
  34. * @param __result Begin iterator of result __sequence.
  35. * @param __binary_pred Equality predicate.
  36. * @return End iterator of result __sequence. */
  37. template<typename _IIter,
  38. class _OutputIterator,
  39. class _BinaryPredicate>
  40. _OutputIterator
  41. __parallel_unique_copy(_IIter __first, _IIter __last,
  42. _OutputIterator __result,
  43. _BinaryPredicate __binary_pred)
  44. {
  45. _GLIBCXX_CALL(__last - __first)
  46. typedef std::iterator_traits<_IIter> _TraitsType;
  47. typedef typename _TraitsType::value_type _ValueType;
  48. typedef typename _TraitsType::difference_type _DifferenceType;
  49. _DifferenceType __size = __last - __first;
  50. if (__size == 0)
  51. return __result;
  52. // Let the first thread process two parts.
  53. _DifferenceType *__counter;
  54. _DifferenceType *__borders;
  55. _ThreadIndex __num_threads = __get_max_threads();
  56. // First part contains at least one element.
  57. # pragma omp parallel num_threads(__num_threads)
  58. {
  59. # pragma omp single
  60. {
  61. __num_threads = omp_get_num_threads();
  62. __borders = new _DifferenceType[__num_threads + 2];
  63. __equally_split(__size, __num_threads + 1, __borders);
  64. __counter = new _DifferenceType[__num_threads + 1];
  65. }
  66. _ThreadIndex __iam = omp_get_thread_num();
  67. _DifferenceType __begin, __end;
  68. // Check for length without duplicates
  69. // Needed for position in output
  70. _DifferenceType __i = 0;
  71. _OutputIterator __out = __result;
  72. if (__iam == 0)
  73. {
  74. __begin = __borders[0] + 1; // == 1
  75. __end = __borders[__iam + 1];
  76. ++__i;
  77. *__out++ = *__first;
  78. for (_IIter __iter = __first + __begin; __iter < __first + __end;
  79. ++__iter)
  80. {
  81. if (!__binary_pred(*__iter, *(__iter - 1)))
  82. {
  83. ++__i;
  84. *__out++ = *__iter;
  85. }
  86. }
  87. }
  88. else
  89. {
  90. __begin = __borders[__iam]; //one part
  91. __end = __borders[__iam + 1];
  92. for (_IIter __iter = __first + __begin; __iter < __first + __end;
  93. ++__iter)
  94. {
  95. if (!__binary_pred(*__iter, *(__iter - 1)))
  96. ++__i;
  97. }
  98. }
  99. __counter[__iam] = __i;
  100. // Last part still untouched.
  101. _DifferenceType __begin_output;
  102. # pragma omp barrier
  103. // Store result in output on calculated positions.
  104. __begin_output = 0;
  105. if (__iam == 0)
  106. {
  107. for (_ThreadIndex __t = 0; __t < __num_threads; ++__t)
  108. __begin_output += __counter[__t];
  109. __i = 0;
  110. _OutputIterator __iter_out = __result + __begin_output;
  111. __begin = __borders[__num_threads];
  112. __end = __size;
  113. for (_IIter __iter = __first + __begin; __iter < __first + __end;
  114. ++__iter)
  115. {
  116. if (__iter == __first
  117. || !__binary_pred(*__iter, *(__iter - 1)))
  118. {
  119. ++__i;
  120. *__iter_out++ = *__iter;
  121. }
  122. }
  123. __counter[__num_threads] = __i;
  124. }
  125. else
  126. {
  127. for (_ThreadIndex __t = 0; __t < __iam; __t++)
  128. __begin_output += __counter[__t];
  129. _OutputIterator __iter_out = __result + __begin_output;
  130. for (_IIter __iter = __first + __begin; __iter < __first + __end;
  131. ++__iter)
  132. {
  133. if (!__binary_pred(*__iter, *(__iter - 1)))
  134. *__iter_out++ = *__iter;
  135. }
  136. }
  137. }
  138. _DifferenceType __end_output = 0;
  139. for (_ThreadIndex __t = 0; __t < __num_threads + 1; __t++)
  140. __end_output += __counter[__t];
  141. delete[] __borders;
  142. return __result + __end_output;
  143. }
  144. /** @brief Parallel std::unique_copy(), without explicit equality predicate
  145. * @param __first Begin iterator of input sequence.
  146. * @param __last End iterator of input sequence.
  147. * @param __result Begin iterator of result __sequence.
  148. * @return End iterator of result __sequence. */
  149. template<typename _IIter, class _OutputIterator>
  150. inline _OutputIterator
  151. __parallel_unique_copy(_IIter __first, _IIter __last,
  152. _OutputIterator __result)
  153. {
  154. typedef typename std::iterator_traits<_IIter>::value_type
  155. _ValueType;
  156. return __parallel_unique_copy(__first, __last, __result,
  157. std::equal_to<_ValueType>());
  158. }
  159. }//namespace __gnu_parallel
  160. #endif /* _GLIBCXX_PARALLEL_UNIQUE_COPY_H */