update boost on linux

This commit is contained in:
Bassem Girgis
2019-08-10 16:06:25 -05:00
parent 76ad52be58
commit 861b918727
5363 changed files with 483306 additions and 116507 deletions

View File

@@ -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 };

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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

View File

@@ -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);
}
}
}
}