Merge branch 'develop'

This commit is contained in:
Ion Gaztañaga
2016-08-10 10:17:38 +02:00
24 changed files with 2020 additions and 938 deletions

View File

@@ -661,6 +661,32 @@ An alternative is to implement a single `operator =()` for copyable and movable
However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources
(like previously allocated memory) when x is assigned from a lvalue. (like previously allocated memory) when x is assigned from a lvalue.
[endsect]
[section:templated_assignment_operator Templated assignment operator in copyable and movable types]
[import ../example/doc_template_assign.cpp]
Given a movable and copyable class, if a templated assignment operator (*) is added:
[template_assign_example_foo_bar]
C++98 and C++11 compilers will behave different when assigning from a `[const] Foo` lvalue:
[template_assign_example_main]
This different behaviour is a side-effect of the move emulation that can't be easily avoided by
[*Boost.Move]. One workaround is to SFINAE-out the templated assignment operator with `disable_if`:
[c++]
template<class U> // Modified templated assignment
typename boost::disable_if<boost::is_same<U, Foo>, Foo&>::type
operator=(const U& rhs)
{ i = -rhs.i; return *this; } //(2)
[endsect] [endsect]
[endsect] [endsect]
@@ -762,6 +788,14 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
[section:release_notes Release Notes] [section:release_notes Release Notes]
[section:release_notes_boost_1_62 Boost 1.62 Release]
* Documented new limitations reported in Trac tickets
[@https://svn.boost.org/trac/boost/ticket/12194 #12194 ['"Copy assignment on moveable and copyable classes uses wrong type"]] and
[@https://svn.boost.org/trac/boost/ticket/12307 #12307 ['"Copy assignment on moveable and copyable classes uses wrong type"]].
[endsect]
[section:release_notes_boost_1_61 Boost 1.61 Release] [section:release_notes_boost_1_61 Boost 1.61 Release]
* Experimental: asymptotically optimal bufferless merge and sort algorithms: [funcref boost::movelib::adaptive_merge adaptive_merge] * Experimental: asymptotically optimal bufferless merge and sort algorithms: [funcref boost::movelib::adaptive_merge adaptive_merge]

View File

@@ -0,0 +1,98 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014.
// 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/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/detail/meta_utils_core.hpp>
#include <boost/move/move.hpp>
//[template_assign_example_foo_bar
class Foo
{
BOOST_COPYABLE_AND_MOVABLE(Foo)
public:
int i;
explicit Foo(int val) : i(val) {}
Foo(BOOST_RV_REF(Foo) obj) : i(obj.i) {}
Foo& operator=(BOOST_RV_REF(Foo) rhs)
{ i = rhs.i; rhs.i = 0; return *this; }
Foo& operator=(BOOST_COPY_ASSIGN_REF(Foo) rhs)
{ i = rhs.i; return *this; } //(1)
template<class U> //(*) TEMPLATED ASSIGNMENT, potential problem
//<-
#if 1
typename ::boost::move_detail::disable_if_same<U, Foo, Foo&>::type
operator=(const U& rhs)
#else
//->
Foo& operator=(const U& rhs)
//<-
#endif
//->
{ i = -rhs.i; return *this; } //(2)
};
//]
struct Bar
{
int i;
explicit Bar(int val) : i(val) {}
};
//<-
#ifdef NDEBUG
#undef NDEBUG
#endif
//->
#include <cassert>
int main()
{
//[template_assign_example_main
Foo foo1(1);
//<-
assert(foo1.i == 1);
//->
Foo foo2(2);
//<-
assert(foo2.i == 2);
Bar bar(3);
assert(bar.i == 3);
//->
foo2 = foo1; // Calls (1) in C++11 but (2) in C++98
//<-
assert(foo2.i == 1);
assert(foo1.i == 1); //Fails in C++98 unless workaround is applied
foo1 = bar;
assert(foo1.i == -3);
foo2 = boost::move(foo1);
assert(foo1.i == 0);
assert(foo2.i == -3);
//->
const Foo foo5(5);
foo2 = foo5; // Calls (1) in C++11 but (2) in C++98
//<-
assert(foo2.i == 5); //Fails in C++98 unless workaround is applied
assert(foo5.i == 5);
//->
//]
return 0;
}
#include <boost/move/detail/config_end.hpp>

File diff suppressed because it is too large Load Diff

View File

@@ -21,12 +21,14 @@
#include <boost/move/utility_core.hpp> #include <boost/move/utility_core.hpp>
#include <boost/move/adl_move_swap.hpp> #include <boost/move/adl_move_swap.hpp>
#include <boost/move/detail/iterator_traits.hpp>
namespace boost { namespace boost {
namespace movelib { namespace movelib {
struct forward_t{}; struct forward_t{};
struct backward_t{}; struct backward_t{};
struct three_way_t{};
struct move_op struct move_op
{ {
@@ -41,6 +43,13 @@ struct move_op
template <class SourceIt, class DestinationIt> template <class SourceIt, class DestinationIt>
DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last) DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
{ return ::boost::move_backward(first, last, dest_last); } { return ::boost::move_backward(first, last, dest_last); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
*dest2it = boost::move(*dest1it);
*dest1it = boost::move(*srcit);
}
}; };
struct swap_op struct swap_op
@@ -56,6 +65,15 @@ struct swap_op
template <class SourceIt, class DestinationIt> template <class SourceIt, class DestinationIt>
DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin) DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
{ return boost::adl_move_swap_ranges_backward(first, last, dest_begin); } { return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest2it));
*dest2it = boost::move(*dest1it);
*dest1it = boost::move(*srcit);
*srcit = boost::move(tmp);
}
}; };
}} //namespace boost::movelib }} //namespace boost::movelib

View File

@@ -257,9 +257,104 @@ void swap_merge_right
op_merge_right(first1, last1, last2, buf_last, comp, swap_op()); op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
} }
// cost: min(L1,L2)^2+max(L1,L2) template <class BidirIt, class Distance, class Compare>
void merge_bufferless_ONlogN_recursive
(BidirIt first, BidirIt middle, BidirIt last, Distance len1, Distance len2, Compare comp)
{
typedef typename iterator_traits<BidirIt>::size_type size_type;
while(1) {
//#define MERGE_BUFFERLESS_RECURSIVE_OPT
#ifndef MERGE_BUFFERLESS_RECURSIVE_OPT
if (len2 == 0) {
return;
}
if (!len1) {
return;
}
if ((len1 | len2) == 1) {
if (comp(*middle, *first))
adl_move_swap(*first, *middle);
return;
}
#else
if (len2 == 0) {
return;
}
if (!len1) {
return;
}
BidirIt middle_prev = middle; --middle_prev;
if(!comp(*middle, *middle_prev))
return;
while(true) {
if (comp(*middle, *first))
break;
++first;
if(--len1 == 1)
break;
}
if (len1 == 1 && len2 == 1) {
//comp(*middle, *first) == true already tested in the loop
adl_move_swap(*first, *middle);
return;
}
#endif
BidirIt first_cut = first;
BidirIt second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2) {
len11 = len1 / 2;
first_cut += len11;
second_cut = lower_bound(middle, last, *first_cut, comp);
len22 = size_type(second_cut - middle);
}
else {
len22 = len2 / 2;
second_cut += len22;
first_cut = upper_bound(first, middle, *second_cut, comp);
len11 = size_type(first_cut - first);
}
BidirIt new_middle = rotate_gcd(first_cut, middle, second_cut);
//Avoid one recursive call doing a manual tail call elimination on the biggest range
const Distance len_internal = len11+len22;
if( len_internal < (len1 + len2 - len_internal) ) {
merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp);
//merge_bufferless_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
first = new_middle;
middle = second_cut;
len1 -= len11;
len2 -= len22;
}
else {
//merge_bufferless_recursive(first, first_cut, new_middle, len11, len22, comp);
merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
middle = first_cut;
last = new_middle;
len1 = len11;
len2 = len22;
}
}
}
//Complexity: NlogN
template<class BidirIt, class Compare>
void merge_bufferless_ONlogN(BidirIt first, BidirIt middle, BidirIt last, Compare comp)
{
merge_bufferless_ONlogN_recursive
(first, middle, last, middle - first, last - middle, comp);
}
//Complexity: min(len1,len2)^2 + max(len1,len2)
template<class RandIt, class Compare> template<class RandIt, class Compare>
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp) void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
{ {
if((middle - first) < (last - middle)){ if((middle - first) < (last - middle)){
while(first != middle){ while(first != middle){
@@ -290,10 +385,21 @@ void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
} }
} }
template<class RandIt, class Compare>
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
{
//#define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
#ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
merge_bufferless_ONlogN(first, middle, last, comp);
#else
merge_bufferless_ON2(first, middle, last, comp);
#endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
}
template<class Comp> template<class Comp>
struct antistable struct antistable
{ {
antistable(Comp &comp) explicit antistable(Comp &comp)
: m_comp(comp) : m_comp(comp)
{} {}
@@ -306,6 +412,49 @@ struct antistable
Comp &m_comp; Comp &m_comp;
}; };
template <class Comp>
class negate
{
public:
negate()
{}
explicit negate(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
{
return !m_comp(l, r);
}
private:
Comp m_comp;
};
template <class Comp>
class inverse
{
public:
inverse()
{}
explicit inverse(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
{
return m_comp(r, l);
}
private:
Comp m_comp;
};
// [r_first, r_last) are already in the right part of the destination range. // [r_first, r_last) are already in the right part of the destination range.
template <class Compare, class InputIterator, class InputOutIterator, class Op> template <class Compare, class InputIterator, class InputOutIterator, class Op>
void op_merge_with_right_placed void op_merge_with_right_placed

View File

@@ -41,6 +41,21 @@ namespace movelib {
static const unsigned MergeSortInsertionSortThreshold = 16; static const unsigned MergeSortInsertionSortThreshold = 16;
template <class RandIt, class Compare>
void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
insertion_sort(first, last, comp);
return;
}
RandIt middle = first + (last - first) / 2;
inplace_stable_sort(first, middle, comp);
inplace_stable_sort(middle, last, comp);
merge_bufferless_ONlogN_recursive
(first, middle, last, size_type(middle - first), size_type(last - middle), comp);
}
// @endcond // @endcond
template<class RandIt, class RandIt2, class Compare> template<class RandIt, class RandIt2, class Compare>

View File

@@ -260,7 +260,7 @@
#define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
public:\ public:\
TYPE& operator=(TYPE &t)\ BOOST_MOVE_FORCEINLINE TYPE& operator=(TYPE &t)\
{ this->operator=(const_cast<const TYPE&>(t)); return *this;}\ { this->operator=(const_cast<const TYPE&>(t)); return *this;}\
public:\ public:\
BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \

View File

@@ -114,6 +114,18 @@ struct is_same<T, T>
static const bool value = true; static const bool value = true;
}; };
//////////////////////////////////////
// enable_if_same
//////////////////////////////////////
template <class T, class U, class R = void>
struct enable_if_same : enable_if<is_same<T, U>, R> {};
//////////////////////////////////////
// disable_if_same
//////////////////////////////////////
template <class T, class U, class R = void>
struct disable_if_same : disable_if<is_same<T, U>, R> {};
} //namespace move_detail { } //namespace move_detail {
} //namespace boost { } //namespace boost {

View File

@@ -0,0 +1,171 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// 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/move for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
#define BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/meta_utils.hpp>
namespace boost {
namespace movelib {
template<class It>
class reverse_iterator
{
public:
typedef typename boost::movelib::iterator_traits<It>::pointer pointer;
typedef typename boost::movelib::iterator_traits<It>::reference reference;
typedef typename boost::movelib::iterator_traits<It>::difference_type difference_type;
typedef typename boost::movelib::iterator_traits<It>::iterator_category iterator_category;
typedef typename boost::movelib::iterator_traits<It>::value_type value_type;
typedef It iterator_type;
reverse_iterator()
: m_current() //Value initialization to achieve "null iterators" (N3644)
{}
explicit reverse_iterator(It r)
: m_current(r)
{}
reverse_iterator(const reverse_iterator& r)
: m_current(r.base())
{}
template<class OtherIt>
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
)
: m_current(r.base())
{}
reverse_iterator & operator=( const reverse_iterator& r)
{ m_current = r.base(); return *this; }
template<class OtherIt>
typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
operator=( const reverse_iterator<OtherIt>& r)
{ m_current = r.base(); return *this; }
It base() const
{ return m_current; }
reference operator*() const
{
It temp(m_current);
--temp;
reference r = *temp;
return r;
}
pointer operator->() const
{
It temp(m_current);
--temp;
return iterator_arrow_result(temp);
}
reference operator[](difference_type off) const
{
return this->m_current[-off - 1];
}
reverse_iterator& operator++()
{
--m_current;
return *this;
}
reverse_iterator operator++(int)
{
reverse_iterator temp((*this));
--m_current;
return temp;
}
reverse_iterator& operator--()
{
++m_current;
return *this;
}
reverse_iterator operator--(int)
{
reverse_iterator temp((*this));
++m_current;
return temp;
}
friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current == r.m_current; }
friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current != r.m_current; }
friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current > r.m_current; }
friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current >= r.m_current; }
friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current < r.m_current; }
friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current <= r.m_current; }
reverse_iterator& operator+=(difference_type off)
{ m_current -= off; return *this; }
reverse_iterator& operator-=(difference_type off)
{ m_current += off; return *this; }
friend reverse_iterator operator+(reverse_iterator l, difference_type off)
{ return (l += off); }
friend reverse_iterator operator+(difference_type off, reverse_iterator r)
{ return (r += off); }
friend reverse_iterator operator-(reverse_iterator l, difference_type off)
{ return (l-= off); }
friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
{ return r.m_current - l.m_current; }
private:
It m_current; // the wrapped iterator
};
template< class Iterator >
reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
{
return reverse_iterator<Iterator>(i);
}
} //namespace movelib {
} //namespace boost {
#include <boost/move/detail/config_end.hpp>
#endif //BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP

View File

@@ -55,8 +55,10 @@
// BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type // BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type
// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect // BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
// BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy // BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
// (Note: this trait does not guarantee T is copy constructible, the copy constructor could be deleted but still be trivial)
// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy // BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
// BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy // BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
// (Note: this trait does not guarantee T is assignable , the copy assignmen could be deleted but still be trivial)
// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy // BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect // BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw // BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
@@ -117,9 +119,7 @@
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
# endif # endif
# if __has_feature(has_trivial_copy) # if __has_feature(has_trivial_copy)
# //There are problems with deleted copy constructors detected as trivially copyable. # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
# //http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && ::boost::move_detail::is_copy_constructible<T>::value)
# endif # endif
# if __has_feature(has_trivial_assign) # if __has_feature(has_trivial_assign)
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) ) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) )
@@ -235,7 +235,9 @@
#endif #endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY #ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T) #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value ||\
(::boost::move_detail::is_copy_constructible<T>::value &&\
BOOST_MOVE_HAS_TRIVIAL_COPY(T))
#else #else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif #endif
@@ -246,12 +248,6 @@
#define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif #endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T)
#else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR #ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)
#else #else
@@ -259,7 +255,9 @@
#endif #endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN #ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN
#define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value ||\
( ::boost::move_detail::is_copy_assignable<T>::value &&\
BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T))
#else #else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
#endif #endif
@@ -821,9 +819,7 @@ struct is_trivially_copy_constructible
{ {
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible. //deleted copy constructors so make sure the type is copy constructible.
static const bool value = ::boost::move_detail::is_pod<T>::value || static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T);
( ::boost::move_detail::is_copy_constructible<T>::value &&
BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) );
}; };
////////////////////////////////////// //////////////////////////////////////
@@ -841,9 +837,7 @@ struct is_trivially_copy_assignable
{ {
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible. //deleted copy constructors so make sure the type is copy constructible.
static const bool value = ::boost::move_detail::is_pod<T>::value || static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T);
( ::boost::move_detail::is_copy_assignable<T>::value &&
BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) );
}; };
////////////////////////////////////// //////////////////////////////////////

View File

@@ -119,6 +119,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_merge", "bench_merge.
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_sort_test", "adaptive_sort_test.vcproj", "{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_merge_test", "adaptive_merge_test.vcproj", "{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_template_assign", "doc_template_assign.vcproj", "{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -247,6 +259,18 @@ Global
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.ActiveCfg = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.Build.0 = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.ActiveCfg = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.Build.0 = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.ActiveCfg = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.Build.0 = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.ActiveCfg = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.Build.0 = Release|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Debug.ActiveCfg = Debug|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Debug.Build.0 = Debug|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Release.ActiveCfg = Release|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Release.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionItems) = postSolution GlobalSection(SolutionItems) = postSolution
..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp ..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp
@@ -267,8 +291,8 @@ Global
..\..\..\..\boost\move\detail\iterator_traits.hpp = ..\..\..\..\boost\move\detail\iterator_traits.hpp ..\..\..\..\boost\move\detail\iterator_traits.hpp = ..\..\..\..\boost\move\detail\iterator_traits.hpp
..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2 ..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2
..\..\..\..\boost\move\make_unique.hpp = ..\..\..\..\boost\move\make_unique.hpp ..\..\..\..\boost\move\make_unique.hpp = ..\..\..\..\boost\move\make_unique.hpp
..\..\..\..\boost\move\algo\merge.hpp = ..\..\..\..\boost\move\algo\merge.hpp ..\..\..\..\boost\move\algo\detail\merge.hpp = ..\..\..\..\boost\move\algo\detail\merge.hpp
..\..\..\..\boost\move\algo\merge_sort.hpp = ..\..\..\..\boost\move\algo\merge_sort.hpp ..\..\..\..\boost\move\algo\detail\merge_sort.hpp = ..\..\..\..\boost\move\algo\detail\merge_sort.hpp
..\..\..\..\boost\move\detail\meta_utils.hpp = ..\..\..\..\boost\move\detail\meta_utils.hpp ..\..\..\..\boost\move\detail\meta_utils.hpp = ..\..\..\..\boost\move\detail\meta_utils.hpp
..\..\..\..\boost\move\detail\meta_utils_core.hpp = ..\..\..\..\boost\move\detail\meta_utils_core.hpp ..\..\..\..\boost\move\detail\meta_utils_core.hpp = ..\..\..\..\boost\move\detail\meta_utils_core.hpp
..\..\..\..\boost\move\move.hpp = ..\..\..\..\boost\move\move.hpp ..\..\..\..\boost\move\move.hpp = ..\..\..\..\boost\move\move.hpp

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="adaptive_merge_test"
ProjectGUID="{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/adaptive_merge_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_merge_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/adaptive_merge_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/adaptive_merge_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_merge_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{163D8753-0546-A605-5C56-3B0FEAD7A52A}">
<File
RelativePath="..\..\test\adaptive_merge_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="adaptive_sort_test"
ProjectGUID="{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/adaptive_sort_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_sort_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/adaptive_sort_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/adaptive_sort_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_sort_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{163D8753-0546-A605-5C56-3B0FEAD7A52A}">
<File
RelativePath="..\..\test\adaptive_sort_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="doc_template_assign"
ProjectGUID="{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/doc_template_assign"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_template_assign_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/doc_template_assign.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/doc_template_assign"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_template_assign.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{475F3C87-6465-7BC5-05A6-2454C0A2A2CF}">
<File
RelativePath="..\..\example\doc_template_assign.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,87 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2016.
// 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/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <cstdlib> //std::srand
#include <algorithm> //std::next_permutation
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#include "order_type.hpp"
#include <boost/move/algo/adaptive_merge.hpp>
#include <boost/move/core.hpp>
template<class T>
bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
{
boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
//Initialize keys
for(std::size_t i=0; i < element_count; ++i){
std::size_t key = num_keys ? (i % num_keys) : i;
elements[i].key=key;
}
std::srand(0);
for (std::size_t i = 0; i != num_iter; ++i)
{
std::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
key_reps[i]=0;
}
for(std::size_t i = 0; i < element_count; ++i){
elements[i].val = key_reps[elements[i].key]++;
}
boost::container::vector<order_type> tmp(elements.get(), elements.get()+element_count);
std::size_t const split = std::size_t(std::rand()) % element_count;
std::stable_sort(tmp.data(), tmp.data()+split, order_type_less<order_type>());
std::stable_sort(tmp.data()+split, tmp.data()+element_count, order_type_less<order_type>());
boost::movelib::adaptive_merge(tmp.data(), tmp.data()+split, tmp.data()+element_count, order_type_less<order_type>());
if (!is_order_type_ordered(tmp.data(), element_count))
{
std::cout << "\n ERROR\n";
throw int(0);
}
}
return true;
}
int main()
{
#ifdef NDEBUG
const std::size_t NIter = 100;
#else
const std::size_t NIter = 10;
#endif
test_random_shuffled<order_type>(10001, 65, NIter);
test_random_shuffled<order_type>(10001, 101, NIter);
test_random_shuffled<order_type>(10001, 1023, NIter);
test_random_shuffled<order_type>(10001, 4095, NIter);
test_random_shuffled<order_type>(10001, 0, NIter);
return 0;
}

View File

@@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2016.
// 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/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <cstdlib> //std::srand
#include <algorithm> //std::next_permutation
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#include "order_type.hpp"
#include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/core.hpp>
template<class T>
bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
{
boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
//Initialize keys
for(std::size_t i=0; i < element_count; ++i){
std::size_t key = num_keys ? (i % num_keys) : i;
elements[i].key=key;
}
std::srand(0);
for (std::size_t i = 0; i != num_iter; ++i)
{
std::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
key_reps[i]=0;
}
for(std::size_t i = 0; i < element_count; ++i){
elements[i].val = key_reps[elements[i].key]++;
}
boost::container::vector<order_type> tmp(elements.get(), elements.get()+element_count);
boost::movelib::adaptive_sort(tmp.data(), tmp.data()+element_count, order_type_less<order_type>());
if (!is_order_type_ordered(tmp.data(), element_count))
{
std::cout << "\n ERROR\n";
throw int(0);
}
}
return true;
}
int main()
{
#ifdef NDEBUG
const std::size_t NIter = 100;
#else
const std::size_t NIter = 10;
#endif
test_random_shuffled<order_type>(10001, 65, NIter);
test_random_shuffled<order_type>(10001, 101, NIter);
test_random_shuffled<order_type>(10001, 1023, NIter);
test_random_shuffled<order_type>(10001, 4095, NIter);
test_random_shuffled<order_type>(10001, 0, NIter);
return 0;
}

View File

@@ -18,62 +18,18 @@
#include <boost/move/unique_ptr.hpp> #include <boost/move/unique_ptr.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
#include "order_type.hpp"
using boost::timer::cpu_timer; using boost::timer::cpu_timer;
using boost::timer::cpu_times; using boost::timer::cpu_times;
using boost::timer::nanosecond_type; using boost::timer::nanosecond_type;
boost::ulong_long_type num_copy;
boost::ulong_long_type num_elements;
struct merged_type
{
public:
std::size_t key;
std::size_t val;
merged_type()
{
++num_elements;
}
merged_type(const merged_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
merged_type & operator=(const merged_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~merged_type ()
{
--num_elements;
}
};
boost::ulong_long_type num_compare;
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS //#define BOOST_MOVE_ADAPTIVE_SORT_STATS
void print_stats(const char *str, boost::ulong_long_type element_count) void print_stats(const char *str, boost::ulong_long_type element_count)
{ {
std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
} }
template<class T>
struct counted_less
{
bool operator()(const T &a,T const &b) const
{ ++num_compare; return a.key < b.key; }
};
#include <boost/move/algo/adaptive_merge.hpp> #include <boost/move/algo/adaptive_merge.hpp>
#include <boost/move/algo/detail/merge.hpp> #include <boost/move/algo/detail/merge.hpp>
#include <boost/move/core.hpp> #include <boost/move/core.hpp>
@@ -101,21 +57,7 @@ std::size_t generate_elements(T elements[], std::size_t element_count, std::size
return split_count; return split_count;
} }
template<class T>
bool test_order(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(counted_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
template<class T, class Compare> template<class T, class Compare>
void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen) void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen)
@@ -126,23 +68,23 @@ void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::si
enum AlgoType enum AlgoType
{ {
InplaceMerge, StdMerge,
AdaptiveMerge, AdaptiveMerge,
SqrtHAdaptiveMerge, SqrtHAdaptiveMerge,
SqrtAdaptiveMerge, SqrtAdaptiveMerge,
Sqrt2AdaptiveMerge, Sqrt2AdaptiveMerge,
QuartAdaptiveMerge, QuartAdaptiveMerge,
BuflessMerge, StdInplaceMerge,
MaxMerge MaxMerge
}; };
const char *AlgoNames [] = { "InplaceMerge " const char *AlgoNames [] = { "StdMerge "
, "AdaptMerge " , "AdaptMerge "
, "SqrtHAdaptMerge " , "SqrtHAdaptMerge "
, "SqrtAdaptMerge " , "SqrtAdaptMerge "
, "Sqrt2AdaptMerge " , "Sqrt2AdaptMerge "
, "QuartAdaptMerge " , "QuartAdaptMerge "
, "BuflessMerge " , "StdInplaceMerge "
}; };
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge); BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
@@ -150,53 +92,53 @@ BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
template<class T> template<class T>
bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock) bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
{ {
std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, counted_less<T>()); std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, order_type_less<T>());
std::printf("%s ", AlgoNames[alg]); std::printf("%s ", AlgoNames[alg]);
num_compare=0; order_type::num_compare=0;
num_copy=0; order_type::num_copy=0;
num_elements = element_count; order_type::num_elements = element_count;
cpu_timer timer; cpu_timer timer;
timer.resume(); timer.resume();
switch(alg) switch(alg)
{ {
case InplaceMerge: case StdMerge:
std::inplace_merge(elements, elements+split_pos, elements+element_count, counted_less<T>()); std::inplace_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
case AdaptiveMerge: case AdaptiveMerge:
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, counted_less<T>()); boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
case SqrtHAdaptiveMerge: case SqrtHAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break; break;
case SqrtAdaptiveMerge: case SqrtAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case Sqrt2AdaptiveMerge: case Sqrt2AdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case QuartAdaptiveMerge: case QuartAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, (element_count-1)/4+1); , (element_count-1)/4+1);
break; break;
case BuflessMerge: case StdInplaceMerge:
boost::movelib::merge_bufferless(elements, elements+split_pos, elements+element_count, counted_less<T>()); boost::movelib::merge_bufferless_ONlogN(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
} }
timer.stop(); timer.stop();
if(num_elements == element_count){ if(order_type::num_elements == element_count){
std::printf(" Tmp Ok "); std::printf(" Tmp Ok ");
} else{ } else{
std::printf(" Tmp KO "); std::printf(" Tmp KO ");
} }
nanosecond_type new_clock = timer.elapsed().wall; nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument //std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%8.04f Cpy:%9.04f", double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("Cmp:%8.04f Cpy:%9.04f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock); double time = double(new_clock);
@@ -219,7 +161,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, units , units
, prev_clock ? double(new_clock)/double(prev_clock): 1.0); , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
prev_clock = new_clock; prev_clock = new_clock;
bool res = test_order(elements, element_count, true); bool res = is_order_type_ordered(elements, element_count, true);
return res; return res;
} }
@@ -235,7 +177,7 @@ bool measure_all(std::size_t L, std::size_t NK)
nanosecond_type prev_clock = 0; nanosecond_type prev_clock = 0;
nanosecond_type back_clock; nanosecond_type back_clock;
bool res = true; bool res = true;
res = res && measure_algo(A,Keys,L,NK,InplaceMerge, prev_clock); res = res && measure_algo(A,Keys,L,NK,StdMerge, prev_clock);
back_clock = prev_clock;/* back_clock = prev_clock;/*
// //
prev_clock = back_clock; prev_clock = back_clock;
@@ -253,70 +195,74 @@ bool measure_all(std::size_t L, std::size_t NK)
prev_clock = back_clock; prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,AdaptiveMerge, prev_clock); res = res && measure_algo(A,Keys,L,NK,AdaptiveMerge, prev_clock);
// //
//prev_clock = back_clock; prev_clock = back_clock;
//res = res && measure_algo(A,Keys,L,NK,BuflessMerge, prev_clock); res = res && measure_algo(A,Keys,L,NK,StdInplaceMerge, prev_clock);
// //
if(!res) if(!res)
throw int(0); throw int(0);
return res; return res;
} }
struct less
{
template<class T, class U>
bool operator()(const T &t, const U &u)
{ return t < u; }
};
//Undef it to run the long test //Undef it to run the long test
#define BENCH_MERGE_SHORT #define BENCH_MERGE_SHORT
#define BENCH_SORT_UNIQUE_VALUES
int main() int main()
{ {
try{ try{
measure_all<merged_type>(101,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<merged_type>(101,7); measure_all<order_type>(101,1);
measure_all<merged_type>(101,31); measure_all<order_type>(101,7);
measure_all<merged_type>(101,0); measure_all<order_type>(101,31);
#endif
measure_all<order_type>(101,0);
// //
measure_all<merged_type>(1101,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<merged_type>(1001,7); measure_all<order_type>(1101,1);
measure_all<merged_type>(1001,31); measure_all<order_type>(1001,7);
measure_all<merged_type>(1001,127); measure_all<order_type>(1001,31);
measure_all<merged_type>(1001,511); measure_all<order_type>(1001,127);
measure_all<merged_type>(1001,0); measure_all<order_type>(1001,511);
#endif
measure_all<order_type>(1001,0);
// //
#ifndef BENCH_MERGE_SHORT #ifndef BENCH_MERGE_SHORT
measure_all<merged_type>(10001,65); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<merged_type>(10001,255); measure_all<order_type>(10001,65);
measure_all<merged_type>(10001,1023); measure_all<order_type>(10001,255);
measure_all<merged_type>(10001,4095); measure_all<order_type>(10001,1023);
measure_all<merged_type>(10001,0); measure_all<order_type>(10001,4095);
#endif
measure_all<order_type>(10001,0);
// //
measure_all<merged_type>(100001,511); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<merged_type>(100001,2047); measure_all<order_type>(100001,511);
measure_all<merged_type>(100001,8191); measure_all<order_type>(100001,2047);
measure_all<merged_type>(100001,32767); measure_all<order_type>(100001,8191);
measure_all<merged_type>(100001,0); measure_all<order_type>(100001,32767);
#endif
measure_all<order_type>(100001,0);
// //
#ifdef NDEBUG #ifdef NDEBUG
measure_all<merged_type>(1000001,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<merged_type>(1000001,1024); measure_all<order_type>(1000001,1);
measure_all<merged_type>(1000001,32768); measure_all<order_type>(1000001,1024);
measure_all<merged_type>(1000001,524287); measure_all<order_type>(1000001,32768);
measure_all<merged_type>(1000001,0); measure_all<order_type>(1000001,524287);
measure_all<merged_type>(1500001,0); #endif
//measure_all<merged_type>(10000001,0); measure_all<order_type>(1000001,0);
//measure_all<merged_type>(15000001,0); measure_all<order_type>(1500001,0);
//measure_all<merged_type>(100000001,0); //measure_all<order_type>(10000001,0);
//measure_all<order_type>(15000001,0);
//measure_all<order_type>(100000001,0);
#endif //NDEBUG #endif //NDEBUG
#endif //#ifndef BENCH_MERGE_SHORT #endif //#ifndef BENCH_MERGE_SHORT
//measure_all<merged_type>(100000001,0); //measure_all<order_type>(100000001,0);
} }
catch(...) catch(...)
{ {

View File

@@ -23,58 +23,15 @@ using boost::timer::cpu_timer;
using boost::timer::cpu_times; using boost::timer::cpu_times;
using boost::timer::nanosecond_type; using boost::timer::nanosecond_type;
#include "order_type.hpp"
boost::ulong_long_type num_copy;
boost::ulong_long_type num_elements;
struct sorted_type
{
public:
std::size_t key;
std::size_t val;
sorted_type()
{
++num_elements;
}
sorted_type(const sorted_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
sorted_type & operator=(const sorted_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~sorted_type ()
{
--num_elements;
}
};
boost::ulong_long_type num_compare;
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS //#define BOOST_MOVE_ADAPTIVE_SORT_STATS
void print_stats(const char *str, boost::ulong_long_type element_count) void print_stats(const char *str, boost::ulong_long_type element_count)
{ {
std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
} }
template<class T>
struct counted_less
{
bool operator()(const T &a,T const &b) const
{ ++num_compare; return a.key < b.key; }
};
#include <boost/move/algo/adaptive_sort.hpp> #include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/algo/detail/merge_sort.hpp> #include <boost/move/algo/detail/merge_sort.hpp>
#include <boost/move/algo/detail/bufferless_merge_sort.hpp> #include <boost/move/algo/detail/bufferless_merge_sort.hpp>
@@ -99,22 +56,6 @@ void generate_elements(T elements[], std::size_t element_count, std::size_t key_
} }
} }
template<class T>
bool test_order(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(counted_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
template<class T, class Compare> template<class T, class Compare>
void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen) void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen)
{ {
@@ -139,6 +80,7 @@ enum AlgoType
Sqrt2AdaptiveSort, Sqrt2AdaptiveSort,
QuartAdaptiveSort, QuartAdaptiveSort,
NoBufMergeSort, NoBufMergeSort,
InplaceStableSort,
SlowStableSort, SlowStableSort,
HeapSort, HeapSort,
MaxSort MaxSort
@@ -152,6 +94,7 @@ const char *AlgoNames [] = { "MergeSort "
, "Sqrt2AdaptSort " , "Sqrt2AdaptSort "
, "QuartAdaptSort " , "QuartAdaptSort "
, "NoBufMergeSort " , "NoBufMergeSort "
, "InplStableSort "
, "SlowSort " , "SlowSort "
, "HeapSort " , "HeapSort "
}; };
@@ -164,60 +107,63 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
generate_elements(elements, element_count, key_reps, key_len); generate_elements(elements, element_count, key_reps, key_len);
std::printf("%s ", AlgoNames[alg]); std::printf("%s ", AlgoNames[alg]);
num_compare=0; order_type::num_compare=0;
num_copy=0; order_type::num_copy=0;
num_elements = element_count; order_type::num_elements = element_count;
cpu_timer timer; cpu_timer timer;
timer.resume(); timer.resume();
switch(alg) switch(alg)
{ {
case MergeSort: case MergeSort:
merge_sort_buffered(elements, element_count, counted_less<T>()); merge_sort_buffered(elements, element_count, order_type_less<T>());
break; break;
case StableSort: case StableSort:
std::stable_sort(elements,elements+element_count,counted_less<T>()); std::stable_sort(elements,elements+element_count,order_type_less<T>());
break; break;
case AdaptiveSort: case AdaptiveSort:
boost::movelib::adaptive_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::adaptive_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case SqrtHAdaptiveSort: case SqrtHAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break; break;
case SqrtAdaptiveSort: case SqrtAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case Sqrt2AdaptiveSort: case Sqrt2AdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case QuartAdaptiveSort: case QuartAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, (element_count-1)/4+1); , (element_count-1)/4+1);
break; break;
case NoBufMergeSort: case NoBufMergeSort:
boost::movelib::bufferless_merge_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::bufferless_merge_sort(elements, elements+element_count, order_type_less<T>());
break;
case InplaceStableSort:
boost::movelib::inplace_stable_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case SlowStableSort: case SlowStableSort:
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case HeapSort: case HeapSort:
std::make_heap(elements, elements+element_count, counted_less<T>()); std::make_heap(elements, elements+element_count, order_type_less<T>());
std::sort_heap(elements, elements+element_count, counted_less<T>()); std::sort_heap(elements, elements+element_count, order_type_less<T>());
break; break;
} }
timer.stop(); timer.stop();
if(num_elements == element_count){ if(order_type::num_elements == element_count){
std::printf(" Tmp Ok "); std::printf(" Tmp Ok ");
} else{ } else{
std::printf(" Tmp KO "); std::printf(" Tmp KO ");
} }
nanosecond_type new_clock = timer.elapsed().wall; nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument //std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%7.03f Cpy:%8.03f", double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock); double time = double(new_clock);
@@ -240,7 +186,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, units , units
, prev_clock ? double(new_clock)/double(prev_clock): 1.0); , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
prev_clock = new_clock; prev_clock = new_clock;
bool res = test_order(elements, element_count, alg != HeapSort && alg != NoBufMergeSort); bool res = is_order_type_ordered(elements, element_count, alg != HeapSort && alg != NoBufMergeSort);
return res; return res;
} }
@@ -281,6 +227,9 @@ bool measure_all(std::size_t L, std::size_t NK)
res = res && measure_algo(A,Keys,L,NK,AdaptiveSort, prev_clock); res = res && measure_algo(A,Keys,L,NK,AdaptiveSort, prev_clock);
// //
prev_clock = back_clock; prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,InplaceStableSort, prev_clock);
//
prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,NoBufMergeSort, prev_clock); res = res && measure_algo(A,Keys,L,NK,NoBufMergeSort, prev_clock);
// //
//prev_clock = back_clock; //prev_clock = back_clock;
@@ -293,59 +242,61 @@ bool measure_all(std::size_t L, std::size_t NK)
//Undef it to run the long test //Undef it to run the long test
#define BENCH_SORT_SHORT #define BENCH_SORT_SHORT
#define BENCH_SORT_UNIQUE_VALUES
struct less
{
template<class T, class U>
bool operator()(const T &t, const U &u)
{ return t < u; }
};
int main() int main()
{ {
measure_all<sorted_type>(101,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<sorted_type>(101,7); //measure_all<order_type>(101,1);
measure_all<sorted_type>(101,31); measure_all<order_type>(101,7);
measure_all<sorted_type>(101,0); measure_all<order_type>(101,31);
#endif
measure_all<order_type>(101,0);
// //
measure_all<sorted_type>(1101,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<sorted_type>(1001,7); measure_all<order_type>(1101,1);
measure_all<sorted_type>(1001,31); measure_all<order_type>(1001,7);
measure_all<sorted_type>(1001,127); measure_all<order_type>(1001,31);
measure_all<sorted_type>(1001,511); measure_all<order_type>(1001,127);
measure_all<sorted_type>(1001,0); measure_all<order_type>(1001,511);
#endif
measure_all<order_type>(1001,0);
// //
#ifndef BENCH_SORT_SHORT #ifndef BENCH_SORT_SHORT
measure_all<sorted_type>(10001,65); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<sorted_type>(10001,255); measure_all<order_type>(10001,65);
measure_all<sorted_type>(10001,1023); measure_all<order_type>(10001,255);
measure_all<sorted_type>(10001,4095); measure_all<order_type>(10001,1023);
measure_all<sorted_type>(10001,0); measure_all<order_type>(10001,4095);
measure_all<order_type>(10001,0);
#endif
// //
measure_all<sorted_type>(100001,511); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<sorted_type>(100001,2047); measure_all<order_type>(100001,511);
measure_all<sorted_type>(100001,8191); measure_all<order_type>(100001,2047);
measure_all<sorted_type>(100001,32767); measure_all<order_type>(100001,8191);
measure_all<sorted_type>(100001,0); measure_all<order_type>(100001,32767);
#endif
measure_all<order_type>(100001,0);
// //
#ifdef NDEBUG //#ifdef NDEBUG
measure_all<sorted_type>(1000001,1); #ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<sorted_type>(1000001,1024); measure_all<order_type>(1000001,1);
measure_all<sorted_type>(1000001,32768); measure_all<order_type>(1000001,1024);
measure_all<sorted_type>(1000001,524287); measure_all<order_type>(1000001,32768);
measure_all<sorted_type>(1000001,0); measure_all<order_type>(1000001,524287);
measure_all<sorted_type>(1500001,0); #endif
//measure_all<sorted_type>(10000001,0); measure_all<order_type>(1000001,0);
#endif //NDEBUG measure_all<order_type>(1500001,0);
//measure_all<order_type>(10000001,0);
//#endif //NDEBUG
#endif //#ifndef BENCH_SORT_SHORT #endif //#ifndef BENCH_SORT_SHORT
//measure_all<sorted_type>(100000001,0); //measure_all<order_type>(100000001,0);
return 0; return 0;
} }

82
test/order_type.hpp Normal file
View File

@@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2016.
// 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/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_TEST_ORDER_TYPE_HPP
#define BOOST_MOVE_TEST_ORDER_TYPE_HPP
#include <boost/config.hpp>
#include <cstddef>
#include <cstdio>
struct order_type
{
public:
std::size_t key;
std::size_t val;
order_type()
{
++num_elements;
}
order_type(const order_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
order_type & operator=(const order_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~order_type ()
{
--num_elements;
}
static boost::ulong_long_type num_compare;
static boost::ulong_long_type num_copy;
static boost::ulong_long_type num_elements;
};
boost::ulong_long_type order_type::num_compare = 0;
boost::ulong_long_type order_type::num_copy = 0;
boost::ulong_long_type order_type::num_elements = 0;
template<class T>
struct order_type_less
{
bool operator()(const T &a,T const &b) const
{ ++order_type::num_compare; return a.key < b.key; }
};
template<class T>
inline bool is_order_type_ordered(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(order_type_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(order_type_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
#endif //BOOST_MOVE_TEST_ORDER_TYPE_HPP