100db7afdSDavid E. O'Brien// Algorithm extensions -*- C++ -*-
200db7afdSDavid E. O'Brien
3*f8a1b7d9SAlexander Kabaev// Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
400db7afdSDavid E. O'Brien//
500db7afdSDavid E. O'Brien// This file is part of the GNU ISO C++ Library.  This library is free
600db7afdSDavid E. O'Brien// software; you can redistribute it and/or modify it under the
700db7afdSDavid E. O'Brien// terms of the GNU General Public License as published by the
800db7afdSDavid E. O'Brien// Free Software Foundation; either version 2, or (at your option)
900db7afdSDavid E. O'Brien// any later version.
1000db7afdSDavid E. O'Brien
1100db7afdSDavid E. O'Brien// This library is distributed in the hope that it will be useful,
1200db7afdSDavid E. O'Brien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1300db7afdSDavid E. O'Brien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1400db7afdSDavid E. O'Brien// GNU General Public License for more details.
1500db7afdSDavid E. O'Brien
1600db7afdSDavid E. O'Brien// You should have received a copy of the GNU General Public License along
1700db7afdSDavid E. O'Brien// with this library; see the file COPYING.  If not, write to the Free
18*f8a1b7d9SAlexander Kabaev// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
1900db7afdSDavid E. O'Brien// USA.
2000db7afdSDavid E. O'Brien
2100db7afdSDavid E. O'Brien// As a special exception, you may use this file as part of a free software
2200db7afdSDavid E. O'Brien// library without restriction.  Specifically, if other files instantiate
2300db7afdSDavid E. O'Brien// templates or use macros or inline functions from this file, or you compile
2400db7afdSDavid E. O'Brien// this file and link it with other files to produce an executable, this
2500db7afdSDavid E. O'Brien// file does not by itself cause the resulting executable to be covered by
2600db7afdSDavid E. O'Brien// the GNU General Public License.  This exception does not however
2700db7afdSDavid E. O'Brien// invalidate any other reasons why the executable file might be covered by
2800db7afdSDavid E. O'Brien// the GNU General Public License.
2900db7afdSDavid E. O'Brien
3000db7afdSDavid E. O'Brien/*
3100db7afdSDavid E. O'Brien *
3200db7afdSDavid E. O'Brien * Copyright (c) 1994
3300db7afdSDavid E. O'Brien * Hewlett-Packard Company
3400db7afdSDavid E. O'Brien *
3500db7afdSDavid E. O'Brien * Permission to use, copy, modify, distribute and sell this software
3600db7afdSDavid E. O'Brien * and its documentation for any purpose is hereby granted without fee,
3700db7afdSDavid E. O'Brien * provided that the above copyright notice appear in all copies and
3800db7afdSDavid E. O'Brien * that both that copyright notice and this permission notice appear
3900db7afdSDavid E. O'Brien * in supporting documentation.  Hewlett-Packard Company makes no
4000db7afdSDavid E. O'Brien * representations about the suitability of this software for any
4100db7afdSDavid E. O'Brien * purpose.  It is provided "as is" without express or implied warranty.
4200db7afdSDavid E. O'Brien *
4300db7afdSDavid E. O'Brien *
4400db7afdSDavid E. O'Brien * Copyright (c) 1996
4500db7afdSDavid E. O'Brien * Silicon Graphics Computer Systems, Inc.
4600db7afdSDavid E. O'Brien *
4700db7afdSDavid E. O'Brien * Permission to use, copy, modify, distribute and sell this software
4800db7afdSDavid E. O'Brien * and its documentation for any purpose is hereby granted without fee,
4900db7afdSDavid E. O'Brien * provided that the above copyright notice appear in all copies and
5000db7afdSDavid E. O'Brien * that both that copyright notice and this permission notice appear
5100db7afdSDavid E. O'Brien * in supporting documentation.  Silicon Graphics makes no
5200db7afdSDavid E. O'Brien * representations about the suitability of this software for any
5300db7afdSDavid E. O'Brien * purpose.  It is provided "as is" without express or implied warranty.
5400db7afdSDavid E. O'Brien */
5500db7afdSDavid E. O'Brien
5600db7afdSDavid E. O'Brien/** @file ext/algorithm
5700db7afdSDavid E. O'Brien *  This file is a GNU extension to the Standard C++ Library (possibly
58*f8a1b7d9SAlexander Kabaev *  containing extensions from the HP/SGI STL subset).
5900db7afdSDavid E. O'Brien */
6000db7afdSDavid E. O'Brien
6100db7afdSDavid E. O'Brien#ifndef _EXT_ALGORITHM
62ffeaf689SAlexander Kabaev#define _EXT_ALGORITHM 1
6300db7afdSDavid E. O'Brien
6400db7afdSDavid E. O'Brien#pragma GCC system_header
65ffeaf689SAlexander Kabaev
6600db7afdSDavid E. O'Brien#include <algorithm>
6700db7afdSDavid E. O'Brien
68*f8a1b7d9SAlexander Kabaev_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
69*f8a1b7d9SAlexander Kabaev
7000db7afdSDavid E. O'Brien  using std::ptrdiff_t;
7100db7afdSDavid E. O'Brien  using std::min;
7200db7afdSDavid E. O'Brien  using std::pair;
7300db7afdSDavid E. O'Brien  using std::input_iterator_tag;
7400db7afdSDavid E. O'Brien  using std::random_access_iterator_tag;
7500db7afdSDavid E. O'Brien  using std::iterator_traits;
7600db7afdSDavid E. O'Brien
7700db7afdSDavid E. O'Brien  //--------------------------------------------------
7800db7afdSDavid E. O'Brien  // copy_n (not part of the C++ standard)
7900db7afdSDavid E. O'Brien
80ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _Size, typename _OutputIterator>
81ffeaf689SAlexander Kabaev    pair<_InputIterator, _OutputIterator>
82ffeaf689SAlexander Kabaev    __copy_n(_InputIterator __first, _Size __count,
83ffeaf689SAlexander Kabaev	     _OutputIterator __result,
8400db7afdSDavid E. O'Brien	     input_iterator_tag)
8500db7afdSDavid E. O'Brien    {
86*f8a1b7d9SAlexander Kabaev      for ( ; __count > 0; --__count)
87*f8a1b7d9SAlexander Kabaev	{
8800db7afdSDavid E. O'Brien	  *__result = *__first;
8900db7afdSDavid E. O'Brien	  ++__first;
9000db7afdSDavid E. O'Brien	  ++__result;
9100db7afdSDavid E. O'Brien	}
92ffeaf689SAlexander Kabaev      return pair<_InputIterator, _OutputIterator>(__first, __result);
9300db7afdSDavid E. O'Brien    }
9400db7afdSDavid E. O'Brien
95ffeaf689SAlexander Kabaev  template<typename _RAIterator, typename _Size, typename _OutputIterator>
96ffeaf689SAlexander Kabaev    inline pair<_RAIterator, _OutputIterator>
97ffeaf689SAlexander Kabaev    __copy_n(_RAIterator __first, _Size __count,
98ffeaf689SAlexander Kabaev	     _OutputIterator __result,
9900db7afdSDavid E. O'Brien	     random_access_iterator_tag)
10000db7afdSDavid E. O'Brien    {
101ffeaf689SAlexander Kabaev      _RAIterator __last = __first + __count;
102*f8a1b7d9SAlexander Kabaev      return pair<_RAIterator, _OutputIterator>(__last, std::copy(__first,
103*f8a1b7d9SAlexander Kabaev								  __last,
104*f8a1b7d9SAlexander Kabaev								  __result));
10500db7afdSDavid E. O'Brien    }
10600db7afdSDavid E. O'Brien
10700db7afdSDavid E. O'Brien  /**
10800db7afdSDavid E. O'Brien   *  @brief Copies the range [first,first+count) into [result,result+count).
10900db7afdSDavid E. O'Brien   *  @param  first  An input iterator.
11000db7afdSDavid E. O'Brien   *  @param  count  The number of elements to copy.
11100db7afdSDavid E. O'Brien   *  @param  result An output iterator.
11200db7afdSDavid E. O'Brien   *  @return   A std::pair composed of first+count and result+count.
11300db7afdSDavid E. O'Brien   *
11400db7afdSDavid E. O'Brien   *  This is an SGI extension.
11500db7afdSDavid E. O'Brien   *  This inline function will boil down to a call to @c memmove whenever
11600db7afdSDavid E. O'Brien   *  possible.  Failing that, if random access iterators are passed, then the
11700db7afdSDavid E. O'Brien   *  loop count will be known (and therefore a candidate for compiler
11800db7afdSDavid E. O'Brien   *  optimizations such as unrolling).
11900db7afdSDavid E. O'Brien   *  @ingroup SGIextensions
12000db7afdSDavid E. O'Brien  */
121ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _Size, typename _OutputIterator>
122ffeaf689SAlexander Kabaev    inline pair<_InputIterator, _OutputIterator>
123ffeaf689SAlexander Kabaev    copy_n(_InputIterator __first, _Size __count, _OutputIterator __result)
12400db7afdSDavid E. O'Brien    {
12500db7afdSDavid E. O'Brien      // concept requirements
126ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
127ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
128ffeaf689SAlexander Kabaev	    typename iterator_traits<_InputIterator>::value_type>)
12900db7afdSDavid E. O'Brien
13000db7afdSDavid E. O'Brien      return __copy_n(__first, __count, __result,
13100db7afdSDavid E. O'Brien		      std::__iterator_category(__first));
13200db7afdSDavid E. O'Brien    }
13300db7afdSDavid E. O'Brien
134ffeaf689SAlexander Kabaev  template<typename _InputIterator1, typename _InputIterator2>
13500db7afdSDavid E. O'Brien    int
136*f8a1b7d9SAlexander Kabaev    __lexicographical_compare_3way(_InputIterator1 __first1,
137*f8a1b7d9SAlexander Kabaev				   _InputIterator1 __last1,
138*f8a1b7d9SAlexander Kabaev				   _InputIterator2 __first2,
139*f8a1b7d9SAlexander Kabaev				   _InputIterator2 __last2)
14000db7afdSDavid E. O'Brien    {
141*f8a1b7d9SAlexander Kabaev      while (__first1 != __last1 && __first2 != __last2)
142*f8a1b7d9SAlexander Kabaev	{
14300db7afdSDavid E. O'Brien	  if (*__first1 < *__first2)
14400db7afdSDavid E. O'Brien	    return -1;
14500db7afdSDavid E. O'Brien	  if (*__first2 < *__first1)
14600db7afdSDavid E. O'Brien	    return 1;
14700db7afdSDavid E. O'Brien	  ++__first1;
14800db7afdSDavid E. O'Brien	  ++__first2;
14900db7afdSDavid E. O'Brien	}
150*f8a1b7d9SAlexander Kabaev      if (__first2 == __last2)
15100db7afdSDavid E. O'Brien	return !(__first1 == __last1);
152*f8a1b7d9SAlexander Kabaev      else
15300db7afdSDavid E. O'Brien	return -1;
15400db7afdSDavid E. O'Brien    }
15500db7afdSDavid E. O'Brien
15600db7afdSDavid E. O'Brien  inline int
15700db7afdSDavid E. O'Brien  __lexicographical_compare_3way(const unsigned char* __first1,
15800db7afdSDavid E. O'Brien				 const unsigned char* __last1,
15900db7afdSDavid E. O'Brien				 const unsigned char* __first2,
16000db7afdSDavid E. O'Brien				 const unsigned char* __last2)
16100db7afdSDavid E. O'Brien  {
16200db7afdSDavid E. O'Brien    const ptrdiff_t __len1 = __last1 - __first1;
16300db7afdSDavid E. O'Brien    const ptrdiff_t __len2 = __last2 - __first2;
16400db7afdSDavid E. O'Brien    const int __result = std::memcmp(__first1, __first2, min(__len1, __len2));
16500db7afdSDavid E. O'Brien    return __result != 0 ? __result
16600db7afdSDavid E. O'Brien			 : (__len1 == __len2 ? 0 : (__len1 < __len2 ? -1 : 1));
16700db7afdSDavid E. O'Brien  }
16800db7afdSDavid E. O'Brien
16900db7afdSDavid E. O'Brien  inline int
17000db7afdSDavid E. O'Brien  __lexicographical_compare_3way(const char* __first1, const char* __last1,
17100db7afdSDavid E. O'Brien				 const char* __first2, const char* __last2)
17200db7afdSDavid E. O'Brien  {
17300db7afdSDavid E. O'Brien#if CHAR_MAX == SCHAR_MAX
174*f8a1b7d9SAlexander Kabaev    return __lexicographical_compare_3way((const signed char*) __first1,
17500db7afdSDavid E. O'Brien					  (const signed char*) __last1,
17600db7afdSDavid E. O'Brien					  (const signed char*) __first2,
17700db7afdSDavid E. O'Brien					  (const signed char*) __last2);
17800db7afdSDavid E. O'Brien#else
17900db7afdSDavid E. O'Brien    return __lexicographical_compare_3way((const unsigned char*) __first1,
18000db7afdSDavid E. O'Brien					  (const unsigned char*) __last1,
18100db7afdSDavid E. O'Brien					  (const unsigned char*) __first2,
18200db7afdSDavid E. O'Brien					  (const unsigned char*) __last2);
18300db7afdSDavid E. O'Brien#endif
18400db7afdSDavid E. O'Brien  }
18500db7afdSDavid E. O'Brien
18600db7afdSDavid E. O'Brien  /**
18700db7afdSDavid E. O'Brien   *  @brief @c memcmp on steroids.
18800db7afdSDavid E. O'Brien   *  @param  first1  An input iterator.
18900db7afdSDavid E. O'Brien   *  @param  last1   An input iterator.
19000db7afdSDavid E. O'Brien   *  @param  first2  An input iterator.
19100db7afdSDavid E. O'Brien   *  @param  last2   An input iterator.
19200db7afdSDavid E. O'Brien   *  @return   An int, as with @c memcmp.
19300db7afdSDavid E. O'Brien   *
19400db7afdSDavid E. O'Brien   *  The return value will be less than zero if the first range is
19500db7afdSDavid E. O'Brien   *  "lexigraphically less than" the second, greater than zero if the second
19600db7afdSDavid E. O'Brien   *  range is "lexigraphically less than" the first, and zero otherwise.
19700db7afdSDavid E. O'Brien   *  This is an SGI extension.
19800db7afdSDavid E. O'Brien   *  @ingroup SGIextensions
19900db7afdSDavid E. O'Brien  */
200ffeaf689SAlexander Kabaev  template<typename _InputIterator1, typename _InputIterator2>
20100db7afdSDavid E. O'Brien    int
202*f8a1b7d9SAlexander Kabaev    lexicographical_compare_3way(_InputIterator1 __first1,
203*f8a1b7d9SAlexander Kabaev				 _InputIterator1 __last1,
204*f8a1b7d9SAlexander Kabaev				 _InputIterator2 __first2,
205*f8a1b7d9SAlexander Kabaev				 _InputIterator2 __last2)
20600db7afdSDavid E. O'Brien    {
20700db7afdSDavid E. O'Brien      // concept requirements
208ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
209ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
210ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_LessThanComparableConcept<
211ffeaf689SAlexander Kabaev	    typename iterator_traits<_InputIterator1>::value_type>)
212ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_LessThanComparableConcept<
213ffeaf689SAlexander Kabaev	    typename iterator_traits<_InputIterator2>::value_type>)
214ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first1, __last1);
215ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first2, __last2);
21600db7afdSDavid E. O'Brien
217*f8a1b7d9SAlexander Kabaev      return __lexicographical_compare_3way(__first1, __last1, __first2,
218*f8a1b7d9SAlexander Kabaev					    __last2);
21900db7afdSDavid E. O'Brien    }
22000db7afdSDavid E. O'Brien
22100db7afdSDavid E. O'Brien  // count and count_if: this version, whose return type is void, was present
22200db7afdSDavid E. O'Brien  // in the HP STL, and is retained as an extension for backward compatibility.
223ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _Tp, typename _Size>
22400db7afdSDavid E. O'Brien    void
225ffeaf689SAlexander Kabaev    count(_InputIterator __first, _InputIterator __last,
22600db7afdSDavid E. O'Brien	  const _Tp& __value,
22700db7afdSDavid E. O'Brien	  _Size& __n)
22800db7afdSDavid E. O'Brien    {
22900db7afdSDavid E. O'Brien      // concept requirements
230ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
231ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_EqualityComparableConcept<
232ffeaf689SAlexander Kabaev	    typename iterator_traits<_InputIterator>::value_type >)
233ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_EqualityComparableConcept<_Tp>)
234ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
235ffeaf689SAlexander Kabaev
23600db7afdSDavid E. O'Brien      for ( ; __first != __last; ++__first)
23700db7afdSDavid E. O'Brien	if (*__first == __value)
23800db7afdSDavid E. O'Brien	  ++__n;
23900db7afdSDavid E. O'Brien    }
24000db7afdSDavid E. O'Brien
241ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _Predicate, typename _Size>
24200db7afdSDavid E. O'Brien    void
243ffeaf689SAlexander Kabaev    count_if(_InputIterator __first, _InputIterator __last,
24400db7afdSDavid E. O'Brien	     _Predicate __pred,
24500db7afdSDavid E. O'Brien	     _Size& __n)
24600db7afdSDavid E. O'Brien    {
24700db7afdSDavid E. O'Brien      // concept requirements
248ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
249ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
250ffeaf689SAlexander Kabaev	    typename iterator_traits<_InputIterator>::value_type>)
251ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
252ffeaf689SAlexander Kabaev
25300db7afdSDavid E. O'Brien      for ( ; __first != __last; ++__first)
25400db7afdSDavid E. O'Brien	if (__pred(*__first))
25500db7afdSDavid E. O'Brien	  ++__n;
25600db7afdSDavid E. O'Brien    }
25700db7afdSDavid E. O'Brien
25800db7afdSDavid E. O'Brien  // random_sample and random_sample_n (extensions, not part of the standard).
25900db7afdSDavid E. O'Brien
260ca6500fcSAlexander Kabaev  /**
261ca6500fcSAlexander Kabaev   *  This is an SGI extension.
262ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
263ca6500fcSAlexander Kabaev   *  @doctodo
264ca6500fcSAlexander Kabaev  */
265*f8a1b7d9SAlexander Kabaev  template<typename _ForwardIterator, typename _OutputIterator,
266*f8a1b7d9SAlexander Kabaev	   typename _Distance>
267ffeaf689SAlexander Kabaev    _OutputIterator
268ffeaf689SAlexander Kabaev    random_sample_n(_ForwardIterator __first, _ForwardIterator __last,
269ffeaf689SAlexander Kabaev                    _OutputIterator __out, const _Distance __n)
27000db7afdSDavid E. O'Brien    {
27100db7afdSDavid E. O'Brien      // concept requirements
272ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
273ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
274ffeaf689SAlexander Kabaev		typename iterator_traits<_ForwardIterator>::value_type>)
275ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
27600db7afdSDavid E. O'Brien
27700db7afdSDavid E. O'Brien      _Distance __remaining = std::distance(__first, __last);
27800db7afdSDavid E. O'Brien      _Distance __m = min(__n, __remaining);
27900db7afdSDavid E. O'Brien
280*f8a1b7d9SAlexander Kabaev      while (__m > 0)
281*f8a1b7d9SAlexander Kabaev	{
282*f8a1b7d9SAlexander Kabaev	  if ((std::rand() % __remaining) < __m)
283*f8a1b7d9SAlexander Kabaev	    {
28400db7afdSDavid E. O'Brien	      *__out = *__first;
28500db7afdSDavid E. O'Brien	      ++__out;
28600db7afdSDavid E. O'Brien	      --__m;
28700db7afdSDavid E. O'Brien	    }
28800db7afdSDavid E. O'Brien	  --__remaining;
28900db7afdSDavid E. O'Brien	  ++__first;
29000db7afdSDavid E. O'Brien	}
29100db7afdSDavid E. O'Brien      return __out;
29200db7afdSDavid E. O'Brien    }
29300db7afdSDavid E. O'Brien
294ca6500fcSAlexander Kabaev  /**
295ca6500fcSAlexander Kabaev   *  This is an SGI extension.
296ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
297ca6500fcSAlexander Kabaev   *  @doctodo
298ca6500fcSAlexander Kabaev  */
299*f8a1b7d9SAlexander Kabaev  template<typename _ForwardIterator, typename _OutputIterator,
300*f8a1b7d9SAlexander Kabaev	   typename _Distance, typename _RandomNumberGenerator>
301ffeaf689SAlexander Kabaev    _OutputIterator
302ffeaf689SAlexander Kabaev    random_sample_n(_ForwardIterator __first, _ForwardIterator __last,
303ffeaf689SAlexander Kabaev                   _OutputIterator __out, const _Distance __n,
30400db7afdSDavid E. O'Brien		   _RandomNumberGenerator& __rand)
30500db7afdSDavid E. O'Brien    {
30600db7afdSDavid E. O'Brien      // concept requirements
307ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
308ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
309ffeaf689SAlexander Kabaev		typename iterator_traits<_ForwardIterator>::value_type>)
310ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_UnaryFunctionConcept<
31100db7afdSDavid E. O'Brien		_RandomNumberGenerator, _Distance, _Distance>)
312ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
31300db7afdSDavid E. O'Brien
31400db7afdSDavid E. O'Brien      _Distance __remaining = std::distance(__first, __last);
31500db7afdSDavid E. O'Brien      _Distance __m = min(__n, __remaining);
31600db7afdSDavid E. O'Brien
317*f8a1b7d9SAlexander Kabaev      while (__m > 0)
318*f8a1b7d9SAlexander Kabaev	{
319*f8a1b7d9SAlexander Kabaev	  if (__rand(__remaining) < __m)
320*f8a1b7d9SAlexander Kabaev	    {
32100db7afdSDavid E. O'Brien	      *__out = *__first;
32200db7afdSDavid E. O'Brien	      ++__out;
32300db7afdSDavid E. O'Brien	      --__m;
32400db7afdSDavid E. O'Brien	    }
32500db7afdSDavid E. O'Brien	  --__remaining;
32600db7afdSDavid E. O'Brien	  ++__first;
32700db7afdSDavid E. O'Brien	}
32800db7afdSDavid E. O'Brien      return __out;
32900db7afdSDavid E. O'Brien    }
33000db7afdSDavid E. O'Brien
331*f8a1b7d9SAlexander Kabaev  template<typename _InputIterator, typename _RandomAccessIterator,
332*f8a1b7d9SAlexander Kabaev	   typename _Distance>
333ffeaf689SAlexander Kabaev    _RandomAccessIterator
334ffeaf689SAlexander Kabaev    __random_sample(_InputIterator __first, _InputIterator __last,
335ffeaf689SAlexander Kabaev		    _RandomAccessIterator __out,
33600db7afdSDavid E. O'Brien		    const _Distance __n)
33700db7afdSDavid E. O'Brien    {
33800db7afdSDavid E. O'Brien      _Distance __m = 0;
33900db7afdSDavid E. O'Brien      _Distance __t = __n;
34000db7afdSDavid E. O'Brien      for ( ; __first != __last && __m < __n; ++__m, ++__first)
34100db7afdSDavid E. O'Brien	__out[__m] = *__first;
34200db7afdSDavid E. O'Brien
343*f8a1b7d9SAlexander Kabaev      while (__first != __last)
344*f8a1b7d9SAlexander Kabaev	{
34500db7afdSDavid E. O'Brien	  ++__t;
346ffeaf689SAlexander Kabaev	  _Distance __M = std::rand() % (__t);
34700db7afdSDavid E. O'Brien	  if (__M < __n)
34800db7afdSDavid E. O'Brien	    __out[__M] = *__first;
34900db7afdSDavid E. O'Brien	  ++__first;
35000db7afdSDavid E. O'Brien	}
35100db7afdSDavid E. O'Brien      return __out + __m;
35200db7afdSDavid E. O'Brien    }
35300db7afdSDavid E. O'Brien
354ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _RandomAccessIterator,
35500db7afdSDavid E. O'Brien	   typename _RandomNumberGenerator, typename _Distance>
356ffeaf689SAlexander Kabaev    _RandomAccessIterator
357ffeaf689SAlexander Kabaev    __random_sample(_InputIterator __first, _InputIterator __last,
358ffeaf689SAlexander Kabaev		    _RandomAccessIterator __out,
35900db7afdSDavid E. O'Brien		    _RandomNumberGenerator& __rand,
36000db7afdSDavid E. O'Brien		    const _Distance __n)
36100db7afdSDavid E. O'Brien    {
36200db7afdSDavid E. O'Brien      // concept requirements
363ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_UnaryFunctionConcept<
36400db7afdSDavid E. O'Brien	    _RandomNumberGenerator, _Distance, _Distance>)
36500db7afdSDavid E. O'Brien
36600db7afdSDavid E. O'Brien      _Distance __m = 0;
36700db7afdSDavid E. O'Brien      _Distance __t = __n;
36800db7afdSDavid E. O'Brien      for ( ; __first != __last && __m < __n; ++__m, ++__first)
36900db7afdSDavid E. O'Brien	__out[__m] = *__first;
37000db7afdSDavid E. O'Brien
371*f8a1b7d9SAlexander Kabaev      while (__first != __last)
372*f8a1b7d9SAlexander Kabaev	{
37300db7afdSDavid E. O'Brien	  ++__t;
37400db7afdSDavid E. O'Brien	  _Distance __M = __rand(__t);
37500db7afdSDavid E. O'Brien	  if (__M < __n)
37600db7afdSDavid E. O'Brien	    __out[__M] = *__first;
37700db7afdSDavid E. O'Brien	  ++__first;
37800db7afdSDavid E. O'Brien	}
37900db7afdSDavid E. O'Brien      return __out + __m;
38000db7afdSDavid E. O'Brien    }
38100db7afdSDavid E. O'Brien
382ca6500fcSAlexander Kabaev  /**
383ca6500fcSAlexander Kabaev   *  This is an SGI extension.
384ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
385ca6500fcSAlexander Kabaev   *  @doctodo
386ca6500fcSAlexander Kabaev  */
387ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _RandomAccessIterator>
388ffeaf689SAlexander Kabaev    inline _RandomAccessIterator
389ffeaf689SAlexander Kabaev    random_sample(_InputIterator __first, _InputIterator __last,
390*f8a1b7d9SAlexander Kabaev		  _RandomAccessIterator __out_first,
391*f8a1b7d9SAlexander Kabaev		  _RandomAccessIterator __out_last)
39200db7afdSDavid E. O'Brien    {
39300db7afdSDavid E. O'Brien      // concept requirements
394ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
395ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
396ffeaf689SAlexander Kabaev	    _RandomAccessIterator>)
397ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
398ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__out_first, __out_last);
39900db7afdSDavid E. O'Brien
40000db7afdSDavid E. O'Brien      return __random_sample(__first, __last,
40100db7afdSDavid E. O'Brien			     __out_first, __out_last - __out_first);
40200db7afdSDavid E. O'Brien    }
40300db7afdSDavid E. O'Brien
404ca6500fcSAlexander Kabaev  /**
405ca6500fcSAlexander Kabaev   *  This is an SGI extension.
406ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
407ca6500fcSAlexander Kabaev   *  @doctodo
408ca6500fcSAlexander Kabaev  */
409ffeaf689SAlexander Kabaev  template<typename _InputIterator, typename _RandomAccessIterator,
41000db7afdSDavid E. O'Brien	   typename _RandomNumberGenerator>
411ffeaf689SAlexander Kabaev    inline _RandomAccessIterator
412ffeaf689SAlexander Kabaev    random_sample(_InputIterator __first, _InputIterator __last,
413*f8a1b7d9SAlexander Kabaev		  _RandomAccessIterator __out_first,
414*f8a1b7d9SAlexander Kabaev		  _RandomAccessIterator __out_last,
41500db7afdSDavid E. O'Brien		  _RandomNumberGenerator& __rand)
41600db7afdSDavid E. O'Brien    {
41700db7afdSDavid E. O'Brien      // concept requirements
418ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
419ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
420ffeaf689SAlexander Kabaev	    _RandomAccessIterator>)
421ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
422ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__out_first, __out_last);
42300db7afdSDavid E. O'Brien
42400db7afdSDavid E. O'Brien      return __random_sample(__first, __last,
42500db7afdSDavid E. O'Brien			     __out_first, __rand,
42600db7afdSDavid E. O'Brien			     __out_last - __out_first);
42700db7afdSDavid E. O'Brien    }
42800db7afdSDavid E. O'Brien
429ca6500fcSAlexander Kabaev  /**
430ca6500fcSAlexander Kabaev   *  This is an SGI extension.
431ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
432ca6500fcSAlexander Kabaev   *  @doctodo
433ca6500fcSAlexander Kabaev  */
434ffeaf689SAlexander Kabaev  template<typename _RandomAccessIterator>
43500db7afdSDavid E. O'Brien    inline bool
436ffeaf689SAlexander Kabaev    is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
43700db7afdSDavid E. O'Brien    {
43800db7afdSDavid E. O'Brien      // concept requirements
439*f8a1b7d9SAlexander Kabaev      __glibcxx_function_requires(_RandomAccessIteratorConcept<
440*f8a1b7d9SAlexander Kabaev				  _RandomAccessIterator>)
441ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_LessThanComparableConcept<
442ffeaf689SAlexander Kabaev	    typename iterator_traits<_RandomAccessIterator>::value_type>)
443ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
44400db7afdSDavid E. O'Brien
445ffeaf689SAlexander Kabaev      return std::__is_heap(__first, __last - __first);
44600db7afdSDavid E. O'Brien    }
44700db7afdSDavid E. O'Brien
448ca6500fcSAlexander Kabaev  /**
449ca6500fcSAlexander Kabaev   *  This is an SGI extension.
450ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
451ca6500fcSAlexander Kabaev   *  @doctodo
452ca6500fcSAlexander Kabaev  */
453ffeaf689SAlexander Kabaev  template<typename _RandomAccessIterator, typename _StrictWeakOrdering>
45400db7afdSDavid E. O'Brien    inline bool
455ffeaf689SAlexander Kabaev    is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
45600db7afdSDavid E. O'Brien	    _StrictWeakOrdering __comp)
45700db7afdSDavid E. O'Brien    {
45800db7afdSDavid E. O'Brien      // concept requirements
459*f8a1b7d9SAlexander Kabaev      __glibcxx_function_requires(_RandomAccessIteratorConcept<
460*f8a1b7d9SAlexander Kabaev				  _RandomAccessIterator>)
461ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering,
462ffeaf689SAlexander Kabaev	    typename iterator_traits<_RandomAccessIterator>::value_type,
463ffeaf689SAlexander Kabaev	    typename iterator_traits<_RandomAccessIterator>::value_type>)
464ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
46500db7afdSDavid E. O'Brien
466ffeaf689SAlexander Kabaev      return std::__is_heap(__first, __comp, __last - __first);
46700db7afdSDavid E. O'Brien    }
46800db7afdSDavid E. O'Brien
46900db7afdSDavid E. O'Brien  // is_sorted, a predicated testing whether a range is sorted in
47000db7afdSDavid E. O'Brien  // nondescending order.  This is an extension, not part of the C++
47100db7afdSDavid E. O'Brien  // standard.
47200db7afdSDavid E. O'Brien
473ca6500fcSAlexander Kabaev  /**
474ca6500fcSAlexander Kabaev   *  This is an SGI extension.
475ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
476ca6500fcSAlexander Kabaev   *  @doctodo
477ca6500fcSAlexander Kabaev  */
478ffeaf689SAlexander Kabaev  template<typename _ForwardIterator>
47900db7afdSDavid E. O'Brien    bool
480ffeaf689SAlexander Kabaev    is_sorted(_ForwardIterator __first, _ForwardIterator __last)
48100db7afdSDavid E. O'Brien    {
48200db7afdSDavid E. O'Brien      // concept requirements
483ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
484ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_LessThanComparableConcept<
485ffeaf689SAlexander Kabaev	    typename iterator_traits<_ForwardIterator>::value_type>)
486ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
48700db7afdSDavid E. O'Brien
48800db7afdSDavid E. O'Brien      if (__first == __last)
48900db7afdSDavid E. O'Brien	return true;
49000db7afdSDavid E. O'Brien
491ffeaf689SAlexander Kabaev      _ForwardIterator __next = __first;
492*f8a1b7d9SAlexander Kabaev      for (++__next; __next != __last; __first = __next, ++__next)
49300db7afdSDavid E. O'Brien	if (*__next < *__first)
49400db7afdSDavid E. O'Brien	  return false;
49500db7afdSDavid E. O'Brien      return true;
49600db7afdSDavid E. O'Brien    }
49700db7afdSDavid E. O'Brien
498ca6500fcSAlexander Kabaev  /**
499ca6500fcSAlexander Kabaev   *  This is an SGI extension.
500ca6500fcSAlexander Kabaev   *  @ingroup SGIextensions
501ca6500fcSAlexander Kabaev   *  @doctodo
502ca6500fcSAlexander Kabaev  */
503ffeaf689SAlexander Kabaev  template<typename _ForwardIterator, typename _StrictWeakOrdering>
50400db7afdSDavid E. O'Brien    bool
505*f8a1b7d9SAlexander Kabaev    is_sorted(_ForwardIterator __first, _ForwardIterator __last,
506*f8a1b7d9SAlexander Kabaev	      _StrictWeakOrdering __comp)
50700db7afdSDavid E. O'Brien    {
50800db7afdSDavid E. O'Brien      // concept requirements
509ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
510ffeaf689SAlexander Kabaev      __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering,
511ffeaf689SAlexander Kabaev	    typename iterator_traits<_ForwardIterator>::value_type,
512ffeaf689SAlexander Kabaev	    typename iterator_traits<_ForwardIterator>::value_type>)
513ffeaf689SAlexander Kabaev      __glibcxx_requires_valid_range(__first, __last);
51400db7afdSDavid E. O'Brien
51500db7afdSDavid E. O'Brien      if (__first == __last)
51600db7afdSDavid E. O'Brien	return true;
51700db7afdSDavid E. O'Brien
518ffeaf689SAlexander Kabaev      _ForwardIterator __next = __first;
519*f8a1b7d9SAlexander Kabaev      for (++__next; __next != __last; __first = __next, ++__next)
52000db7afdSDavid E. O'Brien	if (__comp(*__next, *__first))
52100db7afdSDavid E. O'Brien	  return false;
52200db7afdSDavid E. O'Brien      return true;
52300db7afdSDavid E. O'Brien    }
524*f8a1b7d9SAlexander Kabaev
525*f8a1b7d9SAlexander Kabaev_GLIBCXX_END_NAMESPACE
52600db7afdSDavid E. O'Brien
52700db7afdSDavid E. O'Brien#endif /* _EXT_ALGORITHM */
528