index.html 24 KB

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