diff options
Diffstat (limited to 'boost')
1229 files changed, 42981 insertions, 22934 deletions
diff --git a/boost/accumulators/numeric/functional.hpp b/boost/accumulators/numeric/functional.hpp index d5d79f5c49..858decc199 100644 --- a/boost/accumulators/numeric/functional.hpp +++ b/boost/accumulators/numeric/functional.hpp @@ -99,11 +99,9 @@ namespace boost { namespace numeric }; \ template<typename Arg, typename EnableIf> \ struct Name ## _base \ - : std::unary_function< \ - typename remove_const<Arg>::type \ - , typename result_of_ ## Name<Arg>::type \ - > \ { \ + typedef typename remove_const<Arg>::type argument_type; \ + typedef typename result_of_ ## Name<Arg>::type result_type; \ typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const \ { \ return Op arg; \ @@ -138,12 +136,10 @@ namespace boost { namespace numeric }; \ template<typename Left, typename Right, typename EnableIf> \ struct Name ## _base \ - : std::binary_function< \ - typename remove_const<Left>::type \ - , typename remove_const<Right>::type \ - , typename result_of_ ## Name<Left, Right>::type \ - > \ { \ + typedef typename remove_const<Left>::type first_argument_type; \ + typedef typename remove_const<Right>::type second_argument_type; \ + typedef typename result_of_ ## Name<Left, Right>::type result_type; \ typename result_of_ ## Name<Left, Right>::type \ operator ()(Left &left, Right &right) const \ { \ @@ -220,8 +216,11 @@ namespace boost { namespace numeric { template<typename Left, typename Right, typename EnableIf> struct min_assign_base - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { if(numeric::less(right, left)) @@ -233,8 +232,11 @@ namespace boost { namespace numeric template<typename Left, typename Right, typename EnableIf> struct max_assign_base - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { if(numeric::greater(right, left)) @@ -258,8 +260,10 @@ namespace boost { namespace numeric template<typename To, typename From, typename EnableIf> struct promote_base - : std::unary_function<From, To> { + typedef From argument_type; + typedef To result_type; + To operator ()(From &from) const { return from; @@ -268,8 +272,10 @@ namespace boost { namespace numeric template<typename ToFrom> struct promote_base<ToFrom, ToFrom, void> - : std::unary_function<ToFrom, ToFrom> { + typedef ToFrom argument_type; + typedef ToFrom result_type; + ToFrom &operator ()(ToFrom &tofrom) { return tofrom; @@ -278,10 +284,12 @@ namespace boost { namespace numeric template<typename Arg, typename EnableIf> struct as_min_base - : std::unary_function<Arg, typename remove_const<Arg>::type> { BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + typedef Arg argument_type; + typedef typename remove_const<Arg>::type result_type; + typename remove_const<Arg>::type operator ()(Arg &) const { return (std::numeric_limits<typename remove_const<Arg>::type>::min)(); @@ -290,10 +298,12 @@ namespace boost { namespace numeric template<typename Arg> struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type> - : std::unary_function<Arg, typename remove_const<Arg>::type> { BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + typedef Arg argument_type; + typedef typename remove_const<Arg>::type result_type; + typename remove_const<Arg>::type operator ()(Arg &) const { return -(std::numeric_limits<typename remove_const<Arg>::type>::max)(); @@ -302,10 +312,12 @@ namespace boost { namespace numeric template<typename Arg, typename EnableIf> struct as_max_base - : std::unary_function<Arg, typename remove_const<Arg>::type> { BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + typedef Arg argument_type; + typedef typename remove_const<Arg>::type result_type; + typename remove_const<Arg>::type operator ()(Arg &) const { return (std::numeric_limits<typename remove_const<Arg>::type>::max)(); @@ -314,8 +326,10 @@ namespace boost { namespace numeric template<typename Arg, typename EnableIf> struct as_zero_base - : std::unary_function<Arg, typename remove_const<Arg>::type> { + typedef Arg argument_type; + typedef typename remove_const<Arg>::type result_type; + typename remove_const<Arg>::type operator ()(Arg &) const { return numeric::zero<typename remove_const<Arg>::type>::value; @@ -324,8 +338,10 @@ namespace boost { namespace numeric template<typename Arg, typename EnableIf> struct as_one_base - : std::unary_function<Arg, typename remove_const<Arg>::type> { + typedef Arg argument_type; + typedef typename remove_const<Arg>::type result_type; + typename remove_const<Arg>::type operator ()(Arg &) const { return numeric::one<typename remove_const<Arg>::type>::value; diff --git a/boost/accumulators/numeric/functional/valarray.hpp b/boost/accumulators/numeric/functional/valarray.hpp index c24b45859d..1996c75845 100644 --- a/boost/accumulators/numeric/functional/valarray.hpp +++ b/boost/accumulators/numeric/functional/valarray.hpp @@ -118,17 +118,9 @@ namespace boost { namespace numeric #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \ template<typename Left, typename Right> \ struct Name<Left, Right, std_valarray_tag, std_valarray_tag> \ - : std::binary_function< \ - Left \ - , Right \ - , std::valarray< \ - typename Name< \ - typename Left::value_type \ - , typename Right::value_type \ - >::result_type \ - > \ - > \ { \ + typedef Left first_argument_type; \ + typedef Right second_argument_type; \ typedef typename Left::value_type left_value_type; \ typedef typename Right::value_type right_value_type; \ typedef \ @@ -145,14 +137,9 @@ namespace boost { namespace numeric }; \ template<typename Left, typename Right> \ struct Name<Left, Right, std_valarray_tag, void> \ - : std::binary_function< \ - Left \ - , Right \ - , std::valarray< \ - typename Name<typename Left::value_type, Right>::result_type \ - > \ - > \ { \ + typedef Left first_argument_type; \ + typedef Right second_argument_type; \ typedef typename Left::value_type left_value_type; \ typedef \ std::valarray< \ @@ -167,14 +154,9 @@ namespace boost { namespace numeric }; \ template<typename Left, typename Right> \ struct Name<Left, Right, void, std_valarray_tag> \ - : std::binary_function< \ - Left \ - , Right \ - , std::valarray< \ - typename Name<Left, typename Right::value_type>::result_type \ - > \ - > \ { \ + typedef Left first_argument_type; \ + typedef Right second_argument_type; \ typedef typename Right::value_type right_value_type; \ typedef \ std::valarray< \ @@ -200,8 +182,11 @@ namespace boost { namespace numeric // element-wise min of std::valarray template<typename Left, typename Right> struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag> - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { BOOST_ASSERT(left.size() == right.size()); @@ -219,8 +204,11 @@ namespace boost { namespace numeric // element-wise max of std::valarray template<typename Left, typename Right> struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag> - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { BOOST_ASSERT(left.size() == right.size()); @@ -247,8 +235,10 @@ namespace boost { namespace numeric // promote template<typename To, typename From> struct promote<To, From, std_valarray_tag, std_valarray_tag> - : std::unary_function<From, To> { + typedef From argument_type; + typedef To result_type; + To operator ()(From &arr) const { typename remove_const<To>::type res(arr.size()); @@ -262,8 +252,10 @@ namespace boost { namespace numeric template<typename ToFrom> struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag> - : std::unary_function<ToFrom, ToFrom> { + typedef ToFrom argument_type; + typedef ToFrom result_type; + ToFrom &operator ()(ToFrom &tofrom) const { return tofrom; @@ -275,8 +267,10 @@ namespace boost { namespace numeric // if(numeric::promote<bool>(a == b)) template<typename From> struct promote<bool, From, void, std_valarray_tag> - : std::unary_function<From, bool> { + typedef From argument_type; + typedef bool result_type; + bool operator ()(From &arr) const { BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>)); @@ -300,8 +294,10 @@ namespace boost { namespace numeric // functional::as_min template<typename T> struct as_min<T, std_valarray_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -314,8 +310,10 @@ namespace boost { namespace numeric // functional::as_max template<typename T> struct as_max<T, std_valarray_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -328,8 +326,10 @@ namespace boost { namespace numeric // functional::as_zero template<typename T> struct as_zero<T, std_valarray_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -342,8 +342,10 @@ namespace boost { namespace numeric // functional::as_one template<typename T> struct as_one<T, std_valarray_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() diff --git a/boost/accumulators/numeric/functional/vector.hpp b/boost/accumulators/numeric/functional/vector.hpp index 8a68a3f303..4c2fbd8ada 100644 --- a/boost/accumulators/numeric/functional/vector.hpp +++ b/boost/accumulators/numeric/functional/vector.hpp @@ -195,8 +195,11 @@ namespace boost { namespace numeric // element-wise min of std::vector template<typename Left, typename Right> struct min_assign<Left, Right, std_vector_tag, std_vector_tag> - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { BOOST_ASSERT(left.size() == right.size()); @@ -214,8 +217,11 @@ namespace boost { namespace numeric // element-wise max of std::vector template<typename Left, typename Right> struct max_assign<Left, Right, std_vector_tag, std_vector_tag> - : std::binary_function<Left, Right, void> { + typedef Left first_argument_type; + typedef Right second_argument_type; + typedef void result_type; + void operator ()(Left &left, Right &right) const { BOOST_ASSERT(left.size() == right.size()); @@ -242,8 +248,10 @@ namespace boost { namespace numeric // promote template<typename To, typename From> struct promote<To, From, std_vector_tag, std_vector_tag> - : std::unary_function<From, To> { + typedef From argument_type; + typedef To result_type; + To operator ()(From &arr) const { typename remove_const<To>::type res(arr.size()); @@ -257,8 +265,10 @@ namespace boost { namespace numeric template<typename ToFrom> struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag> - : std::unary_function<ToFrom, ToFrom> { + typedef ToFrom argument_type; + typedef ToFrom result_type; + ToFrom &operator ()(ToFrom &tofrom) const { return tofrom; @@ -269,8 +279,10 @@ namespace boost { namespace numeric // functional::as_min template<typename T> struct as_min<T, std_vector_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -283,8 +295,10 @@ namespace boost { namespace numeric // functional::as_max template<typename T> struct as_max<T, std_vector_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -297,8 +311,10 @@ namespace boost { namespace numeric // functional::as_zero template<typename T> struct as_zero<T, std_vector_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() @@ -311,8 +327,10 @@ namespace boost { namespace numeric // functional::as_one template<typename T> struct as_one<T, std_vector_tag> - : std::unary_function<T, typename remove_const<T>::type> { + typedef T argument_type; + typedef typename remove_const<T>::type result_type; + typename remove_const<T>::type operator ()(T &arr) const { return 0 == arr.size() diff --git a/boost/accumulators/statistics/covariance.hpp b/boost/accumulators/statistics/covariance.hpp index 73c92aebb5..b3030b9676 100644 --- a/boost/accumulators/statistics/covariance.hpp +++ b/boost/accumulators/statistics/covariance.hpp @@ -50,17 +50,9 @@ namespace boost { namespace numeric template<typename Left, typename Right> struct outer_product<Left, Right, std_vector_tag, std_vector_tag> - : std::binary_function< - Left - , Right - , ublas::matrix< - typename functional::multiplies< - typename Left::value_type - , typename Right::value_type - >::result_type - > - > { + typedef Left first_argument_type; + typedef Right second_argument_type; typedef ublas::matrix< typename functional::multiplies< diff --git a/boost/accumulators/statistics/tail.hpp b/boost/accumulators/statistics/tail.hpp index cc9267f9d4..be6cdee392 100644 --- a/boost/accumulators/statistics/tail.hpp +++ b/boost/accumulators/statistics/tail.hpp @@ -248,8 +248,11 @@ namespace impl /////////////////////////////////////////////////////////////////////////////// // struct indirect_cmp - : std::binary_function<std::size_t, std::size_t, bool> { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef bool result_type; + indirect_cmp(std::vector<Sample> const &s) : samples(s) { diff --git a/boost/accumulators/statistics/tail_variate_means.hpp b/boost/accumulators/statistics/tail_variate_means.hpp index d34d4abcd5..a97eab5648 100644 --- a/boost/accumulators/statistics/tail_variate_means.hpp +++ b/boost/accumulators/statistics/tail_variate_means.hpp @@ -118,7 +118,11 @@ namespace impl this->tail_means_.begin() , this->tail_means_.end() , this->tail_means_.begin() +#ifdef BOOST_NO_CXX98_BINDERS + , std::bind(std::divides<float_type>(), std::placeholders::_1, factor) +#else , std::bind2nd(std::divides<float_type>(), factor) +#endif ); } else diff --git a/boost/accumulators/statistics/times2_iterator.hpp b/boost/accumulators/statistics/times2_iterator.hpp index d46dd042ef..dbd81af7cf 100644 --- a/boost/accumulators/statistics/times2_iterator.hpp +++ b/boost/accumulators/statistics/times2_iterator.hpp @@ -23,7 +23,11 @@ namespace boost { namespace accumulators namespace detail { typedef transform_iterator< +#ifdef BOOST_NO_CXX98_BINDERS + decltype(std::bind(std::multiplies<std::size_t>(), 2, std::placeholders::_1)) +#else std::binder1st<std::multiplies<std::size_t> > +#endif , counting_iterator<std::size_t> > times2_iterator; @@ -31,7 +35,11 @@ namespace detail { return make_transform_iterator( make_counting_iterator(i) +#ifdef BOOST_NO_CXX98_BINDERS + , std::bind(std::multiplies<std::size_t>(), 2, std::placeholders::_1) +#else , std::bind1st(std::multiplies<std::size_t>(), 2) +#endif ); } diff --git a/boost/accumulators/statistics/weighted_tail_variate_means.hpp b/boost/accumulators/statistics/weighted_tail_variate_means.hpp index 2c9078335d..b1133109ed 100644 --- a/boost/accumulators/statistics/weighted_tail_variate_means.hpp +++ b/boost/accumulators/statistics/weighted_tail_variate_means.hpp @@ -169,7 +169,11 @@ namespace impl this->tail_means_.begin() , this->tail_means_.end() , this->tail_means_.begin() +#ifdef BOOST_NO_CXX98_BINDERS + , std::bind(numeric::functional::divides<typename array_type::value_type const, float_type const>(), std::placeholders::_1, factor) +#else , std::bind2nd(numeric::functional::divides<typename array_type::value_type const, float_type const>(), factor) +#endif ); return make_iterator_range(this->tail_means_); diff --git a/boost/algorithm/cxx11/is_partitioned.hpp b/boost/algorithm/cxx11/is_partitioned.hpp index cb6c71e33b..c0076b932b 100644 --- a/boost/algorithm/cxx11/is_partitioned.hpp +++ b/boost/algorithm/cxx11/is_partitioned.hpp @@ -18,7 +18,8 @@ namespace boost { namespace algorithm { /// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) -/// \brief Tests to see if a sequence is partitioned according to a predicate +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param first The start of the input sequence /// \param last One past the end of the input sequence @@ -39,7 +40,8 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p } /// \fn is_partitioned ( const Range &r, UnaryPredicate p ) -/// \brief Generates an increasing sequence of values, and stores them in the input Range. +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. /// /// \param r The input range /// \param p The predicate to test the values with diff --git a/boost/algorithm/cxx14/equal.hpp b/boost/algorithm/cxx14/equal.hpp index f1539f885c..9f97be1d62 100644 --- a/boost/algorithm/cxx14/equal.hpp +++ b/boost/algorithm/cxx14/equal.hpp @@ -13,7 +13,6 @@ #define BOOST_ALGORITHM_EQUAL_HPP #include <algorithm> // for std::equal -#include <functional> // for std::binary_function #include <iterator> namespace boost { namespace algorithm { @@ -21,7 +20,7 @@ namespace boost { namespace algorithm { namespace detail { template <class T1, class T2> - struct eq : public std::binary_function<T1, T2, bool> { + struct eq { bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} }; diff --git a/boost/algorithm/cxx17/exclusive_scan.hpp b/boost/algorithm/cxx17/exclusive_scan.hpp new file mode 100644 index 0000000000..03ecea52ec --- /dev/null +++ b/boost/algorithm/cxx17/exclusive_scan.hpp @@ -0,0 +1,52 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file exclusive_scan.hpp +/// \brief ??? +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP +#define BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator, class OutputIterator, class T, class BinaryOperation> +OutputIterator exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init, BinaryOperation bOp) +{ + if (first != last) + { + T saved = init; + do + { + init = bOp(init, *first); + *result = saved; + saved = init; + ++result; + } while (++first != last); + } + return result; +} + +template<class InputIterator, class OutputIterator, class T> +OutputIterator exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init) +{ + typedef typename std::iterator_traits<InputIterator>::value_type VT; + return exclusive_scan(first, last, result, init, std::plus<VT>()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP diff --git a/boost/algorithm/cxx17/for_each_n.hpp b/boost/algorithm/cxx17/for_each_n.hpp new file mode 100644 index 0000000000..b8134cc06a --- /dev/null +++ b/boost/algorithm/cxx17/for_each_n.hpp @@ -0,0 +1,37 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file for_each_n.hpp +/// \brief Apply a functor to the elements of a sequence +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_FOR_EACH_N_HPP +#define BOOST_ALGORITHM_FOR_EACH_N_HPP + +#include <utility> // for std::pair + +namespace boost { namespace algorithm { + +/// \fn for_each_n(InputIterator first, Size n, Function f); +/// \return first + n +/// +/// \param first The start of the first range. +/// \param n One past the end of the first range. +/// \param f A functor to apply to the elements of the sequence +/// \note If f returns a result, the result is ignored. +template<class InputIterator, class Size, class Function> +InputIterator for_each_n(InputIterator first, Size n, Function f) +{ + for ( ; n > 0; --n, ++first ) + f(*first); + + return first; +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_FOR_EACH_N_HPP diff --git a/boost/algorithm/cxx17/inclusive_scan.hpp b/boost/algorithm/cxx17/inclusive_scan.hpp new file mode 100644 index 0000000000..cd015f100f --- /dev/null +++ b/boost/algorithm/cxx17/inclusive_scan.hpp @@ -0,0 +1,60 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file transform_reduce.hpp +/// \brief Combine the (transformed) elements of a sequence (or two) into a single value. +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP +#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator, class OutputIterator, class T, class BinaryOperation> +OutputIterator inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation bOp, T init) +{ + for (; first != last; ++first, (void) ++result) { + init = bOp(init, *first); + *result = init; + } + return result; +} + + +template<class InputIterator, class OutputIterator, class BinaryOperation> +OutputIterator inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation bOp) +{ + if (first != last) { + typename std::iterator_traits<InputIterator>::value_type init = *first; + *result++ = init; + if (++first != last) + return inclusive_scan(first, last, result, bOp, init); + } + + return result; +} + +template<class InputIterator, class OutputIterator> +OutputIterator inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result) +{ + typedef typename std::iterator_traits<InputIterator>::value_type VT; + return inclusive_scan(first, last, result, std::plus<VT>()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/boost/algorithm/cxx17/reduce.hpp b/boost/algorithm/cxx17/reduce.hpp new file mode 100644 index 0000000000..f47695b53a --- /dev/null +++ b/boost/algorithm/cxx17/reduce.hpp @@ -0,0 +1,72 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file reduce.hpp +/// \brief Combine the elements of a sequence into a single value +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_REDUCE_HPP +#define BOOST_ALGORITHM_REDUCE_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator, class T, class BinaryOperation> +T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp) +{ + ; + for (; first != last; ++first) + init = bOp(init, *first); + return init; +} + +template<class InputIterator, class T> +T reduce(InputIterator first, InputIterator last, T init) +{ + typedef typename std::iterator_traits<InputIterator>::value_type VT; + return reduce(first, last, init, std::plus<VT>()); +} + +template<class InputIterator> +typename std::iterator_traits<InputIterator>::value_type +reduce(InputIterator first, InputIterator last) +{ + return reduce(first, last, + typename std::iterator_traits<InputIterator>::value_type()); +} + +template<class Range> +typename boost::range_value<Range>::type +reduce(const Range &r) +{ + return reduce(boost::begin(r), boost::end(r)); +} + +// Not sure that this won't be ambiguous (1) +template<class Range, class T> +T reduce(const Range &r, T init) +{ + return reduce(boost::begin (r), boost::end (r), init); +} + + +// Not sure that this won't be ambiguous (2) +template<class Range, class T, class BinaryOperation> +T reduce(const Range &r, T init, BinaryOperation bOp) +{ + return reduce(boost::begin(r), boost::end(r), init, bOp); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_REDUCE_HPP diff --git a/boost/algorithm/cxx17/transform_exclusive_scan.hpp b/boost/algorithm/cxx17/transform_exclusive_scan.hpp new file mode 100644 index 0000000000..d3b4329a0a --- /dev/null +++ b/boost/algorithm/cxx17/transform_exclusive_scan.hpp @@ -0,0 +1,46 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file transform_exclusive_scan.hpp +/// \brief ???? +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP +#define BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator, class OutputIterator, class T, + class BinaryOperation, class UnaryOperation> +OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init, + BinaryOperation bOp, UnaryOperation uOp) +{ + if (first != last) + { + T saved = init; + do + { + init = bOp(init, uOp(*first)); + *result = saved; + saved = init; + ++result; + } while (++first != last); + } + return result; +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP diff --git a/boost/algorithm/cxx17/transform_inclusive_scan.hpp b/boost/algorithm/cxx17/transform_inclusive_scan.hpp new file mode 100644 index 0000000000..476c117f92 --- /dev/null +++ b/boost/algorithm/cxx17/transform_inclusive_scan.hpp @@ -0,0 +1,58 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file transform_reduce.hpp +/// \brief Combine the (transformed) elements of a sequence (or two) into a single value. +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP +#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator, class OutputIterator, + class BinaryOperation, class UnaryOperation, class T> +OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, + BinaryOperation bOp, UnaryOperation uOp, + T init) +{ + for (; first != last; ++first, (void) ++result) { + init = bOp(init, uOp(*first)); + *result = init; + } + + return result; +} + +template<class InputIterator, class OutputIterator, + class BinaryOperation, class UnaryOperation> +OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, + BinaryOperation bOp, UnaryOperation uOp) +{ + if (first != last) { + typename std::iterator_traits<InputIterator>::value_type init = uOp(*first); + *result++ = init; + if (++first != last) + return transform_inclusive_scan(first, last, result, bOp, uOp, init); + } + + return result; +} + + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/boost/algorithm/cxx17/transform_reduce.hpp b/boost/algorithm/cxx17/transform_reduce.hpp new file mode 100644 index 0000000000..7ebde7d325 --- /dev/null +++ b/boost/algorithm/cxx17/transform_reduce.hpp @@ -0,0 +1,55 @@ +/* + Copyright (c) Marshall Clow 2017. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file transform_reduce.hpp +/// \brief Combine the (transformed) elements of a sequence (or two) into a single value. +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP +#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP + +#include <functional> // for std::plus +#include <iterator> // for std::iterator_traits + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +namespace boost { namespace algorithm { + +template<class InputIterator1, class InputIterator2, class T, + class BinaryOperation1, class BinaryOperation2> +T transform_reduce(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init, + BinaryOperation1 bOp1, BinaryOperation2 bOp2) +{ + for (; first1 != last1; ++first1, (void) ++first2) + init = bOp1(init, bOp2(*first1, *first2)); + return init; +} + +template<class InputIterator, class T, + class BinaryOperation, class UnaryOperation> +T transform_reduce(InputIterator first, InputIterator last, + T init, BinaryOperation bOp, UnaryOperation uOp) +{ + for (; first != last; ++first) + init = bOp(init, uOp(*first)); + return init; +} + +template<class InputIterator1, class InputIterator2, class T> +T transform_reduce(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init) +{ + return transform_reduce(first1, last1, first2, init, + std::plus<T>(), std::multiplies<T>()); +} + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP diff --git a/boost/algorithm/hex.hpp b/boost/algorithm/hex.hpp index 739e89f2f0..b8335843a8 100644 --- a/boost/algorithm/hex.hpp +++ b/boost/algorithm/hex.hpp @@ -73,7 +73,7 @@ namespace detail { else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10; else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10; else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c)); - return retval; + return static_cast<char>(retval); } // My own iterator_traits class. diff --git a/boost/algorithm/is_palindrome.hpp b/boost/algorithm/is_palindrome.hpp index cc63e18075..09881109a3 100644 --- a/boost/algorithm/is_palindrome.hpp +++ b/boost/algorithm/is_palindrome.hpp @@ -35,7 +35,7 @@ namespace boost { namespace algorithm { /// For other sequences function will return false. /// Complexity: O(N). template <typename BidirectionalIterator, typename Predicate> -bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p ) +bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p) { if(begin == end) { @@ -63,7 +63,7 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi /// \return true if the entire sequence is palindrome /// /// \param begin The start of the input sequence -/// \param end One past the end of the input sequence +/// \param end One past the end of the input sequence /// /// \note This function will return true for empty sequences and for palindromes. /// For other sequences function will return false. @@ -71,26 +71,8 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi template <typename BidirectionalIterator> bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end) { - if(begin == end) - { - return true; - } - - --end; - while(begin != end) - { - if(!(*begin == *end)) - { - return false; - } - ++begin; - if(begin == end) - { - break; - } - --end; - } - return true; + return is_palindrome(begin, end, + std::equal_to<typename std::iterator_traits<BidirectionalIterator>::value_type> ()); } /// \fn is_palindrome ( const R& range ) @@ -122,7 +104,6 @@ bool is_palindrome(const R& range, Predicate p) return is_palindrome(boost::begin(range), boost::end(range), p); } - /// \fn is_palindrome ( const char* str ) /// \return true if the entire sequence is palindrome /// @@ -138,7 +119,6 @@ bool is_palindrome(const char* str) return is_palindrome(str, str + strlen(str)); } - /// \fn is_palindrome ( const char* str, Predicate p ) /// \return true if the entire sequence is palindrome /// @@ -155,7 +135,6 @@ bool is_palindrome(const char* str, Predicate p) return true; return is_palindrome(str, str + strlen(str), p); } - }} #endif // BOOST_ALGORITHM_IS_PALINDROME_HPP diff --git a/boost/algorithm/is_partitioned_until.hpp b/boost/algorithm/is_partitioned_until.hpp new file mode 100644 index 0000000000..42683e1d8e --- /dev/null +++ b/boost/algorithm/is_partitioned_until.hpp @@ -0,0 +1,63 @@ +/* + Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.by>, 2017. + + 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_partitioned_until.hpp +/// \brief Tell if a sequence is partitioned +/// \author Alexander Zaitsev + +#ifndef BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP +#define BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +namespace boost { namespace algorithm { + +/// \fn is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p ) +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. +/// +/// \param first The start of the input sequence +/// \param last One past the end of the input sequence +/// \param p The predicate to test the values with +/// +/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. +/// Returns last if the entire sequence is partitioned. +/// Complexity: O(N). +template <typename InputIterator, typename UnaryPredicate> +InputIterator is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p ) +{ +// Run through the part that satisfy the predicate + for ( ; first != last; ++first ) + if ( !p (*first)) + break; +// Now the part that does not satisfy the predicate + for ( ; first != last; ++first ) + if ( p (*first)) + return first; + return last; +} + +/// \fn is_partitioned_until ( const Range &r, UnaryPredicate p ) +/// \brief Tests to see if a sequence is partitioned according to a predicate. +/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence. +/// +/// \param r The input range +/// \param p The predicate to test the values with +/// +/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false. +/// Returns last if the entire sequence is partitioned. +/// Complexity: O(N). +template <typename Range, typename UnaryPredicate> +typename boost::range_iterator<const Range>::type is_partitioned_until ( const Range &r, UnaryPredicate p ) +{ + return boost::algorithm::is_partitioned_until (boost::begin(r), boost::end(r), p); +} + +}} + +#endif // BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP diff --git a/boost/algorithm/searching/boyer_moore.hpp b/boost/algorithm/searching/boyer_moore.hpp index 65a809dd4f..192d4dec25 100644 --- a/boost/algorithm/searching/boyer_moore.hpp +++ b/boost/algorithm/searching/boyer_moore.hpp @@ -152,8 +152,8 @@ Requirements: template<typename Iter, typename Container> - void compute_bm_prefix ( Iter pat_first, Iter pat_last, Container &prefix ) { - const std::size_t count = std::distance ( pat_first, pat_last ); + void compute_bm_prefix ( Iter first, Iter last, Container &prefix ) { + const std::size_t count = std::distance ( first, last ); BOOST_ASSERT ( count > 0 ); BOOST_ASSERT ( prefix.size () == count ); @@ -161,26 +161,26 @@ Requirements: std::size_t k = 0; for ( std::size_t i = 1; i < count; ++i ) { BOOST_ASSERT ( k < count ); - while ( k > 0 && ( pat_first[k] != pat_first[i] )) { + while ( k > 0 && ( first[k] != first[i] )) { BOOST_ASSERT ( k < count ); k = prefix [ k - 1 ]; } - if ( pat_first[k] == pat_first[i] ) + if ( first[k] == first[i] ) k++; prefix [ i ] = k; } } - void build_suffix_table ( patIter pat_first, patIter pat_last ) { - const std::size_t count = (std::size_t) std::distance ( pat_first, pat_last ); + void build_suffix_table ( patIter first, patIter last ) { + const std::size_t count = (std::size_t) std::distance ( first, last ); if ( count > 0 ) { // empty pattern std::vector<typename std::iterator_traits<patIter>::value_type> reversed(count); - (void) std::reverse_copy ( pat_first, pat_last, reversed.begin ()); + (void) std::reverse_copy ( first, last, reversed.begin ()); std::vector<difference_type> prefix (count); - compute_bm_prefix ( pat_first, pat_last, prefix ); + compute_bm_prefix ( first, last, prefix ); std::vector<difference_type> prefix_reversed (count); compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed ); diff --git a/boost/algorithm/searching/knuth_morris_pratt.hpp b/boost/algorithm/searching/knuth_morris_pratt.hpp index c890c9cac0..5b5b64a729 100644 --- a/boost/algorithm/searching/knuth_morris_pratt.hpp +++ b/boost/algorithm/searching/knuth_morris_pratt.hpp @@ -155,9 +155,9 @@ namespace boost { namespace algorithm { void preKmp ( patIter first, patIter last ) { - const /*std::size_t*/ int count = std::distance ( first, last ); + const difference_type count = std::distance ( first, last ); - int i, j; + difference_type i, j; i = 0; j = skip_[0] = -1; @@ -177,7 +177,7 @@ namespace boost { namespace algorithm { void init_skip_table ( patIter first, patIter last ) { const difference_type count = std::distance ( first, last ); - int j; + difference_type j; skip_ [ 0 ] = -1; for ( int i = 1; i <= count; ++i ) { j = skip_ [ i - 1 ]; diff --git a/boost/algorithm/string/detail/case_conv.hpp b/boost/algorithm/string/detail/case_conv.hpp index 42621c74f0..233912ca0f 100644 --- a/boost/algorithm/string/detail/case_conv.hpp +++ b/boost/algorithm/string/detail/case_conv.hpp @@ -30,8 +30,10 @@ namespace boost { // a tolower functor template<typename CharT> - struct to_lowerF : public std::unary_function<CharT, CharT> + struct to_lowerF { + typedef CharT argument_type; + typedef CharT result_type; // Constructor to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {} @@ -50,8 +52,10 @@ namespace boost { // a toupper functor template<typename CharT> - struct to_upperF : public std::unary_function<CharT, CharT> + struct to_upperF { + typedef CharT argument_type; + typedef CharT result_type; // Constructor to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {} diff --git a/boost/algorithm/string/detail/find_iterator.hpp b/boost/algorithm/string/detail/find_iterator.hpp index 9b78a0f7e1..4f90a98fc0 100644 --- a/boost/algorithm/string/detail/find_iterator.hpp +++ b/boost/algorithm/string/detail/find_iterator.hpp @@ -40,7 +40,7 @@ namespace boost { // Protected construction/destruction // Default constructor - find_iterator_base() {}; + find_iterator_base() {} // Copy construction find_iterator_base( const find_iterator_base& Other ) : m_Finder(Other.m_Finder) {} diff --git a/boost/algorithm/string/detail/util.hpp b/boost/algorithm/string/detail/util.hpp index cf4a8b1c8c..7844b6723c 100644 --- a/boost/algorithm/string/detail/util.hpp +++ b/boost/algorithm/string/detail/util.hpp @@ -89,9 +89,10 @@ namespace boost { template< typename SeqT, typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator > - struct copy_iterator_rangeF : - public std::unary_function< iterator_range<IteratorT>, SeqT > + struct copy_iterator_rangeF { + typedef iterator_range<IteratorT> argument_type; + typedef SeqT result_type; SeqT operator()( const iterator_range<IteratorT>& Range ) const { return copy_range<SeqT>(Range); diff --git a/boost/align/aligned_allocator.hpp b/boost/align/aligned_allocator.hpp index 6d0f788952..6176bc27c0 100644 --- a/boost/align/aligned_allocator.hpp +++ b/boost/align/aligned_allocator.hpp @@ -28,8 +28,7 @@ namespace alignment { template<class T, std::size_t Alignment> class aligned_allocator { - BOOST_STATIC_ASSERT(detail:: - is_alignment_constant<Alignment>::value); + BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value); public: typedef T value_type; @@ -124,8 +123,7 @@ public: template<std::size_t Alignment> class aligned_allocator<void, Alignment> { - BOOST_STATIC_ASSERT(detail:: - is_alignment_constant<Alignment>::value); + BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value); public: typedef void value_type; diff --git a/boost/align/aligned_allocator_adaptor.hpp b/boost/align/aligned_allocator_adaptor.hpp index 8905c215d3..c9fae1cf20 100644 --- a/boost/align/aligned_allocator_adaptor.hpp +++ b/boost/align/aligned_allocator_adaptor.hpp @@ -8,13 +8,13 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP #define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP -#include <boost/align/detail/addressof.hpp> #include <boost/align/detail/is_alignment_constant.hpp> #include <boost/align/detail/max_align.hpp> #include <boost/align/detail/max_size.hpp> #include <boost/align/align.hpp> #include <boost/align/aligned_allocator_adaptor_forward.hpp> #include <boost/align/alignment_of.hpp> +#include <boost/core/pointer_traits.hpp> #include <boost/static_assert.hpp> #include <new> @@ -32,39 +32,25 @@ namespace alignment { template<class Allocator, std::size_t Alignment> class aligned_allocator_adaptor : public Allocator { - BOOST_STATIC_ASSERT(detail:: - is_alignment_constant<Alignment>::value); + BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value); #if !defined(BOOST_NO_CXX11_ALLOCATOR) typedef std::allocator_traits<Allocator> traits; - - typedef typename traits:: - template rebind_alloc<char> char_alloc; - - typedef typename traits:: - template rebind_traits<char> char_traits; - + typedef typename traits::template rebind_alloc<char> char_alloc; + typedef typename traits::template rebind_traits<char> char_traits; typedef typename char_traits::pointer char_ptr; #else - typedef typename Allocator:: - template rebind<char>::other char_alloc; - + typedef typename Allocator::template rebind<char>::other char_alloc; typedef typename char_alloc::pointer char_ptr; #endif public: -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename traits::value_type value_type; - typedef typename traits::size_type size_type; -#else typedef typename Allocator::value_type value_type; - typedef typename Allocator::size_type size_type; -#endif - typedef value_type* pointer; typedef const value_type* const_pointer; typedef void* void_pointer; typedef const void* const_void_pointer; + typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; private: @@ -77,11 +63,11 @@ public: template<class U> struct rebind { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef aligned_allocator_adaptor<typename traits:: - template rebind_alloc<U>, Alignment> other; + typedef aligned_allocator_adaptor<typename traits::template + rebind_alloc<U>, Alignment> other; #else - typedef aligned_allocator_adaptor<typename Allocator:: - template rebind<U>::other, Alignment> other; + typedef aligned_allocator_adaptor<typename Allocator::template + rebind<U>::other, Alignment> other; #endif }; @@ -120,10 +106,9 @@ public: std::size_t n = s + min_align - 1; char_alloc a(base()); char_ptr p = a.allocate(sizeof p + n); - void* r = detail::addressof(*p) + sizeof p; + void* r = boost::pointer_traits<char_ptr>::to_address(p) + sizeof p; (void)align(min_align, s, r, n); - ::new(static_cast<void*>(static_cast<char_ptr*>(r) - - 1)) char_ptr(p); + ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p); return static_cast<pointer>(r); } @@ -140,10 +125,9 @@ public: #else char_ptr p = a.allocate(sizeof p + n, h); #endif - void* r = detail::addressof(*p) + sizeof p; + void* r = boost::pointer_traits<char_ptr>::to_address(p) + sizeof p; (void)align(min_align, s, r, n); - ::new(static_cast<void*>(static_cast<char_ptr*>(r) - - 1)) char_ptr(p); + ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p); return static_cast<pointer>(r); } @@ -152,8 +136,7 @@ public: char_ptr r = *p; p->~char_ptr(); char_alloc a(base()); - a.deallocate(r, sizeof r + size * sizeof(value_type) + - min_align - 1); + a.deallocate(r, sizeof r + size * sizeof(value_type) + min_align - 1); } }; diff --git a/boost/align/detail/align.hpp b/boost/align/detail/align.hpp index a58dcea747..905940ad77 100644 --- a/boost/align/detail/align.hpp +++ b/boost/align/detail/align.hpp @@ -20,8 +20,8 @@ align(std::size_t alignment, std::size_t size, void*& ptr, { BOOST_ASSERT(detail::is_alignment(alignment)); if (size <= space) { - char* p = reinterpret_cast<char*>((reinterpret_cast<std:: - size_t>(ptr) + alignment - 1) & ~(alignment - 1)); + char* p = reinterpret_cast<char*>(~(alignment - 1) & + (reinterpret_cast<std::size_t>(ptr) + alignment - 1)); std::size_t n = space - (p - static_cast<char*>(ptr)); if (size <= n) { ptr = p; diff --git a/boost/align/detail/align_down.hpp b/boost/align/detail/align_down.hpp index 9a8c358c41..de3c80d06d 100644 --- a/boost/align/detail/align_down.hpp +++ b/boost/align/detail/align_down.hpp @@ -18,8 +18,8 @@ inline void* align_down(void* ptr, std::size_t alignment) BOOST_NOEXCEPT { BOOST_ASSERT(detail::is_alignment(alignment)); - return reinterpret_cast<void*>(reinterpret_cast<std:: - size_t>(ptr) & ~(alignment - 1)); + return reinterpret_cast<void*>(~(alignment - 1) & + reinterpret_cast<std::size_t>(ptr)); } } /* alignment */ diff --git a/boost/align/detail/align_up.hpp b/boost/align/detail/align_up.hpp index 86686da6ae..ac11f8964f 100644 --- a/boost/align/detail/align_up.hpp +++ b/boost/align/detail/align_up.hpp @@ -18,8 +18,8 @@ inline void* align_up(void* ptr, std::size_t alignment) BOOST_NOEXCEPT { BOOST_ASSERT(detail::is_alignment(alignment)); - return reinterpret_cast<void*>((reinterpret_cast<std:: - size_t>(ptr) + alignment - 1) & ~(alignment - 1)); + return reinterpret_cast<void*>(~(alignment - 1) & + (reinterpret_cast<std::size_t>(ptr) + alignment - 1)); } } /* alignment */ diff --git a/boost/align/detail/alignment_of_msvc.hpp b/boost/align/detail/alignment_of_msvc.hpp index 1526c7c296..440b840db4 100644 --- a/boost/align/detail/alignment_of_msvc.hpp +++ b/boost/align/detail/alignment_of_msvc.hpp @@ -23,8 +23,7 @@ struct offset_value { template<class T> struct alignment_of - : min_size<sizeof(T), - sizeof(offset_value<T>) - (sizeof(T) << 1)> { }; + : min_size<sizeof(T), sizeof(offset_value<T>) - (sizeof(T) << 1)> { }; } /* detail */ } /* alignment */ diff --git a/boost/align/detail/is_alignment.hpp b/boost/align/detail/is_alignment.hpp index 8bedba19c3..542fbe4694 100644 --- a/boost/align/detail/is_alignment.hpp +++ b/boost/align/detail/is_alignment.hpp @@ -4,7 +4,6 @@ Copyright 2014 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) - */ #ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP #define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP diff --git a/boost/archive/basic_text_iarchive.hpp b/boost/archive/basic_text_iarchive.hpp index 583041d8b4..48a646cc1f 100644 --- a/boost/archive/basic_text_iarchive.hpp +++ b/boost/archive/basic_text_iarchive.hpp @@ -21,7 +21,7 @@ // // note the fact that on libraries without wide characters, ostream is // is not a specialization of basic_ostream which in fact is not defined -// in such cases. So we can't use basic_ostream<IStream::char_type> but rather +// in such cases. So we can't use basic_istream<IStream::char_type> but rather // use two template parameters #include <boost/config.hpp> diff --git a/boost/archive/codecvt_null.hpp b/boost/archive/codecvt_null.hpp index 9cc9e5729d..7bce2b9b32 100644 --- a/boost/archive/codecvt_null.hpp +++ b/boost/archive/codecvt_null.hpp @@ -18,8 +18,11 @@ #include <locale> #include <cstddef> // NULL, size_t +#ifndef BOOST_NO_CWCHAR #include <cwchar> // for mbstate_t +#endif #include <boost/config.hpp> +#include <boost/serialization/force_include.hpp> #include <boost/archive/detail/auto_link_archive.hpp> #include <boost/archive/detail/abi_prefix.hpp> // must be the last header @@ -62,7 +65,7 @@ public: template<> class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t> { - virtual BOOST_WARCHIVE_DECL std::codecvt_base::result + virtual BOOST_WARCHIVE_DECL BOOST_DLLEXPORT std::codecvt_base::result do_out( std::mbstate_t & state, const wchar_t * first1, @@ -71,8 +74,8 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, char * first2, char * last2, char * & next2 - ) const; - virtual BOOST_WARCHIVE_DECL std::codecvt_base::result + ) const BOOST_USED; + virtual BOOST_WARCHIVE_DECL BOOST_DLLEXPORT std::codecvt_base::result do_in( std::mbstate_t & state, const char * first1, @@ -81,7 +84,7 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, wchar_t * first2, wchar_t * last2, wchar_t * & next2 - ) const; + ) const BOOST_USED; virtual int do_encoding( ) const throw( ){ return sizeof(wchar_t) / sizeof(char); } @@ -89,7 +92,7 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, return do_encoding(); } public: - explicit codecvt_null(std::size_t no_locale_manage = 0) : + BOOST_DLLEXPORT explicit codecvt_null(std::size_t no_locale_manage = 0) : std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage) {} virtual ~codecvt_null(){}; diff --git a/boost/archive/detail/iserializer.hpp b/boost/archive/detail/iserializer.hpp index 6e02eec7c4..193e98a82e 100644 --- a/boost/archive/detail/iserializer.hpp +++ b/boost/archive/detail/iserializer.hpp @@ -605,7 +605,7 @@ template<class Archive, class T> inline void load(Archive & ar, T &t){ // if this assertion trips. It means we're trying to load a // const object with a compiler that doesn't have correct - // funtion template ordering. On other compilers, this is + // function template ordering. On other compilers, this is // handled below. detail::check_const_loading< T >(); typedef diff --git a/boost/archive/impl/archive_serializer_map.ipp b/boost/archive/impl/archive_serializer_map.ipp index 8dabf0d08f..7f163ec407 100644 --- a/boost/archive/impl/archive_serializer_map.ipp +++ b/boost/archive/impl/archive_serializer_map.ipp @@ -47,6 +47,10 @@ archive_serializer_map<Archive>::insert(const basic_serializer * bs){ template<class Archive> BOOST_ARCHIVE_OR_WARCHIVE_DECL void archive_serializer_map<Archive>::erase(const basic_serializer * bs){ + BOOST_ASSERT(! boost::serialization::singleton< + extra_detail::map<Archive> + >::is_destroyed() + ); if(boost::serialization::singleton< extra_detail::map<Archive> >::is_destroyed()) diff --git a/boost/archive/impl/basic_binary_iprimitive.ipp b/boost/archive/impl/basic_binary_iprimitive.ipp index 7082b003e7..bbe933ccf6 100644 --- a/boost/archive/impl/basic_binary_iprimitive.ipp +++ b/boost/archive/impl/basic_binary_iprimitive.ipp @@ -84,6 +84,7 @@ basic_binary_iprimitive<Archive, Elem, Tr>::init() ); } +#ifndef BOOST_NO_CWCHAR template<class Archive, class Elem, class Tr> BOOST_ARCHIVE_OR_WARCHIVE_DECL void basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws) @@ -93,6 +94,7 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws) load_binary(ws, l * sizeof(wchar_t) / sizeof(char)); ws[l] = L'\0'; } +#endif template<class Archive, class Elem, class Tr> BOOST_ARCHIVE_OR_WARCHIVE_DECL void @@ -110,7 +112,6 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(std::string & s) load_binary(&(*s.begin()), l); } -#ifndef BOOST_NO_CWCHAR template<class Archive, class Elem, class Tr> BOOST_ARCHIVE_OR_WARCHIVE_DECL void basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s) @@ -120,7 +121,6 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s) load_binary(s, l); s[l] = '\0'; } -#endif #ifndef BOOST_NO_STD_WSTRING template<class Archive, class Elem, class Tr> diff --git a/boost/archive/impl/basic_binary_oprimitive.ipp b/boost/archive/impl/basic_binary_oprimitive.ipp index 130831e4fb..7b042173a4 100644 --- a/boost/archive/impl/basic_binary_oprimitive.ipp +++ b/boost/archive/impl/basic_binary_oprimitive.ipp @@ -71,6 +71,7 @@ basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::string &s) } #ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_INTRINSIC_WCHAR_T template<class Archive, class Elem, class Tr> BOOST_ARCHIVE_OR_WARCHIVE_DECL void basic_binary_oprimitive<Archive, Elem, Tr>::save(const wchar_t * ws) @@ -91,6 +92,7 @@ basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::wstring &ws) save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); } #endif +#endif // BOOST_NO_CWCHAR template<class Archive, class Elem, class Tr> BOOST_ARCHIVE_OR_WARCHIVE_DECL diff --git a/boost/archive/impl/text_wiarchive_impl.ipp b/boost/archive/impl/text_wiarchive_impl.ipp index 12af2b9f12..e85625ac32 100644 --- a/boost/archive/impl/text_wiarchive_impl.ipp +++ b/boost/archive/impl/text_wiarchive_impl.ipp @@ -56,7 +56,7 @@ text_wiarchive_impl<Archive>::load(std::string &s) s.resize(0); s.reserve(size); while(size-- > 0){ - int x = is.narrow(is.get(), '\0'); + char x = is.narrow(is.get(), '\0'); s += x; } } diff --git a/boost/archive/impl/xml_woarchive_impl.ipp b/boost/archive/impl/xml_woarchive_impl.ipp index 58f92c9d92..01b1a052d5 100644 --- a/boost/archive/impl/xml_woarchive_impl.ipp +++ b/boost/archive/impl/xml_woarchive_impl.ipp @@ -17,7 +17,9 @@ #include <cstring> // strlen #include <cstdlib> // mbtowc +#ifndef BOOST_NO_CWCHAR #include <cwchar> // wcslen +#endif #include <boost/config.hpp> #if defined(BOOST_NO_STDC_NAMESPACE) diff --git a/boost/archive/iterators/base64_from_binary.hpp b/boost/archive/iterators/base64_from_binary.hpp index 00c4e10c10..ee84994439 100644 --- a/boost/archive/iterators/base64_from_binary.hpp +++ b/boost/archive/iterators/base64_from_binary.hpp @@ -41,7 +41,7 @@ template<class CharType> struct from_6_bit { typedef CharType result_type; CharType operator()(CharType t) const{ - const char * lookup_table = + static const char * lookup_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" diff --git a/boost/archive/iterators/binary_from_base64.hpp b/boost/archive/iterators/binary_from_base64.hpp index 2eb7828251..89b8f889da 100644 --- a/boost/archive/iterators/binary_from_base64.hpp +++ b/boost/archive/iterators/binary_from_base64.hpp @@ -37,7 +37,7 @@ template<class CharType> struct to_6_bit { typedef CharType result_type; CharType operator()(CharType t) const{ - const signed char lookup_table[] = { + static const signed char lookup_table[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, diff --git a/boost/archive/iterators/escape.hpp b/boost/archive/iterators/escape.hpp index a1fee91420..103b31e0fe 100644 --- a/boost/archive/iterators/escape.hpp +++ b/boost/archive/iterators/escape.hpp @@ -102,7 +102,8 @@ public: super_t(base), m_bnext(NULL), m_bend(NULL), - m_full(false) + m_full(false), + m_current_value(0) { } }; diff --git a/boost/archive/iterators/istream_iterator.hpp b/boost/archive/iterators/istream_iterator.hpp index 9a1d555c10..a187f605e6 100644 --- a/boost/archive/iterators/istream_iterator.hpp +++ b/boost/archive/iterators/istream_iterator.hpp @@ -56,7 +56,7 @@ class istream_iterator : //Access the value referred to Elem dereference() const { - return m_istream->peek(); + return static_cast<Elem>(m_istream->peek()); } void increment(){ @@ -75,14 +75,14 @@ public: } istream_iterator() : - m_istream(NULL) + m_istream(NULL), + m_current_value(NULL) {} istream_iterator(const istream_iterator<Elem> & rhs) : m_istream(rhs.m_istream), m_current_value(rhs.m_current_value) {} - }; } // namespace iterators diff --git a/boost/archive/iterators/mb_from_wchar.hpp b/boost/archive/iterators/mb_from_wchar.hpp index b6dc9b2151..05df71c258 100644 --- a/boost/archive/iterators/mb_from_wchar.hpp +++ b/boost/archive/iterators/mb_from_wchar.hpp @@ -18,8 +18,9 @@ #include <boost/assert.hpp> #include <cstddef> // size_t +#ifndef BOOST_NO_CWCHAR #include <cwchar> // mbstate_t - +#endif #include <boost/config.hpp> #if defined(BOOST_NO_STDC_NAMESPACE) namespace std{ diff --git a/boost/archive/iterators/transform_width.hpp b/boost/archive/iterators/transform_width.hpp index d042560e29..09c050a927 100644 --- a/boost/archive/iterators/transform_width.hpp +++ b/boost/archive/iterators/transform_width.hpp @@ -111,6 +111,7 @@ public: transform_width(T start) : super_t(Base(static_cast< T >(start))), m_buffer_out_full(false), + m_buffer_out(0), // To disable GCC warning, but not truly necessary //(m_buffer_in will be initialized later before being //used because m_remaining_bits == 0) diff --git a/boost/archive/iterators/wchar_from_mb.hpp b/boost/archive/iterators/wchar_from_mb.hpp index 52a44bdc79..2af8f6401f 100644 --- a/boost/archive/iterators/wchar_from_mb.hpp +++ b/boost/archive/iterators/wchar_from_mb.hpp @@ -19,7 +19,9 @@ #include <boost/assert.hpp> #include <cctype> #include <cstddef> // size_t +#ifndef BOOST_NO_CWCHAR #include <cwchar> // mbstate_t +#endif #include <algorithm> // copy #include <boost/config.hpp> diff --git a/boost/archive/wcslen.hpp b/boost/archive/wcslen.hpp index 2a3d6351d4..0b60004f09 100644 --- a/boost/archive/wcslen.hpp +++ b/boost/archive/wcslen.hpp @@ -44,7 +44,9 @@ inline std::size_t wcslen(const wchar_t * ws) #else +#ifndef BOOST_NO_CWCHAR #include <cwchar> +#endif #ifdef BOOST_NO_STDC_NAMESPACE namespace std{ using ::wcslen; } #endif diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp index baeb86d78e..afe400e5b7 100644 --- a/boost/asio/detail/config.hpp +++ b/boost/asio/detail/config.hpp @@ -65,7 +65,8 @@ #if !defined(BOOST_ASIO_MSVC) # if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC) # define BOOST_ASIO_MSVC BOOST_MSVC -# elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +# elif defined(_MSC_VER) && (defined(__INTELLISENSE__) \ + || (!defined(__MWERKS__) && !defined(__EDG_VERSION__))) # define BOOST_ASIO_MSVC _MSC_VER # endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC) #endif // defined(BOOST_ASIO_MSVC) @@ -154,6 +155,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1900) +# define BOOST_ASIO_HAS_VARIADIC_TEMPLATES 1 +# endif // (_MSC_VER >= 1900) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES) #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) @@ -172,6 +178,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1900) +# define BOOST_ASIO_HAS_CONSTEXPR 1 +# endif // (_MSC_VER >= 1900) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_CONSTEXPR) #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) #if !defined(BOOST_ASIO_CONSTEXPR) @@ -296,11 +307,11 @@ # endif // (__cplusplus >= 201103) # endif // defined(__clang__) # if defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if defined(__GXX_EXPERIMENTAL_CXX0X__) # define BOOST_ASIO_HAS_STD_ATOMIC 1 # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # endif // defined(__GNUC__) # if defined(BOOST_ASIO_MSVC) # if (_MSC_VER >= 1700) @@ -988,12 +999,14 @@ # if defined(__linux__) # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) # if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) -# if !defined(__INTEL_COMPILER) && !defined(__ICL) +# if !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !(defined(__clang__) && defined(__ANDROID__)) # define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 # define BOOST_ASIO_THREAD_KEYWORD __thread # elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) # define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 # endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) + // && !(defined(__clang__) && defined(__ANDROID__)) # endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) # endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) # endif // defined(__linux__) diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp index db6f3d1b8f..17f57d5221 100644 --- a/boost/asio/detail/dev_poll_reactor.hpp +++ b/boost/asio/detail/dev_poll_reactor.hpp @@ -102,15 +102,21 @@ public: BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data&, bool closing); - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data&); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&); + // Add a new timer queue to the reactor. template <typename Time_Traits> void add_timer_queue(timer_queue<Time_Traits>& queue); diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp index 64c5b2704c..34ed0370f5 100644 --- a/boost/asio/detail/epoll_reactor.hpp +++ b/boost/asio/detail/epoll_reactor.hpp @@ -63,6 +63,7 @@ public: BOOST_ASIO_DECL descriptor_state(); void set_ready_events(uint32_t events) { task_result_ = events; } + void add_ready_events(uint32_t events) { task_result_ |= events; } BOOST_ASIO_DECL operation* perform_io(uint32_t events); BOOST_ASIO_DECL static void do_complete( io_service_impl* owner, operation* base, @@ -123,14 +124,22 @@ public: per_descriptor_data& descriptor_data); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data& descriptor_data, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data& descriptor_data); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data( + per_descriptor_data& descriptor_data); + // Add a new timer queue to the reactor. template <typename Time_Traits> void add_timer_queue(timer_queue<Time_Traits>& timer_queue); diff --git a/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/asio/detail/impl/dev_poll_reactor.ipp index efe2ba7086..7efb05ed02 100644 --- a/boost/asio/detail/impl/dev_poll_reactor.ipp +++ b/boost/asio/detail/impl/dev_poll_reactor.ipp @@ -235,6 +235,11 @@ void dev_poll_reactor::deregister_internal_descriptor( op_queue_[i].cancel_operations(descriptor, ops, ec); } +void dev_poll_reactor::cleanup_descriptor_data( + dev_poll_reactor::per_descriptor_data&) +{ +} + void dev_poll_reactor::run(bool block, op_queue<operation>& ops) { boost::asio::detail::mutex::scoped_lock lock(mutex_); diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp index 610ce31ce5..3d3d244e0a 100644 --- a/boost/asio/detail/impl/epoll_reactor.ipp +++ b/boost/asio/detail/impl/epoll_reactor.ipp @@ -359,10 +359,16 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor, descriptor_lock.unlock(); - free_descriptor_state(descriptor_data); - descriptor_data = 0; - io_service_.post_deferred_completions(ops); + + // Leave descriptor_data set so that it will be freed by the subsequent + // call to cleanup_descriptor_data. + } + else + { + // We are shutting down, so prevent cleanup_descriptor_data from freeing + // the descriptor_data object and let the destructor free it instead. + descriptor_data = 0; } } @@ -388,6 +394,22 @@ void epoll_reactor::deregister_internal_descriptor(socket_type descriptor, descriptor_lock.unlock(); + // Leave descriptor_data set so that it will be freed by the subsequent + // call to cleanup_descriptor_data. + } + else + { + // We are shutting down, so prevent cleanup_descriptor_data from freeing + // the descriptor_data object and let the destructor free it instead. + descriptor_data = 0; + } +} + +void epoll_reactor::cleanup_descriptor_data( + per_descriptor_data& descriptor_data) +{ + if (descriptor_data) + { free_descriptor_state(descriptor_data); descriptor_data = 0; } @@ -451,8 +473,15 @@ void epoll_reactor::run(bool block, op_queue<operation>& ops) // don't call work_started() here. This still allows the io_service to // stop if the only remaining operations are descriptor operations. descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr); - descriptor_data->set_ready_events(events[i].events); - ops.push(descriptor_data); + if (!ops.is_enqueued(descriptor_data)) + { + descriptor_data->set_ready_events(events[i].events); + ops.push(descriptor_data); + } + else + { + descriptor_data->add_ready_events(events[i].events); + } } } diff --git a/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/asio/detail/impl/kqueue_reactor.ipp index b4a7a10b71..8057606ce6 100644 --- a/boost/asio/detail/impl/kqueue_reactor.ipp +++ b/boost/asio/detail/impl/kqueue_reactor.ipp @@ -312,10 +312,16 @@ void kqueue_reactor::deregister_descriptor(socket_type descriptor, descriptor_lock.unlock(); - free_descriptor_state(descriptor_data); - descriptor_data = 0; - io_service_.post_deferred_completions(ops); + + // Leave descriptor_data set so that it will be freed by the subsequent + // call to cleanup_descriptor_data. + } + else + { + // We are shutting down, so prevent cleanup_descriptor_data from freeing + // the descriptor_data object and let the destructor free it instead. + descriptor_data = 0; } } @@ -345,6 +351,22 @@ void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor, descriptor_lock.unlock(); + // Leave descriptor_data set so that it will be freed by the subsequent + // call to cleanup_descriptor_data. + } + else + { + // We are shutting down, so prevent cleanup_descriptor_data from freeing + // the descriptor_data object and let the destructor free it instead. + descriptor_data = 0; + } +} + +void kqueue_reactor::cleanup_descriptor_data( + per_descriptor_data& descriptor_data) +{ + if (descriptor_data) + { free_descriptor_state(descriptor_data); descriptor_data = 0; } diff --git a/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/asio/detail/impl/reactive_descriptor_service.ipp index 56caec9fd3..a0300c47d0 100644 --- a/boost/asio/detail/impl/reactive_descriptor_service.ipp +++ b/boost/asio/detail/impl/reactive_descriptor_service.ipp @@ -88,10 +88,12 @@ void reactive_descriptor_service::destroy( reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, (impl.state_ & descriptor_ops::possible_dup) == 0); - } - boost::system::error_code ignored_ec; - descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); + boost::system::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } } boost::system::error_code reactive_descriptor_service::assign( @@ -128,9 +130,15 @@ boost::system::error_code reactive_descriptor_service::close( reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, (impl.state_ & descriptor_ops::possible_dup) == 0); - } - descriptor_ops::close(impl.descriptor_, impl.state_, ec); + descriptor_ops::close(impl.descriptor_, impl.state_, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } // The descriptor is closed by the OS even if close() returns an error. // @@ -154,6 +162,7 @@ reactive_descriptor_service::release( BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release")); reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false); + reactor_.cleanup_descriptor_data(impl.reactor_data_); construct(impl); } diff --git a/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/asio/detail/impl/reactive_socket_service_base.ipp index 21e77e9f93..3594ae0528 100644 --- a/boost/asio/detail/impl/reactive_socket_service_base.ipp +++ b/boost/asio/detail/impl/reactive_socket_service_base.ipp @@ -89,6 +89,8 @@ void reactive_socket_service_base::destroy( boost::system::error_code ignored_ec; socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); } } @@ -102,9 +104,15 @@ boost::system::error_code reactive_socket_service_base::close( reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, (impl.state_ & socket_ops::possible_dup) == 0); - } - socket_ops::close(impl.socket_, impl.state_, false, ec); + socket_ops::close(impl.socket_, impl.state_, false, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } // The descriptor is closed by the OS even if close() returns an error. // @@ -224,7 +232,7 @@ void reactive_socket_service_base::start_accept_op( reactor_op* op, bool is_continuation, bool peer_is_open) { if (!peer_is_open) - start_op(impl, reactor::read_op, op, true, is_continuation, false); + start_op(impl, reactor::read_op, op, is_continuation, true, false); else { op->ec_ = boost::asio::error::already_open; diff --git a/boost/asio/detail/impl/select_reactor.ipp b/boost/asio/detail/impl/select_reactor.ipp index 80686eaf97..869f73492b 100644 --- a/boost/asio/detail/impl/select_reactor.ipp +++ b/boost/asio/detail/impl/select_reactor.ipp @@ -163,6 +163,11 @@ void select_reactor::deregister_internal_descriptor( op_queue_[i].cancel_operations(descriptor, ops); } +void select_reactor::cleanup_descriptor_data( + select_reactor::per_descriptor_data&) +{ +} + void select_reactor::run(bool block, op_queue<operation>& ops) { boost::asio::detail::mutex::scoped_lock lock(mutex_); diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp index 56313e0923..95ea8bee21 100644 --- a/boost/asio/detail/impl/signal_set_service.ipp +++ b/boost/asio/detail/impl/signal_set_service.ipp @@ -187,6 +187,7 @@ void signal_set_service::fork_service( state->fork_prepared_ = true; lock.unlock(); reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_); + reactor_.cleanup_descriptor_data(reactor_data_); } break; case boost::asio::io_service::fork_parent: @@ -539,8 +540,9 @@ void signal_set_service::remove_service(signal_set_service* service) // Disable the pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock(); - service->reactor_.deregister_descriptor( - read_descriptor, service->reactor_data_, false); + service->reactor_.deregister_internal_descriptor( + read_descriptor, service->reactor_data_); + service->reactor_.cleanup_descriptor_data(service->reactor_data_); lock.lock(); #endif // !defined(BOOST_ASIO_WINDOWS) // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) diff --git a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp index 22818f7e92..93f5ed0713 100644 --- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp +++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp @@ -177,9 +177,16 @@ boost::system::error_code win_iocp_socket_service_base::close( reinterpret_cast<void**>(&reactor_), 0, 0)); if (r) r->deregister_descriptor(impl.socket_, impl.reactor_data_, true); - } - socket_ops::close(impl.socket_, impl.state_, false, ec); + socket_ops::close(impl.socket_, impl.state_, false, ec); + + if (r) + r->cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } impl.socket_ = invalid_socket; impl.state_ = 0; @@ -629,10 +636,14 @@ void win_iocp_socket_service_base::close_for_destruction( reinterpret_cast<void**>(&reactor_), 0, 0)); if (r) r->deregister_descriptor(impl.socket_, impl.reactor_data_, true); + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + if (r) + r->cleanup_descriptor_data(impl.reactor_data_); } - boost::system::error_code ignored_ec; - socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); impl.socket_ = invalid_socket; impl.state_ = 0; impl.cancel_token_.reset(); diff --git a/boost/asio/detail/kqueue_reactor.hpp b/boost/asio/detail/kqueue_reactor.hpp index 6aba2b264f..c6182b4d55 100644 --- a/boost/asio/detail/kqueue_reactor.hpp +++ b/boost/asio/detail/kqueue_reactor.hpp @@ -125,14 +125,22 @@ public: per_descriptor_data& descriptor_data); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data& descriptor_data, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data& descriptor_data); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data( + per_descriptor_data& descriptor_data); + // Add a new timer queue to the reactor. template <typename Time_Traits> void add_timer_queue(timer_queue<Time_Traits>& queue); diff --git a/boost/asio/detail/op_queue.hpp b/boost/asio/detail/op_queue.hpp index 9605248567..89f318eedf 100644 --- a/boost/asio/detail/op_queue.hpp +++ b/boost/asio/detail/op_queue.hpp @@ -139,6 +139,12 @@ public: return front_ == 0; } + // Test whether an operation is already enqueued. + bool is_enqueued(Operation* o) const + { + return op_queue_access::next(o) != 0 || back_ == o; + } + private: friend class op_queue_access; diff --git a/boost/asio/detail/select_reactor.hpp b/boost/asio/detail/select_reactor.hpp index 69b04c82b5..d6f75242e5 100644 --- a/boost/asio/detail/select_reactor.hpp +++ b/boost/asio/detail/select_reactor.hpp @@ -107,13 +107,20 @@ public: BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data&, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( - socket_type descriptor, per_descriptor_data& descriptor_data); + socket_type descriptor, per_descriptor_data&); + + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&); // Move descriptor registration from one descriptor_data object to another. BOOST_ASIO_DECL void move_descriptor(socket_type descriptor, diff --git a/boost/asio/detail/socket_types.hpp b/boost/asio/detail/socket_types.hpp index 8467118b54..0768f70077 100644 --- a/boost/asio/detail/socket_types.hpp +++ b/boost/asio/detail/socket_types.hpp @@ -57,7 +57,11 @@ # include <boost/asio/detail/old_win_sdk_compat.hpp> #else # include <sys/ioctl.h> -# if !defined(__SYMBIAN32__) +# if (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) || defined(__NetBSD__) \ + || defined(__OpenBSD__) || defined(__linux__) +# include <poll.h> +# elif !defined(__SYMBIAN32__) # include <sys/poll.h> # endif # include <sys/types.h> diff --git a/boost/asio/detail/winapi_thread.hpp b/boost/asio/detail/winapi_thread.hpp index 204e73f42a..79aba9b519 100644 --- a/boost/asio/detail/winapi_thread.hpp +++ b/boost/asio/detail/winapi_thread.hpp @@ -20,8 +20,8 @@ #if defined(BOOST_ASIO_WINDOWS) #if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) -#include <memory> #include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/scoped_ptr.hpp> #include <boost/asio/detail/socket_types.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> @@ -42,7 +42,7 @@ public: template <typename Function> winapi_thread(Function f, unsigned int = 0) { - std::auto_ptr<func_base> arg(new func<Function>(f)); + scoped_ptr<func_base> arg(new func<Function>(f)); DWORD thread_id = 0; thread_ = ::CreateThread(0, 0, winapi_thread_function, arg.get(), 0, &thread_id); @@ -106,7 +106,7 @@ private: inline DWORD WINAPI winapi_thread_function(LPVOID arg) { - std::auto_ptr<winapi_thread::func_base> func( + scoped_ptr<winapi_thread::func_base> func( static_cast<winapi_thread::func_base*>(arg)); func->run(); return 0; diff --git a/boost/asio/use_future.hpp b/boost/asio/use_future.hpp index 43f6102e4d..e4ce7f7975 100644 --- a/boost/asio/use_future.hpp +++ b/boost/asio/use_future.hpp @@ -78,10 +78,10 @@ private: /** * See the documentation for boost::asio::use_future_t for a usage example. */ -#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -constexpr use_future_t<> use_future; -#elif defined(BOOST_ASIO_MSVC) +#if defined(BOOST_ASIO_MSVC) __declspec(selectany) use_future_t<> use_future; +#elif defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) +constexpr use_future_t<> use_future; #endif } // namespace asio diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp index 7dfc1c3d18..76b6440b01 100644 --- a/boost/asio/version.hpp +++ b/boost/asio/version.hpp @@ -18,6 +18,6 @@ // BOOST_ASIO_VERSION % 100 is the sub-minor version // BOOST_ASIO_VERSION / 100 % 1000 is the minor version // BOOST_ASIO_VERSION / 100000 is the major version -#define BOOST_ASIO_VERSION 101009 // 1.10.9 +#define BOOST_ASIO_VERSION 101010 // 1.10.10 #endif // BOOST_ASIO_VERSION_HPP diff --git a/boost/atomic/detail/atomic_template.hpp b/boost/atomic/detail/atomic_template.hpp index dd3c741506..7bbc1fffad 100644 --- a/boost/atomic/detail/atomic_template.hpp +++ b/boost/atomic/detail/atomic_template.hpp @@ -19,11 +19,13 @@ #include <cstddef> #include <boost/cstdint.hpp> #include <boost/assert.hpp> -#include <boost/type_traits/is_signed.hpp> -#include <boost/type_traits/is_integral.hpp> #include <boost/atomic/detail/config.hpp> #include <boost/atomic/detail/bitwise_cast.hpp> #include <boost/atomic/detail/operations_fwd.hpp> +#include <boost/atomic/detail/type_traits/is_signed.hpp> +#include <boost/atomic/detail/type_traits/is_integral.hpp> +#include <boost/atomic/detail/type_traits/is_function.hpp> +#include <boost/atomic/detail/type_traits/conditional.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once @@ -56,7 +58,19 @@ BOOST_FORCEINLINE BOOST_CONSTEXPR bool cas_failure_order_must_not_be_stronger_th return (failure_order & 15u) <= (success_order & 15u); } -template< typename T, bool IsInt = boost::is_integral< T >::value > +template< typename T, bool IsFunction = boost::atomics::detail::is_function< T >::value > +struct classify_pointer +{ + typedef void* type; +}; + +template< typename T > +struct classify_pointer< T, true > +{ + typedef void type; +}; + +template< typename T, bool IsInt = boost::atomics::detail::is_integral< T >::value > struct classify { typedef void type; @@ -66,21 +80,157 @@ template< typename T > struct classify< T, true > { typedef int type; }; template< typename T > -struct classify< T*, false > { typedef void* type; }; +struct classify< T*, false > { typedef typename classify_pointer< T >::type type; }; + +template< > +struct classify< void*, false > { typedef void type; }; + +template< > +struct classify< const void*, false > { typedef void type; }; + +template< > +struct classify< volatile void*, false > { typedef void type; }; + +template< > +struct classify< const volatile void*, false > { typedef void type; }; + +template< typename T, typename U > +struct classify< T U::*, false > { typedef void type; }; + +template< bool > +struct boolean_constant {}; +typedef boolean_constant< true > true_constant; +typedef boolean_constant< false > false_constant; + template< typename T, typename Kind > class base_atomic; +//! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types +template< typename T > +class base_atomic< T, void > +{ +public: + typedef T value_type; + +protected: + typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations; + typedef typename boost::atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; + +public: + typedef typename operations::storage_type storage_type; + +private: + typedef boolean_constant< sizeof(value_type) == sizeof(storage_type) > value_matches_storage; + +protected: + typename operations::aligned_storage_type m_storage; + +public: + BOOST_FORCEINLINE explicit base_atomic(value_arg_type v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, value_matches_storage()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, value_matches_storage()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, true_constant) volatile BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); +#else + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, false_constant()); +#endif + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, false_constant) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, true_constant) volatile BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); +#else + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, false_constant()); +#endif + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, false_constant) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + + //! Implementation for integers template< typename T > class base_atomic< T, int > { -private: +public: typedef T value_type; typedef T difference_type; protected: - typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::is_signed< T >::value > operations; + typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::atomics::detail::is_signed< T >::value > operations; typedef value_type value_arg_type; public: @@ -131,10 +281,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = static_cast< storage_type >(expected); const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order); expected = static_cast< value_type >(old_value); return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -148,10 +302,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = static_cast< storage_type >(expected); const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order); expected = static_cast< value_type >(old_value); return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -174,11 +332,6 @@ public: return static_cast< value_type >(operations::fetch_xor(m_storage.value, static_cast< storage_type >(v), order)); } - BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT - { - return operations::is_lock_free(m_storage.value); - } - BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT { return fetch_add(1); @@ -232,7 +385,7 @@ public: template< > class base_atomic< bool, int > { -private: +public: typedef bool value_type; protected: @@ -277,10 +430,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = static_cast< storage_type >(expected); const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order); expected = !!old_value; return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -294,10 +451,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = static_cast< storage_type >(expected); const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order); expected = !!old_value; return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -305,109 +466,16 @@ public: return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); } - BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT - { - return operations::is_lock_free(m_storage.value); - } - - BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) - BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) -}; - - -//! Implementation for user-defined types, such as structs and enums -template< typename T > -class base_atomic< T, void > -{ -private: - typedef T value_type; - -protected: - typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations; - typedef value_type const& value_arg_type; - -public: - typedef typename operations::storage_type storage_type; - -protected: - typename operations::aligned_storage_type m_storage; - -public: - BOOST_FORCEINLINE explicit base_atomic(value_type const& v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) - { - } - - BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(order != memory_order_consume); - BOOST_ASSERT(order != memory_order_acquire); - BOOST_ASSERT(order != memory_order_acq_rel); - - operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order); - } - - BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(order != memory_order_release); - BOOST_ASSERT(order != memory_order_acq_rel); - - return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order)); - } - - BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order)); - } - - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(failure_order != memory_order_release); - BOOST_ASSERT(failure_order != memory_order_acq_rel); - BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); - - storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); - expected = atomics::detail::bitwise_cast< value_type >(old_value); - return res; - } - - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); - } - - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(failure_order != memory_order_release); - BOOST_ASSERT(failure_order != memory_order_acq_rel); - BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); - - storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); - expected = atomics::detail::bitwise_cast< value_type >(old_value); - return res; - } - - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); - } - - BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT - { - return operations::is_lock_free(m_storage.value); - } - BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) }; -//! Implementation for pointers +//! Implementation for pointers to object types template< typename T > class base_atomic< T*, void* > { -private: +public: typedef T* value_type; typedef std::ptrdiff_t difference_type; @@ -465,10 +533,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); expected = atomics::detail::bitwise_cast< value_type >(old_value); return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -482,10 +554,14 @@ public: BOOST_ASSERT(failure_order != memory_order_acq_rel); BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) + return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); +#else storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); expected = atomics::detail::bitwise_cast< value_type >(old_value); return res; +#endif } BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT @@ -493,11 +569,6 @@ public: return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); } - BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT - { - return operations::is_lock_free(m_storage.value); - } - BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT { return fetch_add(1); @@ -532,136 +603,6 @@ public: BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) }; - -//! Implementation for void pointers -template< > -class base_atomic< void*, void* > -{ -private: - typedef void* value_type; - typedef std::ptrdiff_t difference_type; - -protected: - typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations; - typedef value_type value_arg_type; - -public: - typedef operations::storage_type storage_type; - -protected: - operations::aligned_storage_type m_storage; - -public: - BOOST_DEFAULTED_FUNCTION(base_atomic(), {}) - BOOST_FORCEINLINE explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) - { - } - - BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(order != memory_order_consume); - BOOST_ASSERT(order != memory_order_acquire); - BOOST_ASSERT(order != memory_order_acq_rel); - - operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order); - } - - BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(order != memory_order_release); - BOOST_ASSERT(order != memory_order_acq_rel); - - return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order)); - } - - BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return atomics::detail::bitwise_cast< value_type >(operations::fetch_add(m_storage.value, static_cast< storage_type >(v), order)); - } - - BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return atomics::detail::bitwise_cast< value_type >(operations::fetch_sub(m_storage.value, static_cast< storage_type >(v), order)); - } - - BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order)); - } - - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(failure_order != memory_order_release); - BOOST_ASSERT(failure_order != memory_order_acq_rel); - BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); - - storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); - expected = atomics::detail::bitwise_cast< value_type >(old_value); - return res; - } - - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); - } - - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT - { - BOOST_ASSERT(failure_order != memory_order_release); - BOOST_ASSERT(failure_order != memory_order_acq_rel); - BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); - - storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); - expected = atomics::detail::bitwise_cast< value_type >(old_value); - return res; - } - - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { - return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); - } - - BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT - { - return operations::is_lock_free(m_storage.value); - } - - BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT - { - return fetch_add(1); - } - - BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT - { - return (char*)fetch_add(1) + 1; - } - - BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT - { - return fetch_sub(1); - } - - BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT - { - return (char*)fetch_sub(1) - 1; - } - - BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT - { - return (char*)fetch_add(v) + v; - } - - BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT - { - return (char*)fetch_sub(v) - v; - } - - BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) - BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) -}; - } // namespace detail template< typename T > @@ -669,11 +610,11 @@ class atomic : public atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type > { private: - typedef T value_type; typedef atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type > base_type; typedef typename base_type::value_arg_type value_arg_type; public: + typedef typename base_type::value_type value_type; typedef typename base_type::storage_type storage_type; public: @@ -694,11 +635,17 @@ public: return v; } - BOOST_FORCEINLINE operator value_type() volatile const BOOST_NOEXCEPT + BOOST_FORCEINLINE operator value_type() const volatile BOOST_NOEXCEPT { return this->load(); } + BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT + { + // C++17 requires all instances of atomic<> return a value consistent with is_always_lock_free here + return is_always_lock_free; + } + BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return this->m_storage.value; } BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return this->m_storage.value; } BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return this->m_storage.value; } diff --git a/boost/atomic/detail/bitwise_cast.hpp b/boost/atomic/detail/bitwise_cast.hpp index 1405a25d6a..4a285ecab2 100644 --- a/boost/atomic/detail/bitwise_cast.hpp +++ b/boost/atomic/detail/bitwise_cast.hpp @@ -25,6 +25,12 @@ #pragma once #endif +#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600 +#pragma GCC diagnostic push +// missing initializer for member var +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + namespace boost { namespace atomics { namespace detail { @@ -34,7 +40,7 @@ BOOST_FORCEINLINE T* addressof(T& value) BOOST_NOEXCEPT { // Note: The point of using a local struct as the intermediate type instead of char is to avoid gcc warnings // if T is a const volatile char*: - // warning: casting ‘const volatile char* const’ to ‘const volatile char&’ does not dereference pointer + // warning: casting 'const volatile char* const' to 'const volatile char&' does not dereference pointer // The local struct makes sure T is not related to the cast target type. struct opaque_type; return reinterpret_cast< T* >(&const_cast< opaque_type& >(reinterpret_cast< const volatile opaque_type& >(value))); @@ -61,4 +67,8 @@ BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT } // namespace atomics } // namespace boost +#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600 +#pragma GCC diagnostic pop +#endif + #endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ diff --git a/boost/atomic/detail/config.hpp b/boost/atomic/detail/config.hpp index 00f7bff696..7a43e23cbc 100644 --- a/boost/atomic/detail/config.hpp +++ b/boost/atomic/detail/config.hpp @@ -73,4 +73,30 @@ #define BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS #endif +#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#if !(defined(BOOST_LIBSTDCXX11) && (BOOST_LIBSTDCXX_VERSION+0) >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */ +// This macro indicates that there is no <type_traits> standard header that is sufficient for Boost.Atomic needs. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS +#endif +#endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + +// Enable pointer/reference casts between storage and value when possible. +// Note: Despite that MSVC does not employ strict aliasing rules for optimizations +// and does not require an explicit markup for types that may alias, we still don't +// enable the optimization for this compiler because at least MSVC-8 and 9 are known +// to generate broken code sometimes when casts are used. +#if defined(__GNUC__) && (!defined(BOOST_INTEL_CXX_VERSION) || (BOOST_INTEL_CXX_VERSION+0) >= 1300) +#define BOOST_ATOMIC_DETAIL_MAY_ALIAS __attribute__((__may_alias__)) +#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS +#elif defined(__has_attribute) +#if __has_attribute(__may_alias__) +#define BOOST_ATOMIC_DETAIL_MAY_ALIAS __attribute__((__may_alias__)) +#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS +#endif +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_MAY_ALIAS) +#define BOOST_ATOMIC_DETAIL_MAY_ALIAS +#endif + #endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_emulated.hpp b/boost/atomic/detail/ops_emulated.hpp index a21128ec69..e15f37a680 100644 --- a/boost/atomic/detail/ops_emulated.hpp +++ b/boost/atomic/detail/ops_emulated.hpp @@ -142,11 +142,6 @@ struct emulated_operations { store(storage, (storage_type)0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return false; - } }; template< std::size_t Size, bool Signed > diff --git a/boost/atomic/detail/ops_gcc_alpha.hpp b/boost/atomic/detail/ops_gcc_alpha.hpp index 15118f58a2..5a9deb42ea 100644 --- a/boost/atomic/detail/ops_gcc_alpha.hpp +++ b/boost/atomic/detail/ops_gcc_alpha.hpp @@ -339,11 +339,6 @@ struct operations< 4u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; @@ -851,11 +846,6 @@ struct operations< 8u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; diff --git a/boost/atomic/detail/ops_gcc_arm.hpp b/boost/atomic/detail/ops_gcc_arm.hpp index e181b16853..86a75f5b25 100644 --- a/boost/atomic/detail/ops_gcc_arm.hpp +++ b/boost/atomic/detail/ops_gcc_arm.hpp @@ -404,11 +404,6 @@ struct operations< 4u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; @@ -946,11 +941,6 @@ struct operations< 8u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) diff --git a/boost/atomic/detail/ops_gcc_atomic.hpp b/boost/atomic/detail/ops_gcc_atomic.hpp index 0a34c01f16..4e1adae86a 100644 --- a/boost/atomic/detail/ops_gcc_atomic.hpp +++ b/boost/atomic/detail/ops_gcc_atomic.hpp @@ -161,11 +161,6 @@ struct gcc_atomic_operations { __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order)); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT - { - return __atomic_is_lock_free(sizeof(storage_type), &storage); - } }; #if BOOST_ATOMIC_INT128_LOCK_FREE > 0 diff --git a/boost/atomic/detail/ops_gcc_ppc.hpp b/boost/atomic/detail/ops_gcc_ppc.hpp index 4183bc0485..76eae4e232 100644 --- a/boost/atomic/detail/ops_gcc_ppc.hpp +++ b/boost/atomic/detail/ops_gcc_ppc.hpp @@ -331,11 +331,6 @@ struct operations< 4u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; @@ -758,11 +753,6 @@ struct operations< 8u, Signed > : { store(storage, 0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; #endif // defined(__powerpc64__) || defined(__PPC64__) diff --git a/boost/atomic/detail/ops_gcc_sparc.hpp b/boost/atomic/detail/ops_gcc_sparc.hpp index fd42fa8095..08492ac69a 100644 --- a/boost/atomic/detail/ops_gcc_sparc.hpp +++ b/boost/atomic/detail/ops_gcc_sparc.hpp @@ -120,11 +120,6 @@ struct gcc_sparc_cas32 : fence_after(order); return v; } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > @@ -192,11 +187,6 @@ struct gcc_sparc_cas64 : { return compare_exchange_strong(storage, expected, desired, success_order, failure_order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/ops_gcc_sync.hpp b/boost/atomic/detail/ops_gcc_sync.hpp index 2f41aff279..a9a9ae2f72 100644 --- a/boost/atomic/detail/ops_gcc_sync.hpp +++ b/boost/atomic/detail/ops_gcc_sync.hpp @@ -145,11 +145,6 @@ struct gcc_sync_operations : if (order == memory_order_seq_cst) __sync_synchronize(); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; #if BOOST_ATOMIC_INT8_LOCK_FREE > 0 diff --git a/boost/atomic/detail/ops_gcc_x86.hpp b/boost/atomic/detail/ops_gcc_x86.hpp index 98dcdc064e..74e45c1f61 100644 --- a/boost/atomic/detail/ops_gcc_x86.hpp +++ b/boost/atomic/detail/ops_gcc_x86.hpp @@ -104,11 +104,6 @@ struct gcc_x86_operations : { store(storage, (storage_type)0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp index e356e8cfbd..7f3962199a 100644 --- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp +++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp @@ -354,11 +354,6 @@ struct gcc_dcas_x86 #endif // defined(__PIC__) #endif } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; #endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) @@ -611,11 +606,6 @@ struct gcc_dcas_x86_64 return v; #endif } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; #endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) diff --git a/boost/atomic/detail/ops_linux_arm.hpp b/boost/atomic/detail/ops_linux_arm.hpp index 01894b63ee..c26bc2c07b 100644 --- a/boost/atomic/detail/ops_linux_arm.hpp +++ b/boost/atomic/detail/ops_linux_arm.hpp @@ -136,11 +136,6 @@ struct linux_arm_cas : return false; } } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/ops_msvc_arm.hpp b/boost/atomic/detail/ops_msvc_arm.hpp index fd07f093fb..e0a709c991 100644 --- a/boost/atomic/detail/ops_msvc_arm.hpp +++ b/boost/atomic/detail/ops_msvc_arm.hpp @@ -18,11 +18,11 @@ #include <intrin.h> #include <boost/memory_order.hpp> -#include <boost/type_traits/make_signed.hpp> #include <boost/atomic/detail/config.hpp> #include <boost/atomic/detail/interlocked.hpp> #include <boost/atomic/detail/storage_type.hpp> #include <boost/atomic/detail/operations_fwd.hpp> +#include <boost/atomic/detail/type_traits/make_signed.hpp> #include <boost/atomic/capabilities.hpp> #include <boost/atomic/detail/ops_msvc_common.hpp> @@ -105,7 +105,7 @@ struct msvc_arm_operations : static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT { - typedef typename make_signed< storage_type >::type signed_storage_type; + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); } @@ -124,11 +124,6 @@ struct msvc_arm_operations : { Derived::store(storage, (storage_type)0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/ops_msvc_x86.hpp b/boost/atomic/detail/ops_msvc_x86.hpp index 24824214dd..623662468d 100644 --- a/boost/atomic/detail/ops_msvc_x86.hpp +++ b/boost/atomic/detail/ops_msvc_x86.hpp @@ -17,11 +17,11 @@ #define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_ #include <boost/memory_order.hpp> -#include <boost/type_traits/make_signed.hpp> #include <boost/atomic/detail/config.hpp> #include <boost/atomic/detail/interlocked.hpp> #include <boost/atomic/detail/storage_type.hpp> #include <boost/atomic/detail/operations_fwd.hpp> +#include <boost/atomic/detail/type_traits/make_signed.hpp> #include <boost/atomic/capabilities.hpp> #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) #include <boost/cstdint.hpp> @@ -135,7 +135,7 @@ struct msvc_x86_operations : static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT { - typedef typename make_signed< storage_type >::type signed_storage_type; + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); } @@ -154,11 +154,6 @@ struct msvc_x86_operations : { store(storage, (storage_type)0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > @@ -799,11 +794,6 @@ struct msvc_dcas_x86 return v; } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > @@ -893,11 +883,6 @@ struct msvc_dcas_x86_64 { return compare_exchange_strong(storage, expected, desired, success_order, failure_order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/ops_windows.hpp b/boost/atomic/detail/ops_windows.hpp index 867f1c6113..50d951dabf 100644 --- a/boost/atomic/detail/ops_windows.hpp +++ b/boost/atomic/detail/ops_windows.hpp @@ -24,11 +24,11 @@ #define BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_ #include <boost/memory_order.hpp> -#include <boost/type_traits/make_signed.hpp> #include <boost/atomic/detail/config.hpp> #include <boost/atomic/detail/interlocked.hpp> #include <boost/atomic/detail/storage_type.hpp> #include <boost/atomic/detail/operations_fwd.hpp> +#include <boost/atomic/detail/type_traits/make_signed.hpp> #include <boost/atomic/capabilities.hpp> #include <boost/atomic/detail/ops_msvc_common.hpp> #include <boost/atomic/detail/ops_extending_cas_based.hpp> @@ -80,7 +80,7 @@ struct windows_operations : static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT { - typedef typename make_signed< storage_type >::type signed_storage_type; + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); } @@ -99,11 +99,6 @@ struct windows_operations : { store(storage, (storage_type)0, order); } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } }; template< bool Signed > diff --git a/boost/atomic/detail/platform.hpp b/boost/atomic/detail/platform.hpp index cc3cf1b67a..786b1f1971 100644 --- a/boost/atomic/detail/platform.hpp +++ b/boost/atomic/detail/platform.hpp @@ -60,7 +60,8 @@ defined(__ARM_ARCH_6ZK__) ||\ defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\ defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\ - defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)\ + defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) ||\ + defined(__ARM_ARCH_8A__)\ ) #define BOOST_ATOMIC_DETAIL_PLATFORM gcc_arm diff --git a/boost/atomic/detail/storage_type.hpp b/boost/atomic/detail/storage_type.hpp index 63a7cef581..59e6901c26 100644 --- a/boost/atomic/detail/storage_type.hpp +++ b/boost/atomic/detail/storage_type.hpp @@ -38,7 +38,7 @@ BOOST_FORCEINLINE void non_atomic_load(T const volatile& from, T& to) BOOST_NOEX } template< std::size_t Size > -struct buffer_storage +struct BOOST_ATOMIC_DETAIL_MAY_ALIAS buffer_storage { BOOST_ALIGNMENT(16) unsigned char data[Size]; @@ -69,7 +69,7 @@ struct make_storage_type { typedef buffer_storage< Size > type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { type value; @@ -81,9 +81,9 @@ struct make_storage_type template< > struct make_storage_type< 1u, false > { - typedef boost::uint8_t type; + typedef boost::uint8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { type value; @@ -95,9 +95,9 @@ struct make_storage_type< 1u, false > template< > struct make_storage_type< 1u, true > { - typedef boost::int8_t type; + typedef boost::int8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { type value; @@ -109,9 +109,9 @@ struct make_storage_type< 1u, true > template< > struct make_storage_type< 2u, false > { - typedef boost::uint16_t type; + typedef boost::uint16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(2) type value; @@ -123,9 +123,9 @@ struct make_storage_type< 2u, false > template< > struct make_storage_type< 2u, true > { - typedef boost::int16_t type; + typedef boost::int16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(2) type value; @@ -137,9 +137,9 @@ struct make_storage_type< 2u, true > template< > struct make_storage_type< 4u, false > { - typedef boost::uint32_t type; + typedef boost::uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(4) type value; @@ -151,9 +151,9 @@ struct make_storage_type< 4u, false > template< > struct make_storage_type< 4u, true > { - typedef boost::int32_t type; + typedef boost::int32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(4) type value; @@ -165,9 +165,9 @@ struct make_storage_type< 4u, true > template< > struct make_storage_type< 8u, false > { - typedef boost::uint64_t type; + typedef boost::uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(8) type value; @@ -179,9 +179,9 @@ struct make_storage_type< 8u, false > template< > struct make_storage_type< 8u, true > { - typedef boost::int64_t type; + typedef boost::int64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(8) type value; @@ -195,9 +195,9 @@ struct make_storage_type< 8u, true > template< > struct make_storage_type< 16u, false > { - typedef boost::uint128_type type; + typedef boost::uint128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(16) type value; @@ -209,9 +209,9 @@ struct make_storage_type< 16u, false > template< > struct make_storage_type< 16u, true > { - typedef boost::int128_type type; + typedef boost::int128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(16) type value; @@ -222,7 +222,7 @@ struct make_storage_type< 16u, true > #elif !defined(BOOST_NO_ALIGNMENT) -struct storage128_t +struct BOOST_ATOMIC_DETAIL_MAY_ALIAS storage128_t { boost::uint64_t data[2]; @@ -252,7 +252,7 @@ struct make_storage_type< 16u, Signed > { typedef storage128_t type; - struct aligned + struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned { BOOST_ALIGNMENT(16) type value; diff --git a/boost/atomic/detail/type_traits/conditional.hpp b/boost/atomic/detail/type_traits/conditional.hpp new file mode 100644 index 0000000000..71397ab154 --- /dev/null +++ b/boost/atomic/detail/type_traits/conditional.hpp @@ -0,0 +1,42 @@ +/* + * 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) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/conditional.hpp + * + * This header defines \c conditional type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ + +#include <boost/atomic/detail/config.hpp> +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#include <type_traits> +#else +#include <boost/type_traits/conditional.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +using std::conditional; +#else +using boost::conditional; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_function.hpp b/boost/atomic/detail/type_traits/is_function.hpp new file mode 100644 index 0000000000..7b82840f5e --- /dev/null +++ b/boost/atomic/detail/type_traits/is_function.hpp @@ -0,0 +1,42 @@ +/* + * 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) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_function.hpp + * + * This header defines \c is_function type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ + +#include <boost/atomic/detail/config.hpp> +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#include <type_traits> +#else +#include <boost/type_traits/is_function.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +using std::is_function; +#else +using boost::is_function; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_integral.hpp b/boost/atomic/detail/type_traits/is_integral.hpp new file mode 100644 index 0000000000..5deb12034c --- /dev/null +++ b/boost/atomic/detail/type_traits/is_integral.hpp @@ -0,0 +1,43 @@ +/* + * 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) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_integral.hpp + * + * This header defines \c is_integral type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ + +#include <boost/atomic/detail/config.hpp> +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include <type_traits> +#else +#include <boost/type_traits/is_integral.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::is_integral; +#else +using boost::is_integral; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_signed.hpp b/boost/atomic/detail/type_traits/is_signed.hpp new file mode 100644 index 0000000000..bf95163828 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_signed.hpp @@ -0,0 +1,43 @@ +/* + * 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) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_signed.hpp + * + * This header defines \c is_signed type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ + +#include <boost/atomic/detail/config.hpp> +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include <type_traits> +#else +#include <boost/type_traits/is_signed.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::is_signed; +#else +using boost::is_signed; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/make_signed.hpp b/boost/atomic/detail/type_traits/make_signed.hpp new file mode 100644 index 0000000000..831efdc391 --- /dev/null +++ b/boost/atomic/detail/type_traits/make_signed.hpp @@ -0,0 +1,43 @@ +/* + * 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) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/make_signed.hpp + * + * This header defines \c make_signed type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ + +#include <boost/atomic/detail/config.hpp> +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include <type_traits> +#else +#include <boost/type_traits/make_signed.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::make_signed; +#else +using boost::make_signed; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ diff --git a/boost/chrono/duration.hpp b/boost/chrono/duration.hpp index 737328c418..0a09674f1a 100644 --- a/boost/chrono/duration.hpp +++ b/boost/chrono/duration.hpp @@ -433,12 +433,13 @@ namespace chrono { rep rep_; public: -#if defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS || \ - defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO +#if defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO BOOST_FORCEINLINE BOOST_CONSTEXPR duration() : rep_(duration_values<rep>::zero()) { } +#elif defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + BOOST_CONSTEXPR duration() {} #else - BOOST_CONSTEXPR duration() BOOST_NOEXCEPT : rep_() {}; + BOOST_CONSTEXPR duration() = default; #endif template <class Rep2> BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR @@ -542,8 +543,8 @@ namespace chrono { const duration<Rep2, Period2>& rhs) { typedef typename common_type<duration<Rep1, Period1>, - duration<Rep2, Period2> >::type CD; - return CD(CD(lhs).count()+CD(rhs).count()); + duration<Rep2, Period2> >::type common_duration; + return common_duration(common_duration(lhs).count()+common_duration(rhs).count()); } // Duration - @@ -555,8 +556,8 @@ namespace chrono { const duration<Rep2, Period2>& rhs) { typedef typename common_type<duration<Rep1, Period1>, - duration<Rep2, Period2> >::type CD; - return CD(CD(lhs).count()-CD(rhs).count()); + duration<Rep2, Period2> >::type common_duration; + return common_duration(common_duration(lhs).count()-common_duration(rhs).count()); } // Duration * @@ -572,9 +573,9 @@ namespace chrono { >::type operator*(const duration<Rep1, Period>& d, const Rep2& s) { - typedef typename common_type<Rep1, Rep2>::type CR; - typedef duration<CR, Period> CD; - return CD(CD(d).count()*static_cast<CR>(s)); + typedef typename common_type<Rep1, Rep2>::type common_rep; + typedef duration<common_rep, Period> common_duration; + return common_duration(common_duration(d).count()*static_cast<common_rep>(s)); } template <class Rep1, class Period, class Rep2> @@ -601,10 +602,9 @@ namespace chrono { >::type operator/(const duration<Rep1, Period>& d, const Rep2& s) { - typedef typename common_type<Rep1, Rep2>::type CR; - typedef duration<CR, Period> CD; - - return CD(CD(d).count()/static_cast<CR>(s)); + typedef typename common_type<Rep1, Rep2>::type common_rep; + typedef duration<common_rep, Period> common_duration; + return common_duration(common_duration(d).count()/static_cast<common_rep>(s)); } template <class Rep1, class Period1, class Rep2, class Period2> @@ -613,8 +613,8 @@ namespace chrono { operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) { typedef typename common_type<duration<Rep1, Period1>, - duration<Rep2, Period2> >::type CD; - return CD(lhs).count() / CD(rhs).count(); + duration<Rep2, Period2> >::type common_duration; + return common_duration(lhs).count() / common_duration(rhs).count(); } #ifdef BOOST_CHRONO_EXTENSIONS @@ -626,10 +626,9 @@ namespace chrono { >::type operator/(const Rep1& s, const duration<Rep2, Period>& d) { - typedef typename common_type<Rep1, Rep2>::type CR; - typedef duration<CR, Period> CD; - - return static_cast<CR>(s)/CD(d).count(); + typedef typename common_type<Rep1, Rep2>::type common_rep; + typedef duration<common_rep, Period> common_duration; + return static_cast<common_rep>(s)/common_duration(d).count(); } #endif // Duration % @@ -642,10 +641,9 @@ namespace chrono { >::type operator%(const duration<Rep1, Period>& d, const Rep2& s) { - typedef typename common_type<Rep1, Rep2>::type CR; - typedef duration<CR, Period> CD; - - return CD(CD(d).count()%static_cast<CR>(s)); + typedef typename common_type<Rep1, Rep2>::type common_rep; + typedef duration<common_rep, Period> common_duration; + return common_duration(common_duration(d).count()%static_cast<common_rep>(s)); } template <class Rep1, class Period1, class Rep2, class Period2> @@ -654,9 +652,9 @@ namespace chrono { operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) { typedef typename common_type<duration<Rep1, Period1>, - duration<Rep2, Period2> >::type CD; + duration<Rep2, Period2> >::type common_duration; - return CD(CD(lhs).count()%CD(rhs).count()); + return common_duration(common_duration(lhs).count()%common_duration(rhs).count()); } @@ -671,8 +669,8 @@ namespace detail { BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const { - typedef typename common_type<LhsDuration, RhsDuration>::type CD; - return CD(lhs).count() == CD(rhs).count(); + typedef typename common_type<LhsDuration, RhsDuration>::type common_duration; + return common_duration(lhs).count() == common_duration(rhs).count(); } }; @@ -690,8 +688,8 @@ namespace detail { BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const { - typedef typename common_type<LhsDuration, RhsDuration>::type CD; - return CD(lhs).count() < CD(rhs).count(); + typedef typename common_type<LhsDuration, RhsDuration>::type common_duration; + return common_duration(lhs).count() < common_duration(rhs).count(); } }; diff --git a/boost/chrono/io/duration_io.hpp b/boost/chrono/io/duration_io.hpp index 34004484f3..f3aca6adfd 100644 --- a/boost/chrono/io/duration_io.hpp +++ b/boost/chrono/io/duration_io.hpp @@ -21,7 +21,7 @@ #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_floating_point.hpp> #include <locale> -#include <iostream> +#include <iosfwd> #include <sstream> namespace boost diff --git a/boost/chrono/io/time_point_io.hpp b/boost/chrono/io/time_point_io.hpp index 0cbc275c0e..ef51210bd8 100644 --- a/boost/chrono/io/time_point_io.hpp +++ b/boost/chrono/io/time_point_io.hpp @@ -34,20 +34,22 @@ #include <locale> #include <ctime> -#define BOOST_CHRONO_INTERNAL_TIMEGM \ - ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \ +#if ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \ || (defined(sun) || defined(__sun)) \ || (defined __IBMCPP__) \ || defined __ANDROID__ \ || defined __QNXNTO__ \ || (defined(_AIX) && defined __GNUC__) +#define BOOST_CHRONO_INTERNAL_TIMEGM +#endif -#define BOOST_CHRONO_INTERNAL_GMTIME \ - (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \ +#if (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \ || ( (defined(sun) || defined(__sun)) && defined __GNUC__) \ || (defined __IBMCPP__) \ || defined __ANDROID__ \ || (defined(_AIX) && defined __GNUC__) +#define BOOST_CHRONO_INTERNAL_GMTIME +#endif #define BOOST_CHRONO_USES_INTERNAL_TIME_GET @@ -746,7 +748,7 @@ namespace boost namespace detail { -//#if BOOST_CHRONO_INTERNAL_TIMEGM +//#if defined BOOST_CHRONO_INTERNAL_TIMEGM inline int32_t is_leap(int32_t year) { @@ -949,7 +951,7 @@ namespace boost } else { -#if BOOST_CHRONO_INTERNAL_GMTIME +#if defined BOOST_CHRONO_INTERNAL_GMTIME if (detail::internal_gmtime(&t, &tm) == 0) failed = true; #elif defined BOOST_WINDOWS && ! defined(__CYGWIN__) @@ -1157,7 +1159,7 @@ namespace boost if (err & std::ios_base::failbit) goto exit; time_t t; -#if BOOST_CHRONO_INTERNAL_TIMEGM +#if defined BOOST_CHRONO_INTERNAL_TIMEGM t = detail::internal_timegm(&tm); #else t = timegm(&tm); @@ -1209,7 +1211,7 @@ namespace boost time_t t; if (tz == timezone::utc || fz != pe) { -#if BOOST_CHRONO_INTERNAL_TIMEGM +#if defined BOOST_CHRONO_INTERNAL_TIMEGM t = detail::internal_timegm(&tm); #else t = timegm(&tm); diff --git a/boost/chrono/io/time_point_units.hpp b/boost/chrono/io/time_point_units.hpp index 7aef8526da..6a4999a5e5 100644 --- a/boost/chrono/io/time_point_units.hpp +++ b/boost/chrono/io/time_point_units.hpp @@ -15,7 +15,7 @@ #include <boost/chrono/thread_clock.hpp> #include <boost/chrono/io/ios_base_state.hpp> #include <string> -#include <iostream> +#include <iosfwd> #include <ios> #include <locale> #include <algorithm> diff --git a/boost/chrono/process_cpu_clocks.hpp b/boost/chrono/process_cpu_clocks.hpp index ca6bef38e9..93d3c94ac8 100644 --- a/boost/chrono/process_cpu_clocks.hpp +++ b/boost/chrono/process_cpu_clocks.hpp @@ -20,7 +20,7 @@ #include <boost/chrono/time_point.hpp> #include <boost/operators.hpp> #include <boost/chrono/detail/system.hpp> -#include <iostream> +#include <iosfwd> #include <boost/type_traits/common_type.hpp> #include <boost/chrono/clock_string.hpp> @@ -476,7 +476,7 @@ namespace std { (std::numeric_limits<Rep>::max)(), (std::numeric_limits<Rep>::max)()); } - static Res lowest() throw() + static Res lowest() BOOST_NOEXCEPT_OR_NOTHROW { return (min)(); } diff --git a/boost/chrono/time_point.hpp b/boost/chrono/time_point.hpp index 6449fac6e1..fc230955d9 100644 --- a/boost/chrono/time_point.hpp +++ b/boost/chrono/time_point.hpp @@ -31,7 +31,6 @@ time2_demo contained this comment: #define BOOST_CHRONO_TIME_POINT_HPP #include <boost/chrono/duration.hpp> -#include <iostream> #ifndef BOOST_CHRONO_HEADER_ONLY // this must occur after all of the includes and before any code appears: diff --git a/boost/circular_buffer/base.hpp b/boost/circular_buffer/base.hpp index 1dec2f2136..4babd9fbb1 100644 --- a/boost/circular_buffer/base.hpp +++ b/boost/circular_buffer/base.hpp @@ -666,7 +666,7 @@ public: break; } if (is_uninitialized(dest)) { - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*dest), boost::move_if_noexcept(*src)); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(dest), boost::move_if_noexcept(*src)); ++constructed; } else { value_type tmp = boost::move_if_noexcept(*src); @@ -1422,7 +1422,7 @@ private: increment(m_last); m_first = m_last; } else { - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), static_cast<ValT>(item)); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_last), static_cast<ValT>(item)); increment(m_last); ++m_size; } @@ -1439,7 +1439,7 @@ private: m_last = m_first; } else { decrement(m_first); - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_first), static_cast<ValT>(item)); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_first), static_cast<ValT>(item)); ++m_size; } } BOOST_CATCH(...) { @@ -2414,7 +2414,7 @@ private: */ void construct_or_replace(bool construct, pointer pos, param_value_type item) { if (construct) - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), item); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(pos), item); else replace(pos, item); } @@ -2426,14 +2426,14 @@ private: */ void construct_or_replace(bool construct, pointer pos, rvalue_type item) { if (construct) - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), boost::move(item)); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(pos), boost::move(item)); else replace(pos, boost::move(item)); } //! Destroy an item. void destroy_item(pointer p) { - boost::container::allocator_traits<Alloc>::destroy(m_alloc, boost::addressof(*p)); + boost::container::allocator_traits<Alloc>::destroy(m_alloc, cb_details::to_address(p)); #if BOOST_CB_ENABLE_DEBUG invalidate_iterators(iterator(this, p)); cb_details::do_fill_uninitialized_memory(p, sizeof(value_type)); @@ -2566,7 +2566,7 @@ private: if (buffer_capacity == 0) return; while (first != last && !full()) { - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), *first++); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_last), *first++); increment(m_last); ++m_size; } @@ -2831,7 +2831,7 @@ private: pointer p = m_last; BOOST_TRY { for (; ii < construct; ++ii, increment(p)) - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper()); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(p), *wrapper()); for (;ii < n; ++ii, increment(p)) replace(p, *wrapper()); } BOOST_CATCH(...) { @@ -2925,7 +2925,7 @@ private: for (;ii > construct; --ii, increment(p)) replace(p, *wrapper()); for (; ii > 0; --ii, increment(p)) - boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper()); + boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(p), *wrapper()); } BOOST_CATCH(...) { size_type constructed = ii < construct ? construct - ii : 0; m_last = add(m_last, constructed); diff --git a/boost/circular_buffer/details.hpp b/boost/circular_buffer/details.hpp index 3262386acf..13747823ab 100644 --- a/boost/circular_buffer/details.hpp +++ b/boost/circular_buffer/details.hpp @@ -1,7 +1,7 @@ // Helper classes and functions for the circular buffer. // Copyright (c) 2003-2008 Jan Gaspar -// Copyright (c) 2014 Glen Fernandes // C++11 allocator model support. +// Copyright (c) 2014 Glen Joseph Fernandes // C++11 allocator model support. // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +16,7 @@ #include <boost/throw_exception.hpp> #include <boost/container/allocator_traits.hpp> +#include <boost/core/pointer_traits.hpp> #include <boost/move/move.hpp> #include <boost/type_traits/is_nothrow_move_constructible.hpp> #include <boost/utility/addressof.hpp> @@ -34,6 +35,13 @@ namespace boost { namespace cb_details { +template<class Pointer> +inline typename boost::pointer_traits<Pointer>::element_type* +to_address(Pointer p) BOOST_NOEXCEPT +{ + return boost::pointer_traits<Pointer>::to_address(p); +} + template <class Traits> struct nonconst_traits; template<class ForwardIterator, class Diff, class T, class Alloc> @@ -435,10 +443,10 @@ inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator las ForwardIterator next = dest; BOOST_TRY { for (; first != last; ++first, ++dest) - boost::container::allocator_traits<Alloc>::construct(a, boost::addressof(*dest), *first); + boost::container::allocator_traits<Alloc>::construct(a, cb_details::to_address(dest), *first); } BOOST_CATCH(...) { for (; next != dest; ++next) - boost::container::allocator_traits<Alloc>::destroy(a, boost::addressof(*next)); + boost::container::allocator_traits<Alloc>::destroy(a, cb_details::to_address(next)); BOOST_RETHROW } BOOST_CATCH_END @@ -449,7 +457,7 @@ template<class InputIterator, class ForwardIterator, class Alloc> ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a, true_type) { for (; first != last; ++first, ++dest) - boost::container::allocator_traits<Alloc>::construct(a, boost::addressof(*dest), boost::move(*first)); + boost::container::allocator_traits<Alloc>::construct(a, cb_details::to_address(dest), boost::move(*first)); return dest; } @@ -478,10 +486,10 @@ inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const ForwardIterator next = first; BOOST_TRY { for (; n > 0; ++first, --n) - boost::container::allocator_traits<Alloc>::construct(alloc, boost::addressof(*first), item); + boost::container::allocator_traits<Alloc>::construct(alloc, cb_details::to_address(first), item); } BOOST_CATCH(...) { for (; next != first; ++next) - boost::container::allocator_traits<Alloc>::destroy(alloc, boost::addressof(*next)); + boost::container::allocator_traits<Alloc>::destroy(alloc, cb_details::to_address(next)); BOOST_RETHROW } BOOST_CATCH_END diff --git a/boost/compute/algorithm/accumulate.hpp b/boost/compute/algorithm/accumulate.hpp index 328420a07c..be20bee60e 100644 --- a/boost/compute/algorithm/accumulate.hpp +++ b/boost/compute/algorithm/accumulate.hpp @@ -26,6 +26,7 @@ namespace boost { namespace compute { namespace detail { +// Space complexity O(1) template<class InputIterator, class T, class BinaryFunction> inline T generic_accumulate(InputIterator first, InputIterator last, @@ -155,6 +156,9 @@ inline T dispatch_accumulate(InputIterator first, /// reduce(vec.begin(), vec.end(), &result, plus<float>()); // fast /// \endcode /// +/// Space complexity: \Omega(1)<br> +/// Space complexity when optimized to \c reduce(): \Omega(n) +/// /// \see reduce() template<class InputIterator, class T, class BinaryFunction> inline T accumulate(InputIterator first, diff --git a/boost/compute/algorithm/adjacent_difference.hpp b/boost/compute/algorithm/adjacent_difference.hpp index ef13970754..c3b0e7d191 100644 --- a/boost/compute/algorithm/adjacent_difference.hpp +++ b/boost/compute/algorithm/adjacent_difference.hpp @@ -64,6 +64,9 @@ dispatch_adjacent_difference(InputIterator first, /// /// \return \c OutputIterator to the end of the result range /// +/// Space complexity: \Omega(1)<br> +/// Space complexity when \p result == \p first: \Omega(n) +/// /// \see adjacent_find() template<class InputIterator, class OutputIterator, class BinaryFunction> inline OutputIterator diff --git a/boost/compute/algorithm/adjacent_find.hpp b/boost/compute/algorithm/adjacent_find.hpp index 992a01eddc..a71a817f57 100644 --- a/boost/compute/algorithm/adjacent_find.hpp +++ b/boost/compute/algorithm/adjacent_find.hpp @@ -114,6 +114,8 @@ adjacent_find_with_atomics(InputIterator first, /// \return \c InputIteratorm to the first element which compares equal /// to the following element. If none are equal, returns \c last. /// +/// Space complexity: \Omega(1) +/// /// \see find(), adjacent_difference() template<class InputIterator, class Compare> inline InputIterator diff --git a/boost/compute/algorithm/all_of.hpp b/boost/compute/algorithm/all_of.hpp index 34d7518f32..56c5809992 100644 --- a/boost/compute/algorithm/all_of.hpp +++ b/boost/compute/algorithm/all_of.hpp @@ -20,6 +20,8 @@ namespace compute { /// Returns \c true if \p predicate returns \c true for all of the elements in /// the range [\p first, \p last). /// +/// Space complexity: \Omega(1) +/// /// \see any_of(), none_of() template<class InputIterator, class UnaryPredicate> inline bool all_of(InputIterator first, diff --git a/boost/compute/algorithm/any_of.hpp b/boost/compute/algorithm/any_of.hpp index b07779597c..54031fbac5 100644 --- a/boost/compute/algorithm/any_of.hpp +++ b/boost/compute/algorithm/any_of.hpp @@ -24,6 +24,8 @@ namespace compute { /// /// \snippet test/test_any_all_none_of.cpp any_of /// +/// Space complexity: \Omega(1) +/// /// \see all_of(), none_of() template<class InputIterator, class UnaryPredicate> inline bool any_of(InputIterator first, diff --git a/boost/compute/algorithm/binary_search.hpp b/boost/compute/algorithm/binary_search.hpp index 6e19498790..880f3628fb 100644 --- a/boost/compute/algorithm/binary_search.hpp +++ b/boost/compute/algorithm/binary_search.hpp @@ -20,6 +20,8 @@ namespace compute { /// Returns \c true if \p value is in the sorted range [\p first, /// \p last). +/// +/// Space complexity: \Omega(1) template<class InputIterator, class T> inline bool binary_search(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/copy.hpp b/boost/compute/algorithm/copy.hpp index 7779277b82..4866726f6e 100644 --- a/boost/compute/algorithm/copy.hpp +++ b/boost/compute/algorithm/copy.hpp @@ -826,6 +826,8 @@ dispatch_copy(InputIterator first, /// ); /// \endcode /// +/// Space complexity: \Omega(1) +/// /// \see copy_n(), copy_if(), copy_async() template<class InputIterator, class OutputIterator> inline OutputIterator copy(InputIterator first, diff --git a/boost/compute/algorithm/copy_if.hpp b/boost/compute/algorithm/copy_if.hpp index 3cd08ef293..bdedcb8536 100644 --- a/boost/compute/algorithm/copy_if.hpp +++ b/boost/compute/algorithm/copy_if.hpp @@ -38,6 +38,8 @@ inline OutputIterator copy_index_if(InputIterator first, /// Copies each element in the range [\p first, \p last) for which /// \p predicate returns \c true to the range beginning at \p result. +/// +/// Space complexity: \Omega(2n) template<class InputIterator, class OutputIterator, class Predicate> inline OutputIterator copy_if(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/copy_n.hpp b/boost/compute/algorithm/copy_n.hpp index f0989edc67..5280193497 100644 --- a/boost/compute/algorithm/copy_n.hpp +++ b/boost/compute/algorithm/copy_n.hpp @@ -30,6 +30,8 @@ namespace compute { /// boost::compute::copy_n(values, 4, vec.begin(), queue); /// \endcode /// +/// Space complexity: \Omega(1) +/// /// \see copy() template<class InputIterator, class Size, class OutputIterator> inline OutputIterator copy_n(InputIterator first, diff --git a/boost/compute/algorithm/count.hpp b/boost/compute/algorithm/count.hpp index 140d67379f..7a502c6791 100644 --- a/boost/compute/algorithm/count.hpp +++ b/boost/compute/algorithm/count.hpp @@ -23,6 +23,9 @@ namespace compute { /// Returns the number of occurrences of \p value in the range /// [\p first, \p last). /// +/// Space complexity on CPUs: \Omega(1)<br> +/// Space complexity on GPUs: \Omega(n) +/// /// \see count_if() template<class InputIterator, class T> inline size_t count(InputIterator first, diff --git a/boost/compute/algorithm/count_if.hpp b/boost/compute/algorithm/count_if.hpp index c9381ce5d4..81996dc828 100644 --- a/boost/compute/algorithm/count_if.hpp +++ b/boost/compute/algorithm/count_if.hpp @@ -25,6 +25,9 @@ namespace compute { /// Returns the number of elements in the range [\p first, \p last) /// for which \p predicate returns \c true. +/// +/// Space complexity on CPUs: \Omega(1)<br> +/// Space complexity on GPUs: \Omega(n) template<class InputIterator, class Predicate> inline size_t count_if(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/detail/copy_on_device.hpp b/boost/compute/algorithm/detail/copy_on_device.hpp index 8738c8c0b4..034b3bc212 100644 --- a/boost/compute/algorithm/detail/copy_on_device.hpp +++ b/boost/compute/algorithm/detail/copy_on_device.hpp @@ -144,7 +144,7 @@ inline future<OutputIterator> copy_on_device_async(InputIterator first, return make_future(result + std::distance(first, last), event_); } -#ifdef CL_VERSION_2_0 +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 // copy_on_device() specialization for svm_ptr template<class T> inline svm_ptr<T> copy_on_device(svm_ptr<T> first, @@ -181,7 +181,7 @@ inline future<svm_ptr<T> > copy_on_device_async(svm_ptr<T> first, return make_future(result + count, event_); } -#endif // CL_VERSION_2_0 +#endif // BOOST_COMPUTE_CL_VERSION_2_0 } // end detail namespace } // end compute namespace diff --git a/boost/compute/algorithm/detail/copy_to_device.hpp b/boost/compute/algorithm/detail/copy_to_device.hpp index bce5975f53..8601bb20ec 100644 --- a/boost/compute/algorithm/detail/copy_to_device.hpp +++ b/boost/compute/algorithm/detail/copy_to_device.hpp @@ -124,7 +124,7 @@ inline future<DeviceIterator> copy_to_device_async(HostIterator first, return make_future(result + static_cast<difference_type>(count), event_); } -#ifdef CL_VERSION_2_0 +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 // copy_to_device() specialization for svm_ptr template<class HostIterator, class T> inline svm_ptr<T> copy_to_device(HostIterator first, @@ -184,7 +184,7 @@ inline svm_ptr<T> copy_to_device_map(HostIterator first, return result + count; } -#endif // CL_VERSION_2_0 +#endif // BOOST_COMPUTE_CL_VERSION_2_0 } // end detail namespace } // end compute namespace diff --git a/boost/compute/algorithm/detail/copy_to_host.hpp b/boost/compute/algorithm/detail/copy_to_host.hpp index d770a996ef..89b57174fa 100644 --- a/boost/compute/algorithm/detail/copy_to_host.hpp +++ b/boost/compute/algorithm/detail/copy_to_host.hpp @@ -125,7 +125,7 @@ inline future<HostIterator> copy_to_host_async(DeviceIterator first, return make_future(iterator_plus_distance(result, count), event_); } -#ifdef CL_VERSION_2_0 +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 // copy_to_host() specialization for svm_ptr template<class T, class HostIterator> inline HostIterator copy_to_host(svm_ptr<T> first, @@ -189,7 +189,7 @@ inline HostIterator copy_to_host_map(svm_ptr<T> first, return iterator_plus_distance(result, count); } -#endif // CL_VERSION_2_0 +#endif // BOOST_COMPUTE_CL_VERSION_2_0 } // end detail namespace } // end compute namespace diff --git a/boost/compute/algorithm/detail/find_extrema.hpp b/boost/compute/algorithm/detail/find_extrema.hpp index eef2e36c3c..734b75aa90 100644 --- a/boost/compute/algorithm/detail/find_extrema.hpp +++ b/boost/compute/algorithm/detail/find_extrema.hpp @@ -56,7 +56,7 @@ inline InputIterator find_extrema(InputIterator first, // use serial method for OpenCL version 1.0 due to // problems with atomic_cmpxchg() - #ifndef CL_VERSION_1_1 + #ifndef BOOST_COMPUTE_CL_VERSION_1_1 return serial_find_extrema(first, last, compare, find_minimum, queue); #endif diff --git a/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp index 8f2a83c38b..515d7cc6da 100644 --- a/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp +++ b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp @@ -246,6 +246,7 @@ inline void find_extrema_with_reduce(InputIterator input, ); } +// Space complexity: \Omega(2 * work-group-size * work-groups-per-compute-unit) template<class InputIterator, class Compare> InputIterator find_extrema_with_reduce(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/detail/find_if_with_atomics.hpp b/boost/compute/algorithm/detail/find_if_with_atomics.hpp index 112c34cf00..e14fd12ae0 100644 --- a/boost/compute/algorithm/detail/find_if_with_atomics.hpp +++ b/boost/compute/algorithm/detail/find_if_with_atomics.hpp @@ -153,6 +153,7 @@ inline InputIterator find_if_with_atomics_multiple_vpt(InputIterator first, return first + static_cast<difference_type>(index.read(queue)); } +// Space complexity: O(1) template<class InputIterator, class UnaryPredicate> inline InputIterator find_if_with_atomics(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp b/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp index e62c6beb8d..d5e1a2d8c9 100644 --- a/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp +++ b/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp @@ -91,6 +91,7 @@ inline size_t bitonic_block_sort(KeyIterator keys_first, command_queue &queue) { typedef typename std::iterator_traits<KeyIterator>::value_type key_type; + typedef typename std::iterator_traits<ValueIterator>::value_type value_type; meta_kernel k("bitonic_block_sort"); size_t count_arg = k.add_arg<const uint_>("count"); @@ -249,8 +250,11 @@ inline size_t bitonic_block_sort(KeyIterator keys_first, k.var<key_type>("my_key") << ";\n"; if(sort_by_key) { - k << values_first[k.var<const uint_>("gid")] << " = " << - values_first[k.var<const uint_>("offset + my_index")] << ";\n"; + k << + k.decl<value_type>("my_value") << " = " << + values_first[k.var<const uint_>("offset + my_index")] << ";\n" << + "barrier(CLK_GLOBAL_MEM_FENCE);\n" << + values_first[k.var<const uint_>("gid")] << " = my_value;\n"; } k << // end if @@ -418,7 +422,7 @@ inline void merge_blocks_on_gpu(KeyIterator keys_first, ");\n" << "left_idx = equal ? mid_idx + 1 : left_idx + 1;\n" << "right_idx = equal ? right_idx : mid_idx;\n" << - "upper_key = equal ? upper_key : " << + "upper_key = " << keys_first[k.var<const uint_>("left_idx")] << ";\n" << "}\n" << "}\n" << diff --git a/boost/compute/algorithm/detail/radix_sort.hpp b/boost/compute/algorithm/detail/radix_sort.hpp index 8e6d5f9c0a..53b1205c70 100644 --- a/boost/compute/algorithm/detail/radix_sort.hpp +++ b/boost/compute/algorithm/detail/radix_sort.hpp @@ -17,6 +17,9 @@ #include <boost/type_traits/is_signed.hpp> #include <boost/type_traits/is_floating_point.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/not.hpp> + #include <boost/compute/kernel.hpp> #include <boost/compute/program.hpp> #include <boost/compute/command_queue.hpp> @@ -305,9 +308,12 @@ inline void radix_sort_impl(const buffer_iterator<T> first, options << " -DASC"; } + // get type definition if it is a custom struct + std::string custom_type_def = boost::compute::type_definition<T2>() + "\n"; + // load radix sort program program radix_sort_program = cache->get_or_build( - cache_key, options.str(), radix_sort_source, context + cache_key, options.str(), custom_type_def + radix_sort_source, context ); kernel count_kernel(radix_sort_program, "count"); diff --git a/boost/compute/algorithm/detail/serial_reduce.hpp b/boost/compute/algorithm/detail/serial_reduce.hpp index 53aaf140fe..8b121274b9 100644 --- a/boost/compute/algorithm/detail/serial_reduce.hpp +++ b/boost/compute/algorithm/detail/serial_reduce.hpp @@ -20,6 +20,7 @@ namespace boost { namespace compute { namespace detail { +// Space complexity: O(1) template<class InputIterator, class OutputIterator, class BinaryFunction> inline void serial_reduce(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/detail/serial_reduce_by_key.hpp b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp index f9bda8e476..6fb04baa6d 100644 --- a/boost/compute/algorithm/detail/serial_reduce_by_key.hpp +++ b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp @@ -55,11 +55,9 @@ inline size_t serial_reduce_by_key(InputKeyIterator keys_first, size_t result_size_arg = k.add_arg<uint_ *>(memory_object::global_memory, "result_size"); - convert<result_type> to_result_type; - k << k.decl<result_type>("result") << - " = " << to_result_type(values_first[0]) << ";\n" << + " = " << values_first[0] << ";\n" << k.decl<key_type>("previous_key") << " = " << keys_first[0] << ";\n" << k.decl<result_type>("value") << ";\n" << k.decl<key_type>("key") << ";\n" << @@ -70,7 +68,7 @@ inline size_t serial_reduce_by_key(InputKeyIterator keys_first, values_result[0] << " = result;\n" << "for(ulong i = 1; i < count; i++) {\n" << - " value = " << to_result_type(values_first[k.var<uint_>("i")]) << ";\n" << + " value = " << values_first[k.var<uint_>("i")] << ";\n" << " key = " << keys_first[k.var<uint_>("i")] << ";\n" << " if (" << predicate(k.var<key_type>("previous_key"), k.var<key_type>("key")) << ") {\n" << diff --git a/boost/compute/algorithm/equal.hpp b/boost/compute/algorithm/equal.hpp index 35d0c5f0ea..c3c8053b71 100644 --- a/boost/compute/algorithm/equal.hpp +++ b/boost/compute/algorithm/equal.hpp @@ -20,6 +20,8 @@ namespace compute { /// Returns \c true if the range [\p first1, \p last1) and the range /// beginning at \p first2 are equal. +/// +/// Space complexity: \Omega(1) template<class InputIterator1, class InputIterator2> inline bool equal(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/equal_range.hpp b/boost/compute/algorithm/equal_range.hpp index fd82177324..d7008e3cf4 100644 --- a/boost/compute/algorithm/equal_range.hpp +++ b/boost/compute/algorithm/equal_range.hpp @@ -23,6 +23,8 @@ namespace compute { /// Returns a pair of iterators containing the range of values equal /// to \p value in the sorted range [\p first, \p last). +/// +/// Space complexity: \Omega(1) template<class InputIterator, class T> inline std::pair<InputIterator, InputIterator> equal_range(InputIterator first, diff --git a/boost/compute/algorithm/exclusive_scan.hpp b/boost/compute/algorithm/exclusive_scan.hpp index 205d3de658..806a172cf4 100644 --- a/boost/compute/algorithm/exclusive_scan.hpp +++ b/boost/compute/algorithm/exclusive_scan.hpp @@ -44,6 +44,10 @@ namespace compute { /// /// \snippet test/test_scan.cpp exclusive_scan_int_multiplies /// +/// Space complexity on GPUs: \Omega(n)<br> +/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br> +/// Space complexity on CPUs: \Omega(1) +/// /// \see inclusive_scan() template<class InputIterator, class OutputIterator, class T, class BinaryOperator> inline OutputIterator diff --git a/boost/compute/algorithm/fill.hpp b/boost/compute/algorithm/fill.hpp index c711f46b94..646d8acda4 100644 --- a/boost/compute/algorithm/fill.hpp +++ b/boost/compute/algorithm/fill.hpp @@ -64,7 +64,7 @@ inline future<void> fill_async_with_copy(BufferIterator first, ); } -#if defined(CL_VERSION_1_2) +#if defined(BOOST_COMPUTE_CL_VERSION_1_2) // meta-function returing true if Iterator points to a range of values // that can be filled using clEnqueueFillBuffer(). to meet this criteria @@ -172,7 +172,7 @@ dispatch_fill_async(BufferIterator first, return future<void>(event_); } -#ifdef CL_VERSION_2_0 +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 // specializations for svm_ptr<T> template<class T> inline void dispatch_fill(svm_ptr<T> first, @@ -205,7 +205,7 @@ inline future<void> dispatch_fill_async(svm_ptr<T> first, return future<void>(event_); } -#endif // CL_VERSION_2_0 +#endif // BOOST_COMPUTE_CL_VERSION_2_0 // default implementations template<class BufferIterator, class T> @@ -251,7 +251,7 @@ inline future<void> dispatch_fill_async(BufferIterator first, { return fill_async_with_copy(first, count, value, queue); } -#endif // !defined(CL_VERSION_1_2) +#endif // !defined(BOOST_COMPUTE_CL_VERSION_1_2) } // end detail namespace @@ -271,6 +271,8 @@ inline future<void> dispatch_fill_async(BufferIterator first, /// boost::compute::fill(vec.begin(), vec.end(), 7, queue); /// \endcode /// +/// Space complexity: \Omega(1) +/// /// \see boost::compute::fill_n() template<class BufferIterator, class T> inline void fill(BufferIterator first, diff --git a/boost/compute/algorithm/fill_n.hpp b/boost/compute/algorithm/fill_n.hpp index 18a8f706a5..6be2d280a6 100644 --- a/boost/compute/algorithm/fill_n.hpp +++ b/boost/compute/algorithm/fill_n.hpp @@ -20,6 +20,8 @@ namespace compute { /// Fills the range [\p first, \p first + count) with \p value. /// +/// Space complexity: \Omega(1) +/// /// \see fill() template<class BufferIterator, class Size, class T> inline void fill_n(BufferIterator first, diff --git a/boost/compute/algorithm/find.hpp b/boost/compute/algorithm/find.hpp index ef3ebf0c47..a6225b8c99 100644 --- a/boost/compute/algorithm/find.hpp +++ b/boost/compute/algorithm/find.hpp @@ -22,6 +22,8 @@ namespace compute { /// Returns an iterator pointing to the first element in the range /// [\p first, \p last) that equals \p value. +/// +/// Space complexity: \Omega(1) template<class InputIterator, class T> inline InputIterator find(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/find_end.hpp b/boost/compute/algorithm/find_end.hpp index 265a1da542..a0a1b2e8c9 100644 --- a/boost/compute/algorithm/find_end.hpp +++ b/boost/compute/algorithm/find_end.hpp @@ -26,8 +26,8 @@ namespace detail { /// /// \brief Helper function for find_end /// -/// Basically a copy of find_if which returns last occurence -/// instead of first occurence +/// Basically a copy of find_if which returns last occurrence +/// instead of first occurrence /// template<class InputIterator, class UnaryPredicate> inline InputIterator find_end_helper(InputIterator first, @@ -90,6 +90,8 @@ inline InputIterator find_end_helper(InputIterator first, /// \param p_last Iterator pointing to end of pattern /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(n) +/// template<class TextIterator, class PatternIterator> inline TextIterator find_end(TextIterator t_first, TextIterator t_last, diff --git a/boost/compute/algorithm/find_if.hpp b/boost/compute/algorithm/find_if.hpp index db99cc0396..074b47e280 100644 --- a/boost/compute/algorithm/find_if.hpp +++ b/boost/compute/algorithm/find_if.hpp @@ -20,6 +20,8 @@ namespace compute { /// Returns an iterator pointing to the first element in the range /// [\p first, \p last) for which \p predicate returns \c true. +/// +/// Space complexity: \Omega(1) template<class InputIterator, class UnaryPredicate> inline InputIterator find_if(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/find_if_not.hpp b/boost/compute/algorithm/find_if_not.hpp index 61de050d31..a008a99469 100644 --- a/boost/compute/algorithm/find_if_not.hpp +++ b/boost/compute/algorithm/find_if_not.hpp @@ -22,6 +22,8 @@ namespace compute { /// Returns an iterator pointing to the first element in the range /// [\p first, \p last) for which \p predicate returns \c false. /// +/// Space complexity: \Omega(1) +/// /// \see find_if() template<class InputIterator, class UnaryPredicate> inline InputIterator find_if_not(InputIterator first, diff --git a/boost/compute/algorithm/for_each.hpp b/boost/compute/algorithm/for_each.hpp index 3ed399e6e9..7afba2b5f5 100644 --- a/boost/compute/algorithm/for_each.hpp +++ b/boost/compute/algorithm/for_each.hpp @@ -45,6 +45,8 @@ struct for_each_kernel : public meta_kernel /// Calls \p function on each element in the range [\p first, \p last). /// +/// Space complexity: \Omega(1) +/// /// \see transform() template<class InputIterator, class UnaryFunction> inline UnaryFunction for_each(InputIterator first, diff --git a/boost/compute/algorithm/for_each_n.hpp b/boost/compute/algorithm/for_each_n.hpp index d0be784bf7..77932ab209 100644 --- a/boost/compute/algorithm/for_each_n.hpp +++ b/boost/compute/algorithm/for_each_n.hpp @@ -19,6 +19,8 @@ namespace compute { /// Calls \p function on each element in the range [\p first, \p first /// \c + \p count). /// +/// Space complexity: \Omega(1) +/// /// \see for_each() template<class InputIterator, class Size, class UnaryFunction> inline UnaryFunction for_each_n(InputIterator first, diff --git a/boost/compute/algorithm/gather.hpp b/boost/compute/algorithm/gather.hpp index 24c5c727ae..62442587f7 100644 --- a/boost/compute/algorithm/gather.hpp +++ b/boost/compute/algorithm/gather.hpp @@ -62,6 +62,8 @@ private: /// to the range beginning at \p result using the input values from the range /// beginning at \p input. /// +/// Space complexity: \Omega(1) +/// /// \see scatter() template<class InputIterator, class MapIterator, class OutputIterator> inline void gather(MapIterator first, diff --git a/boost/compute/algorithm/generate.hpp b/boost/compute/algorithm/generate.hpp index c70a542683..9ac76a3dca 100644 --- a/boost/compute/algorithm/generate.hpp +++ b/boost/compute/algorithm/generate.hpp @@ -22,6 +22,8 @@ namespace compute { /// Stores the result of \p generator for each element in the range /// [\p first, \p last). +/// +/// Space complexity: \Omega(1) template<class OutputIterator, class Generator> inline void generate(OutputIterator first, OutputIterator last, diff --git a/boost/compute/algorithm/generate_n.hpp b/boost/compute/algorithm/generate_n.hpp index 6d8e607b64..066a831ddf 100644 --- a/boost/compute/algorithm/generate_n.hpp +++ b/boost/compute/algorithm/generate_n.hpp @@ -20,6 +20,8 @@ namespace compute { /// Stores the result of \p generator for each element in the range /// [\p first, \p first + \p count). +/// +/// Space complexity: \Omega(1) template<class OutputIterator, class Size, class Generator> inline void generate_n(OutputIterator first, Size count, diff --git a/boost/compute/algorithm/includes.hpp b/boost/compute/algorithm/includes.hpp index c4e7c793e7..cfef9540a7 100644 --- a/boost/compute/algorithm/includes.hpp +++ b/boost/compute/algorithm/includes.hpp @@ -110,6 +110,7 @@ private: /// \param last2 Iterator pointing to end of second set /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2)) template<class InputIterator1, class InputIterator2> inline bool includes(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/inclusive_scan.hpp b/boost/compute/algorithm/inclusive_scan.hpp index 9f98beaf7c..84f1b8cbf7 100644 --- a/boost/compute/algorithm/inclusive_scan.hpp +++ b/boost/compute/algorithm/inclusive_scan.hpp @@ -42,6 +42,10 @@ namespace compute { /// /// \snippet test/test_scan.cpp inclusive_scan_int_multiplies /// +/// Space complexity on GPUs: \Omega(n)<br> +/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br> +/// Space complexity on CPUs: \Omega(1) +/// /// \see exclusive_scan() template<class InputIterator, class OutputIterator, class BinaryOperator> inline OutputIterator diff --git a/boost/compute/algorithm/inner_product.hpp b/boost/compute/algorithm/inner_product.hpp index 614611f91e..0aeaf9110e 100644 --- a/boost/compute/algorithm/inner_product.hpp +++ b/boost/compute/algorithm/inner_product.hpp @@ -26,6 +26,9 @@ namespace compute { /// Returns the inner product of the elements in the range /// [\p first1, \p last1) with the elements in the range beginning /// at \p first2. +/// +/// Space complexity: \Omega(1)<br> +/// Space complexity when binary operator is recognized as associative: \Omega(n) template<class InputIterator1, class InputIterator2, class T> inline T inner_product(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/inplace_merge.hpp b/boost/compute/algorithm/inplace_merge.hpp index 3080950df5..91f5be5335 100644 --- a/boost/compute/algorithm/inplace_merge.hpp +++ b/boost/compute/algorithm/inplace_merge.hpp @@ -23,6 +23,8 @@ namespace compute { /// Merges the sorted values in the range [\p first, \p middle) with /// the sorted values in the range [\p middle, \p last) in-place. +/// +/// Space complexity: \Omega(n) template<class Iterator> inline void inplace_merge(Iterator first, Iterator middle, diff --git a/boost/compute/algorithm/iota.hpp b/boost/compute/algorithm/iota.hpp index 084c3d8d97..4cd7aa9c7b 100644 --- a/boost/compute/algorithm/iota.hpp +++ b/boost/compute/algorithm/iota.hpp @@ -26,6 +26,8 @@ namespace compute { /// \snippet test/test_iota.cpp iota /// /// Will fill \c vec with the values (\c 0, \c 1, \c 2, \c ...). +/// +/// Space complexity: \Omega(1) template<class BufferIterator, class T> inline void iota(BufferIterator first, BufferIterator last, diff --git a/boost/compute/algorithm/is_partitioned.hpp b/boost/compute/algorithm/is_partitioned.hpp index 3916825057..6ad24f240f 100644 --- a/boost/compute/algorithm/is_partitioned.hpp +++ b/boost/compute/algorithm/is_partitioned.hpp @@ -21,6 +21,8 @@ namespace compute { /// Returns \c true if the values in the range [\p first, \p last) /// are partitioned according to \p predicate. +/// +/// Space complexity: \Omega(1) template<class InputIterator, class UnaryPredicate> inline bool is_partitioned(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/is_permutation.hpp b/boost/compute/algorithm/is_permutation.hpp index 1e502efb37..88b89b7973 100644 --- a/boost/compute/algorithm/is_permutation.hpp +++ b/boost/compute/algorithm/is_permutation.hpp @@ -36,6 +36,7 @@ namespace compute { /// \param last2 Iterator pointing to end of second range /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2)) template<class InputIterator1, class InputIterator2> inline bool is_permutation(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/is_sorted.hpp b/boost/compute/algorithm/is_sorted.hpp index a605159ac3..7441620978 100644 --- a/boost/compute/algorithm/is_sorted.hpp +++ b/boost/compute/algorithm/is_sorted.hpp @@ -30,6 +30,8 @@ namespace compute { /// /// \return \c true if the range [\p first, \p last) is sorted /// +/// Space complexity: \Omega(1) +/// /// \see sort() template<class InputIterator, class Compare> inline bool is_sorted(InputIterator first, diff --git a/boost/compute/algorithm/lexicographical_compare.hpp b/boost/compute/algorithm/lexicographical_compare.hpp index c4f7120807..952e678a68 100644 --- a/boost/compute/algorithm/lexicographical_compare.hpp +++ b/boost/compute/algorithm/lexicographical_compare.hpp @@ -42,10 +42,10 @@ const char lexicographical_compare_source[] = template<class InputIterator1, class InputIterator2> inline bool dispatch_lexicographical_compare(InputIterator1 first1, - InputIterator1 last1, - InputIterator2 first2, - InputIterator2 last2, - command_queue &queue) + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + command_queue &queue) { const boost::compute::context &context = queue.get_context(); @@ -103,6 +103,9 @@ inline bool dispatch_lexicographical_compare(InputIterator1 first1, /// Checks if the first range [first1, last1) is lexicographically /// less than the second range [first2, last2). +/// +/// Space complexity: +/// \Omega(max(distance(\p first1, \p last1), distance(\p first2, \p last2))) template<class InputIterator1, class InputIterator2> inline bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/lower_bound.hpp b/boost/compute/algorithm/lower_bound.hpp index b2011c66ef..f78bbd6364 100644 --- a/boost/compute/algorithm/lower_bound.hpp +++ b/boost/compute/algorithm/lower_bound.hpp @@ -22,6 +22,8 @@ namespace compute { /// Returns an iterator pointing to the first element in the sorted /// range [\p first, \p last) that is not less than \p value. /// +/// Space complexity: \Omega(1) +/// /// \see upper_bound() template<class InputIterator, class T> inline InputIterator diff --git a/boost/compute/algorithm/max_element.hpp b/boost/compute/algorithm/max_element.hpp index 55f2f7ffbf..f9df37420c 100644 --- a/boost/compute/algorithm/max_element.hpp +++ b/boost/compute/algorithm/max_element.hpp @@ -43,6 +43,9 @@ namespace compute { /// boost::compute::max_element(data.begin(), data.end(), compare_first, queue); /// \endcode /// +/// Space complexity on CPUs: \Omega(1)<br> +/// Space complexity on GPUs: \Omega(N) +/// /// \see min_element() template<class InputIterator, class Compare> inline InputIterator diff --git a/boost/compute/algorithm/merge.hpp b/boost/compute/algorithm/merge.hpp index 875a283044..ff3e6e879a 100644 --- a/boost/compute/algorithm/merge.hpp +++ b/boost/compute/algorithm/merge.hpp @@ -37,6 +37,8 @@ namespace compute { /// /// \return \c OutputIterator to the end of the result range /// +/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2)) +/// /// \see inplace_merge() template<class InputIterator1, class InputIterator2, diff --git a/boost/compute/algorithm/min_element.hpp b/boost/compute/algorithm/min_element.hpp index 62744efb98..b52e2670cb 100644 --- a/boost/compute/algorithm/min_element.hpp +++ b/boost/compute/algorithm/min_element.hpp @@ -43,6 +43,9 @@ namespace compute { /// boost::compute::min_element(data.begin(), data.end(), compare_first, queue); /// \endcode /// +/// Space complexity on CPUs: \Omega(1)<br> +/// Space complexity on GPUs: \Omega(N) +/// /// \see max_element() template<class InputIterator, class Compare> inline InputIterator diff --git a/boost/compute/algorithm/minmax_element.hpp b/boost/compute/algorithm/minmax_element.hpp index 3f44c09eaf..4b2aae6dee 100644 --- a/boost/compute/algorithm/minmax_element.hpp +++ b/boost/compute/algorithm/minmax_element.hpp @@ -31,6 +31,9 @@ namespace compute { /// argument is less than (i.e. is ordered before) the second. /// \param queue command queue to perform the operation /// +/// Space complexity on CPUs: \Omega(1)<br> +/// Space complexity on GPUs: \Omega(N) +/// /// \see max_element(), min_element() template<class InputIterator, class Compare> inline std::pair<InputIterator, InputIterator> diff --git a/boost/compute/algorithm/mismatch.hpp b/boost/compute/algorithm/mismatch.hpp index e7db883004..ff31f49f97 100644 --- a/boost/compute/algorithm/mismatch.hpp +++ b/boost/compute/algorithm/mismatch.hpp @@ -28,6 +28,8 @@ namespace compute { /// Returns a pair of iterators pointing to the first position where the /// range [\p first1, \p last1) and the range starting at \p first2 /// differ. +/// +/// Space complexity: \Omega(1) template<class InputIterator1, class InputIterator2> inline std::pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, diff --git a/boost/compute/algorithm/next_permutation.hpp b/boost/compute/algorithm/next_permutation.hpp index e81fbd2ee8..061ea1efe9 100644 --- a/boost/compute/algorithm/next_permutation.hpp +++ b/boost/compute/algorithm/next_permutation.hpp @@ -131,6 +131,7 @@ inline InputIterator np_ceiling(InputIterator first, /// \param last Iterator pointing to end of range /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(1) template<class InputIterator> inline bool next_permutation(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/none_of.hpp b/boost/compute/algorithm/none_of.hpp index c25dd12a87..fc3ed94bc1 100644 --- a/boost/compute/algorithm/none_of.hpp +++ b/boost/compute/algorithm/none_of.hpp @@ -20,6 +20,8 @@ namespace compute { /// Returns \c true if \p predicate returns \c true for none of the elements in /// the range [\p first, \p last). /// +/// Space complexity: \Omega(1) +/// /// \see all_of(), any_of() template<class InputIterator, class UnaryPredicate> inline bool none_of(InputIterator first, diff --git a/boost/compute/algorithm/nth_element.hpp b/boost/compute/algorithm/nth_element.hpp index 68f7a3dbc0..93344271dd 100644 --- a/boost/compute/algorithm/nth_element.hpp +++ b/boost/compute/algorithm/nth_element.hpp @@ -23,6 +23,8 @@ namespace compute { /// Rearranges the elements in the range [\p first, \p last) such that /// the \p nth element would be in that position in a sorted sequence. +/// +/// Space complexity: \Omega(3n) template<class Iterator, class Compare> inline void nth_element(Iterator first, Iterator nth, diff --git a/boost/compute/algorithm/partial_sum.hpp b/boost/compute/algorithm/partial_sum.hpp index d440369a5a..53d36a9db0 100644 --- a/boost/compute/algorithm/partial_sum.hpp +++ b/boost/compute/algorithm/partial_sum.hpp @@ -21,6 +21,10 @@ namespace compute { /// Calculates the cumulative sum of the elements in the range [\p first, /// \p last) and writes the resulting values to the range beginning at /// \p result. +/// +/// Space complexity on GPUs: \Omega(n)<br> +/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br> +/// Space complexity on CPUs: \Omega(1) template<class InputIterator, class OutputIterator> inline OutputIterator partial_sum(InputIterator first, diff --git a/boost/compute/algorithm/partition.hpp b/boost/compute/algorithm/partition.hpp index 7860350e0d..59d0c78f7e 100644 --- a/boost/compute/algorithm/partition.hpp +++ b/boost/compute/algorithm/partition.hpp @@ -22,6 +22,8 @@ namespace compute { /// Partitions the elements in the range [\p first, \p last) according to /// \p predicate. Order of the elements need not be preserved. /// +/// Space complexity: \Omega(3n) +/// /// \see is_partitioned() and stable_partition() /// template<class Iterator, class UnaryPredicate> diff --git a/boost/compute/algorithm/partition_copy.hpp b/boost/compute/algorithm/partition_copy.hpp index 80a2c6475f..3215ec0736 100644 --- a/boost/compute/algorithm/partition_copy.hpp +++ b/boost/compute/algorithm/partition_copy.hpp @@ -24,6 +24,8 @@ namespace compute { /// and all of the elements for which \p predicate returns \c false to /// the range beginning at \p first_false. /// +/// Space complexity: \Omega(2n) +/// /// \see partition() template<class InputIterator, class OutputIterator1, diff --git a/boost/compute/algorithm/partition_point.hpp b/boost/compute/algorithm/partition_point.hpp index 3cc2bc0ca6..748824512d 100644 --- a/boost/compute/algorithm/partition_point.hpp +++ b/boost/compute/algorithm/partition_point.hpp @@ -29,6 +29,8 @@ namespace compute { /// \param predicate Unary predicate to be applied on each element /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(1) +/// /// \see partition() and stable_partition() /// template<class InputIterator, class UnaryPredicate> diff --git a/boost/compute/algorithm/prev_permutation.hpp b/boost/compute/algorithm/prev_permutation.hpp index 03c01bf8f4..ea20835caa 100644 --- a/boost/compute/algorithm/prev_permutation.hpp +++ b/boost/compute/algorithm/prev_permutation.hpp @@ -131,6 +131,7 @@ inline InputIterator pp_floor(InputIterator first, /// \param last Iterator pointing to end of range /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(1) template<class InputIterator> inline bool prev_permutation(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/random_shuffle.hpp b/boost/compute/algorithm/random_shuffle.hpp index 7d2d46a133..8e020830a5 100644 --- a/boost/compute/algorithm/random_shuffle.hpp +++ b/boost/compute/algorithm/random_shuffle.hpp @@ -28,6 +28,8 @@ namespace compute { /// Randomly shuffles the elements in the range [\p first, \p last). /// +/// Space complexity: \Omega(2n) +/// /// \see scatter() template<class Iterator> inline void random_shuffle(Iterator first, diff --git a/boost/compute/algorithm/reduce.hpp b/boost/compute/algorithm/reduce.hpp index 19d070019f..e71d90fe24 100644 --- a/boost/compute/algorithm/reduce.hpp +++ b/boost/compute/algorithm/reduce.hpp @@ -153,6 +153,7 @@ block_reduce(InputIterator first, return result_vector; } +// Space complexity: O( ceil(n / 2 / 256) ) template<class InputIterator, class OutputIterator, class BinaryFunction> inline void generic_reduce(InputIterator first, InputIterator last, @@ -264,6 +265,9 @@ inline void dispatch_reduce(InputIterator first, /// efficient on parallel hardware. For more information, see the documentation /// on the \c accumulate() algorithm. /// +/// Space complexity on GPUs: \Omega(n)<br> +/// Space complexity on CPUs: \Omega(1) +/// /// \see accumulate() template<class InputIterator, class OutputIterator, class BinaryFunction> inline void reduce(InputIterator first, diff --git a/boost/compute/algorithm/reduce_by_key.hpp b/boost/compute/algorithm/reduce_by_key.hpp index 87c73e887f..1a233c7dd4 100644 --- a/boost/compute/algorithm/reduce_by_key.hpp +++ b/boost/compute/algorithm/reduce_by_key.hpp @@ -51,6 +51,9 @@ namespace compute { /// /// \snippet test/test_reduce_by_key.cpp reduce_by_key_int /// +/// Space complexity on GPUs: \Omega(2n)<br> +/// Space complexity on CPUs: \Omega(1) +/// /// \see reduce() template<class InputKeyIterator, class InputValueIterator, class OutputKeyIterator, class OutputValueIterator, diff --git a/boost/compute/algorithm/remove.hpp b/boost/compute/algorithm/remove.hpp index 98feb1f9d8..086ba8cc7f 100644 --- a/boost/compute/algorithm/remove.hpp +++ b/boost/compute/algorithm/remove.hpp @@ -22,6 +22,8 @@ namespace compute { /// Removes each element equal to \p value in the range [\p first, /// \p last). /// +/// Space complexity: \Omega(3n) +/// /// \see remove_if() template<class Iterator, class T> inline Iterator remove(Iterator first, diff --git a/boost/compute/algorithm/remove_if.hpp b/boost/compute/algorithm/remove_if.hpp index 5e416bef88..9aece18bbd 100644 --- a/boost/compute/algorithm/remove_if.hpp +++ b/boost/compute/algorithm/remove_if.hpp @@ -22,6 +22,8 @@ namespace compute { /// Removes each element for which \p predicate returns \c true in the /// range [\p first, \p last). /// +/// Space complexity: \Omega(3n) +/// /// \see remove() template<class Iterator, class Predicate> inline Iterator remove_if(Iterator first, diff --git a/boost/compute/algorithm/replace.hpp b/boost/compute/algorithm/replace.hpp index fd649a2fad..336c1d3e0f 100644 --- a/boost/compute/algorithm/replace.hpp +++ b/boost/compute/algorithm/replace.hpp @@ -68,6 +68,8 @@ private: /// Replaces each instance of \p old_value in the range [\p first, /// \p last) with \p new_value. +/// +/// Space complexity: \Omega(1) template<class Iterator, class T> inline void replace(Iterator first, Iterator last, diff --git a/boost/compute/algorithm/replace_copy.hpp b/boost/compute/algorithm/replace_copy.hpp index 7224bd3ae6..34f61b514f 100644 --- a/boost/compute/algorithm/replace_copy.hpp +++ b/boost/compute/algorithm/replace_copy.hpp @@ -25,6 +25,8 @@ namespace compute { /// beginning at \p result while replacing each instance of \p old_value /// with \p new_value. /// +/// Space complexity: \Omega(1) +/// /// \see replace() template<class InputIterator, class OutputIterator, class T> inline OutputIterator diff --git a/boost/compute/algorithm/reverse.hpp b/boost/compute/algorithm/reverse.hpp index b6a9e8098c..15fe5533ac 100644 --- a/boost/compute/algorithm/reverse.hpp +++ b/boost/compute/algorithm/reverse.hpp @@ -52,6 +52,8 @@ struct reverse_kernel : public meta_kernel /// Reverses the elements in the range [\p first, \p last). /// +/// Space complexity: \Omega(1) +/// /// \see reverse_copy() template<class Iterator> inline void reverse(Iterator first, diff --git a/boost/compute/algorithm/reverse_copy.hpp b/boost/compute/algorithm/reverse_copy.hpp index c839f44651..9fda9d4e27 100644 --- a/boost/compute/algorithm/reverse_copy.hpp +++ b/boost/compute/algorithm/reverse_copy.hpp @@ -51,6 +51,8 @@ struct reverse_copy_kernel : public meta_kernel /// Copies the elements in the range [\p first, \p last) in reversed /// order to the range beginning at \p result. /// +/// Space complexity: \Omega(1) +/// /// \see reverse() template<class InputIterator, class OutputIterator> inline OutputIterator diff --git a/boost/compute/algorithm/rotate.hpp b/boost/compute/algorithm/rotate.hpp index 54cb073cc2..715699340d 100644 --- a/boost/compute/algorithm/rotate.hpp +++ b/boost/compute/algorithm/rotate.hpp @@ -21,6 +21,8 @@ namespace compute { /// Performs left rotation such that element at \p n_first comes to the /// beginning. /// +/// Space complexity: \Omega(distance(\p first, \p last)) +/// /// \see rotate_copy() template<class InputIterator> inline void rotate(InputIterator first, diff --git a/boost/compute/algorithm/rotate_copy.hpp b/boost/compute/algorithm/rotate_copy.hpp index fa1b44c5e5..679b3c998b 100644 --- a/boost/compute/algorithm/rotate_copy.hpp +++ b/boost/compute/algorithm/rotate_copy.hpp @@ -20,6 +20,8 @@ namespace compute { /// Performs left rotation such that element at n_first comes to the /// beginning and the output is stored in range starting at result. /// +/// Space complexity: \Omega(1) +/// /// \see rotate() template<class InputIterator, class OutputIterator> inline void rotate_copy(InputIterator first, diff --git a/boost/compute/algorithm/scatter.hpp b/boost/compute/algorithm/scatter.hpp index bea4201628..8ae5a99443 100644 --- a/boost/compute/algorithm/scatter.hpp +++ b/boost/compute/algorithm/scatter.hpp @@ -79,6 +79,8 @@ private: /// beginning at \p result using the output indices from the range beginning /// at \p map. /// +/// Space complexity: \Omega(1) +/// /// \see gather() template<class InputIterator, class MapIterator, class OutputIterator> inline void scatter(InputIterator first, diff --git a/boost/compute/algorithm/scatter_if.hpp b/boost/compute/algorithm/scatter_if.hpp index 159edd8c86..c7db51d3be 100644 --- a/boost/compute/algorithm/scatter_if.hpp +++ b/boost/compute/algorithm/scatter_if.hpp @@ -83,7 +83,7 @@ private: /// at \p map if stencil is resolved to true. By default the predicate is /// an identity /// -/// +/// Space complexity: \Omega(1) template<class InputIterator, class MapIterator, class StencilIterator, class OutputIterator, class Predicate> inline void scatter_if(InputIterator first, diff --git a/boost/compute/algorithm/search.hpp b/boost/compute/algorithm/search.hpp index 3d3d035b3c..a1f3dece62 100644 --- a/boost/compute/algorithm/search.hpp +++ b/boost/compute/algorithm/search.hpp @@ -34,6 +34,7 @@ namespace compute { /// \param p_last Iterator pointing to end of pattern /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(distance(\p t_first, \p t_last)) template<class TextIterator, class PatternIterator> inline TextIterator search(TextIterator t_first, TextIterator t_last, diff --git a/boost/compute/algorithm/search_n.hpp b/boost/compute/algorithm/search_n.hpp index 9e03111bb0..86ff64dfd9 100644 --- a/boost/compute/algorithm/search_n.hpp +++ b/boost/compute/algorithm/search_n.hpp @@ -102,6 +102,7 @@ private: /// \param value Value which repeats /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(distance(\p t_first, \p t_last)) template<class TextIterator, class ValueType> inline TextIterator search_n(TextIterator t_first, TextIterator t_last, diff --git a/boost/compute/algorithm/set_difference.hpp b/boost/compute/algorithm/set_difference.hpp index 17ce7bd3f6..85a846ba13 100644 --- a/boost/compute/algorithm/set_difference.hpp +++ b/boost/compute/algorithm/set_difference.hpp @@ -122,6 +122,8 @@ private: /// will be stored /// \param queue Queue on which to execute /// +/// Space complexity: +/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2))) template<class InputIterator1, class InputIterator2, class OutputIterator> inline OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/set_intersection.hpp b/boost/compute/algorithm/set_intersection.hpp index 50f291e84a..74d46f57c6 100644 --- a/boost/compute/algorithm/set_intersection.hpp +++ b/boost/compute/algorithm/set_intersection.hpp @@ -110,6 +110,8 @@ private: /// will be stored /// \param queue Queue on which to execute /// +/// Space complexity: +/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2))) template<class InputIterator1, class InputIterator2, class OutputIterator> inline OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/set_symmetric_difference.hpp b/boost/compute/algorithm/set_symmetric_difference.hpp index 6e60b38511..34d280daa3 100644 --- a/boost/compute/algorithm/set_symmetric_difference.hpp +++ b/boost/compute/algorithm/set_symmetric_difference.hpp @@ -133,13 +133,16 @@ private: /// difference will be stored /// \param queue Queue on which to execute /// +/// Space complexity: +/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2))) template<class InputIterator1, class InputIterator2, class OutputIterator> -inline OutputIterator set_symmetric_difference(InputIterator1 first1, - InputIterator1 last1, - InputIterator2 first2, - InputIterator2 last2, - OutputIterator result, - command_queue &queue = system::default_queue()) +inline OutputIterator +set_symmetric_difference(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, + command_queue &queue = system::default_queue()) { typedef typename std::iterator_traits<InputIterator1>::value_type value_type; diff --git a/boost/compute/algorithm/set_union.hpp b/boost/compute/algorithm/set_union.hpp index c61f7b29b3..6b405a0905 100644 --- a/boost/compute/algorithm/set_union.hpp +++ b/boost/compute/algorithm/set_union.hpp @@ -135,6 +135,8 @@ private: /// will be stored /// \param queue Queue on which to execute /// +/// Space complexity: +/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2))) template<class InputIterator1, class InputIterator2, class OutputIterator> inline OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, diff --git a/boost/compute/algorithm/sort.hpp b/boost/compute/algorithm/sort.hpp index 7e0a583e3e..b8fa90f335 100644 --- a/boost/compute/algorithm/sort.hpp +++ b/boost/compute/algorithm/sort.hpp @@ -176,6 +176,8 @@ inline void dispatch_sort(Iterator first, /// boost::compute::sort(data.begin(), data.end(), queue); /// \endcode /// +/// Space complexity: \Omega(n) +/// /// \see is_sorted() template<class Iterator, class Compare> inline void sort(Iterator first, diff --git a/boost/compute/algorithm/sort_by_key.hpp b/boost/compute/algorithm/sort_by_key.hpp index c39bcf9890..fdd2d1c481 100644 --- a/boost/compute/algorithm/sort_by_key.hpp +++ b/boost/compute/algorithm/sort_by_key.hpp @@ -128,6 +128,8 @@ inline void dispatch_sort_by_key(KeyIterator keys_first, /// /// If no compare function is specified, \c less is used. /// +/// Space complexity: \Omega(2n) +/// /// \see sort() template<class KeyIterator, class ValueIterator, class Compare> inline void sort_by_key(KeyIterator keys_first, diff --git a/boost/compute/algorithm/stable_partition.hpp b/boost/compute/algorithm/stable_partition.hpp index 283b068283..2b07f034b9 100644 --- a/boost/compute/algorithm/stable_partition.hpp +++ b/boost/compute/algorithm/stable_partition.hpp @@ -33,6 +33,8 @@ namespace compute { /// \param predicate Unary predicate to be applied on each element /// \param queue Queue on which to execute /// +/// Space complexity: \Omega(3n) +/// /// \see is_partitioned() and partition() /// template<class Iterator, class UnaryPredicate> diff --git a/boost/compute/algorithm/stable_sort.hpp b/boost/compute/algorithm/stable_sort.hpp index 381fc81bc0..0857d75dc9 100644 --- a/boost/compute/algorithm/stable_sort.hpp +++ b/boost/compute/algorithm/stable_sort.hpp @@ -72,6 +72,8 @@ dispatch_gpu_stable_sort(buffer_iterator<T> first, /// Sorts the values in the range [\p first, \p last) according to /// \p compare. The relative order of identical values is preserved. /// +/// Space complexity: \Omega(n) +/// /// \see sort(), is_sorted() template<class Iterator, class Compare> inline void stable_sort(Iterator first, diff --git a/boost/compute/algorithm/stable_sort_by_key.hpp b/boost/compute/algorithm/stable_sort_by_key.hpp index 878f999f44..ce8811ef19 100644 --- a/boost/compute/algorithm/stable_sort_by_key.hpp +++ b/boost/compute/algorithm/stable_sort_by_key.hpp @@ -126,6 +126,8 @@ inline void dispatch_ssort_by_key(KeyIterator keys_first, /// /// If no compare function is specified, \c less is used. /// +/// Space complexity: \Omega(2n) +/// /// \see sort() template<class KeyIterator, class ValueIterator, class Compare> inline void stable_sort_by_key(KeyIterator keys_first, diff --git a/boost/compute/algorithm/swap_ranges.hpp b/boost/compute/algorithm/swap_ranges.hpp index 6ff3e14f6a..a706df7a61 100644 --- a/boost/compute/algorithm/swap_ranges.hpp +++ b/boost/compute/algorithm/swap_ranges.hpp @@ -21,6 +21,8 @@ namespace compute { /// Swaps the elements in the range [\p first1, \p last1) with the /// elements in the range beginning at \p first2. +/// +/// Space complexity: \Omega(distance(\p first1, \p last1)) template<class Iterator1, class Iterator2> inline Iterator2 swap_ranges(Iterator1 first1, Iterator1 last1, diff --git a/boost/compute/algorithm/transform.hpp b/boost/compute/algorithm/transform.hpp index 68750a6523..9137604d55 100644 --- a/boost/compute/algorithm/transform.hpp +++ b/boost/compute/algorithm/transform.hpp @@ -29,6 +29,8 @@ namespace compute { /// /// \snippet test/test_transform.cpp transform_abs /// +/// Space complexity: \Omega(1) +/// /// \see copy() template<class InputIterator, class OutputIterator, class UnaryOperator> inline OutputIterator transform(InputIterator first, diff --git a/boost/compute/algorithm/transform_if.hpp b/boost/compute/algorithm/transform_if.hpp index 0eb0fd434e..9a98102d27 100644 --- a/boost/compute/algorithm/transform_if.hpp +++ b/boost/compute/algorithm/transform_if.hpp @@ -26,6 +26,7 @@ namespace boost { namespace compute { namespace detail { +// Space complexity: O(2n) template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate> inline OutputIterator transform_if_impl(InputIterator first, InputIterator last, @@ -53,14 +54,12 @@ inline OutputIterator transform_if_impl(InputIterator first, << predicate(first[k1.get_global_id(0)]) << " ? 1 : 0;\n"; k1.exec_1d(queue, 0, count); - // count number of elements to be copied - size_t copied_element_count = - ::boost::compute::count(indices.begin(), indices.end(), 1, queue); - // scan indices + size_t copied_element_count = (indices.cend() - 1).read(queue); ::boost::compute::exclusive_scan( indices.begin(), indices.end(), indices.begin(), queue ); + copied_element_count += (indices.cend() - 1).read(queue); // last scan element plus last mask element // copy values ::boost::compute::detail::meta_kernel k2("transform_if_do_copy"); @@ -98,6 +97,8 @@ inline discard_iterator transform_if_impl(InputIterator first, /// Copies each element in the range [\p first, \p last) for which /// \p predicate returns \c true to the range beginning at \p result. +/// +/// Space complexity: O(2n) template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate> inline OutputIterator transform_if(InputIterator first, InputIterator last, diff --git a/boost/compute/algorithm/transform_reduce.hpp b/boost/compute/algorithm/transform_reduce.hpp index fbeee5a691..a59a76aefd 100644 --- a/boost/compute/algorithm/transform_reduce.hpp +++ b/boost/compute/algorithm/transform_reduce.hpp @@ -30,6 +30,9 @@ namespace compute { /// /// \snippet test/test_transform_reduce.cpp sum_abs_int /// +/// Space complexity on GPUs: \Omega(n)<br> +/// Space complexity on CPUs: \Omega(1) +/// /// \see reduce(), inner_product() template<class InputIterator, class OutputIterator, diff --git a/boost/compute/algorithm/unique.hpp b/boost/compute/algorithm/unique.hpp index faa36bad9d..8b7e2a0d0d 100644 --- a/boost/compute/algorithm/unique.hpp +++ b/boost/compute/algorithm/unique.hpp @@ -31,6 +31,8 @@ namespace compute { /// /// \return \c InputIterator to the new logical end of the range /// +/// Space complexity: \Omega(4n) +/// /// \see unique_copy() template<class InputIterator, class BinaryPredicate> inline InputIterator unique(InputIterator first, diff --git a/boost/compute/algorithm/unique_copy.hpp b/boost/compute/algorithm/unique_copy.hpp index 2ce60a9359..d5fffd4ff9 100644 --- a/boost/compute/algorithm/unique_copy.hpp +++ b/boost/compute/algorithm/unique_copy.hpp @@ -127,6 +127,8 @@ inline OutputIterator unique_copy(InputIterator first, /// /// \return \c OutputIterator to the end of the result range /// +/// Space complexity: \Omega(4n) +/// /// \see unique() template<class InputIterator, class OutputIterator, class BinaryPredicate> inline OutputIterator unique_copy(InputIterator first, diff --git a/boost/compute/algorithm/upper_bound.hpp b/boost/compute/algorithm/upper_bound.hpp index a5a82d301c..f592c79b9a 100644 --- a/boost/compute/algorithm/upper_bound.hpp +++ b/boost/compute/algorithm/upper_bound.hpp @@ -22,6 +22,8 @@ namespace compute { /// Returns an iterator pointing to the first element in the sorted /// range [\p first, \p last) that is not less than or equal to /// \p value. +/// +/// Space complexity: \Omega(1) template<class InputIterator, class T> inline InputIterator upper_bound(InputIterator first, diff --git a/boost/compute/buffer.hpp b/boost/compute/buffer.hpp index b5a48806d5..128403cd62 100644 --- a/boost/compute/buffer.hpp +++ b/boost/compute/buffer.hpp @@ -154,7 +154,7 @@ public: /// \p queue to perform the copy. buffer clone(command_queue &queue) const; - #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Creates a new buffer out of this buffer. /// The new buffer is a sub region of this buffer. /// \p flags The mem_flags which should be used to create the new buffer @@ -187,7 +187,7 @@ public: return buffer(mem, false); } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 }; /// \internal_ define get_info() specializations for buffer @@ -201,12 +201,12 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer, ((cl_context, CL_MEM_CONTEXT)) ) -#ifdef CL_VERSION_1_1 +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer, ((cl_mem, CL_MEM_ASSOCIATED_MEMOBJECT)) ((size_t, CL_MEM_OFFSET)) ) -#endif // CL_VERSION_1_1 +#endif // BOOST_COMPUTE_CL_VERSION_1_1 namespace detail { diff --git a/boost/compute/cl.hpp b/boost/compute/cl.hpp index c439d8dfdc..fe25ffde56 100644 --- a/boost/compute/cl.hpp +++ b/boost/compute/cl.hpp @@ -11,10 +11,58 @@ #ifndef BOOST_COMPUTE_CL_HPP #define BOOST_COMPUTE_CL_HPP +#if defined(BOOST_COMPUTE_MAX_CL_VERSION) +# if !defined(CL_USE_DEPRECATED_OPENCL_2_1_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 202 +# define CL_USE_DEPRECATED_OPENCL_2_1_APIS +# endif +# if !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 201 +# define CL_USE_DEPRECATED_OPENCL_2_0_APIS +# endif +# if !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 200 +# define CL_USE_DEPRECATED_OPENCL_1_2_APIS +# endif +# if !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 102 +# define CL_USE_DEPRECATED_OPENCL_1_1_APIS +# endif +# if !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 101 +# define CL_USE_DEPRECATED_OPENCL_1_0_APIS +# endif +#endif + #if defined(__APPLE__) #include <OpenCL/cl.h> #else #include <CL/cl.h> #endif +// select what OpenCL core API versions to use +#if defined(CL_VERSION_1_0) +# define BOOST_COMPUTE_CL_VERSION_1_0 +#endif +#if defined(CL_VERSION_1_1) +# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 101 +# define BOOST_COMPUTE_CL_VERSION_1_1 +# endif +#endif +#if defined(CL_VERSION_1_2) +# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 102 +# define BOOST_COMPUTE_CL_VERSION_1_2 +# endif +#endif +#if defined(CL_VERSION_2_0) +# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 200 +# define BOOST_COMPUTE_CL_VERSION_2_0 +# endif +#endif +#if defined(CL_VERSION_2_1) +# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 201 +# define BOOST_COMPUTE_CL_VERSION_2_1 +# endif +#endif +#if defined(CL_VERSION_2_2) +# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 202 +# define BOOST_COMPUTE_CL_VERSION_2_2 +# endif +#endif + #endif // BOOST_COMPUTE_CL_HPP diff --git a/boost/compute/command_queue.hpp b/boost/compute/command_queue.hpp index 2a1328a959..d9e81e0bd4 100644 --- a/boost/compute/command_queue.hpp +++ b/boost/compute/command_queue.hpp @@ -81,12 +81,17 @@ public: enum properties { enable_profiling = CL_QUEUE_PROFILING_ENABLE, enable_out_of_order_execution = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 + , + on_device = CL_QUEUE_ON_DEVICE, + on_device_default = CL_QUEUE_ON_DEVICE_DEFAULT + #endif }; enum map_flags { map_read = CL_MAP_READ, map_write = CL_MAP_WRITE - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 , map_write_invalidate_region = CL_MAP_WRITE_INVALIDATE_REGION #endif @@ -118,7 +123,7 @@ public: cl_int error = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 if (device.check_version(2, 0)){ std::vector<cl_queue_properties> queue_properties; if(properties){ @@ -323,7 +328,7 @@ public: return event_; } - #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to read a rectangular region from \p buffer to /// host memory. /// @@ -417,7 +422,7 @@ public: return event_; } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 /// Enqueues a command to write data from host memory to \p buffer. /// @@ -494,7 +499,7 @@ public: return event_; } - #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to write a rectangular region from host memory /// to \p buffer. /// @@ -588,7 +593,7 @@ public: return event_; } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 /// Enqueues a command to copy data from \p src_buffer to /// \p dst_buffer. @@ -630,7 +635,7 @@ public: return event_; } - #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to copy a rectangular region from /// \p src_buffer to \p dst_buffer. /// @@ -676,9 +681,9 @@ public: return event_; } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to fill \p buffer with \p pattern. /// /// \see_opencl_ref{clEnqueueFillBuffer} @@ -717,7 +722,7 @@ public: return event_; } - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 /// Enqueues a command to map \p buffer into the host address space. /// Event associated with map operation is returned through @@ -1269,7 +1274,7 @@ public: return event_; } - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to fill \p image with \p fill_color. /// /// \see_opencl_ref{clEnqueueFillImage} @@ -1354,7 +1359,7 @@ public: return event_; } - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 /// Enqueues a kernel for execution. /// @@ -1438,7 +1443,7 @@ public: // clEnqueueTask() was deprecated in OpenCL 2.0. In that case we // just forward to the equivalent clEnqueueNDRangeKernel() call. - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 size_t one = 1; cl_int ret = clEnqueueNDRangeKernel( m_queue, kernel, 1, 0, &one, &one, @@ -1511,7 +1516,10 @@ public: { BOOST_ASSERT(m_queue != 0); - clFlush(m_queue); + cl_int ret = clFlush(m_queue); + if(ret != CL_SUCCESS){ + BOOST_THROW_EXCEPTION(opencl_error(ret)); + } } /// Blocks until all outstanding commands in the queue have finished. @@ -1521,7 +1529,10 @@ public: { BOOST_ASSERT(m_queue != 0); - clFinish(m_queue); + cl_int ret = clFinish(m_queue); + if(ret != CL_SUCCESS){ + BOOST_THROW_EXCEPTION(opencl_error(ret)); + } } /// Enqueues a barrier in the queue. @@ -1530,11 +1541,11 @@ public: BOOST_ASSERT(m_queue != 0); cl_int ret = CL_SUCCESS; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(get_device().check_version(1, 2)){ ret = clEnqueueBarrierWithWaitList(m_queue, 0, 0, 0); } else - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 { // Suppress deprecated declarations warning BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS(); @@ -1547,7 +1558,7 @@ public: } } - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a barrier in the queue after \p events. /// /// \opencl_version_warning{1,2} @@ -1568,7 +1579,7 @@ public: return event_; } - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 /// Enqueues a marker in the queue and returns an event that can be /// used to track its progress. @@ -1577,7 +1588,7 @@ public: event event_; cl_int ret = CL_SUCCESS; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(get_device().check_version(1, 2)){ ret = clEnqueueMarkerWithWaitList(m_queue, 0, 0, &event_.get()); } else @@ -1596,7 +1607,7 @@ public: return event_; } - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a marker after \p events in the queue and returns an /// event that can be used to track its progress. /// @@ -1615,9 +1626,9 @@ public: return event_; } - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 - #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Enqueues a command to copy \p size bytes of data from \p src_ptr to /// \p dst_ptr. /// @@ -1797,7 +1808,7 @@ public: return event_; } - #endif // CL_VERSION_2_0 + #endif // BOOST_COMPUTE_CL_VERSION_2_0 /// Returns \c true if the command queue is the same at \p other. bool operator==(const command_queue &other) const diff --git a/boost/compute/container/detail/scalar.hpp b/boost/compute/container/detail/scalar.hpp index 7ecd86e540..4dee76d2b4 100644 --- a/boost/compute/container/detail/scalar.hpp +++ b/boost/compute/container/detail/scalar.hpp @@ -12,6 +12,7 @@ #define BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP #include <boost/compute/buffer.hpp> +#include <boost/compute/event.hpp> #include <boost/compute/detail/read_write_single_value.hpp> namespace boost { @@ -40,9 +41,9 @@ public: return read_single_value<T>(m_buffer, 0, queue); } - void write(const T &value, command_queue &queue) + event write(const T &value, command_queue &queue) { - write_single_value<T>(value, m_buffer, 0, queue); + return write_single_value<T>(value, m_buffer, 0, queue); } const buffer& get_buffer() const diff --git a/boost/compute/container/valarray.hpp b/boost/compute/container/valarray.hpp index 8ac8e01753..981ec2e545 100644 --- a/boost/compute/container/valarray.hpp +++ b/boost/compute/container/valarray.hpp @@ -67,6 +67,7 @@ public: valarray(const valarray<T> &other) : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T)) { + copy(other.begin(), other.end(), begin()); } valarray(const std::valarray<T> &valarray, diff --git a/boost/compute/context.hpp b/boost/compute/context.hpp index 61e84e9767..13154a968a 100644 --- a/boost/compute/context.hpp +++ b/boost/compute/context.hpp @@ -233,11 +233,11 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context, ((std::vector<cl_context_properties>, CL_CONTEXT_PROPERTIES)) ) -#ifdef CL_VERSION_1_1 +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context, ((cl_uint, CL_CONTEXT_NUM_DEVICES)) ) -#endif // CL_VERSION_1_1 +#endif // BOOST_COMPUTE_CL_VERSION_1_1 } // end compute namespace } // end boost namespace diff --git a/boost/compute/detail/buffer_value.hpp b/boost/compute/detail/buffer_value.hpp index 6a4e78fc19..478fc03252 100644 --- a/boost/compute/detail/buffer_value.hpp +++ b/boost/compute/detail/buffer_value.hpp @@ -124,7 +124,9 @@ public: const context &context = m_buffer.get_context(); command_queue queue(context, context.get_device()); - detail::write_single_value<T>(value, m_buffer, m_index / sizeof(T), queue); + detail::write_single_value<T>( + value, m_buffer, m_index / sizeof(T), queue + ).wait(); return *this; } diff --git a/boost/compute/detail/duration.hpp b/boost/compute/detail/duration.hpp index 601f12d291..98e825fb3c 100644 --- a/boost/compute/detail/duration.hpp +++ b/boost/compute/detail/duration.hpp @@ -17,7 +17,9 @@ #include <chrono> #endif +#ifndef BOOST_COMPUTE_NO_BOOST_CHRONO #include <boost/chrono/duration.hpp> +#endif namespace boost { namespace compute { @@ -34,6 +36,7 @@ make_duration_from_nanoseconds(std::chrono::duration<Rep, Period>, size_t nanose } #endif // BOOST_COMPUTE_NO_HDR_CHRONO +#ifndef BOOST_COMPUTE_NO_BOOST_CHRONO template<class Rep, class Period> inline boost::chrono::duration<Rep, Period> make_duration_from_nanoseconds(boost::chrono::duration<Rep, Period>, size_t nanoseconds) @@ -42,6 +45,7 @@ make_duration_from_nanoseconds(boost::chrono::duration<Rep, Period>, size_t nano boost::chrono::nanoseconds(nanoseconds) ); } +#endif // BOOST_COMPUTE_NO_BOOST_CHRONO } // end detail namespace } // end compute namespace diff --git a/boost/compute/detail/meta_kernel.hpp b/boost/compute/detail/meta_kernel.hpp index 5e6d6e0337..13af7cc437 100644 --- a/boost/compute/detail/meta_kernel.hpp +++ b/boost/compute/detail/meta_kernel.hpp @@ -1036,7 +1036,7 @@ inline meta_kernel& operator<<(meta_kernel &kernel, } // SVM requires OpenCL 2.0 -#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) +#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) template<class T, class IndexExpr> inline meta_kernel& operator<<(meta_kernel &kernel, const svm_ptr_index_expr<T, IndexExpr> &expr) @@ -1072,7 +1072,7 @@ inline meta_kernel& operator<<(meta_kernel &kernel, BOOST_STATIC_ASSERT(N < 16); if(N < 10){ - return kernel << expr.m_arg << ".s" << uint_(N); + return kernel << expr.m_arg << ".s" << int_(N); } else if(N < 16){ #ifdef _MSC_VER diff --git a/boost/compute/detail/parameter_cache.hpp b/boost/compute/detail/parameter_cache.hpp index 0a16cd9b0e..c609490c1e 100644 --- a/boost/compute/detail/parameter_cache.hpp +++ b/boost/compute/detail/parameter_cache.hpp @@ -24,6 +24,7 @@ #include <boost/compute/version.hpp> #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE +#include <cstdio> #include <boost/algorithm/string/trim.hpp> #include <boost/compute/detail/path.hpp> #include <boost/property_tree/ptree.hpp> @@ -117,9 +118,16 @@ private: static std::string version_string() { char buf[32]; - std::snprintf(buf, sizeof(buf), "%d.%d.%d", BOOST_COMPUTE_VERSION_MAJOR, - BOOST_COMPUTE_VERSION_MINOR, - BOOST_COMPUTE_VERSION_PATCH); + // snprintf is in Visual Studio since Visual Studio 2015 (_MSC_VER == 1900) + #if defined (_MSC_VER) && _MSC_VER < 1900 + #define DETAIL_SNPRINTF sprintf_s + #else + #define DETAIL_SNPRINTF std::snprintf + #endif + DETAIL_SNPRINTF(buf, sizeof(buf), "%d.%d.%d", BOOST_COMPUTE_VERSION_MAJOR, + BOOST_COMPUTE_VERSION_MINOR, + BOOST_COMPUTE_VERSION_PATCH); + #undef DETAIL_SNPRINTF return buf; } diff --git a/boost/compute/detail/path.hpp b/boost/compute/detail/path.hpp index ec8760eaf9..d9c5afd182 100644 --- a/boost/compute/detail/path.hpp +++ b/boost/compute/detail/path.hpp @@ -30,7 +30,7 @@ static const std::string& path_delim() // Path to appdata folder. inline const std::string& appdata_path() { - #ifdef WIN32 + #ifdef _WIN32 static const std::string appdata = detail::getenv("APPDATA") + path_delim() + "boost_compute"; #else diff --git a/boost/compute/detail/read_write_single_value.hpp b/boost/compute/detail/read_write_single_value.hpp index fde40d946c..3e613bc8c3 100644 --- a/boost/compute/detail/read_write_single_value.hpp +++ b/boost/compute/detail/read_write_single_value.hpp @@ -14,6 +14,7 @@ #include <boost/throw_exception.hpp> #include <boost/compute/buffer.hpp> +#include <boost/compute/event.hpp> #include <boost/compute/exception.hpp> #include <boost/compute/command_queue.hpp> @@ -47,18 +48,18 @@ inline T read_single_value(const buffer &buffer, command_queue &queue) // writes a single value at index to the buffer template<class T> -inline void write_single_value(const T &value, - const buffer &buffer, - size_t index, - command_queue &queue) +inline event write_single_value(const T &value, + const buffer &buffer, + size_t index, + command_queue &queue) { BOOST_ASSERT(index < buffer.size() / sizeof(T)); BOOST_ASSERT(buffer.get_context() == queue.get_context()); - queue.enqueue_write_buffer(buffer, - index * sizeof(T), - sizeof(T), - &value); + return queue.enqueue_write_buffer(buffer, + index * sizeof(T), + sizeof(T), + &value); } // writes value to the first location in buffer diff --git a/boost/compute/device.hpp b/boost/compute/device.hpp index 5cf2e8c931..427d75d60b 100644 --- a/boost/compute/device.hpp +++ b/boost/compute/device.hpp @@ -62,7 +62,7 @@ public: explicit device(cl_device_id id, bool retain = true) : m_id(id) { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && retain && is_subdevice()){ clRetainDevice(m_id); } @@ -75,7 +75,7 @@ public: device(const device &other) : m_id(other.m_id) { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && is_subdevice()){ clRetainDevice(m_id); } @@ -86,7 +86,7 @@ public: device& operator=(const device &other) { if(this != &other){ - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && is_subdevice()){ clReleaseDevice(m_id); } @@ -94,7 +94,7 @@ public: m_id = other.m_id; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && is_subdevice()){ clRetainDevice(m_id); } @@ -115,7 +115,7 @@ public: /// Move-assigns the device from \p other to \c *this. device& operator=(device&& other) BOOST_NOEXCEPT { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && is_subdevice()){ clReleaseDevice(m_id); } @@ -131,7 +131,7 @@ public: /// Destroys the device object. ~device() { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 if(m_id && is_subdevice()){ BOOST_COMPUTE_ASSERT_CL_SUCCESS( clReleaseDevice(m_id) @@ -282,7 +282,7 @@ public: /// Returns \c true if the device is a sub-device. bool is_subdevice() const { - #if defined(CL_VERSION_1_2) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) try { return get_info<cl_device_id>(CL_DEVICE_PARENT_DEVICE) != 0; } @@ -321,7 +321,7 @@ public: typename detail::get_object_info_type<device, Enum>::type get_info() const; - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Partitions the device into multiple sub-devices according to /// \p properties. /// @@ -393,7 +393,7 @@ public: return partition(properties); } - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 /// Returns \c true if the device is the same at \p other. bool operator==(const device &other) const @@ -528,7 +528,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ) #endif -#ifdef CL_VERSION_1_1 +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((bool, CL_DEVICE_HOST_UNIFIED_MEMORY)) ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR)) @@ -539,9 +539,9 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE)) ((std::string, CL_DEVICE_OPENCL_C_VERSION)) ) -#endif // CL_VERSION_1_1 +#endif // BOOST_COMPUTE_CL_VERSION_1_1 -#ifdef CL_VERSION_1_2 +#ifdef BOOST_COMPUTE_CL_VERSION_1_2 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((std::string, CL_DEVICE_BUILT_IN_KERNELS)) ((bool, CL_DEVICE_LINKER_AVAILABLE)) @@ -554,9 +554,9 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((bool, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC)) ((cl_uint, CL_DEVICE_REFERENCE_COUNT)) ) -#endif // CL_VERSION_1_2 +#endif // BOOST_COMPUTE_CL_VERSION_1_2 -#ifdef CL_VERSION_2_0 +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((size_t, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE)) ((size_t, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE)) @@ -576,7 +576,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device, ((cl_uint, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT)) ((cl_uint, CL_DEVICE_IMAGE_PITCH_ALIGNMENT)) ) -#endif // CL_VERSION_2_0 +#endif // BOOST_COMPUTE_CL_VERSION_2_0 } // end compute namespace } // end boost namespace diff --git a/boost/compute/event.hpp b/boost/compute/event.hpp index 2f53d87650..030c1bb3ba 100644 --- a/boost/compute/event.hpp +++ b/boost/compute/event.hpp @@ -74,7 +74,7 @@ public: marker = CL_COMMAND_MARKER, aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS, release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS - #if defined(CL_VERSION_1_1) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) , read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT, write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT, @@ -218,7 +218,7 @@ public: } } - #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Registers a function to be called when the event status changes to /// \p status (by default CL_COMPLETE). The callback is passed the OpenCL /// event object, the event status, and a pointer to arbitrary user data. @@ -254,7 +254,7 @@ public: new boost::function<void()>(callback) ); } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 /// Returns the total duration of the event from \p start to \p end. /// @@ -300,7 +300,7 @@ public: } private: - #ifdef CL_VERSION_1_1 + #ifdef BOOST_COMPUTE_CL_VERSION_1_1 /// \internal_ static void BOOST_COMPUTE_CL_CALLBACK event_callback_invoker(cl_event, cl_int, void *user_data) @@ -312,7 +312,7 @@ private: delete callback; } - #endif // CL_VERSION_1_1 + #endif // BOOST_COMPUTE_CL_VERSION_1_1 protected: cl_event m_event; @@ -326,7 +326,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event, ((cl_uint, CL_EVENT_REFERENCE_COUNT)) ) -#ifdef CL_VERSION_1_1 +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event, ((cl_context, CL_EVENT_CONTEXT)) ) diff --git a/boost/compute/exception/opencl_error.hpp b/boost/compute/exception/opencl_error.hpp index 29a3a9d258..0f47b56f84 100644 --- a/boost/compute/exception/opencl_error.hpp +++ b/boost/compute/exception/opencl_error.hpp @@ -123,7 +123,7 @@ public: case CL_INVALID_BUFFER_SIZE: return "Invalid Buffer Size"; case CL_INVALID_MIP_LEVEL: return "Invalid MIP Level"; case CL_INVALID_GLOBAL_WORK_SIZE: return "Invalid Global Work Size"; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 case CL_COMPILE_PROGRAM_FAILURE: return "Compile Program Failure"; case CL_LINKER_NOT_AVAILABLE: return "Linker Not Available"; case CL_LINK_PROGRAM_FAILURE: return "Link Program Failure"; @@ -134,8 +134,8 @@ public: case CL_INVALID_COMPILER_OPTIONS: return "Invalid Compiler Options"; case CL_INVALID_LINKER_OPTIONS: return "Invalid Linker Options"; case CL_INVALID_DEVICE_PARTITION_COUNT: return "Invalid Device Partition Count"; - #endif // CL_VERSION_1_2 - #ifdef CL_VERSION_2_0 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 case CL_INVALID_PIPE_SIZE: return "Invalid Pipe Size"; case CL_INVALID_DEVICE_QUEUE: return "Invalid Device Queue"; #endif diff --git a/boost/compute/function.hpp b/boost/compute/function.hpp index b0b893e948..a731e18751 100644 --- a/boost/compute/function.hpp +++ b/boost/compute/function.hpp @@ -164,6 +164,19 @@ public: m_definitions[name] = value; } + bool operator==(const function<Signature>& other) const + { + return + (m_name == other.m_name) + && (m_definitions == other.m_definitions) + && (m_source == other.m_source); + } + + bool operator!=(const function<Signature>& other) const + { + return !(*this == other); + } + /// \internal_ detail::invoked_function<result_type, boost::tuple<> > operator()() const diff --git a/boost/compute/functional/atomic.hpp b/boost/compute/functional/atomic.hpp index 2701561bc3..ac4ac70d7f 100644 --- a/boost/compute/functional/atomic.hpp +++ b/boost/compute/functional/atomic.hpp @@ -15,7 +15,7 @@ #include <boost/compute/function.hpp> #ifndef BOOST_COMPUTE_DOXYGEN_INVOKED -#ifdef CL_VERSION_1_1 +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 #define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atomic_" #else #define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atom_" diff --git a/boost/compute/image/image1d.hpp b/boost/compute/image/image1d.hpp index 2d71934ab4..0f146be089 100644 --- a/boost/compute/image/image1d.hpp +++ b/boost/compute/image/image1d.hpp @@ -50,7 +50,7 @@ public: cl_mem_flags flags = read_write, void *host_ptr = 0) { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 cl_image_desc desc; desc.image_type = CL_MEM_OBJECT_IMAGE1D; desc.image_width = image_width; @@ -61,7 +61,7 @@ public: desc.image_slice_pitch = 0; desc.num_mip_levels = 0; desc.num_samples = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 desc.mem_object = 0; #else desc.buffer = 0; @@ -151,7 +151,7 @@ public: static std::vector<image_format> get_supported_formats(const context &context, cl_mem_flags flags = read_write) { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE1D, flags); #else return std::vector<image_format>(); @@ -164,7 +164,7 @@ public: const context &context, cl_mem_flags flags = read_write) { - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 return image_object::is_supported_format( format, context, CL_MEM_OBJECT_IMAGE1D, flags ); diff --git a/boost/compute/image/image2d.hpp b/boost/compute/image/image2d.hpp index c203a9417f..edfe98de5a 100644 --- a/boost/compute/image/image2d.hpp +++ b/boost/compute/image/image2d.hpp @@ -58,7 +58,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 cl_image_desc desc; desc.image_type = CL_MEM_OBJECT_IMAGE2D; desc.image_width = image_width; @@ -69,7 +69,7 @@ public: desc.image_slice_pitch = 0; desc.num_mip_levels = 0; desc.num_samples = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 desc.mem_object = 0; #else desc.buffer = 0; @@ -108,7 +108,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 cl_image_desc desc; desc.image_type = CL_MEM_OBJECT_IMAGE2D; desc.image_width = image_width; @@ -119,7 +119,7 @@ public: desc.image_slice_pitch = 0; desc.num_mip_levels = 0; desc.num_samples = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 desc.mem_object = 0; #else desc.buffer = 0; diff --git a/boost/compute/image/image3d.hpp b/boost/compute/image/image3d.hpp index 9463cfaa16..5569f2a0b9 100644 --- a/boost/compute/image/image3d.hpp +++ b/boost/compute/image/image3d.hpp @@ -54,7 +54,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 cl_image_desc desc; desc.image_type = CL_MEM_OBJECT_IMAGE3D; desc.image_width = image_width; @@ -65,7 +65,7 @@ public: desc.image_slice_pitch = image_slice_pitch; desc.num_mip_levels = 0; desc.num_samples = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 desc.mem_object = 0; #else desc.buffer = 0; @@ -108,7 +108,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 cl_image_desc desc; desc.image_type = CL_MEM_OBJECT_IMAGE3D; desc.image_width = image_width; @@ -119,7 +119,7 @@ public: desc.image_slice_pitch = image_slice_pitch; desc.num_mip_levels = 0; desc.num_samples = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 desc.mem_object = 0; #else desc.buffer = 0; diff --git a/boost/compute/image/image_sampler.hpp b/boost/compute/image/image_sampler.hpp index 4f1bfe9b86..26f20aa9d5 100644 --- a/boost/compute/image/image_sampler.hpp +++ b/boost/compute/image/image_sampler.hpp @@ -55,7 +55,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 std::vector<cl_sampler_properties> sampler_properties; sampler_properties.push_back(CL_SAMPLER_NORMALIZED_COORDS); sampler_properties.push_back(cl_sampler_properties(normalized_coords)); diff --git a/boost/compute/interop/opengl/context.hpp b/boost/compute/interop/opengl/context.hpp index c35fedddfa..077c86036b 100644 --- a/boost/compute/interop/opengl/context.hpp +++ b/boost/compute/interop/opengl/context.hpp @@ -75,6 +75,10 @@ inline context opengl_create_shared_context() for(size_t i = 0; i < platforms.size(); i++){ const platform &platform = platforms[i]; + // check whether this platform supports OpenCL/OpenGL sharing + if (!platform.supports_extension(cl_gl_sharing_extension)) + continue; + // load clGetGLContextInfoKHR() extension function GetGLContextInfoKHRFunction GetGLContextInfoKHR = reinterpret_cast<GetGLContextInfoKHRFunction>( @@ -92,7 +96,7 @@ inline context opengl_create_shared_context() #if defined(__linux__) CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(), CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(), - #elif defined(WIN32) + #elif defined(_WIN32) CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(), CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(), #endif diff --git a/boost/compute/interop/opengl/opengl_texture.hpp b/boost/compute/interop/opengl/opengl_texture.hpp index c1f3f4f441..ae095d22a9 100644 --- a/boost/compute/interop/opengl/opengl_texture.hpp +++ b/boost/compute/interop/opengl/opengl_texture.hpp @@ -51,7 +51,7 @@ public: { cl_int error = 0; - #ifdef CL_VERSION_1_2 + #ifdef BOOST_COMPUTE_CL_VERSION_1_2 m_mem = clCreateFromGLTexture(context, flags, texture_target, diff --git a/boost/compute/iterator/buffer_iterator.hpp b/boost/compute/iterator/buffer_iterator.hpp index cd68058f64..de2395a552 100644 --- a/boost/compute/iterator/buffer_iterator.hpp +++ b/boost/compute/iterator/buffer_iterator.hpp @@ -58,13 +58,20 @@ struct buffer_iterator_index_expr size_t index, const memory_object::address_space address_space, const IndexExpr &expr) - : m_buffer(buffer), + : m_buffer(buffer.get(), false), m_index(index), m_address_space(address_space), m_expr(expr) { } + ~buffer_iterator_index_expr() + { + // set buffer to null so that its reference count will + // not be decremented when its destructor is called + m_buffer.get() = 0; + } + operator T() const { BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value, @@ -73,10 +80,10 @@ struct buffer_iterator_index_expr return buffer_value<T>(m_buffer, size_t(m_expr) * sizeof(T)); } - const buffer &m_buffer; - size_t m_index; - memory_object::address_space m_address_space; - IndexExpr m_expr; + const buffer m_buffer; + const size_t m_index; + const memory_object::address_space m_address_space; + const IndexExpr m_expr; }; template<class T, class IndexExpr> diff --git a/boost/compute/iterator/counting_iterator.hpp b/boost/compute/iterator/counting_iterator.hpp index 304c1e05cf..384486bcb3 100644 --- a/boost/compute/iterator/counting_iterator.hpp +++ b/boost/compute/iterator/counting_iterator.hpp @@ -47,14 +47,14 @@ struct counting_iterator_index_expr { typedef T result_type; - counting_iterator_index_expr(const T &init, const IndexExpr &expr) + counting_iterator_index_expr(const T init, const IndexExpr &expr) : m_init(init), m_expr(expr) { } - const T &m_init; - IndexExpr m_expr; + const T m_init; + const IndexExpr m_expr; }; template<class T, class IndexExpr> diff --git a/boost/compute/iterator/function_input_iterator.hpp b/boost/compute/iterator/function_input_iterator.hpp index bd89b6c0fc..bb8f0d5d09 100644 --- a/boost/compute/iterator/function_input_iterator.hpp +++ b/boost/compute/iterator/function_input_iterator.hpp @@ -53,7 +53,7 @@ struct function_input_iterator_expr { } - Function m_function; + const Function m_function; }; template<class Function> diff --git a/boost/compute/iterator/permutation_iterator.hpp b/boost/compute/iterator/permutation_iterator.hpp index 8a7f97a402..a0d2dbfbc5 100644 --- a/boost/compute/iterator/permutation_iterator.hpp +++ b/boost/compute/iterator/permutation_iterator.hpp @@ -60,9 +60,9 @@ struct permutation_iterator_access_expr { } - ElementIterator m_element_iter; - IndexIterator m_index_iter; - IndexExpr m_expr; + const ElementIterator m_element_iter; + const IndexIterator m_index_iter; + const IndexExpr m_expr; }; template<class ElementIterator, class IndexIterator, class IndexExpr> diff --git a/boost/compute/iterator/strided_iterator.hpp b/boost/compute/iterator/strided_iterator.hpp index 52e7f07bd8..eb342dc33d 100644 --- a/boost/compute/iterator/strided_iterator.hpp +++ b/boost/compute/iterator/strided_iterator.hpp @@ -56,8 +56,8 @@ struct stride_expr { } - IndexExpr m_index_expr; - Stride m_stride; + const IndexExpr m_index_expr; + const Stride m_stride; }; template<class IndexExpr, class Stride> @@ -90,9 +90,9 @@ struct strided_iterator_index_expr { } - Iterator m_input_iter; - const Stride& m_stride; - IndexExpr m_index_expr; + const Iterator m_input_iter; + const Stride m_stride; + const IndexExpr m_index_expr; }; template<class Iterator, class Stride, class IndexExpr> diff --git a/boost/compute/iterator/transform_iterator.hpp b/boost/compute/iterator/transform_iterator.hpp index c040922f9d..08ff6ee4d4 100644 --- a/boost/compute/iterator/transform_iterator.hpp +++ b/boost/compute/iterator/transform_iterator.hpp @@ -76,9 +76,9 @@ struct transform_iterator_index_expr { } - InputIterator m_input_iter; - UnaryFunction m_transform_expr; - IndexExpr m_index_expr; + const InputIterator m_input_iter; + const UnaryFunction m_transform_expr; + const IndexExpr m_index_expr; }; template<class InputIterator, class UnaryFunction, class IndexExpr> diff --git a/boost/compute/iterator/zip_iterator.hpp b/boost/compute/iterator/zip_iterator.hpp index 2860d73a93..a4af6a3034 100644 --- a/boost/compute/iterator/zip_iterator.hpp +++ b/boost/compute/iterator/zip_iterator.hpp @@ -92,8 +92,8 @@ struct zip_iterator_index_expr { } - IteratorTuple m_iterators; - IndexExpr m_index_expr; + const IteratorTuple m_iterators; + const IndexExpr m_index_expr; }; /// \internal_ diff --git a/boost/compute/kernel.hpp b/boost/compute/kernel.hpp index 72f21a0378..097cba692e 100644 --- a/boost/compute/kernel.hpp +++ b/boost/compute/kernel.hpp @@ -168,7 +168,7 @@ public: typename detail::get_object_info_type<kernel, Enum>::type get_info() const; - #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Returns information about the argument at \p index. /// /// For example, to get the name of the first argument: @@ -197,7 +197,7 @@ public: template<int Enum> typename detail::get_object_info_type<kernel, Enum>::type get_arg_info(size_t index) const; - #endif // CL_VERSION_1_2 + #endif // BOOST_COMPUTE_CL_VERSION_1_2 /// Returns work-group information for the kernel with \p device. /// @@ -266,7 +266,7 @@ public: /// \internal_ void set_arg_svm_ptr(size_t index, void* ptr) { - #ifdef CL_VERSION_2_0 + #ifdef BOOST_COMPUTE_CL_VERSION_2_0 cl_int ret = clSetKernelArgSVMPointer(m_kernel, static_cast<cl_uint>(index), ptr); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); @@ -289,7 +289,7 @@ public: } #endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES - #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) + #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Sets additional execution information for the kernel. /// /// \opencl_version_warning{2,0} @@ -302,7 +302,7 @@ public: BOOST_THROW_EXCEPTION(opencl_error(ret)); } } - #endif // CL_VERSION_2_0 + #endif // BOOST_COMPUTE_CL_VERSION_2_0 /// Returns \c true if the kernel is the same at \p other. bool operator==(const kernel &other) const @@ -365,14 +365,14 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel, ((cl_program, CL_KERNEL_PROGRAM)) ) -#ifdef CL_VERSION_1_2 +#ifdef BOOST_COMPUTE_CL_VERSION_1_2 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel, ((std::string, CL_KERNEL_ATTRIBUTES)) ) -#endif // CL_VERSION_1_2 +#endif // BOOST_COMPUTE_CL_VERSION_1_2 /// \internal_ define get_arg_info() specializations for kernel -#ifdef CL_VERSION_1_2 +#ifdef BOOST_COMPUTE_CL_VERSION_1_2 #define BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(result_type, value) \ namespace detail { \ template<> struct get_object_info_type<kernel, value> { typedef result_type type; }; \ @@ -386,7 +386,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(cl_kernel_arg_acc BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(std::string, CL_KERNEL_ARG_TYPE_NAME) BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(cl_kernel_arg_type_qualifier, CL_KERNEL_ARG_TYPE_QUALIFIER) BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(std::string, CL_KERNEL_ARG_NAME) -#endif // CL_VERSION_1_2 +#endif // BOOST_COMPUTE_CL_VERSION_1_2 namespace detail { diff --git a/boost/compute/lambda/context.hpp b/boost/compute/lambda/context.hpp index ed25b79475..a7248d4639 100644 --- a/boost/compute/lambda/context.hpp +++ b/boost/compute/lambda/context.hpp @@ -78,6 +78,41 @@ struct context : proto::callable_context<context<Args> > stream << stream.lit(x); } + void operator()(proto::tag::terminal, const uchar_ &x) + { + stream << "(uchar)(" << stream.lit(uint_(x)) << "u)"; + } + + void operator()(proto::tag::terminal, const char_ &x) + { + stream << "(char)(" << stream.lit(int_(x)) << ")"; + } + + void operator()(proto::tag::terminal, const ushort_ &x) + { + stream << "(ushort)(" << stream.lit(x) << "u)"; + } + + void operator()(proto::tag::terminal, const short_ &x) + { + stream << "(short)(" << stream.lit(x) << ")"; + } + + void operator()(proto::tag::terminal, const uint_ &x) + { + stream << "(" << stream.lit(x) << "u)"; + } + + void operator()(proto::tag::terminal, const ulong_ &x) + { + stream << "(" << stream.lit(x) << "ul)"; + } + + void operator()(proto::tag::terminal, const long_ &x) + { + stream << "(" << stream.lit(x) << "l)"; + } + // handle placeholders template<int I> void operator()(proto::tag::terminal, placeholder<I>) diff --git a/boost/compute/lambda/functional.hpp b/boost/compute/lambda/functional.hpp index dd7190e4d9..42e75e4991 100644 --- a/boost/compute/lambda/functional.hpp +++ b/boost/compute/lambda/functional.hpp @@ -22,6 +22,11 @@ #include <boost/compute/lambda/result_of.hpp> #include <boost/compute/lambda/placeholder.hpp> +#include <boost/compute/types/fundamental.hpp> +#include <boost/compute/type_traits/scalar_type.hpp> +#include <boost/compute/type_traits/vector_size.hpp> +#include <boost/compute/type_traits/make_vector_type.hpp> + namespace boost { namespace compute { namespace lambda { @@ -29,7 +34,8 @@ namespace lambda { namespace mpl = boost::mpl; namespace proto = boost::proto; -// wraps a unary boolean function +// wraps a unary boolean function whose result type is an int_ when the argument +// type is a scalar, and intN_ if the argument type is a vector of size N #define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(name) \ namespace detail { \ struct BOOST_PP_CAT(name, _func) \ @@ -37,7 +43,12 @@ namespace proto = boost::proto; template<class Expr, class Args> \ struct lambda_result \ { \ - typedef int type; \ + typedef typename proto::result_of::child_c<Expr, 1>::type Arg; \ + typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type result_type; \ + typedef typename ::boost::compute::make_vector_type< \ + ::boost::compute::int_, \ + ::boost::compute::vector_size<result_type>::value \ + >::type type; \ }; \ \ template<class Context, class Arg> \ @@ -60,7 +71,7 @@ namespace proto = boost::proto; ); \ } -// wraps a unary function who's return type is the same as the argument type +// wraps a unary function whose return type is the same as the argument type #define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(name) \ namespace detail { \ struct BOOST_PP_CAT(name, _func) \ @@ -92,7 +103,79 @@ namespace proto = boost::proto; ); \ } -// wraps a binary function +// wraps a unary function whose result type is the scalar type of the first argument +#define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 1>::type Arg; \ + typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type result_type; \ + typedef typename ::boost::compute::scalar_type<result_type>::type type; \ + }; \ + \ + template<class Context, class Arg> \ + static void apply(Context &ctx, const Arg &arg) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \ + >::type const \ + name(const Arg &arg) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \ + ); \ + } + +// wraps a binary boolean function whose result type is an int_ when the first +// argument type is a scalar, and intN_ if the first argument type is a vector +// of size N +#define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ + typedef typename ::boost::compute::make_vector_type< \ + ::boost::compute::int_, \ + ::boost::compute::vector_size<Arg1>::value \ + >::type type; \ + }; \ + \ + template<class Context, class Arg1, class Arg2> \ + static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg1, ctx); \ + ctx.stream << ", "; \ + proto::eval(arg2, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg1, class Arg2> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \ + >::type const \ + name(const Arg1 &arg1, const Arg2 &arg2) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \ + ); \ + } + +// wraps a binary function whose result type is the type of the first argument #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(name) \ namespace detail { \ struct BOOST_PP_CAT(name, _func) \ @@ -126,6 +209,40 @@ namespace proto = boost::proto; ); \ } +// wraps a binary function whose result type is the type of the second argument +#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_2(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 2>::type Arg2; \ + typedef typename ::boost::compute::lambda::result_of<Arg2, Args>::type type; \ + }; \ + \ + template<class Context, class Arg1, class Arg2> \ + static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg1, ctx); \ + ctx.stream << ", "; \ + proto::eval(arg2, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg1, class Arg2> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \ + >::type const \ + name(const Arg1 &arg1, const Arg2 &arg2) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \ + ); \ + } + // wraps a binary function who's result type is the scalar type of the first argument #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(name) \ namespace detail { \ @@ -161,6 +278,41 @@ namespace proto = boost::proto; ); \ } +// wraps a binary function whose result type is the type of the first argument +// and the second argument is a pointer +#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ + typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \ + }; \ + \ + template<class Context, class Arg1, class Arg2> \ + static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg1, ctx); \ + ctx.stream << ", &"; \ + proto::eval(arg2, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg1, class Arg2> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \ + >::type const \ + name(const Arg1 &arg1, const Arg2 &arg2) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \ + ); \ + } + // wraps a ternary function #define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(name) \ namespace detail { \ @@ -197,43 +349,246 @@ namespace proto = boost::proto; ); \ } +// wraps a ternary function whose result type is the type of the third argument +#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_3(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 3>::type Arg3; \ + typedef typename ::boost::compute::lambda::result_of<Arg3, Args>::type type; \ + }; \ + \ + template<class Context, class Arg1, class Arg2, class Arg3> \ + static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg1, ctx); \ + ctx.stream << ", "; \ + proto::eval(arg2, ctx); \ + ctx.stream << ", "; \ + proto::eval(arg3, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg1, class Arg2, class Arg3> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \ + >::type const \ + name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \ + ); \ + } -BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all) -BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any) -BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf) -BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan) -BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite) +// wraps a ternary function whose result type is the type of the first argument +// and the third argument of the function is a pointer +#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_PTR(name) \ + namespace detail { \ + struct BOOST_PP_CAT(name, _func) \ + { \ + template<class Expr, class Args> \ + struct lambda_result \ + { \ + typedef typename proto::result_of::child_c<Expr, 3>::type Arg3; \ + typedef typename ::boost::compute::lambda::result_of<Arg3, Args>::type type; \ + }; \ + \ + template<class Context, class Arg1, class Arg2, class Arg3> \ + static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ + { \ + ctx.stream << #name << "("; \ + proto::eval(arg1, ctx); \ + ctx.stream << ", "; \ + proto::eval(arg2, ctx); \ + ctx.stream << ", &"; \ + proto::eval(arg3, ctx); \ + ctx.stream << ")"; \ + } \ + }; \ + } \ + template<class Arg1, class Arg2, class Arg3> \ + inline typename proto::result_of::make_expr< \ + proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \ + >::type const \ + name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ + { \ + return proto::make_expr<proto::tag::function>( \ + BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \ + ); \ + } +// Common Built-In Functions +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(degrees) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(min) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(max) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mix) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(radians) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sign) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_2(step) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_3(smoothstep) + +// Geometric Built-In Functions +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(length) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(normalize) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(fast_distance) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(fast_length) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(fast_normalize) + +// Integer Built-In Functions BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(abs) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(abs_diff) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(add_sat) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(hadd) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(rhadd) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(clz) +#ifdef BOOST_COMPUTE_CL_VERSION_2_0 +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(ctz) +#endif +// clamp() (since 1.1) already defined in common +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad_hi) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad24) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad_sat) +// max() and min() functions are defined in common +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(mul_hi) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(mul24) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(rotate) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(sub_sat) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(upsample) +#ifdef BOOST_COMPUTE_CL_VERSION_1_2 +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(popcount) +#endif + +// Math Built-In Functions BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acos) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acosh) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acospi) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asin) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asinh) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asinpi) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atan) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(atan2) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atanh) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atanpi) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(atan2pi) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cbrt) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(ceil) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(copysign) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cosh) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cospi) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(erfc) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(erf) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp2) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp10) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(expm1) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(fabs) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fdim) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(floor) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmax) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmin) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmod) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(fract) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(frexp) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(hypot) +BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(ilogb) // ilogb returns intN_ +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(ldexp) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(lgamma) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(lgamma_r) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log2) BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log10) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round) -BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(length) - -BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log1p) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(logb) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad) +#ifdef BOOST_COMPUTE_CL_VERSION_1_1 +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(maxmag) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(minmag) +#endif +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(modf) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(nan) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(nextafter) BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pow) BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pown) BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(powr) +BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(remainder) +BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_PTR(remquo) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rint) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rootn) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt) +BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin) |