forked from boostorg/algorithm
Merge branch 'develop'
This commit is contained in:
@ -106,6 +106,16 @@ Generate an increasing series
|
||||
Apply a functor to the elements of a sequence
|
||||
[endsect:for_each_n]
|
||||
|
||||
[section:transform_inclusive_scan transform_inclusive_scan]
|
||||
[*[^[link boost.algorithm.transform_inclusive_scan transform_inclusive_scan] ] ]
|
||||
Transform each element in a range then combine adjacent elements to create an output range. Inclusive scaning means that the nth input is present in the nth output.
|
||||
[endsect:transform_inclusive_scan]
|
||||
|
||||
[section:transform_exclusive_scan transform_exclusive_scan]
|
||||
[*[^[link boost.algorithm.transform_exclusive_scan transform_exclusive_scan] ] ]
|
||||
Transform each element in a range then combine adjacent elements to create an output range. Exclusive scanning means that the nth input is not present in the nth output.
|
||||
[endsect:transform_exclusive_scan]
|
||||
|
||||
[endsect:CXX17_inner_algorithms]
|
||||
|
||||
[endsect:CXX17]
|
||||
@ -234,8 +244,6 @@ Raise a value to an integral power ([^constexpr] since C++14)
|
||||
* [*[^[link header.boost.algorithm.cxx17.exclusive_scan_hpp exclusive_scan] ] ]
|
||||
* [*[^[link header.boost.algorithm.cxx17.inclusive_scan_hpp inclusive_scan] ] ]
|
||||
* [*[^[link header.boost.algorithm.cxx17.reduce_hpp reduce] ] ]
|
||||
* [*[^[link header.boost.algorithm.cxx17.transform_exclusive_scan_hpp transform_exclusive_scan] ] ]
|
||||
* [*[^[link header.boost.algorithm.cxx17.transform_inclusive_scan_hpp transform_inclusive_scan] ] ]
|
||||
* [*[^[link header.boost.algorithm.cxx17.transform_reduce_hpp transform_reduce] ] ]
|
||||
|
||||
[endsect:not_yet_documented_cxx17_algos]
|
||||
|
@ -26,14 +26,14 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/mpl/identity.hpp> // for identity
|
||||
#include <boost/utility/enable_if.hpp> // for boost::disable_if
|
||||
#include <boost/type_traits/type_identity.hpp> // for boost::type_identity
|
||||
#include <boost/utility/enable_if.hpp> // for boost::disable_if
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn clamp ( T const& val,
|
||||
/// typename boost::mpl::identity<T>::type const & lo,
|
||||
/// typename boost::mpl::identity<T>::type const & hi, Pred p )
|
||||
/// typename boost::type_identity<T>::type const & lo,
|
||||
/// typename boost::type_identity<T>::type const & hi, Pred p )
|
||||
/// \return the value "val" brought into the range [ lo, hi ]
|
||||
/// using the comparison predicate p.
|
||||
/// If p ( val, lo ) return lo.
|
||||
@ -48,8 +48,8 @@ namespace boost { namespace algorithm {
|
||||
///
|
||||
template<typename T, typename Pred>
|
||||
BOOST_CXX14_CONSTEXPR T const & clamp ( T const& val,
|
||||
typename boost::mpl::identity<T>::type const & lo,
|
||||
typename boost::mpl::identity<T>::type const & hi, Pred p )
|
||||
typename boost::type_identity<T>::type const & lo,
|
||||
typename boost::type_identity<T>::type const & hi, Pred p )
|
||||
{
|
||||
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
|
||||
return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
|
||||
@ -57,8 +57,8 @@ namespace boost { namespace algorithm {
|
||||
|
||||
|
||||
/// \fn clamp ( T const& val,
|
||||
/// typename boost::mpl::identity<T>::type const & lo,
|
||||
/// typename boost::mpl::identity<T>::type const & hi )
|
||||
/// typename boost::identity<T>::type const & lo,
|
||||
/// typename boost::identity<T>::type const & hi )
|
||||
/// \return the value "val" brought into the range [ lo, hi ].
|
||||
/// If the value is less than lo, return lo.
|
||||
/// If the value is greater than "hi", return hi.
|
||||
@ -70,8 +70,8 @@ namespace boost { namespace algorithm {
|
||||
///
|
||||
template<typename T>
|
||||
BOOST_CXX14_CONSTEXPR T const& clamp ( const T& val,
|
||||
typename boost::mpl::identity<T>::type const & lo,
|
||||
typename boost::mpl::identity<T>::type const & hi )
|
||||
typename boost::type_identity<T>::type const & lo,
|
||||
typename boost::type_identity<T>::type const & hi )
|
||||
{
|
||||
return boost::algorithm::clamp ( val, lo, hi, std::less<T>());
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/type_identity.hpp> // for boost::type_identity
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
@ -127,7 +127,7 @@ namespace boost { namespace algorithm {
|
||||
/// \param p A binary predicate that returns true if two elements are ordered.
|
||||
///
|
||||
template <typename R, typename Pred>
|
||||
BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same<R, Pred>::value, boost::mpl::identity<bool> >::type
|
||||
BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same<R, Pred>::value, boost::type_identity<bool> >::type
|
||||
is_sorted ( const R &range, Pred p )
|
||||
{
|
||||
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p );
|
||||
|
@ -22,6 +22,21 @@
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn transform_exclusive_scan ( InputIterator first, InputIterator last, OutputIterator result, BinaryOperation bOp, UnaryOperation uOp, T init )
|
||||
/// \brief Transforms elements from the input range with uOp and then combines
|
||||
/// those transformed elements with bOp such that the n-1th element and the nth
|
||||
/// element are combined. Exclusivity means that the nth element is not
|
||||
/// included in the nth combination.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last The end of the input sequence
|
||||
/// \param result The output iterator to write the results into
|
||||
/// \param bOp The operation for combining transformed input elements
|
||||
/// \param uOp The operation for transforming input elements
|
||||
/// \param init The initial value
|
||||
///
|
||||
/// \note This function is part of the C++17 standard library
|
||||
template<class InputIterator, class OutputIterator, class T,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,
|
||||
|
@ -22,6 +22,21 @@
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn transform_inclusive_scan ( InputIterator first, InputIterator last, OutputIterator result, BinaryOperation bOp, UnaryOperation uOp, T init )
|
||||
/// \brief Transforms elements from the input range with uOp and then combines
|
||||
/// those transformed elements with bOp such that the n-1th element and the nth
|
||||
/// element are combined. Inclusivity means that the nth element is included in
|
||||
/// the nth combination.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last The end of the input sequence
|
||||
/// \param result The output iterator to write the results into
|
||||
/// \param bOp The operation for combining transformed input elements
|
||||
/// \param uOp The operation for transforming input elements
|
||||
/// \param init The initial value
|
||||
///
|
||||
/// \note This function is part of the C++17 standard library
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation, class T>
|
||||
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
@ -37,6 +52,20 @@ OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \fn transform_inclusive_scan ( InputIterator first, InputIterator last, OutputIterator result, BinaryOperation bOp, UnaryOperation uOp, T init )
|
||||
/// \brief Transforms elements from the input range with uOp and then combines
|
||||
/// those transformed elements with bOp such that the n-1th element and the nth
|
||||
/// element are combined. Inclusivity means that the nth element is included in
|
||||
/// the nth combination. The first value will be used as the init.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last The end of the input sequence
|
||||
/// \param result The output iterator to write the results into
|
||||
/// \param bOp The operation for combining transformed input elements
|
||||
/// \param uOp The operation for transforming input elements
|
||||
///
|
||||
/// \note This function is part of the C++17 standard library
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
|
72
include/boost/algorithm/is_clamped.hpp
Normal file
72
include/boost/algorithm/is_clamped.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) Ivan Matek, Marshall Clow 2021.
|
||||
|
||||
Distributed under 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)
|
||||
|
||||
*/
|
||||
|
||||
/// \file is_clamped.hpp
|
||||
/// \brief IsClamped algorithm
|
||||
/// \authors Ivan Matek, Marshall Clow
|
||||
///
|
||||
|
||||
#ifndef BOOST_ALGORITHM_IS_CLAMPED_HPP
|
||||
#define BOOST_ALGORITHM_IS_CLAMPED_HPP
|
||||
|
||||
#include <functional> // for std::less
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/type_traits/type_identity.hpp> // for boost::type_identity
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn is_clamped ( T const& val,
|
||||
/// typename boost::type_identity<T>::type const & lo,
|
||||
/// typename boost::type_identity<T>::type const & hi, Pred p )
|
||||
/// \returns true if value "val" is in the range [ lo, hi ]
|
||||
/// using the comparison predicate p.
|
||||
/// If p ( val, lo ) return false.
|
||||
/// If p ( hi, val ) return false.
|
||||
/// Otherwise, returns true.
|
||||
///
|
||||
/// \param val The value to be checked
|
||||
/// \param lo The lower bound of the range
|
||||
/// \param hi The upper bound of the range
|
||||
/// \param p A predicate to use to compare the values.
|
||||
/// p ( a, b ) returns a boolean.
|
||||
///
|
||||
template <typename T, typename Pred>
|
||||
BOOST_CXX14_CONSTEXPR bool is_clamped(
|
||||
T const& val, typename boost::type_identity<T>::type const& lo,
|
||||
typename boost::type_identity<T>::type const& hi, Pred p) {
|
||||
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they
|
||||
// might be equal
|
||||
return p(val, lo) ? false : p(hi, val) ? false : true;
|
||||
}
|
||||
|
||||
/// \fn is_clamped ( T const& val,
|
||||
/// typename boost::type_identity<T>::type const & lo,
|
||||
/// typename boost::type_identity<T>::type const & hi)
|
||||
/// \returns true if value "val" is in the range [ lo, hi ]
|
||||
/// using operator < for comparison.
|
||||
/// If the value is less than lo, return false.
|
||||
/// If the value is greater than hi, return false.
|
||||
/// Otherwise, returns true.
|
||||
///
|
||||
/// \param val The value to be checked
|
||||
/// \param lo The lower bound of the range
|
||||
/// \param hi The upper bound of the range
|
||||
///
|
||||
|
||||
template<typename T>
|
||||
BOOST_CXX14_CONSTEXPR bool is_clamped ( const T& val,
|
||||
typename boost::type_identity<T>::type const & lo,
|
||||
typename boost::type_identity<T>::type const & hi )
|
||||
{
|
||||
return boost::algorithm::is_clamped ( val, lo, hi, std::less<T>());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_CLAMP_HPP
|
@ -40,10 +40,18 @@ namespace boost {
|
||||
// Protected construction/destruction
|
||||
|
||||
// Default constructor
|
||||
find_iterator_base() {}
|
||||
BOOST_DEFAULTED_FUNCTION(find_iterator_base(), {})
|
||||
|
||||
// Copy construction
|
||||
find_iterator_base( const find_iterator_base& Other ) :
|
||||
BOOST_DEFAULTED_FUNCTION(find_iterator_base( const find_iterator_base& Other ), :
|
||||
m_Finder(Other.m_Finder) {}
|
||||
)
|
||||
|
||||
// Assignment
|
||||
BOOST_DEFAULTED_FUNCTION(find_iterator_base& operator=( const find_iterator_base& Other ), {
|
||||
m_Finder = Other.m_Finder;
|
||||
return *this;
|
||||
})
|
||||
|
||||
// Constructor
|
||||
template<typename FinderT>
|
||||
@ -51,7 +59,7 @@ namespace boost {
|
||||
m_Finder(Finder) {}
|
||||
|
||||
// Destructor
|
||||
~find_iterator_base() {}
|
||||
BOOST_DEFAULTED_FUNCTION(~find_iterator_base(), {})
|
||||
|
||||
// Find operation
|
||||
match_type do_find(
|
||||
|
@ -74,7 +74,7 @@ namespace boost {
|
||||
|
||||
\post eof()==true
|
||||
*/
|
||||
find_iterator() {}
|
||||
BOOST_DEFAULTED_FUNCTION(find_iterator(), {})
|
||||
|
||||
//! Copy constructor
|
||||
/*!
|
||||
@ -85,6 +85,18 @@ namespace boost {
|
||||
m_Match(Other.m_Match),
|
||||
m_End(Other.m_End) {}
|
||||
|
||||
//! Copy assignment
|
||||
/*!
|
||||
Assigns a copy of the find_iterator
|
||||
*/
|
||||
BOOST_DEFAULTED_FUNCTION(find_iterator& operator=( const find_iterator& Other ), {
|
||||
if (this == &Other) return *this;
|
||||
this->base_type::operator=(Other);
|
||||
m_Match = Other.m_Match;
|
||||
m_End = Other.m_End;
|
||||
return *this;
|
||||
})
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
Construct new find_iterator for a given finder
|
||||
@ -248,6 +260,20 @@ namespace boost {
|
||||
m_bEof(Other.m_bEof)
|
||||
{}
|
||||
|
||||
//! Assignment operator
|
||||
/*!
|
||||
Assigns a copy of the split_iterator
|
||||
*/
|
||||
BOOST_DEFAULTED_FUNCTION(split_iterator& operator=( const split_iterator& Other ), {
|
||||
if (this == &Other) return *this;
|
||||
this->base_type::operator=(Other);
|
||||
m_Match = Other.m_Match;
|
||||
m_Next = Other.m_Next;
|
||||
m_End = Other.m_End;
|
||||
m_bEof = Other.m_bEof;
|
||||
return *this;
|
||||
})
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
Construct new split_iterator for a given finder
|
||||
|
@ -29,6 +29,7 @@ alias unit_test_framework
|
||||
|
||||
# Misc tests
|
||||
[ run clamp_test.cpp unit_test_framework : : : : clamp_test ]
|
||||
[ run is_clamped_test.cpp unit_test_framework : : : : is_clamped_test ]
|
||||
[ run power_test.cpp unit_test_framework : : : : power_test ]
|
||||
[ compile-fail power_fail1.cpp : : : : ]
|
||||
|
||||
|
246
test/is_clamped_test.cpp
Normal file
246
test/is_clamped_test.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// (C) Copyright Ivan Matek, Marshall Clow 2021.
|
||||
// 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)
|
||||
|
||||
#include <boost/algorithm/is_clamped.hpp>
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#ifdef __cpp_impl_three_way_comparison
|
||||
#if __has_include(<compare>)
|
||||
#define BOOST_IS_CLAMPED_TEST_SPACESHIP
|
||||
#endif
|
||||
#ifdef BOOST_IS_CLAMPED_TEST_SPACESHIP
|
||||
#include <compare>
|
||||
#endif
|
||||
#endif
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
BOOST_CONSTEXPR bool intGreater(int lhs, int rhs) { return lhs > rhs; }
|
||||
|
||||
class custom {
|
||||
public:
|
||||
custom(int x) : v(x) {}
|
||||
custom(const custom &rhs) : v(rhs.v) {}
|
||||
|
||||
bool operator<(const custom &rhs) const { return v < rhs.v; }
|
||||
bool operator==(const custom &rhs) const {
|
||||
return v == rhs.v;
|
||||
} // need this for the test
|
||||
int v;
|
||||
};
|
||||
|
||||
static bool customLess(const custom &lhs, const custom &rhs) { return lhs.v < rhs.v; }
|
||||
|
||||
void test_ints() {
|
||||
// Inside the range, equal to the endpoints, and outside the endpoints.
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 3, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 6, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 7, 1, 6 ));
|
||||
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 3, 6, 1, intGreater ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1, 6, 1, intGreater ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 6, 6, 1, intGreater ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0, 6, 1, intGreater ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 7, 6, 1, intGreater ));
|
||||
|
||||
// Negative numbers
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( -3, -6, -1 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( -1, -6, -1 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( -6, -6, -1 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0, -6, -1 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( -7, -6, -1 ));
|
||||
|
||||
// Mixed positive and negative numbers
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1, -5, 5 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( -5, -5, 5 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 5, -5, 5 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( -6, -5, 5 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 6, -5, 5 ));
|
||||
|
||||
// Unsigned
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 5U, 1U, 6U ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1U, 1U, 6U ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 6U, 1U, 6U ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0U, 1U, 6U ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 8U, 1U, 6U ));
|
||||
|
||||
// Mixed (1)
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 5U, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1U, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 6U, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0U, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 8U, 1, 6 ));
|
||||
|
||||
// Mixed (2)
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 5U, 1, 6. ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 1U, 1, 6. ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 6U, 1, 6. ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0U, 1, 6. ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 8U, 1, 6. ));
|
||||
|
||||
// float->short conversion does not round
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( 50, 50.999, 100 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 50, 51.001, 100 ));
|
||||
}
|
||||
|
||||
void test_floats() {
|
||||
// If floats are IEEE754 certain floats have exact representations.
|
||||
if (std::numeric_limits<float>::is_iec559) {
|
||||
const float lo = 0.125;
|
||||
const float hi = 0.625;
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( lo, lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( hi, lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( lo + 0.01, lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( lo - 0.01, lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( hi + 0.01, lo, hi ));
|
||||
// If we have nextafterf we can be more precise.
|
||||
#if __cplusplus >= 201103L
|
||||
assert(lo < hi);
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( hi, lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( std::nextafterf( lo, hi ), lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( std::nextafterf( hi, lo ), lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( (lo + hi) / 2, lo, hi ));
|
||||
// 1.0 is just for direction of nextafterf, value of 1.0 is not significant.
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( std::nextafterf( lo, lo - 1.0f ), lo, hi ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( std::nextafterf( hi, hi + 1.0f ), lo, hi ));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void test_std_string() {
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( std::string("a3"), std::string("a1"), std::string("a6") ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( std::string("a1"), std::string("a1"), std::string("a6") ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( std::string("a6"), std::string("a1"), std::string("a6") ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( std::string("a7"), std::string("a1"), std::string("a6") ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( std::string("a0"), std::string("a1"), std::string("a6") ));
|
||||
}
|
||||
|
||||
void test_custom() {
|
||||
// Inside the range, equal to the endpoints, and outside the endpoints.
|
||||
const custom c0(0);
|
||||
const custom c1(1);
|
||||
const custom c3(3);
|
||||
const custom c6(6);
|
||||
const custom c7(7);
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c3, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c1, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c6, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( c0, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( c7, c1, c6 ));
|
||||
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c3, c1, c6, customLess ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c1, c1, c6, customLess ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped ( c6, c1, c6, customLess ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( c0, c1, c6, customLess ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped ( c7, c1, c6, customLess ));
|
||||
}
|
||||
|
||||
void test_point_interval() {
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped(1, 1, 1));
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped(0, 1, 1));
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped(2, 1, 1));
|
||||
}
|
||||
|
||||
void test_first_argument_determines_types() {
|
||||
// all arguments are int
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped(5, 5.9, 6.1));
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped(6, 5.9, 6.1));
|
||||
// all arguments are double
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped(5.0, 5.9, 6.1));
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped(6.2, 5.9, 6.1));
|
||||
}
|
||||
|
||||
void test_constexpr() {
|
||||
#if __cplusplus >= 201402L
|
||||
{
|
||||
constexpr bool is_clamped = (ba::is_clamped ( 3, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL (true, is_clamped );
|
||||
}
|
||||
{
|
||||
constexpr bool is_clamped = (ba::is_clamped ( 1, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL (true, is_clamped );
|
||||
}
|
||||
{
|
||||
constexpr bool is_clamped = (ba::is_clamped ( 6, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL (true, is_clamped );
|
||||
}
|
||||
{
|
||||
constexpr bool is_clamped = (ba::is_clamped ( 0, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL(false, is_clamped );
|
||||
}
|
||||
{
|
||||
constexpr bool is_clamped = (ba::is_clamped ( 7, 1, 6 ));
|
||||
BOOST_CHECK_EQUAL(false, is_clamped );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_IS_CLAMPED_TEST_SPACESHIP
|
||||
struct custom_with_spaceship {
|
||||
int v;
|
||||
auto operator<=>(const custom_with_spaceship&) const = default;
|
||||
};
|
||||
#endif
|
||||
|
||||
void test_spaceship() {
|
||||
#ifdef BOOST_IS_CLAMPED_TEST_SPACESHIP
|
||||
// Inside the range, equal to the endpoints, and outside the endpoints.
|
||||
const custom_with_spaceship c0(0);
|
||||
const custom_with_spaceship c1(1);
|
||||
const custom_with_spaceship c3(3);
|
||||
const custom_with_spaceship c6(6);
|
||||
const custom_with_spaceship c7(7);
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped (c3, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped (c1, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( true, ba::is_clamped (c6, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped (c0, c1, c6 ));
|
||||
BOOST_CHECK_EQUAL ( false, ba::is_clamped (c7, c1, c6 ));
|
||||
{
|
||||
constexpr custom_with_spaceship c1(1);
|
||||
constexpr custom_with_spaceship c3(3);
|
||||
constexpr custom_with_spaceship c6(6);
|
||||
constexpr bool clamped = ba::is_clamped (c3, c1, c6 );
|
||||
BOOST_CHECK_EQUAL ( true, clamped );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_main) {
|
||||
test_ints();
|
||||
test_floats();
|
||||
test_std_string();
|
||||
test_custom();
|
||||
test_point_interval();
|
||||
test_first_argument_determines_types();
|
||||
test_constexpr();
|
||||
test_spaceship();
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
typedef std::tuple<std::uint8_t, std::int8_t, std::uint16_t, std::int16_t,
|
||||
std::int32_t, std::uint32_t, std::int64_t, std::uint64_t> test_types_tuple;
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_extremes, T, test_types_tuple) {
|
||||
const T max = std::numeric_limits<T>::max();
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped( max, max, max ));
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped( max, max - 1, max ));
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped( max - 1, max, max ));
|
||||
|
||||
const T min = std::numeric_limits<T>::min();
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped( min, min, min ));
|
||||
BOOST_CHECK_EQUAL(true, ba::is_clamped( min, min, min + 1 ));
|
||||
BOOST_CHECK_EQUAL(false, ba::is_clamped( min, min + 1, min + 1 ));
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user