update boost on linux
This commit is contained in:
@@ -27,7 +27,7 @@ int_log_mean_bin_size = 2,
|
||||
//Minimum value 1
|
||||
int_log_min_split_count = 9,
|
||||
//This is the minimum split count to use spreadsort when it will finish in one
|
||||
//iteration. Make this larger the faster std::sort is relative to integer_sort.
|
||||
//iteration. Make this larger the faster boost::sort::pdqsort is relative to integer_sort.
|
||||
int_log_finishing_count = 31,
|
||||
//Sets the minimum number of items per bin for floating point.
|
||||
float_log_mean_bin_size = 2,
|
||||
@@ -35,7 +35,7 @@ float_log_mean_bin_size = 2,
|
||||
//Minimum value 1
|
||||
float_log_min_split_count = 8,
|
||||
//This is the minimum split count to use spreadsort when it will finish in one
|
||||
//iteration. Make this larger the faster std::sort is relative to float_sort.
|
||||
//iteration. Make this larger the faster boost::sort::pdqsort is relative to float_sort.
|
||||
float_log_finishing_count = 4,
|
||||
//There is a minimum size below which it is not worth using spreadsort
|
||||
min_sort_size = 1000 };
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u]);
|
||||
else
|
||||
positive_float_sort_rec<RandomAccessIter, Div_type, Size_type>
|
||||
(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
|
||||
@@ -273,7 +273,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii]);
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type, Size_type>
|
||||
(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
|
||||
@@ -332,7 +332,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii]);
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
|
||||
Size_type>
|
||||
@@ -390,7 +390,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii], comp);
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
|
||||
Compare, Size_type>(lastPos, bin_cache[ii],
|
||||
@@ -475,7 +475,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii]);
|
||||
//sort negative values using reversed-bin spreadsort
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type, Size_type>
|
||||
@@ -488,7 +488,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u]);
|
||||
//sort positive values using normal spreadsort
|
||||
else
|
||||
positive_float_sort_rec<RandomAccessIter, Div_type, Size_type>
|
||||
@@ -571,7 +571,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii]);
|
||||
//sort negative values using reversed-bin spreadsort
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type,
|
||||
@@ -585,7 +585,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u]);
|
||||
//sort positive values using normal spreadsort
|
||||
else
|
||||
spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Size_type,
|
||||
@@ -670,7 +670,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[ii], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[ii], comp);
|
||||
//sort negative values using reversed-bin spreadsort
|
||||
else
|
||||
negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
|
||||
@@ -685,7 +685,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], comp);
|
||||
//sort positive values using normal spreadsort
|
||||
else
|
||||
spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Compare,
|
||||
@@ -741,7 +741,7 @@ namespace spreadsort {
|
||||
sizeof(typename std::iterator_traits<RandomAccessIter>::value_type))
|
||||
|| !std::numeric_limits<typename
|
||||
std::iterator_traits<RandomAccessIter>::value_type>::is_iec559);
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
|
||||
//These approaches require the user to do the typecast
|
||||
@@ -771,7 +771,7 @@ namespace spreadsort {
|
||||
(first, last, bin_cache, 0, bin_sizes, rshift);
|
||||
}
|
||||
|
||||
//sizeof(Div_type) doesn't match, so use std::sort
|
||||
//sizeof(Div_type) doesn't match, so use boost::sort::pdqsort
|
||||
template <class RandomAccessIter, class Div_type, class Right_shift>
|
||||
inline typename boost::disable_if_c< sizeof(boost::uintmax_t) >=
|
||||
sizeof(Div_type), void >::type
|
||||
@@ -779,7 +779,7 @@ namespace spreadsort {
|
||||
Right_shift rshift)
|
||||
{
|
||||
BOOST_STATIC_WARNING(sizeof(boost::uintmax_t) >= sizeof(Div_type));
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
|
||||
//specialized comparison
|
||||
@@ -812,7 +812,7 @@ namespace spreadsort {
|
||||
(first, last, bin_cache, 0, bin_sizes, rshift, comp);
|
||||
}
|
||||
|
||||
//sizeof(Div_type) doesn't match, so use std::sort
|
||||
//sizeof(Div_type) doesn't match, so use boost::sort::pdqsort
|
||||
template <class RandomAccessIter, class Div_type, class Right_shift,
|
||||
class Compare>
|
||||
inline typename boost::disable_if_c< sizeof(boost::uintmax_t) >=
|
||||
@@ -821,7 +821,7 @@ namespace spreadsort {
|
||||
Right_shift rshift, Compare comp)
|
||||
{
|
||||
BOOST_STATIC_WARNING(sizeof(boost::uintmax_t) >= sizeof(Div_type));
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +186,9 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u]);
|
||||
else
|
||||
spreadsort_rec<RandomAccessIter, Div_type, Size_type>(lastPos,
|
||||
bin_cache[u],
|
||||
@@ -294,7 +294,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], comp);
|
||||
else
|
||||
spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Compare,
|
||||
Size_type, log_mean_bin_size, log_min_split_count, log_finishing_count>
|
||||
@@ -351,7 +351,7 @@ namespace spreadsort {
|
||||
if (count < 2)
|
||||
continue;
|
||||
if (count < max_count)
|
||||
std::sort(lastPos, bin_cache[u]);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u]);
|
||||
else
|
||||
spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Size_type,
|
||||
log_mean_bin_size, log_min_split_count, log_finishing_count>(lastPos,
|
||||
@@ -388,12 +388,12 @@ namespace spreadsort {
|
||||
template <class RandomAccessIter, class Div_type>
|
||||
inline typename boost::disable_if_c< sizeof(Div_type) <= sizeof(size_t)
|
||||
|| sizeof(Div_type) <= sizeof(boost::uintmax_t), void >::type
|
||||
//defaulting to std::sort when integer_sort won't work
|
||||
//defaulting to boost::sort::pdqsort when integer_sort won't work
|
||||
integer_sort(RandomAccessIter first, RandomAccessIter last, Div_type)
|
||||
{
|
||||
//Warning that we're using std::sort, even though integer_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though integer_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Div_type) <= sizeof(size_t) );
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
|
||||
|
||||
@@ -434,13 +434,13 @@ namespace spreadsort {
|
||||
class Compare>
|
||||
inline typename boost::disable_if_c< sizeof(Div_type) <= sizeof(size_t)
|
||||
|| sizeof(Div_type) <= sizeof(boost::uintmax_t), void >::type
|
||||
//defaulting to std::sort when integer_sort won't work
|
||||
//defaulting to boost::sort::pdqsort when integer_sort won't work
|
||||
integer_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
|
||||
Right_shift shift, Compare comp)
|
||||
{
|
||||
//Warning that we're using std::sort, even though integer_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though integer_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Div_type) <= sizeof(size_t) );
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
}
|
||||
|
||||
|
||||
@@ -478,13 +478,13 @@ namespace spreadsort {
|
||||
template <class RandomAccessIter, class Div_type, class Right_shift>
|
||||
inline typename boost::disable_if_c< sizeof(Div_type) <= sizeof(size_t)
|
||||
|| sizeof(Div_type) <= sizeof(boost::uintmax_t), void >::type
|
||||
//defaulting to std::sort when integer_sort won't work
|
||||
//defaulting to boost::sort::pdqsort when integer_sort won't work
|
||||
integer_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
|
||||
Right_shift shift)
|
||||
{
|
||||
//Warning that we're using std::sort, even though integer_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though integer_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Div_type) <= sizeof(size_t) );
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ Phil Endecott and Frank Gennari
|
||||
#include <functional>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/serialization/static_warning.hpp>
|
||||
#include <boost/sort/pdqsort/pdqsort.hpp>
|
||||
#include <boost/sort/spreadsort/detail/constants.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
@@ -37,7 +38,7 @@ namespace spreadsort {
|
||||
unsigned result = 0;
|
||||
//The && is necessary on some compilers to avoid infinite loops
|
||||
//it doesn't significantly impair performance
|
||||
while ((input >> result) && (result < (8*sizeof(T)))) ++result;
|
||||
while ((result < (8*sizeof(T))) && (input >> result)) ++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace spreadsort {
|
||||
template<class RandomAccessIter, class Get_char, class Get_length>
|
||||
inline void
|
||||
update_offset(RandomAccessIter first, RandomAccessIter finish,
|
||||
size_t &char_offset, Get_char getchar, Get_length length)
|
||||
size_t &char_offset, Get_char get_character, Get_length length)
|
||||
{
|
||||
size_t nextOffset = char_offset;
|
||||
while (true) {
|
||||
@@ -88,7 +88,7 @@ namespace spreadsort {
|
||||
//ignore empties, but if the nextOffset would exceed the length or
|
||||
//not match, exit; we've found the last matching character
|
||||
if (length(*curr) > char_offset && (length(*curr) <= (nextOffset + 1)
|
||||
|| getchar((*curr), nextOffset) != getchar((*first), nextOffset))) {
|
||||
|| get_character((*curr), nextOffset) != get_character((*first), nextOffset))) {
|
||||
char_offset = nextOffset;
|
||||
return;
|
||||
}
|
||||
@@ -145,14 +145,14 @@ namespace spreadsort {
|
||||
{
|
||||
size_t minSize = (std::min)(length(x), length(y));
|
||||
for (size_t u = fchar_offset; u < minSize; ++u) {
|
||||
if (getchar(x, u) != getchar(y, u)) {
|
||||
return getchar(x, u) < getchar(y, u);
|
||||
if (get_character(x, u) != get_character(y, u)) {
|
||||
return get_character(x, u) < get_character(y, u);
|
||||
}
|
||||
}
|
||||
return length(x) < length(y);
|
||||
}
|
||||
size_t fchar_offset;
|
||||
Get_char getchar;
|
||||
Get_char get_character;
|
||||
Get_length length;
|
||||
};
|
||||
|
||||
@@ -251,9 +251,9 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_size)
|
||||
std::sort(lastPos, bin_cache[u],
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u],
|
||||
offset_less_than<Data_type, Unsigned_char_type>(char_offset + 1));
|
||||
else
|
||||
string_sort_rec<RandomAccessIter, Unsigned_char_type>(lastPos,
|
||||
@@ -362,9 +362,9 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_size)
|
||||
std::sort(lastPos, bin_cache[u], offset_greater_than<Data_type,
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], offset_greater_than<Data_type,
|
||||
Unsigned_char_type>(char_offset + 1));
|
||||
else
|
||||
reverse_string_sort_rec<RandomAccessIter, Unsigned_char_type>
|
||||
@@ -379,7 +379,7 @@ namespace spreadsort {
|
||||
string_sort_rec(RandomAccessIter first, RandomAccessIter last,
|
||||
size_t char_offset, std::vector<RandomAccessIter> &bin_cache,
|
||||
unsigned cache_offset, size_t *bin_sizes,
|
||||
Get_char getchar, Get_length length)
|
||||
Get_char get_character, Get_length length)
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type
|
||||
Data_type;
|
||||
@@ -394,7 +394,7 @@ namespace spreadsort {
|
||||
//Getting the last non-empty
|
||||
for (;length(*finish) <= char_offset; --finish);
|
||||
++finish;
|
||||
update_offset(first, finish, char_offset, getchar, length);
|
||||
update_offset(first, finish, char_offset, get_character, length);
|
||||
|
||||
const unsigned bin_count = (1 << (sizeof(Unsigned_char_type)*8));
|
||||
//Equal worst-case of radix and comparison is when bin_count = n*log(n).
|
||||
@@ -410,7 +410,7 @@ namespace spreadsort {
|
||||
bin_sizes[0]++;
|
||||
}
|
||||
else
|
||||
bin_sizes[getchar((*current), char_offset) + 1]++;
|
||||
bin_sizes[get_character((*current), char_offset) + 1]++;
|
||||
}
|
||||
//Assign the bin positions
|
||||
bin_cache[cache_offset] = first;
|
||||
@@ -429,7 +429,7 @@ namespace spreadsort {
|
||||
++current) {
|
||||
//empties belong in this bin
|
||||
while (length(*current) > char_offset) {
|
||||
target_bin = bins + getchar((*current), char_offset);
|
||||
target_bin = bins + get_character((*current), char_offset);
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
}
|
||||
@@ -446,9 +446,9 @@ namespace spreadsort {
|
||||
for (RandomAccessIter current = *local_bin; current < next_bin_start;
|
||||
++current) {
|
||||
//Swapping into place until the correct element has been swapped in
|
||||
for (target_bin = bins + getchar((*current), char_offset);
|
||||
for (target_bin = bins + get_character((*current), char_offset);
|
||||
target_bin != local_bin;
|
||||
target_bin = bins + getchar((*current), char_offset))
|
||||
target_bin = bins + get_character((*current), char_offset))
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
*local_bin = next_bin_start;
|
||||
@@ -464,14 +464,14 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_size)
|
||||
std::sort(lastPos, bin_cache[u], offset_char_less_than<Data_type,
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], offset_char_less_than<Data_type,
|
||||
Get_char, Get_length>(char_offset + 1));
|
||||
else
|
||||
string_sort_rec<RandomAccessIter, Unsigned_char_type, Get_char,
|
||||
Get_length>(lastPos, bin_cache[u], char_offset + 1, bin_cache,
|
||||
cache_end, bin_sizes, getchar, length);
|
||||
cache_end, bin_sizes, get_character, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ namespace spreadsort {
|
||||
string_sort_rec(RandomAccessIter first, RandomAccessIter last,
|
||||
size_t char_offset, std::vector<RandomAccessIter> &bin_cache,
|
||||
unsigned cache_offset, size_t *bin_sizes,
|
||||
Get_char getchar, Get_length length, Compare comp)
|
||||
Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
//This section makes handling of long identical substrings much faster
|
||||
//with a mild average performance impact.
|
||||
@@ -495,7 +495,7 @@ namespace spreadsort {
|
||||
//Getting the last non-empty
|
||||
for (;length(*finish) <= char_offset; --finish);
|
||||
++finish;
|
||||
update_offset(first, finish, char_offset, getchar, length);
|
||||
update_offset(first, finish, char_offset, get_character, length);
|
||||
|
||||
const unsigned bin_count = (1 << (sizeof(Unsigned_char_type)*8));
|
||||
//Equal worst-case of radix and comparison is when bin_count = n*log(n).
|
||||
@@ -511,7 +511,7 @@ namespace spreadsort {
|
||||
bin_sizes[0]++;
|
||||
}
|
||||
else
|
||||
bin_sizes[getchar((*current), char_offset) + 1]++;
|
||||
bin_sizes[get_character((*current), char_offset) + 1]++;
|
||||
}
|
||||
//Assign the bin positions
|
||||
bin_cache[cache_offset] = first;
|
||||
@@ -530,7 +530,7 @@ namespace spreadsort {
|
||||
++current) {
|
||||
//empties belong in this bin
|
||||
while (length(*current) > char_offset) {
|
||||
target_bin = bins + getchar((*current), char_offset);
|
||||
target_bin = bins + get_character((*current), char_offset);
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
}
|
||||
@@ -547,9 +547,9 @@ namespace spreadsort {
|
||||
for (RandomAccessIter current = *local_bin; current < next_bin_start;
|
||||
++current) {
|
||||
//Swapping into place until the correct element has been swapped in
|
||||
for (target_bin = bins + getchar((*current), char_offset);
|
||||
for (target_bin = bins + get_character((*current), char_offset);
|
||||
target_bin != local_bin;
|
||||
target_bin = bins + getchar((*current), char_offset))
|
||||
target_bin = bins + get_character((*current), char_offset))
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
*local_bin = next_bin_start;
|
||||
@@ -565,14 +565,14 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_size)
|
||||
std::sort(lastPos, bin_cache[u], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], comp);
|
||||
else
|
||||
string_sort_rec<RandomAccessIter, Unsigned_char_type, Get_char,
|
||||
Get_length, Compare>
|
||||
(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end,
|
||||
bin_sizes, getchar, length, comp);
|
||||
bin_sizes, get_character, length, comp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +583,7 @@ namespace spreadsort {
|
||||
reverse_string_sort_rec(RandomAccessIter first, RandomAccessIter last,
|
||||
size_t char_offset, std::vector<RandomAccessIter> &bin_cache,
|
||||
unsigned cache_offset, size_t *bin_sizes,
|
||||
Get_char getchar, Get_length length, Compare comp)
|
||||
Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
//This section makes handling of long identical substrings much faster
|
||||
//with a mild average performance impact.
|
||||
@@ -598,7 +598,7 @@ namespace spreadsort {
|
||||
++last;
|
||||
//Offsetting on identical characters. This section works
|
||||
//a character at a time for optimal worst-case performance.
|
||||
update_offset(curr, last, char_offset, getchar, length);
|
||||
update_offset(curr, last, char_offset, get_character, length);
|
||||
|
||||
const unsigned bin_count = (1 << (sizeof(Unsigned_char_type)*8));
|
||||
//Equal worst-case of radix and comparison is when bin_count = n*log(n).
|
||||
@@ -616,7 +616,7 @@ namespace spreadsort {
|
||||
bin_sizes[bin_count]++;
|
||||
}
|
||||
else
|
||||
bin_sizes[max_bin - getchar((*current), char_offset)]++;
|
||||
bin_sizes[max_bin - get_character((*current), char_offset)]++;
|
||||
}
|
||||
//Assign the bin positions
|
||||
bin_cache[cache_offset] = first;
|
||||
@@ -635,7 +635,7 @@ namespace spreadsort {
|
||||
++current) {
|
||||
//empties belong in this bin
|
||||
while (length(*current) > char_offset) {
|
||||
target_bin = end_bin - getchar((*current), char_offset);
|
||||
target_bin = end_bin - get_character((*current), char_offset);
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
}
|
||||
@@ -653,9 +653,9 @@ namespace spreadsort {
|
||||
for (RandomAccessIter current = *local_bin; current < next_bin_start;
|
||||
++current) {
|
||||
//Swapping into place until the correct element has been swapped in
|
||||
for (target_bin = end_bin - getchar((*current), char_offset);
|
||||
for (target_bin = end_bin - get_character((*current), char_offset);
|
||||
target_bin != local_bin;
|
||||
target_bin = end_bin - getchar((*current), char_offset))
|
||||
target_bin = end_bin - get_character((*current), char_offset))
|
||||
iter_swap(current, (*target_bin)++);
|
||||
}
|
||||
*local_bin = next_bin_start;
|
||||
@@ -670,14 +670,14 @@ namespace spreadsort {
|
||||
//don't sort unless there are at least two items to Compare
|
||||
if (count < 2)
|
||||
continue;
|
||||
//using std::sort if its worst-case is better
|
||||
//using boost::sort::pdqsort if its worst-case is better
|
||||
if (count < max_size)
|
||||
std::sort(lastPos, bin_cache[u], comp);
|
||||
boost::sort::pdqsort(lastPos, bin_cache[u], comp);
|
||||
else
|
||||
reverse_string_sort_rec<RandomAccessIter, Unsigned_char_type,
|
||||
Get_char, Get_length, Compare>
|
||||
(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end,
|
||||
bin_sizes, getchar, length, comp);
|
||||
bin_sizes, get_character, length, comp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,9 +700,9 @@ namespace spreadsort {
|
||||
string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Unsigned_char_type)
|
||||
{
|
||||
//Warning that we're using std::sort, even though string_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though string_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Unsigned_char_type) <= 2 );
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
|
||||
//Holds the bin vector and makes the initial recursive call
|
||||
@@ -726,9 +726,9 @@ namespace spreadsort {
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type
|
||||
Data_type;
|
||||
//Warning that we're using std::sort, even though string_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though string_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Unsigned_char_type) <= 2 );
|
||||
std::sort(first, last, std::greater<Data_type>());
|
||||
boost::sort::pdqsort(first, last, std::greater<Data_type>());
|
||||
}
|
||||
|
||||
//Holds the bin vector and makes the initial recursive call
|
||||
@@ -737,12 +737,12 @@ namespace spreadsort {
|
||||
inline typename boost::enable_if_c< sizeof(Unsigned_char_type) <= 2, void
|
||||
>::type
|
||||
string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Unsigned_char_type)
|
||||
{
|
||||
size_t bin_sizes[(1 << (8 * sizeof(Unsigned_char_type))) + 1];
|
||||
std::vector<RandomAccessIter> bin_cache;
|
||||
string_sort_rec<RandomAccessIter, Unsigned_char_type, Get_char,
|
||||
Get_length>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length);
|
||||
Get_length>(first, last, 0, bin_cache, 0, bin_sizes, get_character, length);
|
||||
}
|
||||
|
||||
template <class RandomAccessIter, class Get_char, class Get_length,
|
||||
@@ -750,11 +750,11 @@ namespace spreadsort {
|
||||
inline typename boost::disable_if_c< sizeof(Unsigned_char_type) <= 2, void
|
||||
>::type
|
||||
string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Unsigned_char_type)
|
||||
{
|
||||
//Warning that we're using std::sort, even though string_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though string_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Unsigned_char_type) <= 2 );
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
}
|
||||
|
||||
//Holds the bin vector and makes the initial recursive call
|
||||
@@ -763,13 +763,13 @@ namespace spreadsort {
|
||||
inline typename boost::enable_if_c< sizeof(Unsigned_char_type) <= 2, void
|
||||
>::type
|
||||
string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Compare comp, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Compare comp, Unsigned_char_type)
|
||||
{
|
||||
size_t bin_sizes[(1 << (8 * sizeof(Unsigned_char_type))) + 1];
|
||||
std::vector<RandomAccessIter> bin_cache;
|
||||
string_sort_rec<RandomAccessIter, Unsigned_char_type, Get_char
|
||||
, Get_length, Compare>
|
||||
(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
|
||||
(first, last, 0, bin_cache, 0, bin_sizes, get_character, length, comp);
|
||||
}
|
||||
|
||||
//disable_if_c was refusing to compile, so rewrote to use enable_if_c
|
||||
@@ -778,11 +778,11 @@ namespace spreadsort {
|
||||
inline typename boost::enable_if_c< (sizeof(Unsigned_char_type) > 2), void
|
||||
>::type
|
||||
string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Compare comp, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Compare comp, Unsigned_char_type)
|
||||
{
|
||||
//Warning that we're using std::sort, even though string_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though string_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Unsigned_char_type) <= 2 );
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
}
|
||||
|
||||
//Holds the bin vector and makes the initial recursive call
|
||||
@@ -791,13 +791,13 @@ namespace spreadsort {
|
||||
inline typename boost::enable_if_c< sizeof(Unsigned_char_type) <= 2, void
|
||||
>::type
|
||||
reverse_string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Compare comp, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Compare comp, Unsigned_char_type)
|
||||
{
|
||||
size_t bin_sizes[(1 << (8 * sizeof(Unsigned_char_type))) + 1];
|
||||
std::vector<RandomAccessIter> bin_cache;
|
||||
reverse_string_sort_rec<RandomAccessIter, Unsigned_char_type, Get_char,
|
||||
Get_length, Compare>
|
||||
(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
|
||||
(first, last, 0, bin_cache, 0, bin_sizes, get_character, length, comp);
|
||||
}
|
||||
|
||||
template <class RandomAccessIter, class Get_char, class Get_length,
|
||||
@@ -805,11 +805,11 @@ namespace spreadsort {
|
||||
inline typename boost::disable_if_c< sizeof(Unsigned_char_type) <= 2, void
|
||||
>::type
|
||||
reverse_string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Compare comp, Unsigned_char_type)
|
||||
Get_char get_character, Get_length length, Compare comp, Unsigned_char_type)
|
||||
{
|
||||
//Warning that we're using std::sort, even though string_sort was called
|
||||
//Warning that we're using boost::sort::pdqsort, even though string_sort was called
|
||||
BOOST_STATIC_WARNING( sizeof(Unsigned_char_type) <= 2 );
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ Scott McMurray
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/sort/spreadsort/detail/constants.hpp>
|
||||
#include <boost/sort/spreadsort/detail/float_sort.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace sort {
|
||||
@@ -85,11 +87,23 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
inline void float_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else
|
||||
detail::float_sort(first, last);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Floating-point sort algorithm using range.
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
|
||||
*/
|
||||
template <class Range>
|
||||
inline void float_sort(Range& range)
|
||||
{
|
||||
float_sort(boost::begin(range), boost::end(range));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Floating-point sort algorithm using random access iterators with just right-shift functor.
|
||||
|
||||
@@ -103,11 +117,24 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
Right_shift rshift)
|
||||
{
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else
|
||||
detail::float_sort(first, last, rshift(*first, 0), rshift);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Floating-point sort algorithm using range with just right-shift functor.
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
|
||||
|
||||
*/
|
||||
template <class Range, class Right_shift>
|
||||
inline void float_sort(Range& range, Right_shift rshift)
|
||||
{
|
||||
float_sort(boost::begin(range), boost::end(range), rshift);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Float sort algorithm using random access iterators with both right-shift and user-defined comparison operator.
|
||||
@@ -123,10 +150,25 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
Right_shift rshift, Compare comp)
|
||||
{
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
else
|
||||
detail::float_sort(first, last, rshift(*first, 0), rshift, comp);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Float sort algorithm using range with both right-shift and user-defined comparison operator.
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] rshift Functor that returns the result of shifting the value_type right a specified number of bits.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
*/
|
||||
|
||||
template <class Range, class Right_shift, class Compare>
|
||||
inline void float_sort(Range& range, Right_shift rshift, Compare comp)
|
||||
{
|
||||
float_sort(boost::begin(range), boost::end(range), rshift, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ Doxygen comments by Paul A. Bristow Jan 2015
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/sort/spreadsort/detail/constants.hpp>
|
||||
#include <boost/sort/spreadsort/detail/integer_sort.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace sort {
|
||||
@@ -32,7 +34,7 @@ namespace spreadsort {
|
||||
|
||||
|
||||
/*! \brief Integer sort algorithm using random access iterators.
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
@@ -75,13 +77,53 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
{
|
||||
// Don't sort if it's too small to optimize.
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else
|
||||
detail::integer_sort(first, last, *first >> 0);
|
||||
}
|
||||
|
||||
/*! \brief Integer sort algorithm using range.
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors, or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range>
|
||||
inline void integer_sort(Range& range)
|
||||
{
|
||||
integer_sort(boost::begin(range), boost::end(range));
|
||||
}
|
||||
|
||||
/*! \brief Integer sort algorithm using random access iterators with both right-shift and user-defined comparison operator.
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
@@ -124,13 +166,57 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Right_shift shift, Compare comp) {
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
else
|
||||
detail::integer_sort(first, last, shift(*first, 0), shift, comp);
|
||||
}
|
||||
|
||||
/*! \brief Integer sort algorithm using range with both right-shift and user-defined comparison operator.
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] shift Functor that returns the result of shifting the value_type right a specified number of bits.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
*/
|
||||
template <class Range, class Right_shift, class Compare>
|
||||
inline void integer_sort(Range& range, Right_shift shift, Compare comp)
|
||||
{
|
||||
integer_sort(boost::begin(range), boost::end(range), shift, comp);
|
||||
}
|
||||
|
||||
/*! \brief Integer sort algorithm using random access iterators with just right-shift functor.
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
@@ -173,10 +259,54 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Right_shift shift) {
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else
|
||||
detail::integer_sort(first, last, shift(*first, 0), shift);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Integer sort algorithm using range with just right-shift functor.
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
|
||||
\par Performance:
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
* <a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>\n
|
||||
* <a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] shift A functor that returns the result of shifting the value_type right a specified number of bits.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range, class Right_shift>
|
||||
inline void integer_sort(Range& range, Right_shift shift)
|
||||
{
|
||||
integer_sort(boost::begin(range), boost::end(range), shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ Some improvements suggested by:
|
||||
Phil Endecott and Frank Gennari
|
||||
float_mem_cast fix provided by:
|
||||
Scott McMurray
|
||||
Range support provided by:
|
||||
Alexander Zaitsev
|
||||
*/
|
||||
|
||||
#ifndef BOOST_SORT_SPREADSORT_HPP
|
||||
@@ -25,6 +27,8 @@ Scott McMurray
|
||||
#include <boost/sort/spreadsort/integer_sort.hpp>
|
||||
#include <boost/sort/spreadsort/float_sort.hpp>
|
||||
#include <boost/sort/spreadsort/string_sort.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace sort {
|
||||
@@ -139,6 +143,25 @@ namespace spreadsort {
|
||||
boost::uint16_t unused = 0;
|
||||
string_sort(first, last, unused);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Generic @c spreadsort variant detects value_type and calls required sort function.
|
||||
\note Sorting other data types requires picking between @c integer_sort, @c float_sort and @c string_sort directly,
|
||||
as @c spreadsort won't accept types that don't have the appropriate @c type_traits.
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
*/
|
||||
|
||||
template <class Range>
|
||||
void spreadsort(Range& range)
|
||||
{
|
||||
spreadsort(boost::begin(range), boost::end(range));
|
||||
}
|
||||
|
||||
|
||||
} // namespace spreadsort
|
||||
} // namespace sort
|
||||
} // namespace boost
|
||||
|
||||
@@ -21,22 +21,22 @@ Phil Endecott and Frank Gennari
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/sort/spreadsort/detail/constants.hpp>
|
||||
#include <boost/sort/spreadsort/detail/string_sort.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace sort {
|
||||
namespace spreadsort {
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, allowing character-type overloads.\n
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
@@ -76,22 +76,61 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
{
|
||||
//Don't sort if it's too small to optimize
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else
|
||||
detail::string_sort(first, last, unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, allowing character-type overloads.\n
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\tparam Unsigned_char_type Unsigned character type used for string.
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] unused value with the same type as the result of the [] operator, defining the Unsigned_char_type. The actual value is unused.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
|
||||
template <class Range, class Unsigned_char_type>
|
||||
inline void string_sort(Range& range, Unsigned_char_type unused)
|
||||
{
|
||||
string_sort(boost::begin(range), boost::end(range), unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, wraps using default of unsigned char.
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>
|
||||
\n
|
||||
@@ -129,22 +168,58 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
string_sort(first, last, unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, wraps using default of unsigned char.
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range>
|
||||
inline void string_sort(Range& range)
|
||||
{
|
||||
string_sort(boost::begin(range), boost::end(range));
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, allowing character-type overloads.
|
||||
|
||||
(All variants fall back to @c std::sort if the data size is too small, < detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
|
||||
\tparam RandomAccessIter <a href="http://www.cplusplus.com/reference/iterator/RandomAccessIterator/">Random access iterator</a>
|
||||
@@ -185,28 +260,72 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
{
|
||||
//Don't sort if it's too small to optimize.
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
else
|
||||
detail::reverse_string_sort(first, last, unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, allowing character-type overloads.
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, wraps using default of @c unsigned char.
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < detail::min_sort_size).
|
||||
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
|
||||
|
||||
\tparam Comp Functor type to use for comparison.
|
||||
\tparam Unsigned_char_type Unsigned character type used for string.
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
\param[in] unused value with the same type as the result of the [] operator, defining the Unsigned_char_type. The actual value is unused.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
*/
|
||||
template <class Range, class Compare, class Unsigned_char_type>
|
||||
inline void reverse_string_sort(Range& range, Compare comp, Unsigned_char_type unused)
|
||||
{
|
||||
reverse_string_sort(boost::begin(range), boost::end(range), comp, unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms.\n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\param[in] first Iterator pointer to first element.
|
||||
\param[in] last Iterator pointing to one beyond the end of data.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
@@ -242,26 +361,65 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
reverse_string_sort(first, last, comp, unused);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
*/
|
||||
template <class Range, class Compare>
|
||||
inline void reverse_string_sort(Range& range, Compare comp)
|
||||
{
|
||||
reverse_string_sort(boost::begin(range), boost::end(range), comp);
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\param[in] first Iterator pointer to first element.
|
||||
\param[in] last Iterator pointing to one beyond the end of data.
|
||||
\param[in] getchar Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
@@ -290,11 +448,11 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
*/
|
||||
template <class RandomAccessIter, class Get_char, class Get_length>
|
||||
inline void string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length)
|
||||
Get_char get_character, Get_length length)
|
||||
{
|
||||
//Don't sort if it's too small to optimize
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last);
|
||||
boost::sort::pdqsort(first, last);
|
||||
else {
|
||||
//skipping past empties, which allows us to get the character type
|
||||
//.empty() is not used so as not to require a user declaration of it
|
||||
@@ -302,32 +460,73 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
if (++first == last)
|
||||
return;
|
||||
}
|
||||
detail::string_sort(first, last, getchar, length, getchar((*first), 0));
|
||||
detail::string_sort(first, last, get_character, length, get_character((*first), 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range, class Get_char, class Get_length>
|
||||
inline void string_sort(Range& range, Get_char get_character, Get_length length)
|
||||
{
|
||||
string_sort(boost::begin(range), boost::end(range), get_character, length);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief String sort algorithm using random access iterators, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
|
||||
\param[in] first Iterator pointer to first element.
|
||||
\param[in] last Iterator pointing to one beyond the end of data.
|
||||
\param[in] getchar Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
@@ -357,11 +556,11 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
template <class RandomAccessIter, class Get_char, class Get_length,
|
||||
class Compare>
|
||||
inline void string_sort(RandomAccessIter first, RandomAccessIter last,
|
||||
Get_char getchar, Get_length length, Compare comp)
|
||||
Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
//Don't sort if it's too small to optimize
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
else {
|
||||
//skipping past empties, which allows us to get the character type
|
||||
//.empty() is not used so as not to require a user declaration of it
|
||||
@@ -369,32 +568,77 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
if (++first == last)
|
||||
return;
|
||||
}
|
||||
detail::string_sort(first, last, getchar, length, comp,
|
||||
getchar((*first), 0));
|
||||
detail::string_sort(first, last, get_character, length, comp,
|
||||
get_character((*first), 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief String sort algorithm using range, wraps using default of @c unsigned char.
|
||||
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range, class Get_char, class Get_length, class Compare>
|
||||
inline void string_sort(Range& range,
|
||||
Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
string_sort(boost::begin(range), boost::end(range), get_character, length, comp);
|
||||
}
|
||||
|
||||
/*! \brief Reverse String sort algorithm using random access iterators.
|
||||
|
||||
(All variants fall back to @c std::sort if the data size is too small, < @c detail::min_sort_size).
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c integer_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c integer_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. @c s is @c max_splits, which defaults to 11,
|
||||
so its worst-case with default settings for 32-bit integers is
|
||||
<em> O(N * ((32/11) </em> slow radix-based iterations fast comparison-based iterations).\n\n
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_integer_sort.htm"> windows_integer_sort</a>
|
||||
\n
|
||||
<a href="../../doc/graph/osx_integer_sort.htm"> osx_integer_sort</a>
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
|
||||
\param[in] first Iterator pointer to first element.
|
||||
\param[in] last Iterator pointing to one beyond the end of data.
|
||||
\param[in] getchar Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
@@ -424,11 +668,11 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
template <class RandomAccessIter, class Get_char, class Get_length,
|
||||
class Compare>
|
||||
inline void reverse_string_sort(RandomAccessIter first,
|
||||
RandomAccessIter last, Get_char getchar, Get_length length, Compare comp)
|
||||
RandomAccessIter last, Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
//Don't sort if it's too small to optimize
|
||||
if (last - first < detail::min_sort_size)
|
||||
std::sort(first, last, comp);
|
||||
boost::sort::pdqsort(first, last, comp);
|
||||
else {
|
||||
//skipping past empties, which allows us to get the character type
|
||||
//.empty() is not used so as not to require a user declaration of it
|
||||
@@ -438,10 +682,58 @@ Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
return;
|
||||
}
|
||||
//making last just after the end of the non-empty part of the array
|
||||
detail::reverse_string_sort(first, last + 1, getchar, length, comp,
|
||||
getchar((*last), 0));
|
||||
detail::reverse_string_sort(first, last + 1, get_character, length, comp,
|
||||
get_character((*last), 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Reverse String sort algorithm using range.
|
||||
|
||||
(All variants fall back to @c boost::sort::pdqsort if the data size is too small, < @c detail::min_sort_size).
|
||||
|
||||
\details @c string_sort is a fast templated in-place hybrid radix/comparison algorithm,
|
||||
which in testing tends to be roughly 50% to 2X faster than @c std::sort for large tests (>=100kB).\n
|
||||
\par
|
||||
Worst-case performance is <em> O(N * (lg(range)/s + s)) </em>,
|
||||
so @c string_sort is asymptotically faster
|
||||
than pure comparison-based algorithms. \n\n
|
||||
Some performance plots of runtime vs. n and log(range) are provided:\n
|
||||
<a href="../../doc/graph/windows_string_sort.htm"> windows_string_sort</a>\n
|
||||
<a href="../../doc/graph/osx_string_sort.htm"> osx_string_sort</a>
|
||||
|
||||
|
||||
\param[in] range Range [first, last) for sorting.
|
||||
\param[in] get_character Bracket functor equivalent to @c operator[], taking a number corresponding to the character offset.
|
||||
\param[in] length Functor to get the length of the string in characters.
|
||||
\param[in] comp A binary functor that returns whether the first element passed to it should go before the second in order.
|
||||
|
||||
|
||||
\pre [@c first, @c last) is a valid range.
|
||||
\post The elements in the range [@c first, @c last) are sorted in ascending order.
|
||||
|
||||
\return @c void.
|
||||
|
||||
\throws std::exception Propagates exceptions if any of the element comparisons, the element swaps (or moves),
|
||||
the right shift, subtraction of right-shifted elements, functors,
|
||||
or any operations on iterators throw.
|
||||
|
||||
\warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
|
||||
\warning Invalid arguments cause undefined behaviour.
|
||||
\note @c spreadsort function provides a wrapper that calls the fastest sorting algorithm available for a data type,
|
||||
enabling faster generic-programming.
|
||||
|
||||
\remark The lesser of <em> O(N*log(N)) </em> comparisons and <em> O(N*log(K/S + S)) </em>operations worst-case, where:
|
||||
\remark * N is @c last - @c first,
|
||||
\remark * K is the log of the range in bits (32 for 32-bit integers using their full range),
|
||||
\remark * S is a constant called max_splits, defaulting to 11 (except for strings where it is the log of the character size).
|
||||
|
||||
*/
|
||||
template <class Range, class Get_char, class Get_length,
|
||||
class Compare>
|
||||
inline void reverse_string_sort(Range& range, Get_char get_character, Get_length length, Compare comp)
|
||||
{
|
||||
reverse_string_sort(boost::begin(range), boost::end(range), get_character, length, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user