//
// $Id: Algorithm.h,v 1.30 2007/04/22 17:47:25 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004-2007
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#if !defined(ALGORITHM_OL_GUARD)
#define ALGORITHM_OL_GUARD

#include <ObjectiveLib/Functional.h>
#include <ObjectiveLib/Iterator.h>

/**
 * @defgroup Algorithms
 *
 * Support for generic algorithms is provided for use with many different types of
 * @ref Containers "containers". Algorithms are separated from the underlying
 * data structures on which they operate through the use of iterators. Algorithms
 * are only given iterators as arguments, and have no information about what
 * kind of collection the iterators might be from.
 *
 * @sa OLAlgorithm
 */

/**
 * @defgroup Comparisons
 *
 * Algorithms to compare ranges and elements. Tests for eqaulity of ranges and
 * comparisons of ranges are included, as well as tests for finding the maximum
 * or minimum of two elements.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Copying
 *
 * Algorithms for copying elements. Simple algorithms for copying elements from
 * one range to another.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Heaps
 *
 * Algorithms which operate on heaps. A heap is a way of organizing a sequential range
 * as a tree. The first element in the range is always the element that least satisfies
 * the predicate used to sort the heap. That is, if the heap is created using OLLess
 * as the predicate, then the first element will be the largest. This makes heaps very
 * useful for containers like @ref OLPriorityQueue "priority queues", as there is no
 * need to sort through the collection to find the element with the highest priority.
 * Additionally, elements can be added and removed from a heap in logarithmic time.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Merges
 *
 * Algorithms for merging. Merging is the process of combining two sorted ranges
 * into one sorted range. All merge algorithms provide stable merges, meaning
 * that equivilent elements in the input ranges remain in the same relative order
 * after the merge is done.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Partitioning
 *
 * Algorithms for partitioning. Partition algorithms divide a range into two
 * groups: one group satisfies a given predicate, and the other group doesn't.
 * There is a simple partitioning algorithm, and also a more complex stable
 * partitioning algorithm for use when preserving relative order is important.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Searches
 *
 * Algorithms for performing searches. Numerous types of searches are provided
 * including linear searches, binary searches, subsequence searches, searches
 * for mismatches and many others. All searches operate using
 * @ref OLForwardIterator "forward iterators", thus they can be used with any
 * type of @ref Containers "container". However, bear in mind that some
 * containers provide optimized versions of some algorithms, which should be
 * preferred to the generic version when they exist. For example, associative
 * containers, like OLMap, OLSet, and so forth, provide optimized versions of
 * binary searches. Please use those when they are provided.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Sets
 *
 * Algorithms for performing operations on sets. Basic algorithms from set theory
 * are provided, including difference, intersection, symmetric difference and
 * union.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Sorting
 *
 * Algorithms for sorting. Many ways of sorting can be performed, including
 * various partial sorts and stable sorts. Since sorting requires
 * @ref OLRandomAccessIterator "random access iterators" some @ref Containers "containers"
 * cannot be sorted using the generic algorithms. In these cases the container
 * will provide its own sorting messages. Additionally, sorting algorithms should
 * not be used with containers that are inherently sorted. These include
 * all associative containers, like OLMap and OLSet, and the containers based
 * on hash tables, like OLHashMap and OLHashSet.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Swapping
 *
 * Algorithms for swapping elements. Individual elements, elements referred to by
 * iterators, and entire ranges may be swapped.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @defgroup Transformations
 *
 * Algorithms for transforming ranges. Ranges can be transformed in a wide variety of
 * ways including selectively removing and replacing, permuting, reversing, and many
 * others.
 *
 * @sa OLAlgorithm
 *
 * @ingroup Algorithms
 */

/**
 * @class OLAlgorithm Algorithm.h ObjectiveLib/Algorithm.h
 *
 * A class to provide generic algorithms for use with many different types of
 * @ref Containers "containers". Algorithms are separated from the underlying
 * data structures on which they operate through the use of iterators. Algorithms
 * are only given iterators as arguments, and have no information about what
 * kind of collection the iterators might be from.
 *
 * @sa Algorithms
 *
 * @ingroup Algorithms
 */
@interface OLAlgorithm :
#if defined(OL_NO_OPENSTEP)
    Object
#else
    NSObject
#endif
{
}

/**
 * @name Searches
 */
/* @{ */
/**
 * Find the first instance of adjacent elements. This message sends the message
 * #adjacentFindFrom:to:predicate: with OLEqualTo as the predicate.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) adjacentFindFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Find the first instance of adjacent elements. Two elements, @a a and @a b,
 * are considered adjacent if @a a and @a b are next to each other in the range
 * <tt>[first, last)</tt> and the predicate object, @a pred, returns YES when @a a
 * and @a b are passed as arguments. An iterator pointing to the first of the pair is
 * returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param pred the @ref Functors "function object" to use to compare elements
 * @return an iterator pointing to the first in pair of adjacent elements, or an
 * iterator equal to @a last if adjacent elements could not be found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) adjacentFindFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>) pred;

/**
 * Perform a binary search. This message sends the message #binarySearchFrom:to:value:predicate:
 * using a predicate of OLLess.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must already be sorted using
 * the predicate object OLLess.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the value for which to search
 * @return YES if @a object was found, NO otherwise
 *
 * @ingroup Searches
 */
+ (BOOL) binarySearchFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Perform a binary search. A binary search is performed for the value @a object with the
 * @ref Functors "function object" @a pred for comparing objects. Specifically, @a pred
 * indicates what sorted order the elements in the range <tt>[first, last)</tt> are in.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must already be sorted using
 * the predicate object @a pred.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the value for which to search
 * @param pred the predicate object that indicates the sorting order of the range
 * @return YES if @a object was found, NO otherwise
 *
 * @ingroup Searches
 */
+ (BOOL) binarySearchFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Count elements. The number of elements in the range <tt>[first, last)</tt> for which
 * the predicate, @a pred, returns YES is returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param pred the @ref Functors "function object" used to test each element
 * @return the number of elements for which @a pred returned YES
 *
 * @ingroup Searches
 */
+ (unsigned) countFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolUnaryFunction>)pred;

/**
 * Count elements. The number of elements in the range <tt>[first, last)</tt> for which
 * @a object returns YES to the message @c isEqual:.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object with which to compare each element
 * @return the number of elements equal to @a object
 *
 * @ingroup Searches
 */
+ (unsigned) countFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Find the equal range of a given value. This message sends the message
 * #equalRangeFrom:to:value:predicate: with OLLess as the predicate.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted by OLLess.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object for which to search
 * @return a pair of iterators representing the equal range
 *
 * @ingroup Searches
 */
+ (OLPair*) equalRangeFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Find the equal range of a given value. A pair of iterators is returned, one of which
 * represents the first position where @a object can be inserted without disturbing the
 * sorting order, and the other of which represents the last position where @a object can
 * be inserted without disturbing the sorting order. A side effect of this operation is
 * that it will return a range of elements that are all equal to @a object. Additionally,
 * it is simply a combination of #lowerBoundFrom:to:value:predicate: and
 * #upperBoundFrom:to:value:predicate: with the results of those two messages contained
 * in the resulting pair.
 *
 * The returned pair has an instance of OLForwardIterator representing the lower bound
 * as its first value and another instance of OLForwardIterator representing the upper
 * bound as its second value.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted by @a pred.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object for which to search
 * @param pred the @ref Functors "function object" used as the sorting operation for
 * the range <tt>[first, last)</tt>
 * @return a pair of iterators representing the equal range
 *
 * @ingroup Searches
 */
+ (OLPair*) equalRangeFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the last occurrence of a subsequence in a given range. This message sends
 * the message #findEndFrom:to:subFrom:subTo:predicate: using OLEqualTo as the
 * predicate.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the subsequence for which to search
 * @param last2 one position beyond the last in the subsequence for which to search
 * @return an iterator pointing to the last instance found of the subsequence, or
 * an iterator equal to @a last1 if the subsequence cannot be found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findEndFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2;

/**
 * Find the last occurrence of a subsequence in a given range. The last matching
 * subsequence of values in <tt>[first2, last2)</tt> is found in the sequence
 * <tt>[first1, last1)</tt> and an iterator pointing to the beginning of the
 * subsequence is returned. Values are compared using the @ref Functors "function object"
 * @a pred. If the subsequence cannot be found, then an iterator
 * equal to @a last1 is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the subsequence for which to search
 * @param last2 one position beyond the last in the subsequence for which to search
 * @param pred the @ref Functors "function object" used to compare elements
 * @return an iterator pointing to the last instance found of the subsequence, or
 * an iterator equal to @a last1 if the subsequence cannot be found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findEndFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find any of a set of values. This message sends the message
 * #findFirstFrom:to:ofFrom:ofTo:predicate: using OLEqualTo as the predicate.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the range of candidates
 * @param last2 one position beyond the last in the range of candidates
 * @return an iterator pointing to the first match found, or
 * an iterator equal to @a last1 if no match can be found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findFirstFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 ofFrom: (OLForwardIterator*)first2 ofTo: (OLForwardIterator*)last2;

/**
 * Find any of a set of values. The range <tt>[first1, last1)</tt> is searched for the
 * first instance of any value from the range <tt>[first2, last2)</tt> using @a pred
 * as the comparison function. An iterator pointing to the first match is returned,
 * or an iterator equal to @a last1 is returned if no match is found.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the range of candidates
 * @param last2 one position beyond the last in the range of candidates
 * @param pred the @ref Functors "function object" used to compare elements
 * @return an iterator pointing to the first match found, or
 * an iterator equal to @a last1 if no match can be found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findFirstFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 ofFrom: (OLForwardIterator*)first2 ofTo: (OLForwardIterator*)last2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find an element. An iterator pointing to the first element in the range
 * <tt>[first, last)</tt> for which the @ref Functors "function object" @a pred returns YES
 * is returned. If @a pred does not return YES for any elements, then an iterator
 * equal to @a last is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param pred the function that tests elements
 * @return an iterator pointing to the first element for which @a pred returns YES,
 * or an iterator equal to @a last if no match is found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last if: (id<OLBoolUnaryFunction>)pred;

/**
 * Find an element. The range <tt>[first, last)</tt> is searched for an element equal
 * to @a object. Equality is tested using the message @c isEqual:. An iterator pointing
 * to the first equal element, or an iterator equal to @a last if no match is found,
 * is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object for which to search
 * @return an iterator pointing to the first element equal to @a object, or
 * or an iterator equal to @a last if no match is found
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) findFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Determine whether one range exists in another range. This message simply sends
 * the message #includesFrom:to:subFrom:subTo:predicate: using OLLess as the
 * predicate.
 *
 * @pre Both <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted using
 * the predicate OLLess.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the range of elements for which to search
 * @param last2 one position beyond the last in the range of elements for which to search
 * @return YES if the sub-range is found, NO otherwise
 *
 * @ingroup Searches
 */
+ (BOOL) includesFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2;

/**
 * Determine whether one range exists in another range. This message differs from
 * #findFirstFrom:to:ofFrom:ofTo:predicate: in that it simply determines whether all
 * of the elements in the range <tt>[first2, last2)</tt> exist in the range
 * <tt>[first1, last1)</tt> in the same order, although the elements do not need to
 * be contiguous in <tt>[first1, last1)</tt>. The @ref Functors "function object"
 * @a pred indicates the sorting order of both <tt>[first1, last1)</tt> and
 * <tt>[first2, last2)</tt>.
 *
 * @pre Both <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted using
 * the predicate @a pred.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the range of elements for which to search
 * @param last2 one position beyond the last in the range of elements for which to search
 * @param pred the @ref Functors "function object" by which both ranges are sorted
 * @return YES if the sub-range is found, NO otherwise
 *
 * @ingroup Searches
 */
+ (BOOL) includesFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the first position at which a value may be inserted without disturbing the
 * sorting order. This message simply sends the message #lowerBoundFrom:to:value:predicate:
 * using OLLess as the predicate.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted using the predicate OLLess.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object with which to compare objects in the range
 * @return an iterator indicating the first position at which @a object may be inserted
 * without disturbing the sorting order
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) lowerBoundFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Find the first position at which a value may be inserted without disturbing the
 * sorting order. Using a binary search, the message locates the first position at
 * which @a object may be inserted without disturbing the order defined by @a pred.
 * A side effect of this message is that the iterator returned will be the first
 * position of an object equal to @a object, if such an object exists in the range.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted using the predicate @a pred.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object with which to compare objects in the range
 * @param pred the @ref Functors "function object" with which the range is sorted
 * @return an iterator indicating the first position at which @a object may be inserted
 * without disturbing the sorting order
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) lowerBoundFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the element with the highest value. This message simply sends the message
 * #maxElementFrom:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @return an iterator pointing to the highest element
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) maxElementFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Find the element with the highest value. Specifically, the message finds the first
 * element @a i in the range <tt>[first, last)</tt> for which every other element @a j
 * the predicate @a pred message <tt>performBinaryFunctionWithArg: i andArg: j</tt>
 * returns NO. An iterator pointing to the highest value is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param pred the @ref Functors "function object" used for comparison
 * @return an iterator pointing to the highest element
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) maxElementFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the element with the lowest value. This message simply sends the message
 * #minElementFrom:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @return an iterator pointing to the lowest element
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) minElementFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Find the element with the lowest value. Specifically, the message finds the first
 * element @a i in the range <tt>[first, last)</tt> for which every other element @a j
 * the predicate @a pred message <tt>performBinaryFunctionWithArg: j andArg: i</tt>
 * returns NO. An iterator pointing to the highest value is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param pred the @ref Functors "function object" used for comparison
 * @return an iterator pointing to the lowest element
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) minElementFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the first position where two ranges differ. This message simply sends the
 * message #mismatchFrom:to:with:predicate: using OLEqualTo as the predicate.

 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the second range of elements to search
 * @return a pair of instances of OLForwardIterator pointing to the mismatch in
 * both ranges
 *
 * @ingroup Searches
 */
+ (OLPair*) mismatchFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 with: (OLForwardIterator*)first2;

/**
 * Find the first position where two ranges differ. The range <tt>[first1, last)</tt>
 * is compared with the range that begins at @a first2, and the first position where
 * the two differ is returned. The predicate @a pred is used to determine equality. A
 * pair of instances of OLForwardIterator is returned: the first element of the pair
 * points to the mismatch in the range <tt>[first1, last)</tt>, and the second element
 * of the pair points to the mismatch in the range starting from @a first2. If no
 * mismatch is found then the pair contains iterators equal to @a last1 and @a last2.
 * 
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the second range of elements to search
 * @param pred the @ref Functors "function object" used to test objects for equality
 * @return a pair of instances of OLForwardIterator pointing to the mismatch in
 * both ranges
 *
 * @ingroup Searches
 */
+ (OLPair*) mismatchFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 with: (OLForwardIterator*)first2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Search for a number of consecutive instances of an object. This message simply sends
 * the message #searchFrom:to:count:value:predicate: using OLEqualTo as the predicate.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param num the number of instances of @a object for which to search
 * @param object the object for which to search
 * @return an iterator pointing to the beginning of the range of @a num instances
 * of @a object
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) searchFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last count: (unsigned)num value: (id)object;

/**
 * Search for a number of consecutive instances of an object. The message searches the range
 * <tt>[first, last)</tt> for @a num consecutive instances of @a object using @a pred
 * to test objects for equality. An iterator pointing to the beginning of the range of
 * consecutive objects is returned, or if no match is found an iterator equal to @a last
 * is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param num the number of instances of @a object for which to search
 * @param object the object for which to search
 * @param pred the @ref Functors "function object" used to test for equality
 * @return an iterator pointing to the beginning of the range of @a num instances
 * of @a object
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) searchFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last count: (unsigned)num value: (id)object predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find a subsequence within a given range. This message simply sends the message
 * #searchFrom:to:subFrom:subTo:predicate: using OLEqualTo as the predicate.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the subsequence for which to search
 * @param last2 one position beyond the last in the subsequence for which to search
 * @return an iterator pointing to the first instance of the subsequence
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) searchFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2;

/**
 * Find a subsequence within a given range. The first instance of the subsequence described
 * by the range <tt>[first2, last2)</tt> is searched for in the range
 * <tt>[first1, last1)</tt> and an iterator to its position is returned. The predicate
 * @a pred is used to test objects for equality. If no match is
 * found, then an iterator equal to @a last1 is returned.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of elements to search
 * @param last1 one position beyond the last in the range of elements to search
 * @param first2 the first in the subsequence for which to search
 * @param last2 one position beyond the last in the subsequence for which to search
 * @param pred the @ref Functors "function object" used to test objects for equality
 * @return an iterator pointing to the first instance of the subsequence
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) searchFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 subFrom: (OLForwardIterator*)first2 subTo: (OLForwardIterator*)last2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the last position at which a value may be inserted without disturbing the
 * sorting order. This message simply sends the message #upperBoundFrom:to:value:predicate:
 * using OLLess as the predicate.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted using the predicate OLLess.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object with which to compare objects in the range
 * @return an iterator indicating the last position at which @a object may be inserted
 * without disturbing the sorting order
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) upperBoundFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Find the last position at which a value may be inserted without disturbing the
 * sorting order. Using a binary search, the message locates the last position at
 * which @a object may be inserted without disturbing the order defined by @a pred.
 * A side effect of this message is that the iterator returned will be one beyond
 * the last position of an object equal to @a object, if such an object exists in
 * the range.
 *
 * @pre The range <tt>[first, last)</tt> must be sorted using the predicate @a pred.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to search
 * @param last one position beyond the last in the range of elements to search
 * @param object the object with which to compare objects in the range
 * @param pred the @ref Functors "function object" with which the range is sorted
 * @return an iterator indicating the last position at which @a object may be inserted
 * without disturbing the sorting order
 *
 * @ingroup Searches
 */
+ (OLForwardIterator*) upperBoundFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Sorting
 */
/* @{ */
/**
 * Test whether a given range is sorted. This message simply sends the message
 * #isSortedFrom:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @return YES if the range is sorted, NO otherwise
 *
 * @ingroup Sorting
 */
+ (BOOL) isSortedFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Test whether a given range is sorted. The range <tt>[first, last)</tt> is tested
 * to determine whether it is in the order defined by @a pred.
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @param pred the @ref Functors "function object" that defines the sorting order
 * @return YES if the range is sorted, NO otherwise
 *
 * @ingroup Sorting
 */
+ (BOOL) isSortedFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Partially sort a given range. This message simply sends the message
 * #nthElementFrom:nth:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements to sort
 * @param mid the element by which to determine the partial sort
 * @param last one position beyond the last in the range of elements to sort
 *
 * @ingroup Sorting
 */
+ (void) nthElementFrom: (OLRandomAccessIterator*)first nth: (OLRandomAccessIterator*)mid to: (OLRandomAccessIterator*)last;

/**
 * Partially sort a given range. The message reorders the elements in the range
 * <tt>[first, last)</tt> such that every element in the range <tt>[first, nth)</tt>
 * satisfies the predicate @a pred when compared to every element in the range
 * <tt>[nth, last)</tt>. For example, if the predicate is an instance of OLLess,
 * then every element in the range <tt>[first, nth)</tt> will be less than every
 * element in the range <tt>[nth, last)</tt>.
 *
 * This message is similar to #partialSortFrom:middle:to:predicate: except that
 * it does less work. It does not actually sort the elements; it just partitions
 * the sequence around the value of @a mid.
 *
 * @param first the first in the range of elements to sort
 * @param mid the element by which to determine the partial sort
 * @param last one position beyond the last in the range of elements to sort
 * @param pred the @ref Functors "function object" used to compare elements
 *
 * @ingroup Sorting
 */
+ (void) nthElementFrom: (OLRandomAccessIterator*)first nth: (OLRandomAccessIterator*)mid to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Partially sort a given range. This message simply sends the message
 * #partialSortCopyFrom:to:destinationFrom:destinationTo:predicate: using
 * OLLess as the predicate.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 * @param rFirst the first in the destination range
 * @param rLast one position beyond the last in the destination range
 * @return an iterator pointing to one position beyond the last element copied
 *
 * @ingroup Sorting
 */
+ (OLRandomAccessIterator*) partialSortCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destinationFrom: (OLRandomAccessIterator*)rFirst destinationTo: (OLRandomAccessIterator*)rLast;

/**
 * Partially sort a given range. Elements from the range <tt>[first, last)</tt> are
 * copied to the destination @a rFirst. The number of elements copied is the lesser
 * of the distance from @a first to @a last and the distance from @a rFirst to
 * @a rLast. The elements are copied in the order determined by the predicate
 * @a pred.
 * 
 * An iterator is returned pointing to one position beyond the last element copied
 * to the destination.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 * @param rFirst the first in the destination range
 * @param rLast one position beyond the last in the destination range
 * @param pred the @ref Functors "function object" used to determine the sorting order
 * @return an iterator pointing to one position beyond the last element copied
 *
 * @ingroup Sorting
 */
+ (OLRandomAccessIterator*) partialSortCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destinationFrom: (OLRandomAccessIterator*)rFirst destinationTo: (OLRandomAccessIterator*)rLast predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Partially sort a given range. This message simple sends the message
 * #partialSortFrom:middle:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements to sort
 * @param mid the middle position which defines the length of the resulting sorted
 * range
 * @param last one position beyond the last in the range of elements to sort
 *
 * @ingroup Sorting
 */
+ (void) partialSortFrom: (OLRandomAccessIterator*)first middle: (OLRandomAccessIterator*)mid to: (OLRandomAccessIterator*)last;

/**
 * Partially sort a given range. The elements in the range <tt>[first, last)</tt> are
 * sorted such that afterwards the range <tt>[first, mid)</tt> contains elements
 * that satisfy the order defined by @a pred and the remaining elements are placed in
 * unspecified order in the range <tt>[mid, last)</tt>. For example, if the predicate
 * is an instance of OLLess, then the smallest elements will be placed in ascending
 * order in the range <tt>[first, mid)</tt>.
 *
 * @param first the first in the range of elements to sort
 * @param mid the middle position which defines the length of the resulting sorted
 * range
 * @param last one position beyond the last in the range of elements to sort
 * @param pred the @ref Functors "function object" used to determine the sorting order
 *
 * @ingroup Sorting
 */
+ (void) partialSortFrom: (OLRandomAccessIterator*)first middle: (OLRandomAccessIterator*)mid to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Sort a given range. This message simply sends the message #sortFrom:to:predicate:
 * using OLLess as the predicate.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 *
 * @ingroup Sorting
 */
+ (void) sortFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Sort a given range. The elements in the range <tt>[first, last)</tt> are placed in
 * the order defined by the predicate @a pred.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 * @param pred the @ref Functors "function object" used to determine the sorting order
 *
 * @ingroup Sorting
 */
+ (void) sortFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Sort a @ref Heaps "heap". This message simply sends the message #sortHeapFrom:to:predicate:
 * using OLLess as the predicate.
 *
 * @pre The range <tt>[first, last)</tt> must be a heap that was created using the
 * predicate @a pred. That is, #isHeapFrom:to:predicate: must return YES when given
 * @a first, @a last and @a pred as arguments.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 *
 * @sa Heaps
 *
 * @ingroup Sorting
 */
+ (void) sortHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Sort a @ref Heaps "heap". The elements in the range <tt>[first, last)</tt> are placed
 * in the order defined by the predicate @a pred.
 *
 * @pre The range <tt>[first, last)</tt> must be a heap that was created using the
 * predicate @a pred. That is, #isHeapFrom:to:predicate: must return YES when given
 * @a first, @a last and @a pred as arguments.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 * @param pred the @ref Functors "function object" used to determine the sorting order
 *
 * @sa Heaps
 *
 * @ingroup Sorting
 */
+ (void) sortHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Sort a given range stably. This message simply sends the message #stableSortFrom:to:predicate:
 * using OLLess as the predicate.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 *
 * @ingroup Sorting
 */
+ (void) stableSortFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Sort a given range stably. This message is similar to #sortFrom:to:predicate: except
 * that the sort is done stably. A stable sort is one in which the original order of
 * equivilent elements is not disrupted. The resulting sequence will be in the order
 * defined by the predicate @a pred, but the relative order of equivilent elements will
 * not change.
 *
 * @param first the first in the range of elements to sort
 * @param last one position beyond the last in the range of elements to sort
 * @param pred the @ref Functors "function object" used to determine the sorting order
 *
 * @ingroup Sorting
 */
+ (void) stableSortFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Heaps
 */
/* @{ */
/**
 * Test whether a range is a heap. This message simply sends the message
 * #isHeapFrom:to:predicate: using OLLess as the predicate.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @return YES if the range is a heap, NO otherwise
 *
 * @ingroup Heaps
 */
+ (BOOL) isHeapFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Test whether a range is a heap. If the range <tt>[first, last)</tt> is a heap
 * that was created with the predicate @a pred, then this message returns YES.
 *
 * @sa #sortHeapFrom:to:predicate:
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @param pred the @ref Functors "function object" used to determine the order of the heap
 * @return YES if the range is a heap, NO otherwise
 *
 * @ingroup Heaps
 */
+ (BOOL) isHeapFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Convert the given range into a heap. This message simply sends the message
 * #makeHeapFrom:to:predicate: using OLLess as the predicate.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range of elements to make a heap
 * @param last one position beyond the last in the range of elements to make a heap
 *
 * @ingroup Heaps
 */
+ (void) makeHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Convert the given range into a heap. The range <tt>[first, last)</tt> is turned into
 * a heap using @a pred as the definition of the sorting order for the heap.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range of elements to make a heap
 * @param last one position beyond the last in the range of elements to make a heap
 * @param pred the @ref Functors "function object" used to determine the order of the heap
 *
 * @ingroup Heaps
 */
+ (void) makeHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Remove the top element of the heap. This message simply sends the message
 * #popHeapFrom:to:predicate: using OLLess as the predicate.
 *
 * @pre The range <tt>[first, last)</tt> must qualify as a heap using the message
 * #isHeapFrom:to:predicate: with OLLess as the predicate.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range that is a heap
 * @param last one position beyond the last in the range that is a heap
 *
 * @ingroup Heaps
 */
+ (void) popHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Remove the top element of the heap. The element at the position referred to by
 * the iterator @a first is removed. Of course, generic algorithms cannot actually
 * remove anything from a collection as they only operate on iterators. Therefore,
 * the element at the position pointed to by @a first is moved to the end of the range.
 * This means that subsequently the iterator one position before @a last will refer
 * to the element that was 'removed', and the remainder of the range will still
 * qualify as a heap using the message #isHeapFrom:to:predicate:.
 *
 * @pre The range <tt>[first, last)</tt> must qualify as a heap using the message
 * #isHeapFrom:to:predicate: with @a pred as the predicate.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range that is a heap
 * @param last one position beyond the last in the range that is a heap
 * @param pred the @ref Functors "function object" used to determine the order of the heap
 *
 * @ingroup Heaps
 */
+ (void) popHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Add an element to a heap. This message simply sends the message
 * #pushHeapFrom:to:predicate: using OLLess as the predicate.
 *
 * @pre The range <tt>[first, (last - 1))</tt> must be a heap as verified by the
 * message #isHeapFrom:to:predicate:.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range to which to add a heap element
 * @param last one position beyond the last in the range to which to add a heap element
 *
 * @ingroup Heaps
 */
+ (void) pushHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Add an element to a heap. The element at one position before @a last is added to the heap.
 * Subsequently the entire range from <tt>[first, last)</tt> will be a valid heap.
 *
 * @pre The range <tt>[first, (last - 1))</tt> must be a heap as verified by the
 * message #isHeapFrom:to:predicate:.
 *
 * @sa #sortHeapFrom:to:
 *
 * @param first the first in the range to which to add a heap element
 * @param last one position beyond the last in the range to which to add a heap element
 * @param pred the @ref Functors "function object" used to determine the order of the heap
 *
 * @ingroup Heaps
 */
 + (void) pushHeapFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Sets
 */
/* @{ */
/**
 * Find the difference of two sets. This message simply sends the message
 * #setDifferenceFrom:to:andFrom:andTo:destination:predicate: using OLLess as the
 * predicate.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setDifferenceFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest;

/**
 * Find the difference of two sets. Compute the difference of the two sets by placing all
 * elements contained in the range <tt>[first1, last1)</tt> but not in the range
 * <tt>[first2, last2)</tt> into the range starting at @a dest. The resulting range starting
 * with the element at @a dest will be sorted by @a pred. An iterator pointing to one
 * position beyond the last element copied is returned.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * @param pred the @ref Functors "function object" that defines the sorting order of
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setDifferenceFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the intersection of two sets. This message simply sends the message
 * #setIntersectionFrom:to:andFrom:andTo:destination:predicate: using OLLess as the
 * predicate.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setIntersectionFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest;

/**
 * Find the intersection of two sets. Compute the intersection of the two sets by placing
 * all elements contained in both <tt>[first1, last1)</tt> and in <tt>[first2, last2)</tt>
 * into the range starting at @a dest. The resulting range starting with the element at
 * @a dest will be sorted by @a pred. An iterator pointing to one position beyond the last
 * element copied is returned.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * @param pred the @ref Functors "function object" that defines the sorting order of
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setIntersectionFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the symmetric difference of two sets. This message simply sends the message
 * #setSymmetricDifferenceFrom:to:andFrom:andTo:destination:predicate: using OLLess as the
 * predicate.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setSymmetricDifferenceFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest;

/**
 * Find the symmetric difference of two sets. Compute the symmetric difference of the
 * two sets by placing all elements contained in <tt>[first1, last1)</tt> but not
 * contained in <tt>[first2, last2)</tt> and all elements contained in
 * <tt>[first2, last2)</tt> but not contained in <tt>[first1, last)</tt> into the
 * range starting at @a dest. The resulting range starting with the element at
 * @a dest will be sorted by @a pred. An iterator pointing to one position beyond the last
 * element copied is returned.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * @param pred the @ref Functors "function object" that defines the sorting order of
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setSymmetricDifferenceFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Find the union of two sets. This message simply sends the message
 * #setUnionFrom:to:andFrom:andTo:destination:predicate: using OLLess as the
 * predicate.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setUnionFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest;

/**
 * Find the union of two sets. Compute the union of the
 * two sets by placing all elements contained in <tt>[first1, last1)</tt> and all
 * elements contained in <tt>[first2, last2)</tt> into the
 * range starting at @a dest. The resulting range starting with the element at
 * @a dest will be sorted by @a pred. An iterator pointing to one position beyond the last
 * element copied is returned.
 *
 * @pre
 * - <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be sorted in the order
 * defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the range of the first set
 * @param last1 one position beyond the last in the range of the first set
 * @param first2 the first in the range of the second set
 * @param last2 one position beyond the last in the range of the second set
 * @param dest the first element in the range to which to copy the resulting set
 * @param pred the @ref Functors "function object" that defines the sorting order of
 * both the input sets and the resulting output set
 * @return an iterator pointing to one position beyond the last element copied to @a dest
 *
 * @ingroup Sets
 */
+ (OLForwardIterator*) setUnionFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Merges
 */
/* @{ */
/**
 * Merge two consecutive ranges. This message simply sends the message
 * #inPlaceMergeFrom:middle:to:predicate: using OLLess as the predicate.
 *
 * @pre Both <tt>[first, middle)</tt> and <tt>[middle, last)</tt> must be sorted in
 * the order defined by OLLess.
 *
 * @param first the first position in the first range
 * @param middle one position beyond the last in the first range and the first
 * position in the second range
 * @param last one position beyond the last in the second range
 *
 * @ingroup Merges
 */
+ (void) inPlaceMergeFrom: (OLBidirectionalIterator*)first middle: (OLBidirectionalIterator*)middle to: (OLBidirectionalIterator*)last;

/**
 * Merge two consecutive ranges. The sorted range <tt>[first, middle)</tt> is merged with
 * the sorted range <tt>[middle, last)</tt> to create a single sorted range
 * <tt>[first, last)</tt>. The merge is a stable merge, meaning that the equivilent
 * elements in each of the two ranges remain in the same relative order after the merge
 * is done.
 *
 * @pre Both <tt>[first, middle)</tt> and <tt>[middle, last)</tt> must be sorted in
 * the order defined by the predicate @a pred.
 *
 * @param first the first position in the first range
 * @param middle one position beyond the last in the first range and the first
 * position in the second range
 * @param last one position beyond the last in the second range
 * @param pred the predicate that indicates the sorting order
 *
 * @ingroup Merges
 */
+ (void) inPlaceMergeFrom: (OLBidirectionalIterator*)first middle: (OLBidirectionalIterator*)middle to: (OLBidirectionalIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Merge two sorted ranges. This message simply sends the message
 * #mergeFrom:to:andFrom:andTo:destination:predicate: using OLLess as the predicate.
 *
 * @pre
 * - The ranges <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be
 * sorted in the order defined by OLLess.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first1 the first position in the first range
 * @param last1 one position beyond the last in the first range
 * @param first2 the first position in the second range
 * @param last2 one position beyond the last in the second range
 * @param dest the first element in the range to which to copy the merged elements
 * @return an iterator pointing to one position beyond the last element in the
 * resulting range that starts from @a dest.
 *
 * @ingroup Merges
 */
+ (OLForwardIterator*) mergeFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest;

/**
 * Merge two sorted ranges. The sorted range <tt>[first1, last1)</tt> is merged with the
 * sorted range <tt>[first2, last2)</tt> and copied to the location indicated by
 * @a dest. The resulting range starting at @a dest will be sorted using the order
 * defined by @a pred. An iterator pointing to one position beyond the last element in
 * the destination range is returned. The merge is stable, meaning that equivilent
 * elements in the each of the two ranges remain in the same relative order after the
 * merge is done.
 *
 * @pre
 * - The ranges <tt>[first1, last1)</tt> and <tt>[first2, last2)</tt> must be
 * sorted in the order defined by @a pred.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first position in the first range
 * @param last1 one position beyond the last in the first range
 * @param first2 the first position in the second range
 * @param last2 one position beyond the last in the second range
 * @param dest the first element in the range to which to copy the merged elements
 * @param pred the predicate that indicates the sorting order
 * @return an iterator pointing to one position beyond the last element in the
 * resulting range that starts from @a dest.
 *
 * @ingroup Merges
 */
+ (OLForwardIterator*) mergeFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Partitioning
 */
/* @{ */
/**
 * Partition a range. This message reorders the elements in the range <tt>[first, last)</tt>
 * so that all elements which satisfy the predicate @a pred precede all elements which
 * do not. An iterator is returned that points to the location of the partition in
 * the sequence. That is, for the returned iterator @c middle the predicate returns
 * YES for every element in the range <tt>[first, middle)</tt> and NO for every element
 * in the range <tt>[middle, last)</tt>.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range to partition
 * @param last one position beyond the last in the range to partition
 * @param pred the predicate that is used to define the partition
 * @return an iterator pointing to the location in the range <tt>[first, last)</tt>
 * where the partition is located
 *
 * @ingroup Partitioning
 */
+ (OLBidirectionalIterator*) partitionFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last predicate: (id<OLBoolUnaryFunction>)pred;

/**
 * Partition a range stably. This message is very similar to the message
 * #partitionFrom:to:predicate: except that the partition is created stably.
 * That is, the relative order of elements is preserved after the partition is
 * created.
 *
 * @param first the first in the range to partition
 * @param last one position beyond the last in the range to partition
 * @param pred the predicate that is used to define the partition
 * @return an iterator pointing to the location in the range <tt>[first, last)</tt>
 * where the partition is located
 *
 * @ingroup Partitioning
 */
+ (OLForwardIterator*) stablePartitionFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolUnaryFunction>)pred;
/* @} */

/**
 * @name Comparisons
 */
/* @{ */
/**
 * Test whether two ranges are equal. This message sends the message
 * #equalFrom:to:with:predicate: using OLEqualTo as the predicate.
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @param first2 the first in the second range to test
 * @return YES if the ranges are equal, NO otherwise
 *
 * @ingroup Comparisons
 */
+ (BOOL) equalFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last with: (OLForwardIterator*)first2;

/**
 * Test whether two ranges are equal. Each element in the range <tt>[first, last)</tt> is
 * tested with the corresponding element from the range starting with @a first2
 * using the @ref Functors "function object" @a pred. If @a pred returns YES for each of
 * its tests, then this message returns YES.
 *
 * @param first the first in the range of elements to test
 * @param last one position beyond the last in the range of elements to test
 * @param first2 the first in the second range to test
 * @param pred the @ref Functors "function object" for testing
 * @return YES if the ranges are equal, NO otherwise
 *
 * @ingroup Comparisons
 */
+ (BOOL) equalFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last with: (OLForwardIterator*)first2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Compare two ranges lexicographically. This message simply sends the message
 * #lexicographicalCompareFrom:to:andFrom:andTo:predicate: using OLLess as
 * the predicate.
 *
 * @param first1 the first in the first range of elements to test
 * @param last1 one position beyond the last in the first range of elements to test
 * @param first2 the first in the second range of elements to test
 * @param last2 one position beyond the last in the second range of elements to test
 * @return YES if the elements in the first range satisfy the elements when compared
 * to corresponding elements in the second range, NO otherwise
 *
 * @ingroup Comparisons
 */
+ (BOOL) lexicographicalCompareFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2;

/**
 * Compare two ranges lexicographically. A lexicographical comparison is one where each of
 * the elements in the range <tt>[first1, last1)</tt> is compared with each of the
 * elements in the range <tt>[first2, last2)</tt>. If each element in the first range
 * satisfies the predicate @a pred when compared to its corresponding element in the
 * second range, then YES is returned.
 *
 * @param first1 the first in the first range of elements to test
 * @param last1 one position beyond the last in the first range of elements to test
 * @param first2 the first in the second range of elements to test
 * @param last2 one position beyond the last in the second range of elements to test
 * @param pred the predicate used to compare elements in the two ranges
 * @return YES if the elements in the first range satisfy the elements when compared
 * to corresponding elements in the second range, NO otherwise
 *
 * @ingroup Comparisons
 */
+ (BOOL) lexicographicalCompareFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 andFrom: (OLForwardIterator*)first2 andTo: (OLForwardIterator*)last2 predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Return the maximum of two elements. This message simply sends the message
 * #max:or:predicate: using OLLess as the predicate.
 *
 * @param left the first element to compare
 * @param right the second element to compare
 * @return the element that is the maximum element according to OLLess
 *
 * @ingroup Comparisons
 */
+ (id) max: (id)left or: (id)right;

/**
 * Return the maximum of two elements. The two elements are compared using the predicate
 * @a pred with @a left passed as the first argument to the predicate and @a right
 * passed as the second argument. If the predicate returns YES, then @a right is
 * returned, otherwise @a left is returned.
 *
 * @param left the first element to compare
 * @param right the second element to compare
 * @param pred the predicate that is used to compare the two objects
 * @return the element that is the maximum element according to @a pred
 *
 * @ingroup Comparisons
 */
+ (id) max: (id)left or: (id)right predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Return the minimum of two elements. This message simply sends the message
 * #min:or:predicate: using OLLess as the predicate.
 *
 * @param left the first element to compare
 * @param right the second element to compare
 * @return the element that is the minimum element according to OLLess
 *
 * @ingroup Comparisons
 */
+ (id) min: (id)left or: (id)right;

/**
 * Return the minimum of two elements. The two elements are compared using the predicate
 * @a pred with @a left passed as the first argument to the predicate and @a right
 * passed as the second argument. If the predicate returns YES, then @a left is
 * returned, otherwise @a right is returned.
 *
 * @param left the first element to compare
 * @param right the second element to compare
 * @param pred the predicate that is used to compare the two objects
 * @return the element that is the minimum element according to @a pred
 *
 * @ingroup Comparisons
 */
+ (id) min: (id)left or: (id)right predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Copying
 */
/* @{ */
/**
 * Copy elements. The range <tt>[first, last)</tt> is traversed from the end to the
 * beginning, and each element is assigned to its corresponding position in the sequence
 * suggested by @a dest. That is, @a dest represents the position one beyond the last
 * element of the target range. An iterator pointing to the first element of the target
 * range is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note The two ranges of iterators could be expressed as <tt>[first, last)</tt> and
 * <tt>[result, dest)</tt> where @a result is the iterator returned by this message.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to copy
 * @param last one position beyond the last in the range of elements to copy
 * @param dest the iterator one position beyond the end of the destination range
 * @return an iterator pointing to the first element in the destination range
 *
 * @ingroup Copying
 */
+ (OLBidirectionalIterator*) copyBackwardFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last destination: (OLBidirectionalIterator*)dest;

/**
 * Copy elements. The range <tt>[first, last)</tt> is traversed from the beginning to the
 * end, and each element is assigned to its corresponding position in the sequence
 * suggested by @a dest. An iterator pointing to the last element of the target
 * range is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note The two ranges of iterators could be expressed as <tt>[first, last)</tt> and
 * <tt>[dest, result)</tt> where @a result is the iterator returned by this message.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range of elements to copy
 * @param last one position beyond the last in the range of elements to copy
 * @param dest the iterator at the beginning of the destination range
 * @return an iterator pointing to the last element in the destination range
 *
 * @ingroup Copying
 */
+ (OLForwardIterator*) copyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest;
/* @} */

/**
 * @name Transformations
 */
/* @{ */
/**
 * Assign a given value to a number of elements. The operation assigns @a object to
 * @a num elements starting at @a first.
 *
 * @param first the first element from which to begin assignment
 * @param num the number of times to assign @a object
 * @param object the value to assign
 *
 * @ingroup Transformations
 */
+ (void) fillFrom: (OLForwardIterator*)first count: (unsigned)num value: (id)object;

/**
 * Assign a value to a range of elements. The value @a object is assigned to every
 * iterator in the range <tt>[first, last)</tt>.
 *
 * @param first the first in the range of elements to assign
 * @param last one position beyond the last in the range of elements to assign
 * @param object the value to assign
 *
 * @ingroup Transformations
 */
+ (void) fillFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Perform an operation on each element in a given range. Each element in the range
 * <tt>[first, last)</tt> is passed as an argument to the @ref Functors "function object"
 * @a func.
 *
 * @param first the first in the range of elements
 * @param last one position beyond the last in the range of elements
 * @param func the @ref Functors "function object" operating on the elements
 *
 * @ingroup Transformations
 */
+ (void) forEachFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last function: (id<OLUnaryFunction>)func;

/**
 * Turn a range into its next permutation. This message simple sends the message
 * #nextPermutationFrom:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements
 * @param last one beyond the last in the range of elements
 * @return YES if a next permutation was found, NO otherwise
 *
 * @ingroup Transformations
 */
+ (BOOL) nextPermutationFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last;

/**
 * Turn a range into its next permutation. Each range of elements has a finite number of
 * permutations. Where @c n is the distance from the first in the range to the last, each
 * range will have @c n! permutations. The next permutation is computed lexicographically,
 * so if the range is ordered using #lexicographicalCompareFrom:to:andFrom:andTo:predicate:,
 * then the result of finding the next permutation will be unambiguous. If there is no
 * next permutation in the order defined by @a pred, then NO is returned and the sequence
 * is placed in the order of its first permutation in the order defined by @a pred. If a
 * next permutation is found, then the message returns YES and the sequence is placed in
 * the order of the next permutation as defined by @a pred.
 *
 * @sa #prevPermutationFrom:to:predicate:
 *
 * @param first the first in the range of elements
 * @param last one beyond the last in the range of elements
 * @param pred the predicate used to define the lexicographical order of permutations
 * @return YES if a next permutation was found, NO otherwise
 *
 * @ingroup Transformations
 */
+ (BOOL) nextPermutationFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Turn a range into its previous permutation. This message simple sends the message
 * #prevPermutationFrom:to:predicate: using OLLess as the predicate.
 *
 * @param first the first in the range of elements
 * @param last one beyond the last in the range of elements
 * @return YES if a next permutation was found, NO otherwise
 *
 * @ingroup Transformations
 */
+ (BOOL) prevPermutationFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last;

/**
 * Turn a range into its previous permutation. Each range of elements has a finite number of
 * permutations. Where @c n is the distance from the first in the range to the last, each
 * range will have @c n! permutations. The previous permutation is computed lexicographically,
 * so if the range is ordered using #lexicographicalCompareFrom:to:andFrom:andTo:predicate:,
 * then the result of finding the previous permutation will be unambiguous. If there is no
 * previous permutation in the order defined by @a pred, then NO is returned and the sequence
 * is placed in the order of its last permutation in the order defined by @a pred. If a
 * previous permutation is found, then the message returns YES and the sequence is placed in
 * the order of the previous permutation as defined by @a pred.
 *
 * @sa #nextPermutationFrom:to:predicate:
 *
 * @param first the first in the range of elements
 * @param last one beyond the last in the range of elements
 * @param pred the predicate used to define the lexicographical order of permutations
 * @return YES if a next permutation was found, NO otherwise
 *
 * @ingroup Transformations
 */
+ (BOOL) prevPermutationFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Reorder a sequence of elements randomly. The elements in the range
 * <tt>[first, last)</tt> are placed in a random order. The message uses
 * one of the following functions to generate random numbers:
 * - @c random()
 * - @c lrand48()
 * - @c rand_s()
 * - @c rand()
 *
 * You must properly seed the random number generator prior to using this algorithm,
 * and you can find out which random number generator is in use by checking for
 * a defined macro from the following list:
 * - @c OL_HAVE_RANDOM
 * - @c OL_HAVE_LRAND48
 * - @c OL_HAVE_RAND_S
 * - @c OL_HAVE_RAND
 *
 * Only one of those will be defined in the file @c ObjectiveLib/Config.h.
 *
 * @pre The random number generator must have been seeded.
 *
 * @param first the first in the range to shuffle
 * @param last one beyond the last in the range to shuffle
 *
 * @ingroup Transformations
 */
+ (void) randomShuffleFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last;

/**
 * Reorder a sequence of elements randomly. The elements in the range
 * <tt>[first, last)</tt> are placed in a random order. The random number generator
 * @a gen is a special kind of @ref Functors "function object". The argument to the
 * unary function must respond to the message @c unsignedIntValue, which will return
 * an integer greater than or equal to zero. The result of the unary function
 * must also respond to the message @c unsignedIntValue, which will return an integer
 * greater than or equal to zero and less than the value of the @c unsignedIntValue
 * which is the argument to the unary function.
 *
 * @pre @a gen must take an argument that responds to the message @c unsignedIntValue,
 * and must return a result that responds to the message @c unsignedIntValue.
 *
 * @param first the first in the range to shuffle
 * @param last one beyond the last in the range to shuffle
 * @param gen the random number generator to use
 *
 * @ingroup Transformations
 */
+ (void) randomShuffleFrom: (OLRandomAccessIterator*)first to: (OLRandomAccessIterator*)last randGen: (id<OLUnaryFunction>)gen;

/**
 * Copy a range while selectively removing elements. All elements in the range
 * <tt>[first, last)</tt> for which the predicate @a pred does not return YES when
 * passed each element as an argument are copied to the range that begins from
 * @a dest. An iterator that points to one position beyond the last element copied
 * is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range to copy
 * @param last one beyond the last in the range to copy
 * @param dest the first in the range to which to copy elements
 * @param pred the predicate that, when passed each element in the range <tt>[first, last)</tt>
 * as an argument, returns YES for those that should not be copied to @a dest
 * @return an iterator pointing to one position beyond the last element copied to
 * @a dest
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) removeCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest if: (id<OLBoolUnaryFunction>)pred;

/**
 * Copy a range while selectively removing elements. All elements in the range
 * <tt>[first, last)</tt> for which the message @c isEqual:, when passed @a object
 * as an argument, returns NO are copied to the range that begins from @a dest.
 * An iterator that points to one position beyond the last element copied
 * is returned.
 *
 * @pre
 * - All elements in the range <tt>[first, last)</tt> must respond to the
 * message @c isEqual:.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range to copy
 * @param last one beyond the last in the range to copy
 * @param dest the first in the range to which to copy elements
 * @param object the object against which to test each of the elements in the range
 * for equality
 * @return an iterator pointing to one position beyond the last element copied to
 * @a dest
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) removeCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest value: (id)object;

/**
 * Remove elements from a range. Naturally, a generic algorithm cannot erase elements
 * from a range. What the message does instead is to organize the range such that for no
 * element in the new range <tt>[first, middle)</tt> the predicate @a pred will return
 * YES. The iterator @a middle is returned by the message after reorganizing the
 * range <tt>[first, last)</tt>. The range from <tt>[middle, last)</tt> will still
 * contain valid elements, but the exact contents are undefined.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range from which to remove elements
 * @param last one beyond the last in the range from which to remove elements
 * @param pred the @ref Functors "function object" that returns YES for each
 * element that should be removed
 * @return an iterator indicating one position beyond the new last element in the
 * range after removing all elements identified by the predicate @a pred
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) removeFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last if: (id<OLBoolUnaryFunction>)pred;

/**
 * Remove elements from a range. This message is similar to #removeFrom:to:if: except that
 * rather than using a @ref Functors "function object" the message @c isEqual: is sent
 * to each element in the range <tt>[first, last)</tt> with @a object as the argument.
 * If the message returns YES, then the element will not appear in the resulting range
 * <tt>[first, middle)</tt> where @c middle points to one position beyond the last
 * element not equal to @a object. The elements in the range <tt>[middle, last)</tt>
 * are still valid, but the contents are undefined. The iterator @c middle is returned.
 * 
 * @pre All elements in the range <tt>[first, last)</tt> must respond to the message
 * @c isEqual:.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range from which to remove elements
 * @param last one beyond the last in the range from which to remove elements
 * @param object the object that should be removed from the range <tt>[first, last)</tt>
 * @return an iterator indicating one position beyond the new last element in the
 * range after removing all elements identified comparing elements to @a object
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) removeFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last value: (id)object;

/**
 * Copy a range while selectively replacing elements. All elements from the range
 * <tt>[first, last)</tt> are copied to the range that begins at @a dest, but those
 * elements for which the predicate @a pred returns YES are replaced in the destination
 * range with the value @a newv. An iterator that points to one position beyond the
 * last element copied is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range from which to copy elements
 * @param last one beyond the last in the range from which to copy elements
 * @param dest the first in the range to which to copy elements
 * @param pred the predicate that, when passed each element in the range <tt>[first, last)</tt>
 * as an argument, returns YES for those that should be replaced by @a newv
 * @param newv the value used to replace values in the destination range
 * @return an iterator that points to one position beyond the last element copied to
 * the destination
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) replaceCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest if: (id<OLBoolUnaryFunction>)pred newValue: (id)newv;

/**
 * Copy a range while selectively replacing elements. All elements from the range
 * <tt>[first, last)</tt> are copied to the range that begins at @a dest, but those
 * elements for which the message @c isEqual: returns YES when passed @a oldv as an argument
 * are replaced with the value @a newv. An iterator that points to one position beyond the
 * last element copied is returned.
 *
 * @pre
 * - All elements in the range <tt>[first, last)</tt> must respond to the message
 * @c isEqual:.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range from which to copy elements
 * @param last one beyond the last in the range from which to copy elements
 * @param dest the first in the range to which to copy elements
 * @param oldv the value that should be replaced with @a newv in the destination range
 * @param newv the value used to replace values in the destination range
 * @return an iterator that points to one position beyond the last element copied to
 * the destination
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) replaceCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest oldValue: (id)oldv newValue: (id)newv;

/**
 * Replace values in a range. Each element in the range <tt>[first, last)</tt> is tested
 * using the predicate @a pred, and for each case where YES is returned that value is
 * replaced with the value @a newv.
 *
 * @param first the first in the range to check for replacements
 * @param last one beyond the last in the range to check for replacements
 * @param pred the @ref Functors "function object" used to test each element in the range
 * @param newv the value with which to replace the candidate values
 *
 * @ingroup Transformations
 */
+ (void) replaceFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last if: (id<OLBoolUnaryFunction>)pred newValue: (id)newv;

/**
 * Replace values in a range. Each element in the range <tt>[first, last)</tt> is sent
 * the message @c isEqual: using @a oldv as an argument. For each case where @c isEqual:
 * returns YES the value is replaced with the value of @a newv.
 *
 * @pre Each element in the range <tt>[first, last)</tt> must respond to the message
 * @c isEqual:.
 *
 * @param first the first in the range to check for replacements
 * @param last one beyond the last in the range to check for replacements
 * @param oldv the value with which to compare the values in the range
 * @param newv the value with which to replace the candidate values
 *
 * @ingroup Transformations
 */
+ (void) replaceFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last oldValue: (id)oldv newValue: (id)newv;

/**
 * Copy a range in reverse order. The elements in the range <tt>[first, last)</tt> are
 * copied to the range starting at @a dest in reverse order. An iterator pointing to
 * one position beyond the last element copied in the destination range is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range from which to copy elements
 * @param last one beyond the last in the range from which to copy elements
 * @param dest the first element in the range to which to copy elements
 * @return an iterator that points to one position beyond the last element copied
 * to the destination range
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) reverseCopyFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last destination: (OLForwardIterator*)dest;

/**
 * Reverse the order of a range of elements. The range <tt>[first, last)</tt> is
 * placed in reverse order.
 *
 * @param first the first in the range to reverse
 * @param last one beyond the last in the range to reverse
 *
 * @ingroup Transformations
 */
+ (void) reverseFrom: (OLBidirectionalIterator*)first to: (OLBidirectionalIterator*)last;

/**
 * Copy a range and rotate it in one step. Rotation in this context is roughly equivilent
 * to the idea of "left shifting". As it is copied the range is shifted to the left
 * by the distance between @a first and @a mid. The value of @a mid is copied to the
 * position of @a first, @a mid plus one is copied to @a first plus one, and so on. The
 * existing values at @a first and the values that follow it are copied to @a mid,
 * and so on. Another way of thinking of it is that the two ranges <tt>[first, mid)</tt>
 * and <tt>[mid, last)</tt> are swapped. An iterator pointing to one position beyond the
 * last element copied to the destination range is returned.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first element in the range from which to copy
 * @param mid the position at which to perform the pivot of rotation in the range from
 * which to copy
 * @param last one beyond the last element in the range from which to copy
 * @param dest the first in the destination range to which to copy
 * @return an iterator pointing to one position beyond the last element copied
 * to the destination range
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) rotateCopyFrom: (OLForwardIterator*)first middle: (OLForwardIterator*)mid to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest;

/**
 * Rotate a given range. Rotation in this context is roughly equivilent
 * to the idea of "left shifting". The range is shifted to the left
 * by the distance between @a first and @a mid. The value of @a mid is copied to the
 * position of @a first, @a mid plus one is copied to @a first plus one, and so on. The
 * existing values at @a first and the values that follow it are copied to @a mid,
 * and so on. Another way of thinking of it is that the two ranges <tt>[first, mid)</tt>
 * and <tt>[mid, last)</tt> are swapped. An iterator pointing to the new position
 * of the element originally pointed to by @a mid is returned. In other words the
 * returned iterator is equal to the position of @a first plus the distance between
 * @a mid and @a last.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first element in the range from which to copy
 * @param mid the position at which to perform the pivot of rotation in the range from
 * which to copy
 * @param last one beyond the last element in the range from which to copy
 * @return an iterator pointing to the new position of the element originally pointed
 * to by @a mid
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) rotateFrom: (OLForwardIterator*)first middle: (OLForwardIterator*)mid to: (OLForwardIterator*)last;

/**
 * Transform a range. The message performs the unary function @a func on each element
 * in the range <tt>[first, last)</tt> and copies the result to the range that begins
 * from @a dest. Each element is passed as the argument to the unary function's
 * @c performUnaryFunctionWithArg: message, which presumably will do something to
 * the argument and return another object as the result. An iterator is returned that
 * points to one position beyond the last element copied to the destination range.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first element in the range to transform
 * @param last one beyond the last element in the range to transform
 * @param dest the first element in the range to which to copy the results of the
 * transformation
 * @param func the @ref Functors "function object" used to transform the range
 * @return an iterator pointing to one position beyond the last element copied to
 * the destination range
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) transformFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest function: (id<OLUnaryFunction>)func;

/**
 * Transform a range. This message is very similar to #transformFrom:to:destination:function:
 * except that another argument to the @ref Functors "function object", which is now
 * a binary function, is plucked from the range starting from @a first2 and passed as the
 * second argument to @a func. As with #transformFrom:to:destination:function:, each
 * element in the range <tt>[first1, last)</tt> is passed to @a func as the first argument
 * to the @c performBinaryFunctionWithArg:andArg: message. An iterator is returned that
 * points to one position beyond the last element copied to the destination range.
 *
 * @pre
 * - The range starting from @a first2 must have at least as many valid elements as
 * the range starting from @a first1.
 * - The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first element in the range to transform
 * @param last one beyond the last element in the range to transform
 * @param first2 the first in the range of elements to use as second arguments to @a func
 * @param dest the first element in the range to which to copy the results of the
 * transformation
 * @param func the @ref Functors "function object" used to transform the range
 * @return an iterator pointing to one position beyond the last element copied to
 * the destination range
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) transformFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last withArgsFrom: (OLForwardIterator*)first2 destination: (OLForwardIterator*)dest function: (id<OLBinaryFunction>)func;

/**
 * Copy a range while eliminating duplicates. This message simple sends the message
 * #uniqueCopyFrom:to:destination:predicate: using OLEqualTo as the predicate.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @param first the first in the range to copy
 * @param last one beyond the last in the range to copy
 * @param dest the first in the range to which to copy
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) uniqueCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest;

/**
 * Copy a range while eliminating duplicates. Elements from the range <tt>[first, last)</tt>
 * are copied to the range starting at @a dest, except that where there is a series of
 * consecutive elements for which the predicate @a pred returns YES, only the first is
 * copied. An iterator is returned that points to one position beyond the last element
 * copied to the destination range.
 *
 * @pre The range starting from @a dest must either have enough valid elements to hold the
 * result, or @a dest be a type of @ref InsertIterators "insert iterator".
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range to copy
 * @param last one beyond the last in the range to copy
 * @param dest the first in the range to which to copy
 * @param pred the @ref Functors "function object" used to test for consecutive elements
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) uniqueCopyFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last destination: (OLForwardIterator*)dest predicate: (id<OLBoolBinaryFunction>)pred;

/**
 * Remove consecutive elements from a range. This message simply sends the message
 * #uniqueFrom:to:predicate: using OLEqualTo as the predicate.
 *
 * @param first the first in the range to transform
 * @param last one beyond the last in the range to transform
 * @return an iterator pointing to one beyond the last in the range of unique elements
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) uniqueFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Remove consecutive elements from a range. The message returns an iterator @c end that
 * is in the range <tt>[first, last)</tt>, and all elements in the range <tt>[first, end)</tt>
 * will be unique. Uniqueness is tested using the predicate @a pred, and for any two
 * consecutive elements which for which the predicate returns YES, only the first will
 * appear in the resulting range <tt>[first, end)</tt>. The elements that remain in the
 * range <tt>[end, last)</tt> will be valid, but the contents are undefined.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first the first in the range to transform
 * @param last one beyond the last in the range to transform
 * @param pred the @ref Functors "function object" used to test elements for equality
 * @return an iterator pointing to one beyond the last in the range of unique elements
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) uniqueFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last predicate: (id<OLBoolBinaryFunction>)pred;
/* @} */

/**
 * @name Swapping
 */
/* @{ */
/**
 * Swap two elements. The message performs a very fast swap of two distinct elements
 * given pointers to the elements.
 *
 * @param left the first element to swap
 * @param right the second element to swap
 *
 * @ingroup Swapping
 */
+ (void) swap: (id*)left and: (id*)right;

/**
 * Swap elements to which iterators point. The element pointed to by @a left is assigned
 * to the element pointed to by the iterator @a right and vice versa.
 *
 * @param left the first iterator to swap
 * @param right the second iterator to swap
 *
 * @ingroup Swapping
 */
+ (void) swapIterators: (OLIterator*)left and: (OLIterator*)right;

/**
 * Swap elements in two ranges. All elements in the range <tt>[first1, last1)</tt> are assigned
 * to the corresponding element in the range starting at @a first2 and vice versa. An
 * iterator is returned pointing to one position beyond the last element swapped in the
 * range starting from @a first2.
 *
 * @pre The range starting at @a first2 must have at least as many valid elements as
 * the range <tt>[first1, last1)</tt>.
 *
 * @note If OpenStep is present the returned object will be autoreleased before being returned.
 *
 * @param first1 the first in the first range to swap
 * @param last1 one beyond the last in the first range to swap
 * @param first2 the first in the second range to swap
 * @return an iterator pointing to one beyond the last element swapped in the range
 * starting from @a first2
 *
 * @ingroup Transformations
 */
+ (OLForwardIterator*) swapRangesFrom: (OLForwardIterator*)first1 to: (OLForwardIterator*)last1 with: (OLForwardIterator*)first2;
/* @} */

@end

#endif
