Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/algorithm/minmax/index.html @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 23.9 KB
Line 
1<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
2<HTML>
3<HEAD>
4   <LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
5   <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6   <META name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
7   <META name="Author" content="Herve Bronnimann">
8   <META name="Description" content="Small library to propose minmax_element algorithm.">
9   <title>Boost Minmax library</title>
10</HEAD>
11<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
12
13<h2><img src="../../../boost.png" WIDTH="276" HEIGHT="86">Header &lt;<A
14HREF="../../../boost/algorithm/minmax.hpp">boost/algorithm/minmax.hpp</A>&gt; </H2>
15
16<quote>
17<b>
18<a href="#minmax_element">Motivation</a><br>
19<a href="#synopsis">Synopsis</a><br>
20<a href="#description">Function templates description</a><br>
21<a href="#definition">Definition</a><br>
22<a href="#reqs">Requirements on types</a><br>
23<a href="#precond">Preconditions</a><br>
24<a href="#postcond">Postconditions</a><br>
25<a href="#complexity">Complexity</a><br>
26<a href="#example">Example</a><br>
27<a href="#notes">Notes</a><br>
28<a href="#rationale">Rationale</a><br>
29<a href="#perf">Note about performance</a><br>
30<a href="#acks">Acknowledgements</a>
31</b>
32</quote>
33
34
35<a name="minmax_element">
36<h3>
37Motivation</h3>
38
39<p>The minmax library is composed of two headers, <a
40href="../../../boost/algorithm/minmax.hpp">&lt;boost/algorithm/minmax.hpp></a>
41and <a
42href="../../../boost/algorithm/minmax_element.hpp">&lt;boost/algorithm/minmax_element.hpp></a>.
43(See <a href="#two_headers">rationale</a>.)
44The problem solved by this library is that simultaneous min and max
45computation requires
46only one comparison, but using <tt>std::min</tt> and <tt>std::max</tt>
47forces two comparisons. Worse, to compute the minimum and
48maximum elements of a range of <tt>n</tt> elements requires only
49<tt>3n/2+1</tt> comparisons, instead of the <tt>2n</tt> (in two passes)
50forced by <tt>std::min_element</tt> and <tt>std::max_element</tt>.
51I always thought it is a waste to have to call two functions to compute the
52extent of a range, performing two passes over the input, when one should
53be enough. The present library solves both problems.</p>
54
55<p>The first file implements the function templates
56<tt>minmax</tt>
57as straightforward extensions of the C++
58standard. As it returns a pair of <tt>const&amp;</tt>, we must use the <a
59href=:../../../../tuple/index.html>Boost.tuple</a> library to construct such
60pairs. (Please note: the intent is not to fix the known defaults of
61<tt>std::min</tt>
62and <tt>std::max</tt>, but to add one more algorithms that combines both; see the
63<a href="#no-fix">rationale</a>.)</p>
64
65<p>The second file implements the function templates
66<tt>minmax_element</tt>. In a
67second part, it also proposes variants that can usually not be computed by
68the minmax algorithm, and which are more flexible in case some elements are equal.
69Those variants could have been also provided with policy-based design,
70but I ruled against that (see <a href="#no-policy">rationale</a>).
71</p>
72
73<p>If you are interested about
74<a href="doc/minmax_benchs.html">performance</a>,
75you will see that <tt>minmax_element</tt> is just slightly less efficient
76than a single <tt>min_element</tt> or <tt>max_element</tt>, and thus
77twice as efficient as two separate calls to <tt>min_element</tt> and
78<tt>max_element</tt>. From a
79theoretical standpoint,
80all the <tt>minmax_element</tt> functions perform at most
81<tt>3n/2+1</tt>
82comparisons and exactly n increments of the
83<tt>ForwardIterator</tt>.</p>
84</a>
85
86<a name="synopsis">
87<h3>
88Synopsis of <tt>&lt;boost/algorithm/minmax.hpp></tt></h3>
89
90<pre>#include &lt;boost/tuple/tuple.hpp>
91
92namespace boost {
93
94  template &lt;class T>
95  tuple&lt;T const&amp;, T const&amp;> >
96  minmax(const T&amp; a, const T&amp; b);
97
98  template &lt;class T, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
99  tuple&lt;T const&amp;, T const&amp;> >
100  minmax(const T&amp; a, const T&amp; b, BinaryPredicate comp);
101
102}
103</pre>
104
105<h3>
106Synopsis of <tt>&lt;boost/algorithm/minmax_element.hpp></tt></h3>
107
108<pre>#include &lt;utility> // for std::pair
109
110namespace boost {
111
112  template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
113  std::pair&lt;ForwardIterator,ForwardIterator>
114  minmax_element(ForwardIterator first, ForwardIterator last);
115
116  template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
117  std::pair&lt;ForwardIterator,ForwardIterator>
118  minmax_element(ForwardIterator first, ForwardIterator last,
119                 BinaryPredicate comp);
120
121}
122</pre>
123
124In addition, there are a bunch of extensions which specify
125which element(s) you want to pick in case of equal elements. They are:
126<ul>
127<li><tt>first_min_element</tt> and <tt>last_min_element</tt></li>
128<li><tt>first_max_element</tt> and <tt>last_max_element</tt></li>
129<li><tt>first_min_first_max_element</tt>,
130<tt>first_min_last_max_element</tt>,
131<tt>last_min_first_max_element</tt>, and
132<tt>last_min_last_max_element</tt></li>
133</ul>
134I won't bore you with the complete synopsis, they have exactly the same
135declaration as their corresponding <tt>_element</tt> function. Still,
136you can find the complete synopsis <a href="doc/minmax_synopsis.html">here</a>.
137</a>
138
139<a name="description">
140<h3>
141Function templates description</h3>
142The <tt>minmax</tt> algorithm returns a pair <tt>p</tt> containing either
143<i>(a,b)</i>
144or <i>(b,a)</i>, such that <tt>p.first&lt;p.second</tt> in the first version,
145or <tt>comp(p.first,p.second)</tt> in the second version. If the elements
146are equivalent, the pair <i>(a,b) </i>is returned. <a href="#Note1">[1]</a>
147<p>The <tt>minmax_element </tt>is semantically equivalent to <tt>first_min_first_max_element</tt>.
148<p><tt>First_min_element</tt> and <tt>first_max_element</tt> find the smallest
149and largest elements in the range <tt>[first, last)</tt>. If there are
150several instance of these elements, the first one is returned. They are
151identical to
152<tt>std::min_element</tt> and <tt>std::max_element</tt>and
153are only included in this library for symmetry.
154<p><tt>Last_min_element</tt> and <tt>last_max_element</tt> find the smallest
155and largest elements in the range <tt>[first, last)</tt>. They are almost
156identical to
157<tt>std::min_element</tt> and <tt>std::max_element</tt>, except
158that they return the last instance of the largest element (and not the
159first, as <tt>first_min_element</tt> and <tt>last_max_element</tt> would).
160<p>The family of algorithms comprising <tt>first_min_first_max_element</tt>,
161<tt>first_min_first_max_element</tt>,
162<tt>first_min_first_max_element</tt>,
163and <tt>first_min_first_max_element</tt> can be described generically as
164follows (using <i><tt>which</tt></i> and
165<i><tt>what</tt></i> for <tt>first</tt>
166or <tt>last</tt>): <tt><i>which</i>_min_<i>what</i>_max_element</tt> finds
167the (first or last, according to <i><tt>which</tt></i>) smallest element
168and the (first or last, according to <i><tt>what</tt></i>) largest element
169in the range
170<tt>[first, last)</tt>. The first version is semantically
171equivalent to:
172<pre><tt>  std::make_pair(boost::<i>which</i>_min_element(first,last),
173                 boost::<i>what</i>_max_element(first,last))</tt>,</pre>
174and the second version to:
175<pre><tt>  std::make_pair(boost::<i>which</i>_min_element(first,last,comp),
176                 boost::<i>what</i>_max_element(first,last,comp))</tt>.</pre>
177
178<p><br><b><i>Note</i></b>: the <tt>first_min_last_max_element</tt> can also be described
179as finding the first and last elements in the range if it were stably sorted.
180</a>
181
182<a name="definition">
183<h3>
184Definition</h3>
185Defined in <a href="../../../boost/algorithm/minmax.hpp">minmax.hpp</a>
186and
187in <a href="../../../boost/algorithm/minmax_element.hpp">minmax_element.hpp</a>.
188</a>
189
190<a name="reqs">
191<h3>
192Requirements on types</h3>
193For minmax, <tt>T</tt> must be a model of <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
194Comparable</a>.
195<p>For all the other function templates, versions with two template parameters:
196<ul>
197<li>
198<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
199Iterator</a>.</li>
200
201<li>
202<tt>ForwardIterator</tt>'s value type is <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
203Comparable</a>.</li>
204</ul>
205For the versions with three template parameters:
206<ul>
207<li>
208<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
209Iterator</a>.</li>
210
211<li>
212<tt>BinaryPredicate</tt> is a model of <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
213Predicate</a>.</li>
214
215<li>
216<tt>ForwardIterator</tt>'s value type is convertible to <tt>BinaryPredicate</tt>'s
217first argument type and second argument type.</li>
218</ul>
219</a>
220
221<a name="precond">
222<h3>
223Preconditions</h3>
224
225<ul>
226<li>
227<tt>[first, last)</tt> is a valid range.</li>
228</ul>
229</a>
230
231<a name="postcond">
232<h3>
233Postconditions</h3>
234In addition to the semantic description above. for <tt>minmax_element</tt>
235and all the <tt><i>which</i>_min_<i>what</i>_max_element</tt>
236variants, the return value is
237<tt>last</tt> or <tt>std::make_pair(last,last)</tt>
238if and only if <tt>[first, last)</tt> is an empty range. Otherwise, the
239return value or both members of the resulting pair are iterators in the
240range
241<tt>[first, last)</tt>.
242</a>
243
244<a name="complexity">
245<h3>
246<a NAME="Complexity"></a>Complexity</h3>
247Minmax performs a single comparison and is otherwise of constant complexity.
248The use of <tt>boost::tuple&lt;T const&amp;></tt> prevents copy
249constructors in case the arguments are passed by reference.
250<p>The complexity of all the other algorithms is linear. They all perform
251exactly n increment operations, and zero comparisons if <tt>[first,last)</tt>
252is empty, otherwise :
253<ul>
254<li>
255all the <tt>min_element</tt> and <tt>max_element</tt> variants perform
256exactly<tt>(n-1)</tt> comparisons,</li>
257
258<li>
259<tt>minmax_element</tt> , <tt>first_min_first_max_element</tt>, and <tt>last_min_last_max_element</tt>
260perform at most <tt>3(n/2)-1</tt> comparisons if <tt>n</tt> is even and
261non-zero, and at most <tt>3(n/2)+1</tt> if <tt>n</tt> is odd,
262<a href="#Note2">[2]</a></li>
263
264<li>
265<tt>first_min_last_max_element</tt>, and <tt>last_min_first_max_element</tt>
266perform exactly <tt>3n/2-2</tt> comparisons if n is even and non-zero,
267and at most <tt>3(n/2)</tt> if <tt>n</tt> is odd,
268<a href="#Note1">[3]</a></li>
269</ul>
270where <tt>n</tt> is the number of elements in <tt>[first,last)</tt>.
271</a>
272
273<a name="example">
274<h3>
275Example</h3>
276This example is included in the distribution in the examples section of
277the library under
278<a href="example/minmax_ex.cpp">minmax_ex.cpp</a>.
279
280<pre>int main()
281{
282  using namespace std;
283  boost::tuple&lt;int const&amp;, int const&amp;> result1 = boost::minmax(1, 0);
284
285  assert( result1.get<0>() == 0 );
286  assert( result1.get<1>() == 1 );
287
288  <a href="http://www.sgi.com/tech/stl/List.html">list</a>&lt;int> L;
289  <a href="http://www.sgi.com/tech/stl/generate_n.html">generate_n</a>(<a href="http://www.sgi.com/tech/stl/front_insert_iterator.html">front_inserter</a>(L), 1000, rand);
290
291  typedef list&lt;int>::const_iterator iterator;
292  pair&lt; iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
293  cout &lt;&lt; "The smallest element is " &lt;&lt; *(result2.first) &lt;&lt; endl;
294  cout &lt;&lt; "The largest element is  " &lt;&lt; *(result2.second) &lt;&lt; endl;
295
296  assert( result2.first  == std::min_element(L.begin(), L.end());
297  assert( result2.second == std::max_element(L.begin(), L.end());
298}</pre>
299</a>
300
301<a name="notes">
302<h3>
303Notes</h3>
304<a NAME="Note1"></a><a href="#Note1">[1]</a> We do not support
305idioms such as <tt><a href="../../tuple/doc/tuple_users_guide.html#tiers">tie</a>(a,b)=minmax(a,b)</tt>
306to order two elements <tt>a</tt>, <tt>b</tt>, although this would have
307the desired effect if we returned a reference instead of a constant
308reference. The reason is that two unnecessary assignments are
309performed if a and b are in order. It is better to stick to <tt>if (b&lt;a)
310swap(a,b)</tt> to achieve that effect.
311<p><a NAME="Note2"></a><a href="#Note2">[2]</a> These algorithms always
312perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
313the number of comparisons in any case (Cormen, Leiserson, Rivest: "Introduction
314to Algorithms", section 9.1, Exercise 9.1-). The algorithms essentially compare
315the elements in pairs, performing 1 comparison for the first two elements,
316then 3 comparisons for each remaining pair of elements (one to order the
317elements and one for updating each the minimum and and the maximum). When
318the number of elements is odd, the last one needs to be compared to the
319current minimum and also to the current maximum. In addition, for <tt>minmax</tt>,
320in cases where equality of the two members in the pair could occur, and
321the update stores the second, we save the first to check at the end if
322the update should have stored the first (in case of equality). It's hard
323to predict if the last comparison is performed or not, hence the at most
324in both cases.
325<p><a NAME="Note3"></a><a href="#Note3">[3]</a> These algorithms always
326perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
327the number of comparisons in any case. The method is the same as in note
328<a href="#Note2">[2]</a>
329above, and like above, when the number of elements is odd, the last one
330needs to be compared to the current minimum and also to the current maximum.
331We can avoid the latter comparison if the former is successful, hence the
332<i>at
333most</i> instead of <i>exactly</i> in the odd case.
334</a>
335
336<a name="rationale">
337<h3>
338<b>Rationale:</b></h3>
339
340<a name="two_headers">
341<h4><b>Why not a single header <tt>&amp;boost/algorithm/minmax.hpp></tt>?</b></h4>
342<p>This was the design originally proposed and approved in the formal
343review. As the need for Boost.tuple became clear (due to the limitations
344of <tt>std::pair</tt>), it became also annoying to require another
345library for <tt>minmax_element</tt> which does not need it. Hence the
346separation into two header files.</p>
347
348<a name="no-fix">
349<h4><b>Your minmax suffers from the same problems as std::min and
350std::max.</b></h4>
351<p>I am aware of the problems with std::min and
352std::max, and all the debate that has been going on (please consult
353<a href="http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/alexandr.htm">Alexandrescu's paper</a> and the links therein). But I don't see the purpose of this
354library as fixing something that is part of the C++ standard. I humbly
355think it's beyond the scope of this library. Rather, I am
356following the way of the standard in simply providing one more function
357of the same family. If someone else wants to fix std::min, their fix
358would probably apply to boost::minmax as well.</p>
359</a>
360
361<h4><b>Why no <tt>min/max_element_if</tt>?</b></h4>
362<p>In a first version of the library, I proposed <tt>_if</tt> versions of
363all the algorithms (well, not all, because that would be too much).
364However, there is simply no reason to do so, and all the versions I had
365were just as fast implemented using the excellent
366<tt>&lt;boost/iterator_adaptors.hpp></tt> library. Namely, a call to
367<tt>min_element_if(first, last, pred)</tt> would be just as well
368implemented by:
369<pre>
370     // equivalent to min_element_if(first, last, pred)
371     min_element(boost::make_filter_iterator(first, last, pred),
372                 boost::make_filter_iterator(last, last, pred));
373</pre>
374Arguably, the <tt>min_element_if</tt> version is somewhat shorter, but
375the overhead of iterator adaptors is not large, and they get rid of a
376lot of code (think of all the combinations between first/last and
377doubling them with _if variants!).</p>
378
379<h4><b>Discussion: about std::max_element</b></h4>
380<p>This rationale is somewhat historical, but explains why there are all
381these <tt>first/last_min/max_element</tt> functions.</p>
382<p>The C++ standard mandates that <tt>std::min_element</tt> and <tt>std::max_element</tt>
383return the first instance of the smallest and largest elements (as opposed
384to, say, the last). This arbitrary choice has some consistency: In the
385case of v of type vector&lt;int>, for instance, it is true that <tt>std::min_element(v.begin(),v.end(),std::less&lt;int>())
386== std::max_element(v.begin(),v.end(),std::greater&lt;int>())</tt>.
387<p>There is of course nothing wrong with this: it's simply a matter of
388choice. Yet another way to specify min_element and max_element is to define
389them as the first and the last elements if the range was stably sorted.
390(The <i>stable</i> sort is necessary to disambiguate between iterators
391that have the same value.) In that case, min should return the first instance
392and max should return the last. Then, both functions are related by
393<tt>reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less&lt;int>()))
394==
395std::last_max_element(v.rbegin(),v.rend(),std::greater&lt;int>())</tt>.
396This definition is subtly different from the previous one.</p>
397<p>The definition problem surfaces when one tries to design a minmax_element,
398using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction
399to Algorithms", section 9.1). It <i>should</i> be possible to derive an
400algorithm using only <tt>3n/2</tt> comparisons if <tt>[first,last) </tt>has
401<tt>n</tt>
402elements, but if one tries to write a function called <tt>first_min_first_max_element()</tt>
403which returns both <tt>std::min_element</tt> and <tt>std::max_element</tt>
404in a pair, the trivial implementation does not work. The problem, rather
405subtly, is about equal elements: I had to think for a while to find a
406way to perform only three
407comparisons per pair and return the first min and first max elements.
408For a long time, it seemed any
409attempts at doing so would consume four comparisons per pair in the worst
410case. This implementation achieves three.</p>
411<p>It is not possible (or even desirable) to change the meaning of
412<tt>max_element</tt>,
413but it is still beneficial to provide a function called <tt>minmax_element</tt>,
414which returns a pair of <tt>min_element</tt> and <tt>max_element</tt>.
415Although it is easy enough to call <tt>min_element</tt> and <tt>max_element</tt>,
416this performs
417<tt>2(n-1)</tt> comparisons, and necessitates <b>two</b>
418passes over the input. In contrast,
419<tt>minmax_element</tt> will perform
420the fewer comparisons and perform a <b>single</b> pass over the input.
421The savings can be significant when the iterator type is not a raw pointer,
422or even is just a model of the InputIterator concept (although in that
423case the interface would have to be
424changed, as the return type could not be copied, so one could e.g.
425return a value).</p>
426<p>In order to benefit from all the variants of the algorithm, I propose
427to introduce both <tt>first_min_element</tt> and <tt>last_min_element</tt>,
428and their counterparts <tt>first_max_element</tt> and <tt>last_max_element</tt>.
429Then I also propose all the variants algorithms: <tt>first_min_last_max_element</tt>
430and <tt>last_min_first_max_element</tt>, which perform only at most <tt>3n/2</tt>
431comparisons, and only a single pass on the input. In fact, it can be proven
432that computing minmax requires at least <tt>3(n/2)-2</tt> comparisons in
433any instance of the problem (Cormen, Leiserson, Rivest, 2nd edition, section
4349.1). The implementation I give does not perform unnecessary comparisons
435(whose result could have been computed by transitivity from previous
436comparisons).</p>
437<p>It appears that <tt>first_min_last_max_element</tt> may be just a tad
438slower than
439<tt>first_min_element</tt> alone, still much less than <tt>first_min_element</tt>
440and
441<tt>last_max_element</tt> called separately.  <a href="#Performance">[2]</a>
442
443<h4><b>Why algorithms and not accumulators?</b></h4>
444<p>The minmax algorithms are useful in computing the extent of a range.
445In computer graphics, we need a bounding box of a set of objects.
446In that case the need for a single pass is even more stringent
447as all three directions must be done at once. Food for thoughts: there
448is matter for a nice generic programming library with stackable <tt>update_min</tt>
449and <tt>update_max</tt> function objects which store a reference to the
450<tt>min_result</tt>and
451<tt>max_result</tt> variables, in conjunction with the <tt>for_each</tt>
452algorithm).</p>
453<p>I believe many standard sequential algorithms could be reformulated
454with accumulators (and many others, such as in statistics, expectation /
455variance / etc.). It seems that there is room for another library, but I
456do not see it competing with minmax, rather extending several algorithms
457(including minmax) to the accumulator framework. However, I felt it is
458beyond the scope of this library to provide such accumulators.</p>
459
460<a NAME="no-policy">
461<h4><b>This first/last is a perfect application for a policy-based
462design.</b></h4>
463<p>True, and I could have gone that way, with the default policy for
464<tt>min_element</tt> and <tt>max_element</tt> to pick the first
465occurence of the result. This would have thinned the number of
466combinations of the minmax_element variants. But it would also have
467meant to change the interface of <tt>boost::minmax_element</tt>.
468One of the goals of the <tt>minmax_element</tt> algorithm is its
469eventual addition to the C++ standard, in connection with
470<tt>std::min_element</tt> and <tt>std::max_element</tt>
471(and I feel that it would be quite natural
472given the shortness of the implementation, and the not quite trivial
473detail which is needed to get it right). So changing the interface by
474adding policies would have meant unfortunately to depart from the
475standard and created an obstacle towards that goal. Besides, the code
476remains rather readable and simple without policies. So I am quite happy
477to keep it like this.
478</p></a>
479</a>
480
481<a name="perf">
482<a href="doc/minmax_benchs.html"><h3><b>About performance</b></h3></a>
483</a>
484
485<a name="acks">
486<h3>
487Acknowledgements</h3>
488My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
489who had <tt>minmax_element</tt> as an assignment helped clarify the issues,
490and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>.
491The identification of the issue surrounding <tt>max_element</tt> is solely
492my own.
493<p>One <tt>minmax_element</tt> implementation, which performs <tt>3(n/2)+O(log
494n)</tt> comparisons on the average when the elements are <tt>random_shuffle</tt>d,
495was suggested by my student Marc Glisse. The current one, which performs
496<tt>3(n/2)+1</tt>
497comparisons in the worst case, was suggested by John Iacono.<p>
498<p>Finally, Matthew Wilson and Jeremy Siek contributed pre-review
499comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary
500Powell participated in the review of the library, managed by Thomas
501Witt. In particular, Gennadiy suggested a factorization of the code;
502while I haven't followed it all the way, his suggestions do make the
503code more readable and still work with older compilers.
504Late after the review, as I finally scrounged to add the library for a
505release, Eric Niebler noted the bad behavior of <tt>std::pair</tt> for
506<tt>minmax</tt> and suggested to use Boost.tuple instead.
507All my thanks for the excellent advice and reviews from all.
508<h3>
509See also</h3>
510<tt><a href="http://www.sgi.com/tech/stl/min.html">min</a></tt>, <tt><a href="http://www.sgi.com/tech/stl/max.html">max</a></tt>,
511<tt><a href="http://www.sgi.com/tech/stl/min_element.html">min_element</a></tt>,
512<tt><a href="http://www.sgi.com/tech/stl/max_element.html">max_element</a></tt>,
513<tt><a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
514Comparable</a></tt>,
515<tt><a href="http://www.sgi.com/tech/stl/sort.html">sort</a></tt>,
516<tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt>
517.
518<hr SIZE="6">
519<br>Last modified 2004-07-01
520<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
521Br&ouml;nnimann, Polytechnic University, 2002--2004.
522Use, modification, and distribution is subject to the Boost Software
523License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
524<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
525</font></font>
526</body>
527</html>
Note: See TracBrowser for help on using the repository browser.