clamp.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. Copyright (c) Marshall Clow 2008-2012.
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. Revision history:
  6. 27 June 2009 mtc First version
  7. 23 Oct 2010 mtc Added predicate version
  8. */
  9. /// \file clamp.hpp
  10. /// \brief Clamp algorithm
  11. /// \author Marshall Clow
  12. ///
  13. /// Suggested by olafvdspek in https://svn.boost.org/trac/boost/ticket/3215
  14. #ifndef BOOST_ALGORITHM_CLAMP_HPP
  15. #define BOOST_ALGORITHM_CLAMP_HPP
  16. #include <functional> // For std::less
  17. #include <iterator> // For std::iterator_traits
  18. #include <cassert>
  19. #include <boost/config.hpp>
  20. #include <boost/range/begin.hpp>
  21. #include <boost/range/end.hpp>
  22. #include <boost/mpl/identity.hpp> // for identity
  23. #include <boost/utility/enable_if.hpp> // for boost::disable_if
  24. namespace boost { namespace algorithm {
  25. /// \fn clamp ( T const& val,
  26. /// typename boost::mpl::identity<T>::type const & lo,
  27. /// typename boost::mpl::identity<T>::type const & hi, Pred p )
  28. /// \return the value "val" brought into the range [ lo, hi ]
  29. /// using the comparison predicate p.
  30. /// If p ( val, lo ) return lo.
  31. /// If p ( hi, val ) return hi.
  32. /// Otherwise, return the original value.
  33. ///
  34. /// \param val The value to be clamped
  35. /// \param lo The lower bound of the range to be clamped to
  36. /// \param hi The upper bound of the range to be clamped to
  37. /// \param p A predicate to use to compare the values.
  38. /// p ( a, b ) returns a boolean.
  39. ///
  40. template<typename T, typename Pred>
  41. BOOST_CXX14_CONSTEXPR T const & clamp ( T const& val,
  42. typename boost::mpl::identity<T>::type const & lo,
  43. typename boost::mpl::identity<T>::type const & hi, Pred p )
  44. {
  45. // assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
  46. return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
  47. }
  48. /// \fn clamp ( T const& val,
  49. /// typename boost::mpl::identity<T>::type const & lo,
  50. /// typename boost::mpl::identity<T>::type const & hi )
  51. /// \return the value "val" brought into the range [ lo, hi ].
  52. /// If the value is less than lo, return lo.
  53. /// If the value is greater than "hi", return hi.
  54. /// Otherwise, return the original value.
  55. ///
  56. /// \param val The value to be clamped
  57. /// \param lo The lower bound of the range to be clamped to
  58. /// \param hi The upper bound of the range to be clamped to
  59. ///
  60. template<typename T>
  61. BOOST_CXX14_CONSTEXPR T const& clamp ( const T& val,
  62. typename boost::mpl::identity<T>::type const & lo,
  63. typename boost::mpl::identity<T>::type const & hi )
  64. {
  65. return boost::algorithm::clamp ( val, lo, hi, std::less<T>());
  66. }
  67. /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
  68. /// std::iterator_traits<InputIterator>::value_type const & lo,
  69. /// std::iterator_traits<InputIterator>::value_type const & hi )
  70. /// \return clamp the sequence of values [first, last) into [ lo, hi ]
  71. ///
  72. /// \param first The start of the range of values
  73. /// \param last One past the end of the range of input values
  74. /// \param out An output iterator to write the clamped values into
  75. /// \param lo The lower bound of the range to be clamped to
  76. /// \param hi The upper bound of the range to be clamped to
  77. ///
  78. template<typename InputIterator, typename OutputIterator>
  79. BOOST_CXX14_CONSTEXPR OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
  80. typename std::iterator_traits<InputIterator>::value_type const & lo,
  81. typename std::iterator_traits<InputIterator>::value_type const & hi )
  82. {
  83. // this could also be written with bind and std::transform
  84. while ( first != last )
  85. *out++ = boost::algorithm::clamp ( *first++, lo, hi );
  86. return out;
  87. }
  88. /// \fn clamp_range ( const Range &r, OutputIterator out,
  89. /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
  90. /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
  91. /// \return clamp the sequence of values [first, last) into [ lo, hi ]
  92. ///
  93. /// \param r The range of values to be clamped
  94. /// \param out An output iterator to write the clamped values into
  95. /// \param lo The lower bound of the range to be clamped to
  96. /// \param hi The upper bound of the range to be clamped to
  97. ///
  98. template<typename Range, typename OutputIterator>
  99. BOOST_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
  100. clamp_range ( const Range &r, OutputIterator out,
  101. typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
  102. typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
  103. {
  104. return boost::algorithm::clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
  105. }
  106. /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
  107. /// std::iterator_traits<InputIterator>::value_type const & lo,
  108. /// std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
  109. /// \return clamp the sequence of values [first, last) into [ lo, hi ]
  110. /// using the comparison predicate p.
  111. ///
  112. /// \param first The start of the range of values
  113. /// \param last One past the end of the range of input values
  114. /// \param out An output iterator to write the clamped values into
  115. /// \param lo The lower bound of the range to be clamped to
  116. /// \param hi The upper bound of the range to be clamped to
  117. /// \param p A predicate to use to compare the values.
  118. /// p ( a, b ) returns a boolean.
  119. ///
  120. template<typename InputIterator, typename OutputIterator, typename Pred>
  121. BOOST_CXX14_CONSTEXPR OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
  122. typename std::iterator_traits<InputIterator>::value_type const & lo,
  123. typename std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
  124. {
  125. // this could also be written with bind and std::transform
  126. while ( first != last )
  127. *out++ = boost::algorithm::clamp ( *first++, lo, hi, p );
  128. return out;
  129. }
  130. /// \fn clamp_range ( const Range &r, OutputIterator out,
  131. /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
  132. /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
  133. /// Pred p )
  134. /// \return clamp the sequence of values [first, last) into [ lo, hi ]
  135. /// using the comparison predicate p.
  136. ///
  137. /// \param r The range of values to be clamped
  138. /// \param out An output iterator to write the clamped values into
  139. /// \param lo The lower bound of the range to be clamped to
  140. /// \param hi The upper bound of the range to be clamped to
  141. /// \param p A predicate to use to compare the values.
  142. /// p ( a, b ) returns a boolean.
  143. //
  144. // Disable this template if the first two parameters are the same type;
  145. // In that case, the user will get the two iterator version.
  146. template<typename Range, typename OutputIterator, typename Pred>
  147. BOOST_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
  148. clamp_range ( const Range &r, OutputIterator out,
  149. typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
  150. typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
  151. Pred p )
  152. {
  153. return boost::algorithm::clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );
  154. }
  155. }}
  156. #endif // BOOST_ALGORITHM_CLAMP_HPP