// Algorithm implementation -*- C++ -*-
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
// Free Software Foundation, Inc.
//
// 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
// Free Software Foundation; either version 3, or (at your option)
// 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.
// 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.
// 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/>.
/*
*
* 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.
*/
/** @file stl_algo.h
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _STL_ALGO_H
#define _STL_ALGO_H 1
#include <cstdlib> // for rand
#include <bits/algorithmfwd.h>
#include <bits/stl_heap.h>
#include <bits/stl_tempbuf.h> // for _Temporary_buffer
#include <debug/debug.h>
#include <initializer_list>
// See concept_check.h for the __glibcxx_*_requires macros.
_GLIBCXX_BEGIN_NAMESPACE(std)
/**
* @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>
inline 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>
inline 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;
}
// for_each
/// This is an overload used by find() for the Input Iterator case.
template<typename _InputIterator, typename _Tp>
inline _InputIterator
__find(_InputIterator __first, _InputIterator __last,
const _Tp& __val, input_iterator_tag)
{
while (__first != __last && !(*__first == __val))
++__first;
return __first;
}
/// This is an overload used by find_if() for the Input Iterator case.
template<typename _InputIterator, typename _Predicate>
inline _InputIterator
__find_if(_InputIterator __first, _InputIterator __last,
_Predicate __pred, input_iterator_tag)
{
while (__first != __last && !bool(__pred(*__first)))
++__first;
return __first;
}
/// This is an overload used by find() for the RAI case.
template<typename _RandomAccessIterator, typename _Tp>
_RandomAccessIterator
__find(_RandomAccessIterator __first, _RandomAccessIterator __last,
const _Tp& __val, random_access_iterator_tag)
{
typename iterator_traits<_RandomAccessIterator>::difference_type
__trip_count = (__last - __first) >> 2;
for (; __trip_count > 0; --__trip_count)
{
if (*__first == __val)
return __first;
++__first;
if (*__first == __val)
return __first;
++__first;
if (*__first == __val)
return __first;
++__first;
if (*__first == __val)
return __first;
++__first;
}
switch (__last - __first)
{
case 3:
if (*__first == __val)
return __first;
++__first;
case 2:
if (*__first == __val)
return __first;
++__first;
case 1:
if (*__first == __val)
return __first;
++__first;
case 0:
default:
return __last;
}
}
/// This is an overload used by find_if() for the RAI case.
template<typename _RandomAccessIterator, typename _Predicate>
_RandomAccessIterator
__find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Predicate __pred, random_access_iterator_tag)
{
typename iterator_traits<_RandomAccessIterator>::difference_type
__trip_count = (__last - __first) >> 2;
for (; __trip_count > 0; --__trip_count)
{
if (__pred(*__first))
return __first;
++__first;
if (__pred(*__first))
return __first;
++__first;
if (__pred(*__first))
return __first;
++__first;
if (__pred(*__first))
return __first;
++__first;
}
switch (__last - __first)
{
case 3:
if (__pred(*__first))
return __first;
++__first;
case 2:
if (__pred(*__first))
return __first;
++__first;
case 1:
if (__pred(*__first))
return __first;
++__first;
case 0:
default:
return __last;
}
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
/// This is an overload used by find_if_not() for the Input Iterator case.
template<typename _InputIterator, typename _Predicate>
inline _InputIterator
__find_if_not(_InputIterator __first, _InputIterator __last,
_Predicate __pred, input_iterator_tag)
{
while (__first != __last && bool(__pred(*__first)))
++__first;
return __first;
}
/// This is an overload used by find_if_not() for the RAI case.
template<typename _RandomAccessIterator, typename _Predicate>
_RandomAccessIterator
__find_if_not(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Predicate __pred, random_access_iterator_tag)
{
typename iterator_traits<_RandomAccessIterator>::difference_type
__tri
- 1
- 2
前往页