algorithm 18.8 KB
Newer Older
1 2
// Algorithm extensions -*- C++ -*-

3 4
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
// 2009, 2010, 2011
5
// Free Software Foundation, Inc.
6 7 8 9
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
10
// Free Software Foundation; either version 3, or (at your option)
11 12 13 14 15 16 17
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

18 19 20
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
21

22 23 24 25
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 * Copyright (c) 1996
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */

53 54
/** @file ext/algorithm
 *  This file is a GNU extension to the Standard C++ Library (possibly
55
 *  containing extensions from the HP/SGI STL subset).
56 57
 */

58
#ifndef _EXT_ALGORITHM
Benjamin Kosnik committed
59
#define _EXT_ALGORITHM 1
60

61
#pragma GCC system_header
Benjamin Kosnik committed
62

63
#include <algorithm>
64

65 66 67
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
68

69 70 71 72 73 74 75 76 77 78
  using std::ptrdiff_t;
  using std::min;
  using std::pair;
  using std::input_iterator_tag;
  using std::random_access_iterator_tag;
  using std::iterator_traits;

  //--------------------------------------------------
  // copy_n (not part of the C++ standard)

79 80 81 82
  template<typename _InputIterator, typename _Size, typename _OutputIterator>
    pair<_InputIterator, _OutputIterator>
    __copy_n(_InputIterator __first, _Size __count,
	     _OutputIterator __result,
83 84
	     input_iterator_tag)
    {
Paolo Carlini committed
85 86 87 88 89 90
      for ( ; __count > 0; --__count)
	{
	  *__result = *__first;
	  ++__first;
	  ++__result;
	}
91
      return pair<_InputIterator, _OutputIterator>(__first, __result);
92 93
    }

94 95 96 97
  template<typename _RAIterator, typename _Size, typename _OutputIterator>
    inline pair<_RAIterator, _OutputIterator>
    __copy_n(_RAIterator __first, _Size __count,
	     _OutputIterator __result,
98 99
	     random_access_iterator_tag)
    {
100
      _RAIterator __last = __first + __count;
Paolo Carlini committed
101 102 103
      return pair<_RAIterator, _OutputIterator>(__last, std::copy(__first,
								  __last,
								  __result));
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    }

  /**
   *  @brief Copies the range [first,first+count) into [result,result+count).
   *  @param  first  An input iterator.
   *  @param  count  The number of elements to copy.
   *  @param  result An output iterator.
   *  @return   A std::pair composed of first+count and result+count.
   *
   *  This is an SGI extension.
   *  This inline function will boil down to a call to @c memmove whenever
   *  possible.  Failing that, if random access iterators are passed, then the
   *  loop count will be known (and therefore a candidate for compiler
   *  optimizations such as unrolling).
   *  @ingroup SGIextensions
  */
120 121 122
  template<typename _InputIterator, typename _Size, typename _OutputIterator>
    inline pair<_InputIterator, _OutputIterator>
    copy_n(_InputIterator __first, _Size __count, _OutputIterator __result)
123 124
    {
      // concept requirements
Benjamin Kosnik committed
125 126
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
127
	    typename iterator_traits<_InputIterator>::value_type>)
128

129 130
      return __gnu_cxx::__copy_n(__first, __count, __result,
				 std::__iterator_category(__first));
131 132
    }

133
  template<typename _InputIterator1, typename _InputIterator2>
134
    int
Paolo Carlini committed
135 136 137 138
    __lexicographical_compare_3way(_InputIterator1 __first1,
				   _InputIterator1 __last1,
				   _InputIterator2 __first2,
				   _InputIterator2 __last2)
139
    {
Paolo Carlini committed
140 141 142 143 144 145 146 147 148 149
      while (__first1 != __last1 && __first2 != __last2)
	{
	  if (*__first1 < *__first2)
	    return -1;
	  if (*__first2 < *__first1)
	    return 1;
	  ++__first1;
	  ++__first2;
	}
      if (__first2 == __last2)
150
	return !(__first1 == __last1);
Paolo Carlini committed
151
      else
152 153 154 155 156 157 158 159 160 161 162
	return -1;
    }

  inline int
  __lexicographical_compare_3way(const unsigned char* __first1,
				 const unsigned char* __last1,
				 const unsigned char* __first2,
				 const unsigned char* __last2)
  {
    const ptrdiff_t __len1 = __last1 - __first1;
    const ptrdiff_t __len2 = __last2 - __first2;
163 164
    const int __result = __builtin_memcmp(__first1, __first2,
					  min(__len1, __len2));
165
    return __result != 0 ? __result
166 167 168
			 : (__len1 == __len2 ? 0 : (__len1 < __len2 ? -1 : 1));
  }

169
  inline int
170 171 172 173
  __lexicographical_compare_3way(const char* __first1, const char* __last1,
				 const char* __first2, const char* __last2)
  {
#if CHAR_MAX == SCHAR_MAX
Paolo Carlini committed
174 175 176 177
    return __lexicographical_compare_3way((const signed char*) __first1,
					  (const signed char*) __last1,
					  (const signed char*) __first2,
					  (const signed char*) __last2);
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
#else
    return __lexicographical_compare_3way((const unsigned char*) __first1,
					  (const unsigned char*) __last1,
					  (const unsigned char*) __first2,
					  (const unsigned char*) __last2);
#endif
  }

  /**
   *  @brief @c memcmp on steroids.
   *  @param  first1  An input iterator.
   *  @param  last1   An input iterator.
   *  @param  first2  An input iterator.
   *  @param  last2   An input iterator.
   *  @return   An int, as with @c memcmp.
   *
   *  The return value will be less than zero if the first range is
195 196 197
   *  <em>lexigraphically less than</em> the second, greater than zero
   *  if the second range is <em>lexigraphically less than</em> the
   *  first, and zero otherwise.
198 199 200
   *  This is an SGI extension.
   *  @ingroup SGIextensions
  */
201
  template<typename _InputIterator1, typename _InputIterator2>
202
    int
Paolo Carlini committed
203 204 205 206
    lexicographical_compare_3way(_InputIterator1 __first1,
				 _InputIterator1 __last1,
				 _InputIterator2 __first2,
				 _InputIterator2 __last2)
207 208
    {
      // concept requirements
Benjamin Kosnik committed
209 210 211
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
      __glibcxx_function_requires(_LessThanComparableConcept<
212
	    typename iterator_traits<_InputIterator1>::value_type>)
Benjamin Kosnik committed
213
      __glibcxx_function_requires(_LessThanComparableConcept<
214
	    typename iterator_traits<_InputIterator2>::value_type>)
Benjamin Kosnik committed
215 216
      __glibcxx_requires_valid_range(__first1, __last1);
      __glibcxx_requires_valid_range(__first2, __last2);
217

Paolo Carlini committed
218 219
      return __lexicographical_compare_3way(__first1, __last1, __first2,
					    __last2);
220 221
    }

222 223
  // count and count_if: this version, whose return type is void, was present
  // in the HP STL, and is retained as an extension for backward compatibility.
224
  template<typename _InputIterator, typename _Tp, typename _Size>
225
    void
226
    count(_InputIterator __first, _InputIterator __last,
227 228 229 230
	  const _Tp& __value,
	  _Size& __n)
    {
      // concept requirements
Benjamin Kosnik committed
231 232
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_EqualityComparableConcept<
233
	    typename iterator_traits<_InputIterator>::value_type >)
Benjamin Kosnik committed
234
      __glibcxx_function_requires(_EqualityComparableConcept<_Tp>)
Benjamin Kosnik committed
235 236
      __glibcxx_requires_valid_range(__first, __last);

237 238 239 240 241
      for ( ; __first != __last; ++__first)
	if (*__first == __value)
	  ++__n;
    }

242
  template<typename _InputIterator, typename _Predicate, typename _Size>
243
    void
244
    count_if(_InputIterator __first, _InputIterator __last,
245 246 247 248
	     _Predicate __pred,
	     _Size& __n)
    {
      // concept requirements
Benjamin Kosnik committed
249 250
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
251
	    typename iterator_traits<_InputIterator>::value_type>)
Benjamin Kosnik committed
252 253
      __glibcxx_requires_valid_range(__first, __last);

254 255 256 257 258 259 260
      for ( ; __first != __last; ++__first)
	if (__pred(*__first))
	  ++__n;
    }

  // random_sample and random_sample_n (extensions, not part of the standard).

261 262 263 264 265
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
Paolo Carlini committed
266 267
  template<typename _ForwardIterator, typename _OutputIterator,
	   typename _Distance>
268 269 270
    _OutputIterator
    random_sample_n(_ForwardIterator __first, _ForwardIterator __last,
                    _OutputIterator __out, const _Distance __n)
271 272
    {
      // concept requirements
Benjamin Kosnik committed
273 274
      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
275
		typename iterator_traits<_ForwardIterator>::value_type>)
Benjamin Kosnik committed
276
      __glibcxx_requires_valid_range(__first, __last);
277 278

      _Distance __remaining = std::distance(__first, __last);
279
      _Distance __m = min(__n, __remaining);
280

Paolo Carlini committed
281 282 283 284
      while (__m > 0)
	{
	  if ((std::rand() % __remaining) < __m)
	    {
285 286 287
	      *__out = *__first;
	      ++__out;
	      --__m;
Paolo Carlini committed
288 289 290
	    }
	  --__remaining;
	  ++__first;
291 292 293 294
	}
      return __out;
    }

295 296 297 298 299
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
Paolo Carlini committed
300 301
  template<typename _ForwardIterator, typename _OutputIterator,
	   typename _Distance, typename _RandomNumberGenerator>
302 303
    _OutputIterator
    random_sample_n(_ForwardIterator __first, _ForwardIterator __last,
304
                   _OutputIterator __out, const _Distance __n,
305 306 307
		   _RandomNumberGenerator& __rand)
    {
      // concept requirements
Benjamin Kosnik committed
308 309
      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
310
		typename iterator_traits<_ForwardIterator>::value_type>)
Benjamin Kosnik committed
311
      __glibcxx_function_requires(_UnaryFunctionConcept<
312
		_RandomNumberGenerator, _Distance, _Distance>)
Benjamin Kosnik committed
313
      __glibcxx_requires_valid_range(__first, __last);
314 315

      _Distance __remaining = std::distance(__first, __last);
316
      _Distance __m = min(__n, __remaining);
317

Paolo Carlini committed
318 319 320 321
      while (__m > 0)
	{
	  if (__rand(__remaining) < __m)
	    {
322 323 324
	      *__out = *__first;
	      ++__out;
	      --__m;
Paolo Carlini committed
325 326 327
	    }
	  --__remaining;
	  ++__first;
328 329 330 331
	}
      return __out;
    }

Paolo Carlini committed
332 333
  template<typename _InputIterator, typename _RandomAccessIterator,
	   typename _Distance>
334 335 336
    _RandomAccessIterator
    __random_sample(_InputIterator __first, _InputIterator __last,
		    _RandomAccessIterator __out,
337 338 339 340
		    const _Distance __n)
    {
      _Distance __m = 0;
      _Distance __t = __n;
341
      for ( ; __first != __last && __m < __n; ++__m, ++__first)
342 343
	__out[__m] = *__first;

Paolo Carlini committed
344 345 346 347 348 349 350 351
      while (__first != __last)
	{
	  ++__t;
	  _Distance __M = std::rand() % (__t);
	  if (__M < __n)
	    __out[__M] = *__first;
	  ++__first;
	}
352 353 354
      return __out + __m;
    }

355
  template<typename _InputIterator, typename _RandomAccessIterator,
356
	   typename _RandomNumberGenerator, typename _Distance>
357 358 359
    _RandomAccessIterator
    __random_sample(_InputIterator __first, _InputIterator __last,
		    _RandomAccessIterator __out,
360 361 362 363
		    _RandomNumberGenerator& __rand,
		    const _Distance __n)
    {
      // concept requirements
Benjamin Kosnik committed
364
      __glibcxx_function_requires(_UnaryFunctionConcept<
365 366 367 368 369 370 371
	    _RandomNumberGenerator, _Distance, _Distance>)

      _Distance __m = 0;
      _Distance __t = __n;
      for ( ; __first != __last && __m < __n; ++__m, ++__first)
	__out[__m] = *__first;

Paolo Carlini committed
372 373 374 375 376 377 378 379
      while (__first != __last)
	{
	  ++__t;
	  _Distance __M = __rand(__t);
	  if (__M < __n)
	    __out[__M] = *__first;
	  ++__first;
	}
380 381 382
      return __out + __m;
    }

383 384 385 386 387
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
388 389 390
  template<typename _InputIterator, typename _RandomAccessIterator>
    inline _RandomAccessIterator
    random_sample(_InputIterator __first, _InputIterator __last,
Paolo Carlini committed
391 392
		  _RandomAccessIterator __out_first,
		  _RandomAccessIterator __out_last)
393 394
    {
      // concept requirements
Benjamin Kosnik committed
395 396
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
397
	    _RandomAccessIterator>)
Benjamin Kosnik committed
398 399
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_valid_range(__out_first, __out_last);
400 401 402 403 404

      return __random_sample(__first, __last,
			     __out_first, __out_last - __out_first);
    }

405 406 407 408 409
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
410
  template<typename _InputIterator, typename _RandomAccessIterator,
411
	   typename _RandomNumberGenerator>
412 413
    inline _RandomAccessIterator
    random_sample(_InputIterator __first, _InputIterator __last,
Paolo Carlini committed
414 415
		  _RandomAccessIterator __out_first,
		  _RandomAccessIterator __out_last,
416
		  _RandomNumberGenerator& __rand)
417 418
    {
      // concept requirements
Benjamin Kosnik committed
419 420
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
421
	    _RandomAccessIterator>)
Benjamin Kosnik committed
422 423
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_valid_range(__out_first, __out_last);
424 425 426 427 428

      return __random_sample(__first, __last,
			     __out_first, __rand,
			     __out_last - __out_first);
    }
429

430 431 432
#ifdef __GXX_EXPERIMENTAL_CXX0X__
  using std::is_heap;
#else
433 434 435 436 437
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
438
  template<typename _RandomAccessIterator>
439
    inline bool
440
    is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
441 442
    {
      // concept requirements
Paolo Carlini committed
443 444
      __glibcxx_function_requires(_RandomAccessIteratorConcept<
				  _RandomAccessIterator>)
Benjamin Kosnik committed
445
      __glibcxx_function_requires(_LessThanComparableConcept<
446
	    typename iterator_traits<_RandomAccessIterator>::value_type>)
Benjamin Kosnik committed
447
      __glibcxx_requires_valid_range(__first, __last);
448

Benjamin Kosnik committed
449
      return std::__is_heap(__first, __last - __first);
450 451
    }

452 453 454 455 456
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
457
  template<typename _RandomAccessIterator, typename _StrictWeakOrdering>
458
    inline bool
459
    is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
460 461 462
	    _StrictWeakOrdering __comp)
    {
      // concept requirements
Paolo Carlini committed
463 464
      __glibcxx_function_requires(_RandomAccessIteratorConcept<
				  _RandomAccessIterator>)
Benjamin Kosnik committed
465
      __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering,
466
	    typename iterator_traits<_RandomAccessIterator>::value_type,
467
	    typename iterator_traits<_RandomAccessIterator>::value_type>)
Benjamin Kosnik committed
468
      __glibcxx_requires_valid_range(__first, __last);
469

Benjamin Kosnik committed
470
      return std::__is_heap(__first, __comp, __last - __first);
471
    }
472
#endif
473 474 475 476 477

  // is_sorted, a predicated testing whether a range is sorted in
  // nondescending order.  This is an extension, not part of the C++
  // standard.

478 479 480 481 482
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
483
  template<typename _ForwardIterator>
484
    bool
485
    is_sorted(_ForwardIterator __first, _ForwardIterator __last)
486 487
    {
      // concept requirements
Benjamin Kosnik committed
488 489
      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
      __glibcxx_function_requires(_LessThanComparableConcept<
490
	    typename iterator_traits<_ForwardIterator>::value_type>)
Benjamin Kosnik committed
491
      __glibcxx_requires_valid_range(__first, __last);
492 493 494 495

      if (__first == __last)
	return true;

496
      _ForwardIterator __next = __first;
Paolo Carlini committed
497
      for (++__next; __next != __last; __first = __next, ++__next)
498 499 500 501 502
	if (*__next < *__first)
	  return false;
      return true;
    }

503 504 505 506 507
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
508
  template<typename _ForwardIterator, typename _StrictWeakOrdering>
509
    bool
Paolo Carlini committed
510 511
    is_sorted(_ForwardIterator __first, _ForwardIterator __last,
	      _StrictWeakOrdering __comp)
512 513
    {
      // concept requirements
Benjamin Kosnik committed
514 515
      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
      __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering,
516
	    typename iterator_traits<_ForwardIterator>::value_type,
517
	    typename iterator_traits<_ForwardIterator>::value_type>)
Benjamin Kosnik committed
518
      __glibcxx_requires_valid_range(__first, __last);
519 520 521 522

      if (__first == __last)
	return true;

523
      _ForwardIterator __next = __first;
Paolo Carlini committed
524
      for (++__next; __next != __last; __first = __next, ++__next)
525 526 527 528
	if (__comp(*__next, *__first))
	  return false;
      return true;
    }
529

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
  /**
   *  @brief Find the median of three values.
   *  @param  a  A value.
   *  @param  b  A value.
   *  @param  c  A value.
   *  @return One of @p a, @p b or @p c.
   *
   *  If @c {l,m,n} is some convolution of @p {a,b,c} such that @c l<=m<=n
   *  then the value returned will be @c m.
   *  This is an SGI extension.
   *  @ingroup SGIextensions
  */
  template<typename _Tp>
    const _Tp&
    __median(const _Tp& __a, const _Tp& __b, const _Tp& __c)
    {
      // concept requirements
      __glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
      if (__a < __b)
	if (__b < __c)
	  return __b;
	else if (__a < __c)
	  return __c;
	else
	  return __a;
      else if (__a < __c)
	return __a;
      else if (__b < __c)
	return __c;
      else
	return __b;
    }

  /**
   *  @brief Find the median of three values using a predicate for comparison.
   *  @param  a     A value.
   *  @param  b     A value.
   *  @param  c     A value.
   *  @param  comp  A binary predicate.
   *  @return One of @p a, @p b or @p c.
   *
   *  If @c {l,m,n} is some convolution of @p {a,b,c} such that @p comp(l,m)
   *  and @p comp(m,n) are both true then the value returned will be @c m.
   *  This is an SGI extension.
   *  @ingroup SGIextensions
  */
  template<typename _Tp, typename _Compare>
    const _Tp&
    __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp)
    {
      // concept requirements
      __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool,
				                         _Tp, _Tp>)
      if (__comp(__a, __b))
	if (__comp(__b, __c))
	  return __b;
	else if (__comp(__a, __c))
	  return __c;
	else
	  return __a;
      else if (__comp(__a, __c))
	return __a;
      else if (__comp(__b, __c))
	return __c;
      else
	return __b;
    }

598 599
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
600 601

#endif /* _EXT_ALGORITHM */