xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/parallel/search.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the terms
7*e4b17023SJohn Marino // of the GNU General Public License as published by the Free Software
8*e4b17023SJohn Marino // Foundation; either version 3, or (at your option) any later
9*e4b17023SJohn Marino // version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, but
12*e4b17023SJohn Marino // WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*e4b17023SJohn Marino // General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /** @file parallel/search.h
26*e4b17023SJohn Marino  *  @brief Parallel implementation base for std::search() and
27*e4b17023SJohn Marino  *  std::search_n().
28*e4b17023SJohn Marino  *  This file is a GNU parallel extension to the Standard C++ Library.
29*e4b17023SJohn Marino  */
30*e4b17023SJohn Marino 
31*e4b17023SJohn Marino // Written by Felix Putze.
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_SEARCH_H
34*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_SEARCH_H 1
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino #include <bits/stl_algobase.h>
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino #include <parallel/parallel.h>
39*e4b17023SJohn Marino #include <parallel/equally_split.h>
40*e4b17023SJohn Marino 
41*e4b17023SJohn Marino namespace __gnu_parallel
42*e4b17023SJohn Marino {
43*e4b17023SJohn Marino   /**
44*e4b17023SJohn Marino    *  @brief Precalculate __advances for Knuth-Morris-Pratt algorithm.
45*e4b17023SJohn Marino    *  @param __elements Begin iterator of sequence to search for.
46*e4b17023SJohn Marino    *  @param __length Length of sequence to search for.
47*e4b17023SJohn Marino    *  @param __off Returned __offsets.
48*e4b17023SJohn Marino    */
49*e4b17023SJohn Marino   template<typename _RAIter, typename _DifferenceTp>
50*e4b17023SJohn Marino     void
__calc_borders(_RAIter __elements,_DifferenceTp __length,_DifferenceTp * __off)51*e4b17023SJohn Marino     __calc_borders(_RAIter __elements, _DifferenceTp __length,
52*e4b17023SJohn Marino 		   _DifferenceTp* __off)
53*e4b17023SJohn Marino     {
54*e4b17023SJohn Marino       typedef _DifferenceTp _DifferenceType;
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino       __off[0] = -1;
57*e4b17023SJohn Marino       if (__length > 1)
58*e4b17023SJohn Marino 	__off[1] = 0;
59*e4b17023SJohn Marino       _DifferenceType __k = 0;
60*e4b17023SJohn Marino       for (_DifferenceType __j = 2; __j <= __length; __j++)
61*e4b17023SJohn Marino 	{
62*e4b17023SJohn Marino           while ((__k >= 0) && !(__elements[__k] == __elements[__j-1]))
63*e4b17023SJohn Marino             __k = __off[__k];
64*e4b17023SJohn Marino           __off[__j] = ++__k;
65*e4b17023SJohn Marino 	}
66*e4b17023SJohn Marino     }
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino   // Generic parallel find algorithm (requires random access iterator).
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino   /** @brief Parallel std::search.
71*e4b17023SJohn Marino    *  @param __begin1 Begin iterator of first sequence.
72*e4b17023SJohn Marino    *  @param __end1 End iterator of first sequence.
73*e4b17023SJohn Marino    *  @param __begin2 Begin iterator of second sequence.
74*e4b17023SJohn Marino    *  @param __end2 End iterator of second sequence.
75*e4b17023SJohn Marino    *  @param __pred Find predicate.
76*e4b17023SJohn Marino    *  @return Place of finding in first sequences. */
77*e4b17023SJohn Marino   template<typename __RAIter1,
78*e4b17023SJohn Marino            typename __RAIter2,
79*e4b17023SJohn Marino            typename _Pred>
80*e4b17023SJohn Marino     __RAIter1
__search_template(__RAIter1 __begin1,__RAIter1 __end1,__RAIter2 __begin2,__RAIter2 __end2,_Pred __pred)81*e4b17023SJohn Marino     __search_template(__RAIter1 __begin1, __RAIter1 __end1,
82*e4b17023SJohn Marino 		      __RAIter2 __begin2, __RAIter2 __end2,
83*e4b17023SJohn Marino 		      _Pred __pred)
84*e4b17023SJohn Marino     {
85*e4b17023SJohn Marino       typedef std::iterator_traits<__RAIter1> _TraitsType;
86*e4b17023SJohn Marino       typedef typename _TraitsType::difference_type _DifferenceType;
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino       _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2));
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino       _DifferenceType __pattern_length = __end2 - __begin2;
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino       // Pattern too short.
93*e4b17023SJohn Marino       if(__pattern_length <= 0)
94*e4b17023SJohn Marino 	return __end1;
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino       // Last point to start search.
97*e4b17023SJohn Marino       _DifferenceType __input_length = (__end1 - __begin1) - __pattern_length;
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino       // Where is first occurrence of pattern? defaults to end.
100*e4b17023SJohn Marino       _DifferenceType __result = (__end1 - __begin1);
101*e4b17023SJohn Marino       _DifferenceType *__splitters;
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino       // Pattern too long.
104*e4b17023SJohn Marino       if (__input_length < 0)
105*e4b17023SJohn Marino 	return __end1;
106*e4b17023SJohn Marino 
107*e4b17023SJohn Marino       omp_lock_t __result_lock;
108*e4b17023SJohn Marino       omp_init_lock(&__result_lock);
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino       _ThreadIndex __num_threads = std::max<_DifferenceType>
111*e4b17023SJohn Marino 	(1, std::min<_DifferenceType>(__input_length,
112*e4b17023SJohn Marino 				      __get_max_threads()));
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino       _DifferenceType __advances[__pattern_length];
115*e4b17023SJohn Marino       __calc_borders(__begin2, __pattern_length, __advances);
116*e4b17023SJohn Marino 
117*e4b17023SJohn Marino #     pragma omp parallel num_threads(__num_threads)
118*e4b17023SJohn Marino       {
119*e4b17023SJohn Marino #       pragma omp single
120*e4b17023SJohn Marino 	{
121*e4b17023SJohn Marino 	  __num_threads = omp_get_num_threads();
122*e4b17023SJohn Marino 	  __splitters = new _DifferenceType[__num_threads + 1];
123*e4b17023SJohn Marino 	  __equally_split(__input_length, __num_threads, __splitters);
124*e4b17023SJohn Marino 	}
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino 	_ThreadIndex __iam = omp_get_thread_num();
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino 	_DifferenceType __start = __splitters[__iam],
129*e4b17023SJohn Marino 	                 __stop = __splitters[__iam + 1];
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino 	_DifferenceType __pos_in_pattern = 0;
132*e4b17023SJohn Marino 	bool __found_pattern = false;
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino 	while (__start <= __stop && !__found_pattern)
135*e4b17023SJohn Marino 	  {
136*e4b17023SJohn Marino 	    // Get new value of result.
137*e4b17023SJohn Marino #pragma omp flush(__result)
138*e4b17023SJohn Marino 	    // No chance for this thread to find first occurrence.
139*e4b17023SJohn Marino 	    if (__result < __start)
140*e4b17023SJohn Marino 	      break;
141*e4b17023SJohn Marino 	    while (__pred(__begin1[__start + __pos_in_pattern],
142*e4b17023SJohn Marino 			  __begin2[__pos_in_pattern]))
143*e4b17023SJohn Marino 	      {
144*e4b17023SJohn Marino 		++__pos_in_pattern;
145*e4b17023SJohn Marino 		if (__pos_in_pattern == __pattern_length)
146*e4b17023SJohn Marino 		  {
147*e4b17023SJohn Marino 		    // Found new candidate for result.
148*e4b17023SJohn Marino 		    omp_set_lock(&__result_lock);
149*e4b17023SJohn Marino 		    __result = std::min(__result, __start);
150*e4b17023SJohn Marino 		    omp_unset_lock(&__result_lock);
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino 		    __found_pattern = true;
153*e4b17023SJohn Marino 		    break;
154*e4b17023SJohn Marino 		  }
155*e4b17023SJohn Marino 	      }
156*e4b17023SJohn Marino 	    // Make safe jump.
157*e4b17023SJohn Marino 	    __start += (__pos_in_pattern - __advances[__pos_in_pattern]);
158*e4b17023SJohn Marino 	    __pos_in_pattern = (__advances[__pos_in_pattern] < 0
159*e4b17023SJohn Marino 				? 0 : __advances[__pos_in_pattern]);
160*e4b17023SJohn Marino 	  }
161*e4b17023SJohn Marino       } //parallel
162*e4b17023SJohn Marino 
163*e4b17023SJohn Marino       omp_destroy_lock(&__result_lock);
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino       delete[] __splitters;
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino       // Return iterator on found element.
168*e4b17023SJohn Marino       return (__begin1 + __result);
169*e4b17023SJohn Marino     }
170*e4b17023SJohn Marino } // end namespace
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_SEARCH_H */
173