From 4ad181f464ddaaad63e65e81a47c57b301daac33 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Sat, 31 Jul 2021 21:20:56 +0200 Subject: [PATCH 01/13] Add is_clamped.hpp, is_clamped_test.cpp --- include/boost/algorithm/is_clamped.hpp | 73 ++++++++ test/Jamfile.v2 | 1 + test/is_clamped_test.cpp | 224 +++++++++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 include/boost/algorithm/is_clamped.hpp create mode 100644 test/is_clamped_test.cpp diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp new file mode 100644 index 0000000..a736fba --- /dev/null +++ b/include/boost/algorithm/is_clamped.hpp @@ -0,0 +1,73 @@ +/* + Copyright (c) Marshall Clow 2008-2012. + + 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 +/// \author TODO +/// + +#ifndef BOOST_ALGORITHM_IS_CLAMPED_HPP +#define BOOST_ALGORITHM_IS_CLAMPED_HPP + +#include // For std::less +#include // For std::iterator_traits +#include + +#include // for identity + +namespace boost { namespace algorithm { + +/// \fn is_clamped ( T const& val, +/// typename boost::mpl::identity::type const & lo, +/// typename boost::mpl::identity::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 + BOOST_CXX14_CONSTEXPR bool is_clamped( + T const& val, typename boost::mpl::identity::type const& lo, + typename boost::mpl::identity::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::mpl::identity::type const & lo, +/// typename boost::mpl::identity::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 + BOOST_CXX14_CONSTEXPR bool is_clamped ( const T& val, + typename boost::mpl::identity::type const & lo, + typename boost::mpl::identity::type const & hi ) + { + return boost::algorithm::is_clamped ( val, lo, hi, std::less()); + } + +}} + +#endif // BOOST_ALGORITHM_CLAMP_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e7091e0..5f5e73c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -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 : : : : ] diff --git a/test/is_clamped_test.cpp b/test/is_clamped_test.cpp new file mode 100644 index 0000000..d5ea2b1 --- /dev/null +++ b/test/is_clamped_test.cpp @@ -0,0 +1,224 @@ +// (C) Copyright TODO +// 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 +#include +#include +#include +#ifdef __cpp_impl_three_way_comparison +#include +#endif +#include +#include +#include + +#define BOOST_TEST_MAIN +#include + +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. )); + + short foo = 50; + // float->short conversion does not round + BOOST_CHECK_EQUAL ( true, ba::is_clamped ( foo, 50.999, 100 )); + BOOST_CHECK_EQUAL ( false, ba::is_clamped ( foo, 51.001, 100 )); +} +void test_floats() { + // If floats are IEEE754 certain floats have exact representations. + if (std::numeric_limits::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_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 __cpp_impl_three_way_comparison +struct custom_with_spaceship { + int v; + auto operator<=>(const custom_with_spaceship&) const = default; +}; +#endif + +void test_spaceship() { + #ifdef __cpp_impl_three_way_comparison + // 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_constexpr(); + test_spaceship(); +} + +#if __cplusplus >= 201103L +typedef std::tuple test_types_tuple; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_extremes, T, test_types_tuple) { + const T max = std::numeric_limits::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::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 From 02b05e5e2429ccb9657052cb3d5908c324520885 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Sun, 1 Aug 2021 00:48:46 +0200 Subject: [PATCH 02/13] rm unneeded include --- include/boost/algorithm/is_clamped.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index a736fba..b4fe822 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -15,7 +15,6 @@ #define BOOST_ALGORITHM_IS_CLAMPED_HPP #include // For std::less -#include // For std::iterator_traits #include #include // for identity From aab7e1c1217ca5e5eb4ac051d163358c3a062c64 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Sun, 29 Aug 2021 23:02:22 +0200 Subject: [PATCH 03/13] fix spaceship support macro check, proper order of includes in test --- test/is_clamped_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/is_clamped_test.cpp b/test/is_clamped_test.cpp index d5ea2b1..e2d5cba 100644 --- a/test/is_clamped_test.cpp +++ b/test/is_clamped_test.cpp @@ -3,11 +3,11 @@ // 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 #include +#include #include #include -#ifdef __cpp_impl_three_way_comparison +#ifdef __cpp_impl_three_way_comparison &&__has_include() #include #endif #include @@ -167,7 +167,7 @@ void test_constexpr() { } -#ifdef __cpp_impl_three_way_comparison +#ifdef __cpp_impl_three_way_comparison &&__has_include() struct custom_with_spaceship { int v; auto operator<=>(const custom_with_spaceship&) const = default; @@ -175,7 +175,7 @@ struct custom_with_spaceship { #endif void test_spaceship() { - #ifdef __cpp_impl_three_way_comparison + #ifdef __cpp_impl_three_way_comparison &&__has_include() // Inside the range, equal to the endpoints, and outside the endpoints. const custom_with_spaceship c0(0); const custom_with_spaceship c1(1); From ba3f706b1d726f36214a3281f7ffec1c0e1e9343 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Sun, 29 Aug 2021 23:05:56 +0200 Subject: [PATCH 04/13] comment uniformization --- include/boost/algorithm/is_clamped.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index b4fe822..0d541f8 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -48,10 +48,10 @@ namespace boost { namespace algorithm { /// \fn is_clamped ( T const& val, /// typename boost::mpl::identity::type const & lo, /// typename boost::mpl::identity::type const & hi) -/// \returns true if value "val" is in the range [ lo, 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. +/// If the value is greater than hi, return false. /// Otherwise, returns true. /// /// \param val The value to be checked From c5f6f52560545e8bd70e390a70c55dd2ff308d0f Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sun, 29 Aug 2021 16:19:52 -0700 Subject: [PATCH 05/13] Remove dependency on boost::mpl from 'clamp' and 'is_sorted' --- include/boost/algorithm/clamp.hpp | 20 ++++++++++---------- include/boost/algorithm/cxx11/is_sorted.hpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/algorithm/clamp.hpp b/include/boost/algorithm/clamp.hpp index 82a99bd..1378f95 100644 --- a/include/boost/algorithm/clamp.hpp +++ b/include/boost/algorithm/clamp.hpp @@ -26,14 +26,14 @@ #include #include #include -#include // for identity -#include // for boost::disable_if +#include // for boost::type_identity +#include // for boost::disable_if namespace boost { namespace algorithm { /// \fn clamp ( T const& val, -/// typename boost::mpl::identity::type const & lo, -/// typename boost::mpl::identity::type const & hi, Pred p ) +/// typename boost::type_identity::type const & lo, +/// typename boost::type_identity::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 BOOST_CXX14_CONSTEXPR T const & clamp ( T const& val, - typename boost::mpl::identity::type const & lo, - typename boost::mpl::identity::type const & hi, Pred p ) + typename boost::type_identity::type const & lo, + typename boost::type_identity::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::type const & lo, -/// typename boost::mpl::identity::type const & hi ) +/// typename boost::identity::type const & lo, +/// typename boost::identity::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 BOOST_CXX14_CONSTEXPR T const& clamp ( const T& val, - typename boost::mpl::identity::type const & lo, - typename boost::mpl::identity::type const & hi ) + typename boost::type_identity::type const & lo, + typename boost::type_identity::type const & hi ) { return boost::algorithm::clamp ( val, lo, hi, std::less()); } diff --git a/include/boost/algorithm/cxx11/is_sorted.hpp b/include/boost/algorithm/cxx11/is_sorted.hpp index 0aa8122..e02fb36 100644 --- a/include/boost/algorithm/cxx11/is_sorted.hpp +++ b/include/boost/algorithm/cxx11/is_sorted.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include // 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 - BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same::value, boost::mpl::identity >::type + BOOST_CXX14_CONSTEXPR typename boost::lazy_disable_if_c< boost::is_same::value, boost::type_identity >::type is_sorted ( const R &range, Pred p ) { return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p ); From 240904836885fa5b424f607834c338524521f571 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Tue, 31 Aug 2021 21:39:59 +0200 Subject: [PATCH 06/13] fix spaceship detection macros, add tests for point interval and first argument determines type --- test/is_clamped_test.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/test/is_clamped_test.cpp b/test/is_clamped_test.cpp index e2d5cba..149edec 100644 --- a/test/is_clamped_test.cpp +++ b/test/is_clamped_test.cpp @@ -7,9 +7,14 @@ #include #include #include -#ifdef __cpp_impl_three_way_comparison &&__has_include() +#ifdef __cpp_impl_three_way_comparison +#if __has_include() +#define BOOST_IS_CLAMPED_TEST_SPACESHIP +#endif +#ifdef BOOST_IS_CLAMPED_TEST_SPACESHIP #include #endif +#endif #include #include #include @@ -84,11 +89,11 @@ void test_ints() { BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 0U, 1, 6. )); BOOST_CHECK_EQUAL ( false, ba::is_clamped ( 8U, 1, 6. )); - short foo = 50; // float->short conversion does not round - BOOST_CHECK_EQUAL ( true, ba::is_clamped ( foo, 50.999, 100 )); - BOOST_CHECK_EQUAL ( false, ba::is_clamped ( foo, 51.001, 100 )); + 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::is_iec559) { @@ -141,6 +146,21 @@ void test_custom() { 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 { @@ -167,7 +187,7 @@ void test_constexpr() { } -#ifdef __cpp_impl_three_way_comparison &&__has_include() +#ifdef BOOST_IS_CLAMPED_TEST_SPACESHIP struct custom_with_spaceship { int v; auto operator<=>(const custom_with_spaceship&) const = default; @@ -175,7 +195,7 @@ struct custom_with_spaceship { #endif void test_spaceship() { - #ifdef __cpp_impl_three_way_comparison &&__has_include() + #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); @@ -202,6 +222,8 @@ BOOST_AUTO_TEST_CASE(test_main) { test_floats(); test_std_string(); test_custom(); + test_point_interval(); + test_first_argument_determines_types(); test_constexpr(); test_spaceship(); } From d717d999be4ad4557d303d85ba2c6924a0f78ce1 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Tue, 31 Aug 2021 21:45:41 +0200 Subject: [PATCH 07/13] boost::type_identity modernization --- include/boost/algorithm/is_clamped.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index 0d541f8..8619564 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -17,7 +17,7 @@ #include // For std::less #include -#include // for identity +#include // for boost::type_identity namespace boost { namespace algorithm { @@ -38,8 +38,8 @@ namespace boost { namespace algorithm { /// template BOOST_CXX14_CONSTEXPR bool is_clamped( - T const& val, typename boost::mpl::identity::type const& lo, - typename boost::mpl::identity::type const& hi, Pred p) { + T const& val, typename boost::type_identity::type const& lo, + typename boost::type_identity::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; @@ -48,7 +48,7 @@ namespace boost { namespace algorithm { /// \fn is_clamped ( T const& val, /// typename boost::mpl::identity::type const & lo, /// typename boost::mpl::identity::type const & hi) -/// \returns true if value val is in the range [ lo, 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. @@ -60,9 +60,9 @@ namespace boost { namespace algorithm { /// template - BOOST_CXX14_CONSTEXPR bool is_clamped ( const T& val, - typename boost::mpl::identity::type const & lo, - typename boost::mpl::identity::type const & hi ) + BOOST_CXX14_CONSTEXPR bool is_clamped ( const T& val, + typename boost::type_identity::type const & lo, + typename boost::type_identity::type const & hi ) { return boost::algorithm::is_clamped ( val, lo, hi, std::less()); } From 0c2e904c0df23db207f42a087260c25f70bc378f Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Tue, 31 Aug 2021 21:57:03 +0200 Subject: [PATCH 08/13] fix comments for type_identity --- include/boost/algorithm/is_clamped.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index 8619564..9238bbc 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -14,7 +14,7 @@ #ifndef BOOST_ALGORITHM_IS_CLAMPED_HPP #define BOOST_ALGORITHM_IS_CLAMPED_HPP -#include // For std::less +#include // for std::less #include #include // for boost::type_identity @@ -22,8 +22,8 @@ namespace boost { namespace algorithm { /// \fn is_clamped ( T const& val, -/// typename boost::mpl::identity::type const & lo, -/// typename boost::mpl::identity::type const & hi, Pred p ) +/// typename boost::type_identity::type const & lo, +/// typename boost::type_identity::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. @@ -46,8 +46,8 @@ namespace boost { namespace algorithm { } /// \fn is_clamped ( T const& val, -/// typename boost::mpl::identity::type const & lo, -/// typename boost::mpl::identity::type const & hi) +/// typename boost::type_identity::type const & lo, +/// typename boost::type_identity::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. From 9031f17bb818a1cb80c6185be1856466dd08bda9 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Mon, 13 Sep 2021 00:22:03 +0200 Subject: [PATCH 09/13] update CR --- include/boost/algorithm/is_clamped.hpp | 2 +- test/is_clamped_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index 9238bbc..3f00444 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) Marshall Clow 2008-2012. + 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) diff --git a/test/is_clamped_test.cpp b/test/is_clamped_test.cpp index 149edec..575e343 100644 --- a/test/is_clamped_test.cpp +++ b/test/is_clamped_test.cpp @@ -1,4 +1,4 @@ -// (C) Copyright TODO +// (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) From 9d5ddb6a7a4f318738f98aa1f65f84c8b01de2b7 Mon Sep 17 00:00:00 2001 From: Ivan Matek Date: Mon, 13 Sep 2021 00:28:03 +0200 Subject: [PATCH 10/13] update authors --- include/boost/algorithm/is_clamped.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/algorithm/is_clamped.hpp b/include/boost/algorithm/is_clamped.hpp index 3f00444..72287d3 100644 --- a/include/boost/algorithm/is_clamped.hpp +++ b/include/boost/algorithm/is_clamped.hpp @@ -8,7 +8,7 @@ /// \file is_clamped.hpp /// \brief IsClamped algorithm -/// \author TODO +/// \authors Ivan Matek, Marshall Clow /// #ifndef BOOST_ALGORITHM_IS_CLAMPED_HPP From a9cd6c353f909bbebbb39009ddd6f1635d2dfc00 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 3 Oct 2021 17:16:12 +0300 Subject: [PATCH 11/13] fix -Wdeprecated-copy warnings in string algorithms --- .../algorithm/string/detail/find_iterator.hpp | 14 ++++++++-- .../boost/algorithm/string/find_iterator.hpp | 28 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/boost/algorithm/string/detail/find_iterator.hpp b/include/boost/algorithm/string/detail/find_iterator.hpp index 4f90a98..c990785 100644 --- a/include/boost/algorithm/string/detail/find_iterator.hpp +++ b/include/boost/algorithm/string/detail/find_iterator.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 @@ -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( diff --git a/include/boost/algorithm/string/find_iterator.hpp b/include/boost/algorithm/string/find_iterator.hpp index 5a52d92..47c20e6 100644 --- a/include/boost/algorithm/string/find_iterator.hpp +++ b/include/boost/algorithm/string/find_iterator.hpp @@ -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 From 02f436c25dd4a5b23df945085a2f1d6ce4c3a5e9 Mon Sep 17 00:00:00 2001 From: Jonathan Gopel Date: Sun, 5 Jun 2022 14:03:16 +0000 Subject: [PATCH 12/13] Add documentation to transform_inclusive_scan Problem: - There is no documentation for the existing functions. This will make it harder for users to consume these functions, especially as new variants are added. Solution: - Add documentation. --- doc/algorithm.qbk | 6 +++- .../cxx17/transform_inclusive_scan.hpp | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 64e8dfb..06d8092 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -106,6 +106,11 @@ 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] + [endsect:CXX17_inner_algorithms] [endsect:CXX17] @@ -235,7 +240,6 @@ Raise a value to an integral power ([^constexpr] since C++14) * [*[^[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] diff --git a/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp index 3160770..9d877c0 100644 --- a/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp +++ b/include/boost/algorithm/cxx17/transform_inclusive_scan.hpp @@ -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 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 OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, From 6b7a38f639d3aa549bece0f42505d0c5bc52e33a Mon Sep 17 00:00:00 2001 From: Jonathan Gopel Date: Sun, 5 Jun 2022 14:18:33 +0000 Subject: [PATCH 13/13] Add documentation to transform_exclusive_scan Problem: - There is no documentation for the existing functions. This will make it harder for users to consume these functions, espcially as new variants are added. Solution: - Add documentation. --- doc/algorithm.qbk | 6 +++++- .../algorithm/cxx17/transform_exclusive_scan.hpp | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 06d8092..50b3044 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -111,6 +111,11 @@ Apply a functor to the elements of a sequence 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] @@ -239,7 +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_reduce_hpp transform_reduce] ] ] [endsect:not_yet_documented_cxx17_algos] diff --git a/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp b/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp index 68318a5..86446b8 100644 --- a/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp +++ b/include/boost/algorithm/cxx17/transform_exclusive_scan.hpp @@ -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 OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,