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 <<A 14HREF="../../../boost/algorithm/minmax.hpp">boost/algorithm/minmax.hpp</A>> </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"><boost/algorithm/minmax.hpp></a> 41and <a 42href="../../../boost/algorithm/minmax_element.hpp"><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&</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><boost/algorithm/minmax.hpp></tt></h3> 89 90<pre>#include <boost/tuple/tuple.hpp> 91 92namespace boost { 93 94 template <class T> 95 tuple<T const&, T const&> 96 minmax(const T& a, const T& b); 97 98 template <class T, class <a href="https://www.boost.org/sgi/stl/BinaryPredicate.html">BinaryPredicate</a>> 99 tuple<T const&, T const&> 100 minmax(const T& a, const T& b, BinaryPredicate comp); 101 102} 103</pre> 104 105<h3> 106Synopsis of <tt><boost/algorithm/minmax_element.hpp></tt></h3> 107 108<pre>#include <utility> // for std::pair 109 110namespace boost { 111 112 template <class <a href="https://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a>> 113 std::pair<ForwardIterator,ForwardIterator> 114 minmax_element(ForwardIterator first, ForwardIterator last); 115 116 template <class <a href="https://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="https://www.boost.org/sgi/stl/BinaryPredicate.html">BinaryPredicate</a>> 117 std::pair<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<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_last_max_element</tt>, 162<tt>last_min_first_max_element</tt>, 163and <tt>last_min_last_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="https://www.boost.org/sgi/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="https://www.boost.org/sgi/stl/ForwardIterator.html">Forward 199Iterator</a>.</li> 200 201<li> 202<tt>ForwardIterator</tt>'s value type is <a href="https://www.boost.org/sgi/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="https://www.boost.org/sgi/stl/ForwardIterator.html">Forward 209Iterator</a>.</li> 210 211<li> 212<tt>BinaryPredicate</tt> is a model of <a href="https://www.boost.org/sgi/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> 246Complexity</h3> 247Minmax performs a single comparison and is otherwise of constant complexity. 248The use of <tt>boost::tuple<T const&></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<int const&, int const&> result1 = boost::minmax(1, 0); 284 285 assert( result1.get<0>() == 0 ); 286 assert( result1.get<1>() == 1 ); 287 288 <a href="https://www.boost.org/sgi/stl/List.html">list</a><int> L; 289 <a href="https://www.boost.org/sgi/stl/generate_n.html">generate_n</a>(<a href="https://www.boost.org/sgi/stl/front_insert_iterator.html">front_inserter</a>(L), 1000, rand); 290 291 typedef list<int>::const_iterator iterator; 292 pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end()); 293 cout << "The smallest element is " << *(result2.first) << endl; 294 cout << "The largest element is " << *(result2.second) << 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<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><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="#Alexandrescu">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><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<int>, for instance, it is true that <tt>std::min_element(v.begin(),v.end(),std::less<int>()) 386== std::max_element(v.begin(),v.end(),std::greater<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<int>())) 394== 395std::last_max_element(v.rbegin(),v.rend(),std::greater<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="#Note2">[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> 488 489<a name="Alexandrescu"> 490<a href="http://www.drdobbs.com/generic-min-and-max-redivivus/184403774">Generic: Min and Max Redivivus, by Andrei Alexandrescu</a> 491Dr. Dobbs, April 2001 492 493<p>My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>) 494who had <tt>minmax_element</tt> as an assignment helped clarify the issues, 495and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>. 496The identification of the issue surrounding <tt>max_element</tt> is solely 497my own. 498<p>One <tt>minmax_element</tt> implementation, which performs <tt>3(n/2)+O(log 499n)</tt> comparisons on the average when the elements are <tt>random_shuffle</tt>d, 500was suggested by my student Marc Glisse. The current one, which performs 501<tt>3(n/2)+1</tt> 502comparisons in the worst case, was suggested by John Iacono.<p> 503<p>Finally, Matthew Wilson and Jeremy Siek contributed pre-review 504comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary 505Powell participated in the review of the library, managed by Thomas 506Witt. In particular, Gennadiy suggested a factorization of the code; 507while I haven't followed it all the way, his suggestions do make the 508code more readable and still work with older compilers. 509Late after the review, as I finally scrounged to add the library for a 510release, Eric Niebler noted the bad behavior of <tt>std::pair</tt> for 511<tt>minmax</tt> and suggested to use Boost.tuple instead. 512All my thanks for the excellent advice and reviews from all. 513<h3> 514See also</h3> 515<tt><a href="https://www.boost.org/sgi/stl/min.html">min</a></tt>, <tt><a href="https://www.boost.org/sgi/stl/max.html">max</a></tt>, 516<tt><a href="https://www.boost.org/sgi/stl/min_element.html">min_element</a></tt>, 517<tt><a href="https://www.boost.org/sgi/stl/max_element.html">max_element</a></tt>, 518<tt><a href="https://www.boost.org/sgi/stl/LessThanComparable.html">LessThan 519Comparable</a></tt>, 520<tt><a href="https://www.boost.org/sgi/stl/sort.html">sort</a></tt>, 521<tt><a href="https://www.boost.org/sgi/stl/nth_element.html">nth_element</a></tt> 522. 523<hr SIZE="6"> 524<br>Last modified 2012-12-10 525<p><font face="Arial,Helvetica"><font size=-1>© Copyright Hervé 526Brönnimann, Polytechnic University, 2002--2004. 527Use, modification, and distribution is subject to the Boost Software 528License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at 529<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>) 530</font></font> 531</body> 532</html> 533