////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2025-2026. 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) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../bench/bench_utils.hpp" namespace bc = boost::container; ////////////////////////////////////////////////////////////////////////////// // Value types ////////////////////////////////////////////////////////////////////////////// class MyInt { int int_; public: inline explicit MyInt(int i = 0) : int_(i) {} inline MyInt(const MyInt &other) : int_(other.int_) {} inline MyInt & operator=(const MyInt &other) { int_ = other.int_; return *this; } inline ~MyInt() { int_ = 0; } inline int int_value() const { return int_; } friend inline bool operator==(const MyInt& a, const MyInt& b) { return a.int_ == b.int_; } friend inline bool operator!=(const MyInt& a, const MyInt& b) { return a.int_ != b.int_; } friend inline bool operator<(const MyInt& a, const MyInt& b) { return a.int_ < b.int_; } friend inline bool operator>(const MyInt& a, const MyInt& b) { return a.int_ > b.int_; } }; class MyFatInt { int int0_; int int1_; int int2_; int int3_; int int4_; int int5_; int int6_; int int7_; public: inline explicit MyFatInt(int i = 0) : int0_(i++) , int1_(i++) , int2_(i++) , int3_(i++) , int4_(i++) , int5_(i++) , int6_(i++) , int7_(i++) {} inline MyFatInt(const MyFatInt &other) : int0_(other.int0_) , int1_(other.int1_) , int2_(other.int2_) , int3_(other.int3_) , int4_(other.int4_) , int5_(other.int5_) , int6_(other.int6_) , int7_(other.int7_) {} inline MyFatInt & operator=(const MyFatInt &other) { int0_ = other.int0_; int1_ = other.int1_; int2_ = other.int2_; int3_ = other.int3_; int4_ = other.int4_; int5_ = other.int5_; int6_ = other.int6_; int7_ = other.int7_; return *this; } inline ~MyFatInt() { int0_ = 0; int1_ = 0; int2_ = 0; int3_ = 0; int4_ = 0; int5_ = 0; int6_ = 0; int7_ = 0; } inline int int_value() const { return int0_; } friend inline bool operator==(const MyFatInt& a, const MyFatInt& b) { return a.int0_ == b.int0_; } friend inline bool operator!=(const MyFatInt& a, const MyFatInt& b) { return a.int0_ != b.int0_; } friend inline bool operator<(const MyFatInt& a, const MyFatInt& b) { return a.int0_ < b.int0_; } }; inline int int_value(int x) { return x; } inline int int_value(const MyInt& x) { return x.int_value(); } inline int int_value(const MyFatInt& x) { return x.int_value(); } ////////////////////////////////////////////////////////////////////////////// // Functors ////////////////////////////////////////////////////////////////////////////// template struct add_one { T operator()(const T& x) const { return T(int_value(x) + 1); } }; template struct is_odd { bool operator()(const T& x) const { return (int_value(x) & 1) != 0; } }; template struct summer { int sum; summer() : sum(0) {} void operator()(const T& x) { sum = static_cast((static_cast(sum) + static_cast(int_value(x)))); } }; template struct is_negative { bool operator()(const T& x) const { return int_value(x) < 0; } }; template struct is_zero_or_positive { bool operator()(const T& x) const { return int_value(x) >= 0; } }; template struct counter { int n; counter() : n(0) {} T operator()() { return T(n++); } }; template class equal_to_ref { typedef T value_type; const value_type &t_; public: BOOST_CONTAINER_FORCEINLINE explicit equal_to_ref(const value_type &t) : t_(t) {} template BOOST_CONTAINER_FORCEINLINE bool operator()(const U &t)const { return t_ == t; } }; template class less_than_ref { typedef T value_type; const value_type& t_; public: BOOST_CONTAINER_FORCEINLINE explicit less_than_ref(const value_type& t) : t_(t) { } template BOOST_CONTAINER_FORCEINLINE bool operator()(const U& t)const { return t < t_; } }; template class less_and_greater_ref { typedef T value_type; const value_type& l_; const value_type& g_; public: BOOST_CONTAINER_FORCEINLINE explicit less_and_greater_ref(const value_type& l, const value_type& g) : l_(l), g_(g) { } template BOOST_CONTAINER_FORCEINLINE bool operator()(const U& t)const { return t < l_ || t > g_ ; } }; template class unequal_to_ref { typedef T value_type; const value_type &t_; public: BOOST_CONTAINER_FORCEINLINE explicit unequal_to_ref(const value_type &t) : t_(t) {} template BOOST_CONTAINER_FORCEINLINE bool operator()(const U &t)const { return t_ != t; } }; ////////////////////////////////////////////////////////////////////////////// // C++03 fallbacks for C++11-only functions ////////////////////////////////////////////////////////////////////////////// namespace bench_detail { #if BOOST_CXX_VERSION < 201103L template bool all_of(InIt first, InIt last, Pred pred) { for (; first != last; ++first) if (!pred(*first)) return false; return true; } template bool any_of(InIt first, InIt last, Pred pred) { for (; first != last; ++first) if (pred(*first)) return true; return false; } template bool none_of(InIt first, InIt last, Pred pred) { for (; first != last; ++first) if (pred(*first)) return false; return true; } template inline InpIter find_if_not(InpIter first, Sent last, Pred pred) { return std::find_if(first, last, boost::container::not_pred(pred)); } template OutIt copy_if(InIt first, InIt last, OutIt d_first, Pred pred) { for (; first != last; ++first) if (pred(*first)) *d_first++ = *first; return d_first; } template OutIt copy_n(InIt first, Size count, OutIt result) { for (Size i = 0; i < count; ++i, ++first, ++result) *result = *first; return result; } template bool is_sorted(FwdIt first, FwdIt last) { if (first == last) return true; FwdIt next = first; for (++next; next != last; first = next, ++next) if (*next < *first) return false; return true; } template FwdIt is_sorted_until(FwdIt first, FwdIt last) { if (first == last) return last; FwdIt next = first; for (++next; next != last; first = next, ++next) if (*next < *first) return next; return last; } template bool is_partitioned(InIt first, InIt last, Pred pred) { for (; first != last; ++first) if (!pred(*first)) break; for (; first != last; ++first) if (pred(*first)) return false; return true; } template std::pair partition_copy(InIt first, InIt last, OutIt1 out_true, OutIt2 out_false, Pred pred) { for (; first != last; ++first) { if (pred(*first)) *out_true++ = *first; else *out_false++ = *first; } return std::pair(out_true, out_false); } template FwdIt partition_point(FwdIt first, FwdIt last, Pred pred) { for (; first != last; ++first) if (!pred(*first)) return first; return last; } #else using std::all_of; using std::any_of; using std::none_of; using std::find_if_not; using std::copy_if; using std::copy_n; using std::is_sorted; using std::is_sorted_until; using std::is_partitioned; using std::partition_copy; using std::partition_point; #endif template BidirIt find_last_dispatch(BidirIt first, BidirIt last, const T& val, std::bidirectional_iterator_tag) { BidirIt it = last; while (it != first) { --it; if (*it == val) return it; } return last; } template FwdIt find_last_dispatch(FwdIt first, FwdIt last, const T& val, std::forward_iterator_tag) { FwdIt result = last; for (; first != last; ++first) if (*first == val) result = first; return result; } template BOOST_CONTAINER_FORCEINLINE It find_last(It first, It last, const T& val) { typedef typename std::iterator_traits::iterator_category cat; return find_last_dispatch(first, last, val, cat()); } template BidirIt find_last_if_dispatch(BidirIt first, BidirIt last, Pred pred, std::bidirectional_iterator_tag) { BidirIt it = last; while (it != first) { --it; if (pred(*it)) return it; } return last; } template FwdIt find_last_if_dispatch(FwdIt first, FwdIt last, Pred pred, std::forward_iterator_tag) { FwdIt result = last; for (; first != last; ++first) if (pred(*first)) result = first; return result; } template BOOST_CONTAINER_FORCEINLINE It find_last_if(It first, It last, Pred pred) { typedef typename std::iterator_traits::iterator_category cat; return find_last_if_dispatch(first, last, pred, cat()); } template BidirIt find_last_if_not_dispatch(BidirIt first, BidirIt last, Pred pred, std::bidirectional_iterator_tag) { BidirIt it = last; while (it != first) { --it; if (!pred(*it)) return it; } return last; } template FwdIt find_last_if_not_dispatch(FwdIt first, FwdIt last, Pred pred, std::forward_iterator_tag) { FwdIt result = last; for (; first != last; ++first) if (!pred(*first)) result = first; return result; } template BOOST_CONTAINER_FORCEINLINE It find_last_if_not(It first, It last, Pred pred) { typedef typename std::iterator_traits::iterator_category cat; return find_last_if_not_dispatch(first, last, pred, cat()); } //Not benchmarked: //inplace_merge //not implemented (c++03) //find_end //find_first_of //adjacent_find //copy_backward //move //move_backward //transform //replace_copy //replace_copy_if //unique //unique_copy //rotate //rotate_copy //max_element //min_element //minmax_element //nth_element //includes //set_union //lexicographical_compare // -- sorting -- //sort (random-access non-implementable?) //stable_sort (random-access non-implementable?) //partial_sort (random-access non-implementable?) //partial_sort_copy(random-access non-implementable?) // -- binary search -- //lower_bound (binary/random-access non-implementable?) //upper_bound (binary/random-access non-implementable?) //equal_range (binary/random-access non-implementable?) //binary_search (binary/random-access non-implementable?) // -- heap -- //push_heap (binary/random-access non-implementable?) //pop_heap (binary/random-access non-implementable?) //make_heap (binary/random-access non-implementable?) //sort_heap (binary/random-access non-implementable?) // -- permutation -- //next_permutation //prev_permutation //is_permutation // -- numeric -- //iota //accumulate //inner_product //adjacent_difference //partial_sum //not implemented (c++11): //move //move_backward //shuffle (random-access non-implementable?) //is_heap (random-access non-implementable?) //is_heap_until (random-access non-implementable?) //not implemented (c++14) //mismatch with two full ranges //equal with two full ranges //not implemented (c++17) //for_each_n //random_shuffle (random-access non-implementable?) //sample (random-access non-implementable?) //reduce //exclusive_scan //inclusive_scan //transform_reduce //transform_exclusive_scan //transform_inclusive_scan //not implemented (c++20) //shift_left //shift_right //lexicographical_compare_three_way //range-based? //contains //contains_subrange //starts_with //ends_with //fold_left //fold_left_first //fold_right //fold_right_last //fold_left_with_iter //fold_left_first_with_iter //generate_random } // namespace bench_detail ////////////////////////////////////////////////////////////////////////////// // Fill helpers ////////////////////////////////////////////////////////////////////////////// template void fill_test_data(C& c, std::size_t n) { typedef typename C::value_type VT; for (std::size_t i = 0; i < n; ++i) c.push_back(VT(static_cast(i))); } template void fill_test_data(bc::nest& c, std::size_t n) { for (std::size_t i = 0; i < n; ++i) c.insert(T(static_cast(i))); } ////////////////////////////////////////////////////////////////////////////// // Benchmark helpers ////////////////////////////////////////////////////////////////////////////// inline double calc_ns_per_elem(boost::move_detail::nanosecond_type ns, std::size_t iters, std::size_t elems) { return double(ns) / double(iters * elems); } inline void print_subheader() { std::cout << std::left << std::setw(32) << "< algo >" << std::right << std::setw(20) << "< speedup >" << std::right << std::setw(20) << "< std ns/item >" << std::right << std::setw(20) << "< seg ns/item >" << '\n'; } struct geomean_accumulator { double log_sum; int count; void reset() { log_sum = 0.0; count = 0; } void add(double ratio) { if(ratio > 0.0) { log_sum += std::log(ratio); ++count; } } double result() const { return count > 0 ? std::exp(log_sum / count) : 0.0; } } g_geomean = { 0.0, 0 }; inline void print_ratio(const char* algo, const char*, double std_ns, double seg_ns) { double ratio = (seg_ns > 0.0) ? std_ns / seg_ns : 0.0; g_geomean.add(ratio); std::cout << std::left << std::setw(32) << algo << std::right << std::setw(20) << std::fixed << std::setprecision(2) << ((ratio < 1.0) ? "! " : "") << ratio << 'x' << std::right << std::setw(20) << std::fixed << std::setprecision(3) << std_ns << std::right << std::setw(20) << std::fixed << std::setprecision(3) << seg_ns << '\n'; } ////////////////////////////////////////////////////////////////////////////// // Measurement infrastructure ////////////////////////////////////////////////////////////////////////////// template inline boost::move_detail::nanosecond_type measure_batch(std::size_t iters, F f, ResetF reset_f) { cpu_timer t; std::size_t n_ = (iters + 7) / 8; t.resume(); switch (iters % 8) { case 0: do { t.resume(); f(); BOOST_FALLTHROUGH; case 7: f(); BOOST_FALLTHROUGH; case 6: f(); BOOST_FALLTHROUGH; case 5: f(); BOOST_FALLTHROUGH; case 4: f(); BOOST_FALLTHROUGH; case 3: f(); BOOST_FALLTHROUGH; case 2: f(); BOOST_FALLTHROUGH; case 1: f(); t.stop(); if (BOOST_UNLIKELY(--n_ == 0)) break; reset_f(); } while (true); } return t.elapsed(); } struct noop_reset { BOOST_CONTAINER_FORCEINLINE void operator()() {} }; template inline void compare_batch(std::size_t iters, std::size_t nelems, F1 std_op, R1 std_reset, F2 seg_op, R2 seg_reset, const char* label, const char* cname) { typedef boost::move_detail::nanosecond_type ns_type; ns_type t1 = measure_batch(iters, std_op, std_reset); ns_type t2 = measure_batch(iters, seg_op, seg_reset); print_ratio(label, cname, calc_ns_per_elem(t1, iters, nelems), calc_ns_per_elem(t2, iters, nelems)); } template inline void compare_batch(std::size_t iters, std::size_t nelems, F1 std_op, F2 seg_op, const char* label, const char* cname) { compare_batch(iters, nelems, std_op, noop_reset(), seg_op, noop_reset(), label, cname); } ////////////////////////////////////////////////////////////////////////////// // Benchmark operation functors ////////////////////////////////////////////////////////////////////////////// namespace bench_ops { template struct batch_state { C c1, c2, c3, c4, c5, c6, c7, c8; C* cs[8]; int idx; const C &orig; batch_state(const C &c_) : c1(c_), c2(c_), c3(c_), c4(c_), c5(c_), c6(c_), c7(c_), c8(c_), idx(0), orig(c_) { cs[0]=&c1; cs[1]=&c2; cs[2]=&c3; cs[3]=&c4; cs[4]=&c5; cs[5]=&c6; cs[6]=&c7; cs[7]=&c8; } }; template struct batch_reset { batch_state &bs; batch_reset(batch_state &b) : bs(b) {} BOOST_CONTAINER_FORCEINLINE void operator()() { bs.idx = 0; bs.c1 = bs.c2 = bs.c3 = bs.c4 = bs.c5 = bs.c6 = bs.c7 = bs.c8 = bs.orig; } }; // --- all_of --- template struct std_all_of { const C &c; Pred pred; int &result; std_all_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bench_detail::all_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; template struct seg_all_of { const C &c; Pred pred; int &result; seg_all_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_all_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; // --- any_of --- template struct std_any_of { const C &c; Pred pred; int &result; std_any_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bench_detail::any_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; template struct seg_any_of { const C &c; Pred pred; int &result; seg_any_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_any_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; // --- none_of --- template struct std_none_of { const C &c; Pred pred; int &result; std_none_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bench_detail::none_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; template struct seg_none_of { const C &c; Pred pred; int &result; seg_none_of(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_none_of(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; // --- for_each --- template struct std_for_each { typedef typename C::value_type VT; const C &c; int &result; std_for_each(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { summer s; clobber(); s = std::for_each(c.begin(), c.end(), s); result = s.sum; escape(&result); } }; template struct seg_for_each { typedef typename C::value_type VT; const C &c; int &result; seg_for_each(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { summer s; clobber(); s = bc::segmented_for_each(c.begin(), c.end(), s); result = s.sum; escape(&result); } }; // --- copy --- template struct std_copy { const C &c; OutT &out; std_copy(const C &c_, OutT &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::copy(c.begin(), c.end(), out.begin()); escape(&out[0]); } }; template struct seg_copy { const C &c; OutT &out; seg_copy(const C &c_, OutT &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_copy(c.begin(), c.end(), out.begin()); escape(&out[0]); } }; // --- copy_if --- template struct std_copy_if { const C &c; OutT &out; Pred pred; std_copy_if(const C &c_, OutT &o_, Pred p_) : c(c_), out(o_), pred(p_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bench_detail::copy_if(c.begin(), c.end(), out.begin(), pred); escape(&out[0]); } }; template struct seg_copy_if { const C &c; OutT &out; Pred pred; seg_copy_if(const C &c_, OutT &o_, Pred p_) : c(c_), out(o_), pred(p_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_copy_if(c.begin(), c.end(), out.begin(), pred); escape(&out[0]); } }; // --- fill --- template struct std_fill { C &c2; const typename C::value_type &val; std_fill(C &c_, const typename C::value_type &v_) : c2(c_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::fill(c2.begin(), c2.end(), val); escape(&c2); } }; template struct seg_fill { C &c2; const typename C::value_type &val; seg_fill(C &c_, const typename C::value_type &v_) : c2(c_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_fill(c2.begin(), c2.end(), val); escape(&c2); } }; // --- count --- template struct std_count { const C &c; const typename C::value_type &val; int &result; std_count(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = static_cast(std::count(c.begin(), c.end(), val)); escape(&result); } }; template struct seg_count { const C &c; const typename C::value_type &val; int &result; seg_count(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = static_cast(bc::segmented_count(c.begin(), c.end(), val)); escape(&result); } }; // --- count_if --- template struct std_count_if { const C &c; Pred pred; int &result; std_count_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = static_cast(std::count_if(c.begin(), c.end(), pred)); escape(&result); } }; template struct seg_count_if { const C &c; Pred pred; int &result; seg_count_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = static_cast(bc::segmented_count_if(c.begin(), c.end(), pred)); escape(&result); } }; // --- find --- template struct std_find { typedef typename C::const_iterator cit_t; const C &c; const typename C::value_type &val; int &result; std_find(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = std::find(c.begin(), c.end(), val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; template struct seg_find { typedef typename C::const_iterator cit_t; const C &c; const typename C::value_type &val; int &result; seg_find(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find(c.begin(), c.end(), val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; // --- find_if --- template struct std_find_if { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; std_find_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = std::find_if(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; template struct seg_find_if { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; seg_find_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find_if(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; // --- find_if_not --- template struct std_find_if_not { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; std_find_if_not(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::find_if_not(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; template struct seg_find_if_not { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; seg_find_if_not(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find_if_not(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; // --- find_last --- template struct std_find_last { typedef typename C::const_iterator cit_t; const C &c; const typename C::value_type &val; int &result; std_find_last(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::find_last(c.begin(), c.end(), val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; template struct seg_find_last { typedef typename C::const_iterator cit_t; const C &c; const typename C::value_type &val; int &result; seg_find_last(const C &c_, const typename C::value_type &v_, int &r_) : c(c_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find_last(c.begin(), c.end(), val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; // --- find_last_if --- template struct std_find_last_if { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; std_find_last_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::find_last_if(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; template struct seg_find_last_if { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; seg_find_last_if(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find_last_if(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; // --- find_last_if_not --- template struct std_find_last_if_not { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; std_find_last_if_not(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::find_last_if_not(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; template struct seg_find_last_if_not { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; seg_find_last_if_not(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_find_last_if_not(c.begin(), c.end(), pred); result = (it != c.end()) ? int_value(*it) : -1; escape(&result); } }; // --- equal --- template struct std_equal { const C &c; R2 &range2; int &result; std_equal(const C &c_, R2 &r2_, int &r_) : c(c_), range2(r2_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = std::equal(c.begin(), c.end(), range2.begin()) ? 1 : 0; escape(&result); } }; template struct seg_equal { const C &c; R2 &range2; int &result; seg_equal(const C &c_, R2 &r2_, int &r_) : c(c_), range2(r2_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_equal(c.begin(), c.end(), range2.begin()) ? 1 : 0; escape(&result); } }; // --- replace --- template struct std_replace_op { typedef const typename C::value_type* cptr; C &c2; cptr &pold_val; cptr &pnew_val; std_replace_op(C &c_, cptr &po_, cptr &pn_) : c2(c_), pold_val(po_), pnew_val(pn_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::replace(c2.begin(), c2.end(), *pold_val, *pnew_val); escape(&c2); cptr pt(pold_val); pold_val = pnew_val; pnew_val = pt; } }; template struct seg_replace_op { typedef const typename C::value_type* cptr; C &c2; cptr &pold_val; cptr &pnew_val; seg_replace_op(C &c_, cptr &po_, cptr &pn_) : c2(c_), pold_val(po_), pnew_val(pn_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_replace(c2.begin(), c2.end(), *pold_val, *pnew_val); escape(&c2); cptr pt(pold_val); pold_val = pnew_val; pnew_val = pt; } }; // --- transform --- template struct std_transform { typedef typename C::value_type VT; const C &c; boost::container::vector &out; std_transform(const C &c_, boost::container::vector &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::transform(c.begin(), c.end(), out.begin(), add_one()); escape(&out[0]); } }; template struct seg_transform { typedef typename C::value_type VT; const C &c; boost::container::vector &out; seg_transform(const C &c_, boost::container::vector &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_transform(c.begin(), c.end(), out.begin(), add_one()); escape(&out[0]); } }; // --- fill_n --- template struct std_fill_n { C &c2; typename C::difference_type n; const typename C::value_type &val; std_fill_n(C &c_, typename C::difference_type n_, const typename C::value_type &v_) : c2(c_), n(n_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::fill_n(c2.begin(), n, val); escape(&c2); } }; template struct seg_fill_n { C &c2; typename C::difference_type n; const typename C::value_type &val; seg_fill_n(C &c_, typename C::difference_type n_, const typename C::value_type &v_) : c2(c_), n(n_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_fill_n(c2.begin(), n, val); escape(&c2); } }; // --- copy_n --- template struct std_copy_n { const C &c; typename C::difference_type n; OutT &out; std_copy_n(const C &c_, typename C::difference_type n_, OutT &o_) : c(c_), n(n_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bench_detail::copy_n(c.begin(), n, out.begin()); escape(&out[0]); } }; template struct seg_copy_n { const C &c; typename C::difference_type n; OutT &out; seg_copy_n(const C &c_, typename C::difference_type n_, OutT &o_) : c(c_), n(n_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_copy_n(c.begin(), n, out.begin()); escape(&out[0]); } }; // --- generate --- template struct std_generate { typedef typename C::value_type VT; C &c2; int &result; std_generate(C &c_, int &r_) : c2(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::generate(c2.begin(), c2.end(), counter()); result = int_value(*c2.begin()); escape(&result); } }; template struct seg_generate { typedef typename C::value_type VT; C &c2; int &result; seg_generate(C &c_, int &r_) : c2(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_generate(c2.begin(), c2.end(), counter()); result = int_value(*c2.begin()); escape(&result); } }; // --- generate_n --- template struct std_generate_n { typedef typename C::value_type VT; C &c2; typename C::difference_type n; int &result; std_generate_n(C &c_, typename C::difference_type n_, int &r_) : c2(c_), n(n_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::generate_n(c2.begin(), n, counter()); result = int_value(*c2.begin()); escape(&result); } }; template struct seg_generate_n { typedef typename C::value_type VT; C &c2; typename C::difference_type n; int &result; seg_generate_n(C &c_, typename C::difference_type n_, int &r_) : c2(c_), n(n_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_generate_n(c2.begin(), n, counter()); result = int_value(*c2.begin()); escape(&result); } }; // --- remove_copy --- template struct std_remove_copy { const C &c; OutT &out; const typename C::value_type &val; std_remove_copy(const C &c_, OutT &o_, const typename C::value_type &v_) : c(c_), out(o_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::remove_copy(c.begin(), c.end(), out.begin(), val); escape(&out[0]); } }; template struct seg_remove_copy { const C &c; OutT &out; const typename C::value_type &val; seg_remove_copy(const C &c_, OutT &o_, const typename C::value_type &v_) : c(c_), out(o_), val(v_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_remove_copy(c.begin(), c.end(), out.begin(), val); escape(&out[0]); } }; // --- remove_copy_if --- template struct std_remove_copy_if { const C &c; OutT &out; Pred pred; std_remove_copy_if(const C &c_, OutT &o_, Pred p_) : c(c_), out(o_), pred(p_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::remove_copy_if(c.begin(), c.end(), out.begin(), pred); escape(&out[0]); } }; template struct seg_remove_copy_if { const C &c; OutT &out; Pred pred; seg_remove_copy_if(const C &c_, OutT &o_, Pred p_) : c(c_), out(o_), pred(p_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_remove_copy_if(c.begin(), c.end(), out.begin(), pred); escape(&out[0]); } }; // --- reverse --- template struct std_reverse { C &c2; int &result; std_reverse(C &c_, int &r_) : c2(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::reverse(c2.begin(), c2.end()); result = int_value(*c2.begin()); escape(&result); } }; template struct seg_reverse { C &c2; int &result; seg_reverse(C &c_, int &r_) : c2(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_reverse(c2.begin(), c2.end()); result = int_value(*c2.begin()); escape(&result); } }; // --- reverse_copy --- template struct std_reverse_copy { typedef typename C::value_type VT; const C &c; boost::container::vector &out; std_reverse_copy(const C &c_, boost::container::vector &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::reverse_copy(c.begin(), c.end(), out.begin()); escape(&out[0]); } }; template struct seg_reverse_copy { typedef typename C::value_type VT; const C &c; boost::container::vector &out; seg_reverse_copy(const C &c_, boost::container::vector &o_) : c(c_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_reverse_copy(c.begin(), c.end(), out.begin()); escape(&out[0]); } }; // --- is_sorted --- template struct std_is_sorted { const C &c; int &result; std_is_sorted(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bench_detail::is_sorted(c.begin(), c.end()) ? 1 : 0; escape(&result); } }; template struct seg_is_sorted { const C &c; int &result; seg_is_sorted(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_is_sorted(c.begin(), c.end()) ? 1 : 0; escape(&result); } }; // --- is_sorted_until --- template struct std_is_sorted_until { typedef typename C::const_iterator cit_t; const C &c; int &result; std_is_sorted_until(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::is_sorted_until(c.begin(), c.end()); result = (it == c.end()) ? 1 : 0; escape(&result); } }; template struct seg_is_sorted_until { typedef typename C::const_iterator cit_t; const C &c; int &result; seg_is_sorted_until(const C &c_, int &r_) : c(c_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_is_sorted_until(c.begin(), c.end()); result = (it == c.end()) ? 1 : 0; escape(&result); } }; // --- is_partitioned --- template struct std_is_partitioned { const C &c; Pred pred; int &result; std_is_partitioned(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bench_detail::is_partitioned(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; template struct seg_is_partitioned { const C &c; Pred pred; int &result; seg_is_partitioned(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = bc::segmented_is_partitioned(c.begin(), c.end(), pred) ? 1 : 0; escape(&result); } }; // --- merge --- template struct std_merge { const C &c; const C &c2; OutVec &out; std_merge(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::merge(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; template struct seg_merge { const C &c; const C &c2; OutVec &out; seg_merge(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_merge(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; // --- mismatch --- template struct std_mismatch { const C &c; R2 &range2; int &result; std_mismatch(const C &c_, R2 &r2_, int &r_) : c(c_), range2(r2_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = (std::mismatch(c.begin(), c.end(), range2.begin()).first == c.end()) ? 1 : 0; escape(&result); } }; template struct seg_mismatch { const C &c; R2 &range2; int &result; seg_mismatch(const C &c_, R2 &r2_, int &r_) : c(c_), range2(r2_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); result = (bc::segmented_mismatch(c.begin(), c.end(), range2.begin()).first == c.end()) ? 1 : 0; escape(&result); } }; // --- swap_ranges --- template struct std_swap_ranges { C &c2; C &c3; int &result; std_swap_ranges(C &c2_, C &c3_, int &r_) : c2(c2_), c3(c3_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::swap_ranges(c2.begin(), c2.end(), c3.begin()); result = int_value(*c2.begin()); escape(&result); } }; template struct seg_swap_ranges { C &c2; C &c3; int &result; seg_swap_ranges(C &c2_, C &c3_, int &r_) : c2(c2_), c3(c3_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_swap_ranges(c2.begin(), c2.end(), c3.begin()); result = int_value(*c2.begin()); escape(&result); } }; // --- search --- template struct std_search { typedef typename C::const_iterator cit_t; typedef typename C::value_type VT; const C &c; const VT *pattern; std::size_t pat_size; int &result; std_search(const C &c_, const VT *p_, std::size_t ps_, int &r_) : c(c_), pattern(p_), pat_size(ps_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = std::search(c.begin(), c.end(), pattern, pattern + pat_size); result = (it == c.end()) ? 0 : 1; escape(&result); } }; template struct seg_search { typedef typename C::const_iterator cit_t; typedef typename C::value_type VT; const C &c; const VT *pattern; std::size_t pat_size; int &result; seg_search(const C &c_, const VT *p_, std::size_t ps_, int &r_) : c(c_), pattern(p_), pat_size(ps_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_search(c.begin(), c.end(), pattern, pattern + pat_size); result = (it == c.end()) ? 0 : 1; escape(&result); } }; // --- search_n --- template struct std_search_n { typedef typename C::const_iterator cit_t; const C &c; typename C::difference_type cnt; const typename C::value_type &val; int &result; std_search_n(const C &c_, typename C::difference_type n_, const typename C::value_type &v_, int &r_) : c(c_), cnt(n_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = std::search_n(c.begin(), c.end(), cnt, val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; template struct seg_search_n { typedef typename C::const_iterator cit_t; const C &c; typename C::difference_type cnt; const typename C::value_type &val; int &result; seg_search_n(const C &c_, typename C::difference_type n_, const typename C::value_type &v_, int &r_) : c(c_), cnt(n_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_search_n(c.begin(), c.end(), cnt, val); result = (it == c.end()) ? 0 : 1; escape(&result); } }; // --- set_union --- template struct std_set_union { const C &c; const C &c2; OutVec &out; std_set_union(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::set_union(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; template struct seg_set_union { const C &c; const C &c2; OutVec &out; seg_set_union(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_set_union(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; // --- set_difference --- template struct std_set_difference { const C &c; const C &c2; OutVec &out; std_set_difference(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::set_difference(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; template struct seg_set_difference { const C &c; const C &c2; OutVec &out; seg_set_difference(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_set_difference(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; // --- set_intersection --- template struct std_set_intersection { const C &c; const C &c2; OutVec &out; std_set_intersection(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::set_intersection(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; template struct seg_set_intersection { const C &c; const C &c2; OutVec &out; seg_set_intersection(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_set_intersection(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; // --- set_symmetric_difference --- template struct std_set_symmetric_difference { const C &c; const C &c2; OutVec &out; std_set_symmetric_difference(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::set_symmetric_difference(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; template struct seg_set_symmetric_difference { const C &c; const C &c2; OutVec &out; seg_set_symmetric_difference(const C &c_, const C &c2_, OutVec &o_) : c(c_), c2(c2_), out(o_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_set_symmetric_difference(c.begin(), c.end(), c2.begin(), c2.end(), out.begin()); escape(&out[0]); } }; // --- partition_copy --- template struct std_partition_copy { typedef typename C::value_type VT; const C &c; boost::container::vector &t_out; boost::container::vector &f_out; std_partition_copy(const C &c_, boost::container::vector &t_, boost::container::vector &f_) : c(c_), t_out(t_), f_out(f_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bench_detail::partition_copy(c.begin(), c.end(), t_out.begin(), f_out.begin(), is_odd()); escape(&t_out[0]); } }; template struct seg_partition_copy { typedef typename C::value_type VT; const C &c; boost::container::vector &t_out; boost::container::vector &f_out; seg_partition_copy(const C &c_, boost::container::vector &t_, boost::container::vector &f_) : c(c_), t_out(t_), f_out(f_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_partition_copy(c.begin(), c.end(), t_out.begin(), f_out.begin(), is_odd()); escape(&t_out[0]); } }; // --- partition_point --- template struct std_partition_point { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; std_partition_point(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bench_detail::partition_point(c.begin(), c.end(), pred); result = (it == c.end()) ? 1 : 0; escape(&result); } }; template struct seg_partition_point { typedef typename C::const_iterator cit_t; const C &c; Pred pred; int &result; seg_partition_point(const C &c_, Pred p_, int &r_) : c(c_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); cit_t it = bc::segmented_partition_point(c.begin(), c.end(), pred); result = (it == c.end()) ? 1 : 0; escape(&result); } }; // --- Batch: replace_if --- template struct std_replace_if_batch { batch_state &bs; Pred pred; const typename C::value_type &new_val; std_replace_if_batch(batch_state &b_, Pred p_, const typename C::value_type &nv_) : bs(b_), pred(p_), new_val(nv_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); std::replace_if(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred, new_val); escape(bs.cs[bs.idx]); ++bs.idx; } }; template struct seg_replace_if_batch { batch_state &bs; Pred pred; const typename C::value_type &new_val; seg_replace_if_batch(batch_state &b_, Pred p_, const typename C::value_type &nv_) : bs(b_), pred(p_), new_val(nv_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); bc::segmented_replace_if(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred, new_val); escape(bs.cs[bs.idx]); ++bs.idx; } }; // --- Batch: remove --- template struct std_remove_batch { typedef typename C::iterator it_t; batch_state &bs; const typename C::value_type &val; int &result; std_remove_batch(batch_state &b_, const typename C::value_type &v_, int &r_) : bs(b_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = std::remove(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), val); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; template struct seg_remove_batch { typedef typename C::iterator it_t; batch_state &bs; const typename C::value_type &val; int &result; seg_remove_batch(batch_state &b_, const typename C::value_type &v_, int &r_) : bs(b_), val(v_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = bc::segmented_remove(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), val); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; // --- Batch: remove_if --- template struct std_remove_if_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; std_remove_if_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = std::remove_if(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; template struct seg_remove_if_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; seg_remove_if_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = bc::segmented_remove_if(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; // --- Batch: partition --- template struct std_partition_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; std_partition_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = std::partition(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; template struct seg_partition_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; seg_partition_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = bc::segmented_partition(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; // --- Batch: stable_partition --- template struct std_stable_partition_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; std_stable_partition_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = std::stable_partition(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; template struct seg_stable_partition_batch { typedef typename C::iterator it_t; batch_state &bs; Pred pred; int &result; seg_stable_partition_batch(batch_state &b_, Pred p_, int &r_) : bs(b_), pred(p_), result(r_) {} BOOST_CONTAINER_FORCEINLINE void operator()() { clobber(); it_t it = bc::segmented_stable_partition(bs.cs[bs.idx]->begin(), bs.cs[bs.idx]->end(), pred); result = (it == bs.cs[bs.idx]->end()) ? 1 : 0; escape(&result); ++bs.idx; } }; } // namespace bench_ops ////////////////////////////////////////////////////////////////////////////// // Individual benchmarks ////////////////////////////////////////////////////////////////////////////// template void bench_all_of(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_all_of(c, pred, result), bench_ops::seg_all_of(c, pred, result), label, cname); } template void bench_any_of(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_any_of(c, pred, result), bench_ops::seg_any_of(c, pred, result), label, cname); } template void bench_none_of(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_none_of(c, pred, result), bench_ops::seg_none_of(c, pred, result), label, cname); } template void bench_for_each(const C &c, std::size_t iters, const char* cname) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_for_each(c, result), bench_ops::seg_for_each(c, result), "for_each", cname); } template void bench_copy(const C &c, std::size_t iters, const char* cname, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type out_t; out_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_copy(c, out), bench_ops::seg_copy(c, out), label, cname); } template void bench_copy_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type out_t; out_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_copy_if(c, out, pred), bench_ops::seg_copy_if(c, out, pred), label, cname); } template void bench_fill(const C &c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; VT val(42); C c2(c); compare_batch(iters, c.size(), bench_ops::std_fill(c2, val), bench_ops::seg_fill(c2, val), "fill", cname); } template void bench_count(const C &c, std::size_t iters, const char* cname, const typename C::value_type& val, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_count(c, val, result), bench_ops::seg_count(c, val, result), label, cname); } template void bench_count_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_count_if(c, pred, result), bench_ops::seg_count_if(c, pred, result), label, cname); } template void bench_find(const C &c, std::size_t iters, const char* cname, const typename C::value_type& val, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find(c, val, result), bench_ops::seg_find(c, val, result), label, cname); } template void bench_find_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find_if(c, pred, result), bench_ops::seg_find_if(c, pred, result), label, cname); } template void bench_find_if_not(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find_if_not(c, pred, result), bench_ops::seg_find_if_not(c, pred, result), label, cname); } template void bench_find_last(const C &c, std::size_t iters, const char* cname, const typename C::value_type& val, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find_last(c, val, result), bench_ops::seg_find_last(c, val, result), label, cname); } template void bench_find_last_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find_last_if(c, pred, result), bench_ops::seg_find_last_if(c, pred, result), label, cname); } template void bench_find_last_if_not(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_find_last_if_not(c, pred, result), bench_ops::seg_find_last_if_not(c, pred, result), label, cname); } template void bench_equal(const C &c, const C &c2, std::size_t iters, const char* cname, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type range2_t; range2_t range2(c2.begin(), c2.end()); int result = 0; compare_batch(iters, c.size(), bench_ops::std_equal(c, range2, result), bench_ops::seg_equal(c, range2, result), label, cname); } template void bench_replace(const C &c, std::size_t iters, const char* cname, const typename C::value_type& old_val, const typename C::value_type& new_val, const char* label) { typedef const typename C::value_type* cptr; cptr p1o = &old_val, p1n = &new_val; cptr p2o = &old_val, p2n = &new_val; C c2a(c), c2b(c); compare_batch(iters, c.size(), bench_ops::std_replace_op(c2a, p1o, p1n), bench_ops::seg_replace_op(c2b, p2o, p2n), label, cname); } template void bench_replace_if(const C &c, std::size_t iters, const char* cname, Pred pred, const typename C::value_type& new_val, const char* label) { bench_ops::batch_state bs1(c), bs2(c); compare_batch(iters, c.size(), bench_ops::std_replace_if_batch(bs1, pred, new_val), bench_ops::batch_reset(bs1), bench_ops::seg_replace_if_batch(bs2, pred, new_val), bench_ops::batch_reset(bs2), label, cname); } template void bench_transform(const C &c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; boost::container::vector out(c.size()); compare_batch(iters, c.size(), bench_ops::std_transform(c, out), bench_ops::seg_transform(c, out), "transform", cname); } template void bench_fill_n(const C &c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; VT val(42); typename C::difference_type n = static_cast(c.size()); C c2(c); compare_batch(iters, c.size(), bench_ops::std_fill_n(c2, n, val), bench_ops::seg_fill_n(c2, n, val), "fill_n", cname); } template void bench_copy_n(const C &c, std::size_t iters, const char* cname, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type out_t; out_t out(c.size()); typename C::difference_type n = static_cast(c.size()); compare_batch(iters, c.size(), bench_ops::std_copy_n(c, n, out), bench_ops::seg_copy_n(c, n, out), label, cname); } template void bench_generate(const C &c, std::size_t iters, const char* cname) { C c2(c); int result = 0; compare_batch(iters, c.size(), bench_ops::std_generate(c2, result), bench_ops::seg_generate(c2, result), "generate", cname); } template void bench_generate_n(const C &c, std::size_t iters, const char* cname) { typename C::difference_type n = static_cast(c.size()); C c2(c); int result = 0; compare_batch(iters, c.size(), bench_ops::std_generate_n(c2, n, result), bench_ops::seg_generate_n(c2, n, result), "generate_n", cname); } template void bench_remove(const C &c, std::size_t iters, const char* cname, const typename C::value_type& val, const char* label) { int result = 0; bench_ops::batch_state bs1(c), bs2(c); compare_batch(iters, c.size(), bench_ops::std_remove_batch(bs1, val, result), bench_ops::batch_reset(bs1), bench_ops::seg_remove_batch(bs2, val, result), bench_ops::batch_reset(bs2), label, cname); } template void bench_remove_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; bench_ops::batch_state bs1(c), bs2(c); compare_batch(iters, c.size(), bench_ops::std_remove_if_batch(bs1, pred, result), bench_ops::batch_reset(bs1), bench_ops::seg_remove_if_batch(bs2, pred, result), bench_ops::batch_reset(bs2), label, cname); } template void bench_remove_copy(const C &c, std::size_t iters, const char* cname, const typename C::value_type& val, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type out_t; out_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_remove_copy(c, out, val), bench_ops::seg_remove_copy(c, out, val), label, cname); } template void bench_remove_copy_if(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type out_t; out_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_remove_copy_if(c, out, pred), bench_ops::seg_remove_copy_if(c, out, pred), label, cname); } template void bench_reverse(const C &c, std::size_t iters, const char* cname) { C c2(c); int result = 0; compare_batch(iters, c.size(), bench_ops::std_reverse(c2, result), bench_ops::seg_reverse(c2, result), "reverse", cname); } template void bench_reverse_copy(const C &c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; boost::container::vector out(c.size()); compare_batch(iters, c.size(), bench_ops::std_reverse_copy(c, out), bench_ops::seg_reverse_copy(c, out), "reverse_copy", cname); } template void bench_is_sorted(const C &c, std::size_t iters, const char* cname, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_is_sorted(c, result), bench_ops::seg_is_sorted(c, result), label, cname); } template void bench_is_sorted_until(const C &c, std::size_t iters, const char* cname, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_is_sorted_until(c, result), bench_ops::seg_is_sorted_until(c, result), label, cname); } template void bench_is_partitioned(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_is_partitioned(c, pred, result), bench_ops::seg_is_partitioned(c, pred, result), label, cname); } template void bench_merge(const C &c, const C &c2, std::size_t iters, const char* cname) { typedef typename C::value_type VT; typedef boost::container::vector out_vec_t; out_vec_t out(c.size() + c2.size()); compare_batch(iters, c.size(), bench_ops::std_merge(c, c2, out), bench_ops::seg_merge(c, c2, out), "merge", cname); } template void bench_mismatch(const C &c, const C &c2, std::size_t iters, const char* cname, const char* label) { typedef typename C::value_type VT; typedef typename boost::move_detail::if_c, boost::container::vector >::type range2_t; range2_t range2(c2.begin(), c2.end()); int result = 0; compare_batch(iters, c.size(), bench_ops::std_mismatch(c, range2, result), bench_ops::seg_mismatch(c, range2, result), label, cname); } template void bench_swap_ranges(const C &c, std::size_t iters, const char* cname) { typedef typename C::iterator it_t; typedef typename C::value_type VT; C c2(c); C c3(c2); for (it_t it = c3.begin(), ite = c3.end(); it != ite; ++it) *it = VT(int_value(*it) * 3); int result = 0; compare_batch(iters, c.size(), bench_ops::std_swap_ranges(c2, c3, result), bench_ops::seg_swap_ranges(c2, c3, result), "swap_ranges", cname); } template void bench_search(const C &c, std::size_t iters, const char* cname, const typename C::value_type* pattern, std::size_t pat_size, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_search(c, pattern, pat_size, result), bench_ops::seg_search(c, pattern, pat_size, result), label, cname); } template void bench_search_n(const C &c, std::size_t iters, const char* cname, typename C::difference_type count, const typename C::value_type& val, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_search_n(c, count, val, result), bench_ops::seg_search_n(c, count, val, result), label, cname); } template void bench_set_union(const C &c, const C &c2, std::size_t iters, const char* cname) { typedef typename C::value_type VT; typedef boost::container::vector out_vec_t; out_vec_t out(c.size() + c2.size()); compare_batch(iters, c.size(), bench_ops::std_set_union(c, c2, out), bench_ops::seg_set_union(c, c2, out), "set_union", cname); } template void bench_set_difference(const C &c, const C &c2, std::size_t iters, const char* cname) { typedef typename C::value_type VT; typedef boost::container::vector out_vec_t; out_vec_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_set_difference(c, c2, out), bench_ops::seg_set_difference(c, c2, out), "set_difference", cname); } template void bench_set_intersection(const C &c, const C &c2, std::size_t iters, const char* cname) { typedef typename C::value_type VT; typedef boost::container::vector out_vec_t; out_vec_t out(c.size()); compare_batch(iters, c.size(), bench_ops::std_set_intersection(c, c2, out), bench_ops::seg_set_intersection(c, c2, out), "set_intersection", cname); } template void bench_set_symmetric_difference(const C &c, const C &c2, std::size_t iters, const char* cname) { typedef typename C::value_type VT; typedef boost::container::vector out_vec_t; out_vec_t out(c.size() + c2.size()); compare_batch(iters, c.size(), bench_ops::std_set_symmetric_difference(c, c2, out), bench_ops::seg_set_symmetric_difference(c, c2, out), "set_symmetric_difference", cname); } template void bench_partition(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; bench_ops::batch_state bs1(c), bs2(c); compare_batch(iters, c.size(), bench_ops::std_partition_batch(bs1, pred, result), bench_ops::batch_reset(bs1), bench_ops::seg_partition_batch(bs2, pred, result), bench_ops::batch_reset(bs2), label, cname); } template void bench_stable_partition(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; bench_ops::batch_state bs1(c), bs2(c); compare_batch(iters, c.size(), bench_ops::std_stable_partition_batch(bs1, pred, result), bench_ops::batch_reset(bs1), bench_ops::seg_stable_partition_batch(bs2, pred, result), bench_ops::batch_reset(bs2), label, cname); } template void bench_partition_copy(const C &c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; boost::container::vector t_out(c.size()); boost::container::vector f_out(c.size()); compare_batch(iters, c.size(), bench_ops::std_partition_copy(c, t_out, f_out), bench_ops::seg_partition_copy(c, t_out, f_out), "partition_copy", cname); } template void bench_partition_point(const C &c, std::size_t iters, const char* cname, Pred pred, const char* label) { int result = 0; compare_batch(iters, c.size(), bench_ops::std_partition_point(c, pred, result), bench_ops::seg_partition_point(c, pred, result), label, cname); } ////////////////////////////////////////////////////////////////////////////// // Run all benchmarks for a container type ////////////////////////////////////////////////////////////////////////////// template void run_all(const C& c, std::size_t iters, const char* cname) { typedef typename C::value_type VT; const VT zero(0); const VT min1(-1); const VT quart((int)c.size()/4); const VT half((int)c.size()/2); const VT threequart((int)c.size()*3/4); g_geomean.reset(); print_subheader(); //all_of bench_all_of(c, iters, cname, is_zero_or_positive(), "all_of(hit)"); bench_all_of(c, iters, cname, unequal_to_ref(half), "all_of(miss)"); //any_of bench_any_of(c, iters, cname, equal_to_ref(half), "any_of(hit)"); bench_any_of(c, iters, cname, is_negative(), "any_of(miss)"); //copy bench_copy(c, iters, cname, "copy"); bench_copy(c, iters, cname, "copy(2xS)"); //copy_if bench_copy_if(c, iters, cname, is_odd(), "copy_if(hit)"); bench_copy_if(c, iters, cname, is_odd(), "copy_if(2xS hit)"); bench_copy_if(c, iters, cname, is_negative(), "copy_if(miss)"); bench_copy_if(c, iters, cname, is_negative(), "copy_if(2xS miss)"); //copy_n bench_copy_n(c, iters, cname, "copy_n"); bench_copy_n(c, iters, cname, "copy_n(2xS)"); //count bench_count(c, iters, cname, zero, "count(hit)"); bench_count(c, iters, cname, min1, "count(miss)"); //count_if bench_count_if(c, iters, cname, is_odd(), "count_if(hit)"); bench_count_if(c, iters, cname, is_negative(), "count_if(miss)"); //equal { C c2(c); bench_equal(c, c2, iters, cname, "equal(hit)"); bench_equal(c, c2, iters, cname, "equal(2xS hit)"); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = min1; bench_equal(c, c2, iters, cname, "equal(miss)"); bench_equal(c, c2, iters, cname, "equal(2xS miss)"); } //fill bench_fill(c, iters, cname); //fill_n bench_fill_n(c, iters, cname); //find bench_find(c, iters, cname, half, "find(hit)"); bench_find(c, iters, cname, min1, "find(miss)"); //find_if bench_find_if(c, iters, cname, equal_to_ref(half), "find_if(hit)"); bench_find_if(c, iters, cname, is_negative(), "find_if(miss)"); //find_if_not bench_find_if_not(c, iters, cname, unequal_to_ref(half), "find_if_not(hit)"); bench_find_if_not(c, iters, cname, is_zero_or_positive(), "find_if_not(miss)"); //find_last bench_find_last(c, iters, cname, half, "find_last(hit)"); bench_find_last(c, iters, cname, min1, "find_last(miss)"); //find_last_if bench_find_last_if(c, iters, cname, equal_to_ref(half), "find_last_if(hit)"); bench_find_last_if(c, iters, cname, is_negative(), "find_last_if(miss)"); //find_last_if_not bench_find_last_if_not(c, iters, cname, unequal_to_ref(half), "find_last_if_not(hit)"); bench_find_last_if_not(c, iters, cname, is_zero_or_positive(), "find_last_if_not(miss)"); //for_each bench_for_each(c, iters, cname); //generate bench_generate(c, iters, cname); //generate_n bench_generate_n(c, iters, cname); //is_partitioned { bench_is_partitioned(c, iters, cname, is_negative(), "is_partitioned(hit)"); C c2(c); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = min1; bench_is_partitioned(c2, iters, cname, is_negative(), "is_partitioned(miss)"); } //is_sorted { bench_is_sorted(c, iters, cname, "is_sorted(hit)"); C c2(c); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = min1; bench_is_sorted(c2, iters, cname, "is_sorted(miss)"); } //is_sorted_until { bench_is_sorted_until(c, iters, cname, "is_sorted_until(hit)"); C c2(c); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = min1; bench_is_sorted_until(c2, iters, cname, "is_sorted_until(miss)"); } //merge { C c2(c); for (typename C::iterator it = c2.begin(); it != c2.end(); ++it) *it = VT(int_value(*it) * 2); bench_merge(c, c2, iters, cname); } //mismatch { C c2(c); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = min1; bench_mismatch(c, c2, iters, cname, "mismatch(hit)"); bench_mismatch(c, c2, iters, cname, "mismatch(2xS hit)"); *boost::container::make_iterator_uadvance(c2.begin(), c2.size()/2) = *boost::container::make_iterator_uadvance(c.begin(), c.size()/2); bench_mismatch(c, c2, iters, cname, "mismatch(miss)"); bench_mismatch(c, c2, iters, cname, "mismatch(2xS miss)"); } //none_of bench_none_of(c, iters, cname, is_negative(), "none_of(hit)"); bench_none_of(c, iters, cname, equal_to_ref(VT(static_cast(c.size()/2))), "none_of(miss)"); bench_partition(c, iters, cname, is_odd(), "partition(hit)"); bench_partition(c, iters, cname, is_negative(), "partition(miss)"); //partition_copy bench_partition_copy(c, iters, cname); //partition_point (not tested since it's not optimized for random access iterators) //bench_partition_point(c, iters, cname, less_than_ref(static_cast((int)c.size()/2)), "partition_point(hit)"); //bench_partition_point(c, iters, cname, is_zero_or_positive(), "partition_point(miss)"); //remove bench_remove(c, iters, cname, half, "remove(hit)"); bench_remove(c, iters, cname, min1, "remove(miss)"); //remove_copy bench_remove_copy(c, iters, cname, half, "remove_copy(hit)"); bench_remove_copy(c, iters, cname, half, "remove_copy(2xS hit)"); bench_remove_copy(c, iters, cname, min1, "remove_copy(miss)"); bench_remove_copy(c, iters, cname, min1, "remove_copy(2xS miss)"); //remove_copy_if bench_remove_copy_if(c, iters, cname, less_and_greater_ref(quart, threequart), "remove_copy_if(hit)"); bench_remove_copy_if(c, iters, cname, less_and_greater_ref(quart, threequart), "remove_copy_if(2xS hit)"); bench_remove_copy_if(c, iters, cname, is_negative(), "remove_copy_if(miss)"); bench_remove_copy_if(c, iters, cname, is_negative(), "remove_copy_if(2xS miss)"); //remove_if bench_remove_if(c, iters, cname, less_and_greater_ref(quart, threequart), "remove_if(hit)"); bench_remove_if(c, iters, cname, is_negative(), "remove_if(miss)"); //replace { //Replace half of the elements to ensure that the "hit" case is not too fast C c2(c); is_odd is_odd_pred; for (typename C::iterator it = c2.begin(); it != c2.end(); ++it){ if( is_odd_pred(*it) ) *it = min1; } bench_replace(c2, iters, cname, min1, VT(-2), "replace(hit)"); } bench_replace(c, iters, cname, min1, VT(-2), "replace(miss)"); //replace_if bench_replace_if(c, iters, cname, is_odd(), VT(-2), "replace_if(hit)"); bench_replace_if(c, iters, cname, is_negative(), VT(-2), "replace_if(miss)"); //reverse bench_reverse(c, iters, cname); //reverse_copy bench_reverse_copy(c, iters, cname); //search { int ihalf = static_cast(c.size() / 2); VT hit_pat[] = {half, VT(ihalf + 1), VT(ihalf + 2)}; bench_search(c, iters, cname, hit_pat, 3, "search(hit)"); VT miss_pat[] = {min1, VT(-2), VT(-3)}; bench_search(c, iters, cname, miss_pat, 3, "search(miss)"); } //search_n bench_search_n(c, iters, cname, 1, half, "search_n(hit)"); bench_search_n(c, iters, cname, 3, min1, "search_n(miss)"); //set_difference, set_symmetric_difference, set_union { C c2(c); for (typename C::iterator it = c2.begin(); it != c2.end(); ++it) *it = VT(int_value(*it) * 2); bench_set_difference(c, c2, iters, cname); bench_set_intersection(c, c2, iters, cname); bench_set_symmetric_difference(c, c2, iters, cname); bench_set_union(c, c2, iters, cname); } //stable_partition (not tested since it's not optimized for random access iterators) //bench_stable_partition(c, iters, cname, is_odd(), "stable_partition(hit)"); //bench_stable_partition(c, iters, cname, is_negative(), "stable_partition(miss)"); //swap_ranges bench_swap_ranges(c, iters, cname); //transform bench_transform(c, iters, cname); std::cout << '\n' << std::left << std::setw(32) << "GEOMEAN" << std::right << std::setw(20) << std::fixed << std::setprecision(2) << g_geomean.result() << "x\n"; } ////////////////////////////////////////////////////////////////////////////// // Run all benchmarks for a given value type ////////////////////////////////////////////////////////////////////////////// template void run_benchmarks() { //#define SIMPLE_TEST #if defined(NDEBUG) && !defined(SIMPLE_TEST) const std::size_t N = 100000; const std::size_t iter = 3000; #else const std::size_t N = 10000; const std::size_t iter = 100; #endif std::cout << "\n=== Segmented algorithm benchmark [" << typeid(T).name() << "] ===\n" << "Elements: " << N << " Iterations: " << iter << "\n\n"; { std::cout << "--- bc::deque<" << typeid(T).name() << "> ---\n"; bc::deque dq; fill_test_data(dq, N); run_all(dq, iter, "deque"); std::cout << "\n"; }/* { std::cout << "--- bc::nest<" << typeid(T).name() << "> ---\n"; bc::nest nt; fill_test_data(nt, N); run_all(nt, iter, "nest"); std::cout << "\n"; }*/ } ////////////////////////////////////////////////////////////////////////////// // Main ////////////////////////////////////////////////////////////////////////////// int main() { //run_benchmarks(); run_benchmarks(); //run_benchmarks(); return 0; }