diff --git a/include/boost/minmax.hpp b/include/boost/minmax.hpp
index 9c4202f..8404828 100644
--- a/include/boost/minmax.hpp
+++ b/include/boost/minmax.hpp
@@ -1,17 +1,25 @@
// (C) Copyright Eric Niebler 2004.
-// Use, modification and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
+// (C) Copyright Herve Bronnimann 2004.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
+ 26 June 2004
+ Added the code for the boost minmax library. (Herve)
25 February 2004
- Initial version.
+ Initial version. (Eric)
*/
#ifndef BOOST_MINMAX_HPP
#define BOOST_MINMAX_HPP
+/*
+ * These macros by Eric Niebler should move into a config file.
+ * I'll leave them for now, until Eric sees fit to remove them.
+ */
+
#include © Copyright Hervé
+Brönnimann, Polytechnic University, 2002--2004. Permission to copy, use,
+modify, sell and distribute this software and its documentation is granted
+provided this copyright notice appears in all copies. This software and
+its documentation is provided "as is" without express or implied warranty,
+and with no claim as to its suitability for any purpose.
+
+
diff --git a/minmax/doc/minmax_synopsis.html b/minmax/doc/minmax_synopsis.html
new file mode 100644
index 0000000..c0895a5
--- /dev/null
+++ b/minmax/doc/minmax_synopsis.html
@@ -0,0 +1,114 @@
+
+
+ © Copyright Hervé
+Brönnimann, Polytechnic University, 2002. Permission to copy, use,
+modify, sell and distribute this software and its documentation is granted
+provided this copyright notice appears in all copies. This software and
+its documentation is provided "as is" without express or implied warranty,
+and with no claim as to its suitability for any purpose.
+
+
diff --git a/minmax/example/Jamfile b/minmax/example/Jamfile
new file mode 100644
index 0000000..75caeed
--- /dev/null
+++ b/minmax/example/Jamfile
@@ -0,0 +1,14 @@
+# Boost.Minmax Library Example Jamfile
+#
+# Copyright (C) 2002--2004, Herve Bronnimann
+#
+# Use, modification, and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+subproject libs/minmax/example ;
+
+exe minmax_ex : minmax_ex.cpp ;
+exe minmax_timer : minmax_timer.cpp ;
+
diff --git a/minmax/example/minmax_ex.cpp b/minmax/example/minmax_ex.cpp
new file mode 100644
index 0000000..2ac9109
--- /dev/null
+++ b/minmax/example/minmax_ex.cpp
@@ -0,0 +1,23 @@
+#include The minmax library is composed of a single header <boost/minmax.hpp>.
+I always thought it is a waste to have to call two functions to compute the
+extent of a range, performing two passes over the input, when one should
+be enough. The first part implements the function templates
+minmax
+and minmax_element as straightforward extensions of the C++
+standard. (Please note: the intent is not to fix the known defaults of
+std::min
+and std::max, but to add one more algorithms that combines both; see the
+rationale.) The second part proposes variants that can usually not be computed by
+the minmax algorithm, and which are more flexible in case some elements are equal.
+Those variants could have been also provided with policy-based design,
+but I ruled against that (see rationale).
+ If you are interested about
+performance,
+you will see that minmax_element is just slightly less efficient
+than a single min_element or max_element, and thus
+twice as efficient as two separate calls to min_element and
+max_element. From a
+theoretical standpoint,
+all the minmax_element functions perform at most
+3n/2+1
+comparisons and exactly n increments of the
+ForwardIterator. The minmax_element is semantically equivalent to first_min_first_max_element.
+ First_min_element and first_max_element find the smallest
+and largest elements in the range [first, last). If there are
+several instance of these elements, the first one is returned. They are
+identical to
+std::min_element and std::max_elementand
+are only included in this library for symmetry.
+ Last_min_element and last_max_element find the smallest
+and largest elements in the range [first, last). They are almost
+identical to
+std::min_element and std::max_element, except
+that they return the last instance of the largest element (and not the
+first, as first_min_element and last_max_element would).
+ The family of algorithms comprising first_min_first_max_element,
+first_min_first_max_element,
+first_min_first_max_element,
+and first_min_first_max_element can be described generically as
+follows (using which and
+what for first
+or last): which_min_what_max_element finds
+the (first or last, according to which) smallest element
+and the (first or last, according to what) largest element
+in the range
+[first, last). The first version is semantically
+equivalent to:
+ For all the other function templates, versions with two template parameters:
+ The complexity of all the other algorithms is linear. They all perform
+exactly n increment operations, and zero comparisons if [first,last)
+is empty, otherwise :
+ [2] These algorithms always
+perform at least 3n/2-2 comparisons, which is a lower bound on
+the number of comparisons in any case (Cormen, Leiserson, Rivest: "Introduction
+to Algorithms", section 9.1, Exercise 9.1-). The algorithms essentially compare
+the elements in pairs, performing 1 comparison for the first two elements,
+then 3 comparisons for each remaining pair of elements (one to order the
+elements and one for updating each the minimum and and the maximum). When
+the number of elements is odd, the last one needs to be compared to the
+current minimum and also to the current maximum. In addition, for minmax,
+in cases where equality of the two members in the pair could occur, and
+the update stores the second, we save the first to check at the end if
+the update should have stored the first (in case of equality). It's hard
+to predict if the last comparison is performed or not, hence the at most
+in both cases.
+ [3] These algorithms always
+perform at least 3n/2-2 comparisons, which is a lower bound on
+the number of comparisons in any case. The method is the same as in note
+[2]
+above, and like above, when the number of elements is odd, the last one
+needs to be compared to the current minimum and also to the current maximum.
+We can avoid the latter comparison if the former is successful, hence the
+at
+most instead of exactly in the odd case.
+
+
+
+ I am aware of the problems with std::min and
+std::max, and all the debate that has been going on (please consult
+Alexandrescu's
+paper and the links therein). But I don't see the purpose of this
+library as fixing something that is part of the C++ standard. I humbly
+think it's beyond the scope of this library. Rather, I am
+following the way of the standard in simply providing one more function
+of the same family. If someone else wants to fix std::min, their fix
+would probably apply to boost::minmax as well. In a first version of the library, I proposed _if versions of
+all the algorithms (well, not all, because that would be too much).
+However, there is simply no reason to do so, and all the versions I had
+were just as fast implemented using the excellent
+<boost/iterator_adaptors.hpp> library. Namely, a call to
+min_element_if(first, last, pred) would be just as well
+implemented by:
+
+Minmax_element Performance
+About performance
+Of course, there are many factors that affect the performance of an algorithm.
+The number of comparison is only one, but also branch prediction, pipelining,
+locality of reference (affects cache efficiency), etc. In practice,
+we observe that when the iterator type is a pointer,
+boost::minmax_element
+is only a tad slower than
+std::min_element, and is even faster
+than
+boost::first_min_last_max_element! This is even more true
+for slower iterators (list<>::iterator or
+map<>iterator
+for instance). The following experiments were conducted on a Pentium III
+500 Mhz running Linux and compiled with g++, version 2.95.2, flags -O3.
+In the tables, we use different distributions: Identical means that
+all the elements are identical, 2-valued means that we replace the
+second half of the identical elements by a distinct element, increasing
+means that all the elements are distinct and in increasing order, decreasing
+is the reverse, and random is produced by random_shuffle.
+
+The program that created these tables is included in the distribution,
+under minmax_timer.cpp
+
+
+
+
+
+vector<int>::iterator
+
+Identical
+
+2-valued
+
+Increasing
+
+Decreasing
+
+Random
+
+
+
+std::min_element
+
+23.26M/s
+
+23.26M/s
+
+23.15M/s
+
+22.94M/s
+
+22.94M/s
+
+
+
+std::max_element
+
+23.26M/s
+
+23.26M/s
+
+23.15M/s
+
+22.94M/s
+
+22.62M/s
+
+
+
+boost::first_min_element
+
+23.15M/s
+
+23.04M/s
+
+23.04M/s
+
+22.94M/s
+
+22.83M/s
+
+
+
+boost::last_min_element
+
+23.26M/s
+
+23.26M/s
+
+23.26M/s
+
+22.83M/s
+
+16.23M/s
+
+
+
+boost::first_max_element
+
+23.15M/s
+
+23.26M/s
+
+23.15M/s
+
+23.04M/s
+
+22.93M/s
+
+
+
+boost::last_max_element
+
+23.26M/s
+
+23.15M/s
+
+23.15M/s
+
+22.94M/s
+
+16.18M/s
+
+
+
+boost::minmax_element
+
+21.83M/s
+
+21.83M/s
+
+21.83M/s
+
+21.55M/s
+
+17.79M/s
+
+
+
+boost::first_min_last_max_element
+
+18.52M/s
+
+18.38M/s
+
+18.38M/s
+
+18.94M/s
+
+16.29M/s
+
+
+
+boost::last_min_first_max_element
+
+20.08M/s
+
+20.83M/s
+
+20.75M/s
+
+19.76M/s
+
+15.87M/s
+
+
+
+boost::last_min_last_max_element
+
+18.66M/s
+
+19.69M/s
+
+19.69M/s
+
+19.23M/s
+
+15.77M/s
+
+
+
+
+list<int>::iterator
+
+Identical
+
+2-valued
+
+Increasing
+
+Decreasing
+
+Random
+
+
+
+std::min_element
+
+5.8M/s
+
+5.8M/s
+
+5.80M/s
+
+5.73M/s
+
+5.73M/s
+
+
+
+std::max_element
+
+5.81M/s
+
+5.81M/s
+
+5.78M/s
+
+5.73M/s
+
+5.75M/s
+
+
+
+boost::first_min_element
+
+5.81M/s
+
+5.81M/s
+
+5.79M/s
+
+5.75M/s
+
+5.73M/s
+
+
+
+boost::last_min_element
+
+5.81M/s
+
+5.80M/s
+
+5.79M/s
+
+5.73M/s
+
+5.03M/s
+
+
+
+boost::first_max_element
+
+5.81M/s
+
+5.80M/s
+
+5.78M/s
+
+5.74M/s
+
+5.73M/s
+
+
+
+boost::last_max_element
+
+5.81M/s
+
+5.80M/s
+
+5.79M/s
+
+5.73M/s
+
+5.07M/s
+
+
+
+boost::minmax_element
+
+5.68M/s
+
+5.80M/s
+
+5.66M/s
+
+5.74M/s
+
+5.30M/s
+
+
+
+boost::first_min_last_max_element
+
+5.79M/s
+
+5.81M/s
+
+5.78M/s
+
+5.73M/s
+
+5.04M/s
+
+
+
+boost::last_min_first_max_element
+
+5.69M/s
+
+5.79M/s
+
+5.69M/s
+
+5.73M/s
+
+4.84M/s
+
+
+
+boost::last_min_last_max_element
+
+5.61M/s
+
+5.79M/s
+
+5.64M/s
+
+5.74M/s
+
+4.75M/s
+
+
+
+
+multiset<int>::iterator
+
+Identical
+
+2-valued
+
+Increasing
+
+Decreasing
+
+Random
+
+
+
+std::min_element
+
+4.03M/s
+
+4.04M/s
+
+4.02M/s
+
+4.04M/s
+
+2.97M/s
+
+
+
+std::max_element3.007M
+
+4.02M/s
+
+4.02M/s
+
+4.01M/s
+
+4.02M/s
+
+2.96M/s
+
+
+
+boost::first_min_element
+
+4.01M/s
+
+4.04M/s
+
+4.03M/s
+
+4.04M/s
+
+3.01M/s
+
+
+
+boost::last_min_element
+
+4.03M/s
+
+4.04M/s
+
+4.04M/s
+
+4.04M/s
+
+3.00M/s
+
+
+
+boost::first_max_element
+
+4.04M/s
+
+4.04M/s
+
+4.04M/s
+
+4.06M/s
+
+3.01M/s
+
+
+
+boost::last_max_element
+
+4.04M/s
+
+4.04M/s
+
+4.03M/s
+
+4.04M/s
+
+3.00M/s
+
+
+
+boost::minmax_element
+
+3.98M/s
+
+3.99M/s
+
+3.98M/s
+
+3.99M/s
+
+3.00M/s
+
+
+
+boost::first_min_last_max_element
+
+3.99M/s
+
+3.98M/s
+
+3.97M/s
+
+3.99M/s
+
+2.99M/s
+
+
+
+boost::last_min_first_max_element
+
+3.97M/s
+
+3.98M/s
+
+3.96M/s
+
+3.98M/s
+
+3.00M/s
+
+
+
+boost::last_min_last_max_element
+
+4.00M/s
+
+4.00M/s
+
+4.00M/s
+
+4.02M/s
+
+2.97M/s
+
+
Last modified 2004-06-28
+
+Minmax_element
+Synopsis
+
+namespace boost {
+
+ template <class T>
+ std::pair<const T&,const T&>
+ minmax(const T& a, const T& b);
+
+ template <class T, class BinaryPredicate>
+ std::pair<const T&,const T&>
+ minmax(const T& a, const T& b, BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ minmax_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ minmax_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+
+ template <class ForwardIterator>
+ ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ first_min_first_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ first_min_first_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ first_min_last_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ first_min_last_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ last_min_first_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ last_min_first_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ last_min_last_max_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ last_min_last_max_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+}
+
+
+
Last modified 2002-05-09
+
+#include
+#include
");
+ test_container< std::multiset
+
+Header <boost/minmax.hpp>
+
+Motivation
+
+
+
+
+Synopsis
+Function templates description
+Definition
+Requirements on types
+Preconditions
+Postconditions
+Complexity
+Example
+Notes
+Rationale
+Note about performance
+Acknowledgements
+
+
+Motivation
+
+
+Synopsis
+
+namespace boost {
+
+ // Minmax
+
+ template <class T>
+ std::pair<const T&,const T&>
+ minmax(const T& a, const T& b);
+
+ template <class T, class BinaryPredicate>
+ std::pair<const T&,const T&>
+ minmax(const T& a, const T& b, BinaryPredicate comp);
+
+ // Minmax_element
+
+ template <class ForwardIterator>
+ std::pair<ForwardIterator,ForwardIterator>
+ minmax_element(ForwardIterator first, ForwardIterator last);
+
+ template <class ForwardIterator, class BinaryPredicate>
+ std::pair<ForwardIterator,ForwardIterator>
+ minmax_element(ForwardIterator first, ForwardIterator last,
+ BinaryPredicate comp);
+
+}
+
+
+In addition, there are a bunch of extensions which specify
+which element(s) you want to pick in case of equal elements. They are:
+
+
+I won't bore you with the complete synopsis, they have exactly the same
+declaration as their corresponding _element function. Still,
+you can find the complete synopsis here.
+
+Function templates description
+The minmax algorithm returns a pair p containing either
+(a,b)
+or (b,a), such that p.first<p.second in the first version,
+or comp(p.first,p.second) in the second version. If the elements
+are equivalent, the pair (a,b) is returned. [1]
+ std::make_pair(boost::which_min_element(first,last),
+ boost::what_max_element(first,last)),
+and the second version to:
+ std::make_pair(boost::which_min_element(first,last,comp),
+ boost::what_max_element(first,last,comp)).
+
+
Note: the first_min_last_max_element can also be described
+as finding the first and last elements in the range if it were stably sorted.
+
+Definition
+Defined in minmax.hpp.
+
+Requirements on types
+For minmax, T must be a model of LessThan
+Comparable.
+
+
+For the versions with three template parameters:
+
+
+
+
+
+
+Preconditions
+
+
+
+
+
+
+
+Postconditions
+In addition to the semantic description above. for minmax_element
+and all the which_min_what_max_element
+variants, the return value is
+last or std::make_pair(last,last)
+if and only if [first, last) is an empty range. Otherwise, the
+return value or both members of the resulting pair are iterators in the
+range
+[first, last).
+
+
+
+
+Complexity
+Minmax performs a single comparison and is otherwise of constant complexity.
+
+
+where n is the number of elements in [first,last).
+
+
+
+
+Example
+This example is included in the distribution in the examples section of
+the library under
+minmax_ex.cpp.
+
+int main()
+{
+ using namespace std;
+ list<int> L;
+ generate_n(front_inserter(L), 1000, rand);
+
+ typedef list<int>::const_iterator iterator;
+ pair< iterator, iterator > result = boost::minmax_element(L.begin(), L.end());
+ cout << "The smallest element is " << *(result.first) << endl;
+ cout << "The largest element is " << *(result.second) << endl;
+ assert( result.first == std::min_element(L.begin(), L.end());
+ assert( result.second == std::max_element(L.begin(), L.end());
+}
+
+
+
+
+Notes
+[1] It is not recommended to use
+idioms such as tie(a,b)=minmax(a,b)
+to order two elements a, b, although this would have
+the desired effect. The reason is that two unnecessary assignments are
+performed if a and b are in order. It is better to stick to if (b<a)
+swap(a,b) to achieve that effect.
+
+Rationale:
+
+
+Your minmax suffers from the same problems as std::min and
+std::max.
+Why no min/max_element_if?
+
+ // equivalent to min_element_if(first, last, pred)
+ min_element(boost::make_filter_iterator(first, last, pred),
+ boost::make_filter_iterator(last, last, pred));
+
+Arguably, the min_element_if version is somewhat shorter, but
+the overhead of iterator adaptors is not large, and they get rid of a
+lot of code (think of all the combinations between first/last and
+doubling them with _if variants!).
This rationale is somewhat historical, but explains why there are all +these first/last_min/max_element functions.
+The C++ standard mandates that std::min_element and std::max_element +return the first instance of the smallest and largest elements (as opposed +to, say, the last). This arbitrary choice has some consistency: In the +case of v of type vector<int>, for instance, it is true that std::min_element(v.begin(),v.end(),std::less<int>()) +== std::max_element(v.begin(),v.end(),std::greater<int>()). +
There is of course nothing wrong with this: it's simply a matter of +choice. Yet another way to specify min_element and max_element is to define +them as the first and the last elements if the range was stably sorted. +(The stable sort is necessary to disambiguate between iterators +that have the same value.) In that case, min should return the first instance +and max should return the last. Then, both functions are related by +reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less<int>())) +== +std::last_max_element(v.rbegin(),v.rend(),std::greater<int>()). +This definition is subtly different from the previous one.
+The definition problem surfaces when one tries to design a minmax_element, +using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction +to Algorithms", section 9.1). It should be possible to derive an +algorithm using only 3n/2 comparisons if [first,last) has +n +elements, but if one tries to write a function called first_min_first_max_element() +which returns both std::min_element and std::max_element +in a pair, the trivial implementation does not work. The problem, rather +subtly, is about equal elements: I had to think for a while to find a +way to perform only three +comparisons per pair and return the first min and first max elements. +For a long time, it seemed any +attempts at doing so would consume four comparisons per pair in the worst +case. This implementation achieves that.
+It is not possible (or even desirable) to change the meaning of +max_element, +but it is still beneficial to provide a function called minmax_element, +which returns a pair of min_element and max_element. +Although it is easy enough to call min_element and max_element, +this performs +2(n-1) comparisons, and necessitates two +passes over the input. In contrast, +minmax_element will perform +the fewer comparisons and perform a single pass over the input. +The savings can be significant when the iterator type is not a raw pointer, +or even is just a model of the InputIterator concept (although in that +case the interface would have to be +changed, as the return type could not be copied, so one could e.g. +return a value).
+In order to benefit from all the variants of the algorithm, I propose +to introduce both first_min_element and last_min_element, +and their counterparts first_max_element and last_max_element. +Then I also propose all the variants algorithms: first_min_last_max_element +and last_min_first_max_element, which perform only at most 3n/2 +comparisons, and only a single pass on the input. In fact, it can be proven +that computing minmax requires at least 3(n/2)-2 comparisons in +any instance of the problem (Cormen, Leiserson, Rivest, 2nd edition, section +9.1). The implementation I give does not perform unnecessary comparisons +(whose result could have been computed by transitivity from previous +comparisons).
+It appears that first_min_last_max_element may be just a tad +slower than +first_min_element alone, still much less than first_min_element +and +last_max_element called separately. [2] + +
The minmax algorithms are useful in computing the extent of a range. +In computer graphics, we need a bounding box of a set of objects. +In that case the need for a single pass is even more stringent +as all three directions must be done at once. Food for thoughts: there +is matter for a nice generic programming library with stackable update_min +and update_max function objects which store a reference to the +min_resultand +max_result variables, in conjunction with the for_each +algorithm).
+I believe many standard sequential algorithms could be reformulated +with accumulators (and many others, such as in statistics, expectation / +variance / etc.). It seems that there is room for another library, but I +do not see it competing with minmax, rather extending several algorithms +(including minmax) to the accumulator framework. However, I felt it is +beyond the scope of this library to provide such accumulators.
+ + +True, and I could have gone that way, with the default policy for +min_element and max_element to pick the first +occurence of the result. This would have thinned the number of +combinations of the minmax_element variants. But it would also have +meant to change the interface of boost::minmax_element. +One of the goals of the minmax_element algorithm is its +eventual addition to the C++ standard, in connection with +std::min_element and std::max_element +(and I feel that it would be quite natural +given the shortness of the implementation, and the not quite trivial +detail which is needed to get it right). So changing the interface by +adding policies would have meant unfortunately to depart from the +standard and created an obstacle towards that goal. Besides, the code +remains rather readable and simple without policies. So I am quite happy +to keep it like this. +
+ + + +One minmax_element implementation, which performs 3(n/2)+O(log +n) comparisons on the average when the elements are random_shuffled, +was suggested by my student Marc Glisse. The current one, which performs +3(n/2)+1 +comparisons in the worst case, was suggested by John Iacono.
+
Finally, Matthew Wilson and Jeremy Siek contributed pre-review +comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary +Powell participated in the review of the library, managed by Thomas +Witt. In particular, Gennadiy suggested a factorization of the code; +while I haven't followed it all the way, his suggestions do make the +code more readable and still work with older compilers. +All my thanks for the excellent advice and reviews from all. +
© Copyright Hervé
+Brönnimann, Polytechnic University, 2002--2004.
+Use, modification, and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file License_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+
+
diff --git a/minmax/test/Jamfile b/minmax/test/Jamfile
new file mode 100644
index 0000000..735622d
--- /dev/null
+++ b/minmax/test/Jamfile
@@ -0,0 +1,23 @@
+# Boost.Minmax Library Test Jamfile
+#
+# Copyright (C) 2002--2004, Herve Bronnimann
+#
+# Use, modification, and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+subproject libs/minmax/test ;
+
+# bring in rules for testing
+SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
+include testing.jam ;
+
+# Make tests run by default.
+DEPENDS all : test ;
+
+{
+ test-suite minmax:
+ [ run minmax_test.cpp ]
+ ;
+}
diff --git a/minmax/test/Jamfile.v2 b/minmax/test/Jamfile.v2
new file mode 100644
index 0000000..95b1c68
--- /dev/null
+++ b/minmax/test/Jamfile.v2
@@ -0,0 +1,17 @@
+# Boost.Minmax Library test Jamfile
+#
+# Copyright (C) 2002--2004, Herve Bronnimann
+#
+# Use, modification, and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import testing ;
+
+{
+ test-suite minmax:
+ [ run minmax_test.cpp ]
+ ;
+}
+
diff --git a/minmax/test/minmax_test.cpp b/minmax/test/minmax_test.cpp
new file mode 100644
index 0000000..9cc0f59
--- /dev/null
+++ b/minmax/test/minmax_test.cpp
@@ -0,0 +1,241 @@
+#include
+#include