|
Boost : |
From: David Walthall (walthall_at_[hidden])
Date: 2007-03-21 12:20:05
Sam Schetterer wrote:
> Hi. I am just wondering if there is still interest in the library, because
> I have not recieved any comments on the library in the last two days, no
> posts at all, while I have made multiple posts, some with very important
> ideas in them.
Hi Sam,
I downloaded your library to do some testing. The first issue I ran
into was that MSVC 7.1 complained about some of the specializations:
template<>
void insertion<char*>(typename std::deque<char*>::iterator& a, int l, int r)
and
template<>
void r_insertion<char*>(typename std::deque<char*>::iterator& a, int l,
int r)
(This may be a vc 7.1 bug, I'm not sure.)
The second issue is that in rquicksort.hpp (and possibly other places),
a lot of the functions have parameters named 'strfnc', but the functions
use parameters named 'strfunc'.
The final issue is that create_id_string has some bugs. (It only works
if %s is the first control sequence it encounters, so format strings
like "%e" will crash.)
After fixing those issues, I found that the radix_qsort and radix_sort
are slower than standard sort. Maybe this is a result of when I
commented out the specializations of insertion and r_insertion?
I've attached the changes I made to the sorting stuff to get it to
compile and run on MSVC 7.1. I've also included the code that I used to
get the timings. (I know that timings are difficult to get, and I
welcome any comments/criticisms. Perhaps my results are bad because I
ended up sorting an already sorted array. However, all of the sorts
were fast enough that I had to do this to a non-zero number.)
Here are my results:
radix_sort: people = 0.94s, radixtest = 0.12s
radix_qsort: people = 0.69s, radixtest = 2.4s
std::sort: people = 0.037s, radixtest = 0.015s
Specs: Windows XP Professional x64 SP2, Visual C++ 7.1, Intel Xeon dual
core @ 2.66GHz, 2.0 GB RAM.
Do you have anything that shows that your code beats std::sort?
David
//include file for radix quicksort
#ifndef BOOST_RQUICKSORT_HPP
#define BOOST_RQUICKSORT_HPP
#include <cstring>
#include <cstdlib>
#include "detail/insertion.hpp"
#include <stdarg.h>
namespace boost
{
namespace detail
{
template<class T>
inline unsigned char qdigit(const T& a, int d)
{
return a.idstring_qs[d];
}
typedef char* cptr;
template<>
inline unsigned char qdigit<cptr>(const cptr& a, int d)
{
return a[d];
}
template<class T>
void rquicksort(T* ar, int l, int r, int bit)
{
if((r - l) <= 16) { insertion(ar, l, r); return;}
register T* a = ar;
register int i = l - 1, j = r, d = bit, v = qdigit(a[j], d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(qdigit(a[++i], d) < v) ;
while(v < qdigit(a[--j], d)) if(j == l) break;
if(i > j) break;
std::swap(a[i], a[j]);
if(qdigit(a[i], d) == v) {++p; std::swap(a[p], a[i]);}
if(qdigit(a[j], d) == v) {--q; std::swap(a[q], a[j]);}
}
if(p == q)
{
if(v != '\0') rquicksort(a, l, r, d + 1);
return;
}
if(qdigit(a[i], d) < v) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(a[k], a[j]);
for(k = r; k >= q; i++, k--) std::swap(a[k], a[i]);
rquicksort(a, l, j, d);
if((i == r) && (qdigit(a[i], d) == v)) ++i;
if(v != '\0') rquicksort(a, j + 1, i - 1, d + 1);
rquicksort(a, i, r, d);
}
template<class T>
void rrquicksort(T* ar, int l, int r, int bit)
{
if((r - l) <= 16) { r_insertion(ar, l, r); return;}
register T* a = ar;
register int i = l - 1, j = r, d = bit, v = qdigit(a[j], d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(v < qdigit(a[++i], d)) ;
while(qdigit(a[--j], d) < v) if(j == l) break;
if(i > j) break;
std::swap(a[i], a[j]);
if(qdigit(a[i], d) == v) {++p; std::swap(a[p], a[i]);}
if(qdigit(a[j], d) == v) {--q; std::swap(a[q], a[j]);}
}
if(p == q)
{
if(v != '\0') rrquicksort(a, l, r, d + 1);
return;
}
if(v < qdigit(a[i], d)) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(a[k], a[j]);
for(k = r; k >= q; i++, k--) std::swap(a[k], a[i]);
rrquicksort(a, l, j, d);
if((i == r) && (qdigit(a[i], d) == v)) ++i;
if(v != '\0') rrquicksort(a, j + 1, i - 1, d + 1);
rrquicksort(a, i, r, d);
}
}
template<class T>
inline void radix_qsort(T* data, int size) //normal
{
detail::rquicksort(data, 0, size, 0);
}
template<class T>
inline void r_radix_qsort(T* data, int size) //reverse
{
detail::rrquicksort(data, 0, size, 0);
}
/////////////////////////user-defined functions
namespace detail
{
template<class T>
void rquicksort(T* ar, int l, int r, int bit, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&))
{
if((r - l) <= 16) { insertion(ar, l, r, ltfunc); return;}
register T* a = ar;
register int i = l - 1, j = r, d = bit, v = strfunc(a[j], d);
int p = i, q = j;
while(i < j)
{
while(strfunc(a[++i], d) < v) ;
while(v < strfunc(a[--j], d)) if(j == l) break;
if(i > j) break;
std::swap(a[i], a[j]);
if(strfunc(a[i], d) == v) {++p; std::swap(a[p], a[i]);}
if(strfunc(a[j], d) == v) {--q; std::swap(a[q], a[j]);}
}
if(p == q)
{
if(v != '\0') rquicksort(a, l, r, d + 1);
return;
}
if(strfunc(a[i], d) < v) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(a[k], a[j]);
for(k = r; k >= q; i++, k--) std::swap(a[k], a[i]);
rquicksort(a, l, j, d);
if((i == r) && (strfunc(a[i], d) == v)) ++i;
if(v != '\0') rquicksort(a, j + 1, i - 1, d + 1);
rquicksort(a, i, r, d);
}
template<class T>
void rrquicksort(T* ar, int l, int r, int bit, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&))
{
if((r - l) <= 16) { r_insertion(ar, l, r, ltfunc); return;}
register T* a = ar;
register int i = l - 1, j = r, d = bit, v = strfunc(a[j], d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(v < strfunc(a[++i], d)) ;
while(strfunc(a[--j], d) < v) if(j == l) break;
if(i > j) break;
std::swap(a[i], a[j]);
if(strfunc(a[i], d) == v) {++p; std::swap(a[p], a[i]);}
if(strfunc(a[j], d) == v) {--q; std::swap(a[q], a[j]);}
}
if(p == q)
{
if(v != '\0') rrquicksort(a, l, r, d + 1);
return;
}
if(v < strfunc(a[i], d)) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(a[k], a[j]);
for(k = r; k >= q; i++, k--) std::swap(a[k], a[i]);
rrquicksort(a, l, j, d);
if((i == r) && (strfunc(a[i], d) == v)) ++i;
if(v != '\0') rrquicksort(a, j + 1, i - 1, d + 1);
rrquicksort(a, i, r, d);
}
}
template<class T>
inline void radix_qsort(T* data, int size, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&)) //normal
{
detail::rquicksort(data, 0, size, 0, strfunc, ltfunc);
}
template<class T>
inline void r_radix_qsort(T* data, int size, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&)) //reverse
{
detail::rrquicksort(data, 0, size, 0, strfunc, ltfunc);
}
//////////////////////////////////////////////////////////////////////////variable bytes
template<class T>
inline void radix_qsort(T* a, int size, int startbyte)
{
detail::rquicksort(a, 0, size, startbyte);
}
template<class T>
inline void radix_qsort(T* a, int start, int size, int startbyte)
{
detail::rquicksort(a, start, size, startbyte);
}
template<class T>
inline void radix_qsort(T* a, int size, int startbyte, unsigned char(*strfunc)(const T&, int d), bool(*ltfunc)(const T&, const T&))
{
detail::rquicksort(a, 0, size, startbyte, strfunc, ltfunc);
}
template<class T>
inline void radix_qsort(T* a, int start, int size, int startbyte, unsigned char(*strfunc)(const T&, int d), bool(*ltfunc)(const T&, const T&))
{
detail::rquicksort(a, start, size, startbyte, strfunc, ltfunc);
}
////////////////////////////////////////////////////////////stl iterator
namespace detail
{
template<class T>
void rquicksort(typename std::deque<T>::iterator& a, int l, int r, int bit)
{
if((r - l) <= 16) { insertion<T>(a, l, r); return;}
register int i = l - 1, j = r, d = bit, v = qdigit(*(a + j), d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(qdigit(*(a + ++i), d) < v) ;
while(v < qdigit(*(a + --j), d)) if(j == l) break;
if(i > j) break;
std::swap(*(a + i), *(a + j));
if(qdigit(*(a + i), d) == v) {++p; std::swap(*(a + p), *(a + i));}
if(qdigit(*(a + j), d) == v) {--q; std::swap(*(a + q), *(a + j));}
}
if(p == q)
{
if(v != '\0') rquicksort<T>(a, l, r, d + 1);
return;
}
if(qdigit(*(a + i), d) < v) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(*(a + k), *(a + j));
for(k = r; k >= q; i++, k--) std::swap(*(a + k), *(a + i));
rquicksort<T>(a, l, j, d);
if((i == r) && (qdigit(*(a + i), d) == v)) ++i;
if(v != '\0') rquicksort<T>(a, j + 1, i - 1, d + 1);
rquicksort<T>(a, i, r, d);
}
template<class T>
void rrquicksort(typename std::deque<T>::iterator& a, int l, int r, int bit)
{
if((r - l) <= 16) { r_insertion<T>(a, l, r); return;}
register int i = l - 1, j = r, d = bit, v = qdigit(*(a + j), d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(v < qdigit(*(a + ++i), d)) ;
while(qdigit(*(a + --j), d) < v) if(j == l) break;
if(i > j) break;
std::swap(*(a + i), *(a + j));
if(qdigit(*(a + i), d) == v) {++p; std::swap(*(a + p), *(a + i));}
if(qdigit(*(a + j), d) == v) {--q; std::swap(*(a + q), *(a + j));}
}
if(p == q)
{
if(v != '\0') rrquicksort<T>(a, l, r, d + 1);
return;
}
if(v < qdigit(*(a + i), d)) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(*(a + k), *(a + j));
for(k = r; k >= q; i++, k--) std::swap(*(a + k), *(a + i));
rrquicksort<T>(a, l, j, d);
if((i == r) && (qdigit(*(a + i), d) == v)) ++i;
if(v != '\0') rrquicksort<T>(a, j + 1, i - 1, d + 1);
rrquicksort<T>(a, i, r, d);
}
}
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& data, int size) //normal
{
detail::rquicksort<T>(data, 0, size, 0);
}
template<class T>
inline void r_radix_qsort(typename std::deque<T>::iterator& data, int size) //reverse
{
detail::rrquicksort<T>(data, 0, size, 0);
}
/////////////////////////user-defined functions
namespace detail
{
template<class T>
void rquicksort(typename std::deque<T>::iterator& a, int l, int r, int bit, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&))
{
if((r - l) <= 16) { insertion<T>(a, l, r, ltfunc); return;}
register int i = l - 1, j = r, d = bit, v = strfunc(*(a + j), d);
int p = i, q = j;
while(i < j)
{
while(strfunc(*(a + ++i), d) < v) ;
while(v < strfunc(*(a + --j), d)) if(j == l) break;
if(i > j) break;
std::swap(*(a + i), *(a + j));
if(strfunc(*(a + i), d) == v) {++p; std::swap(*(a + p), *(a + i));}
if(strfunc(*(a + j), d) == v) {--q; std::swap(*(a + q), *(a + j));}
}
if(p == q)
{
if(v != '\0') rquicksort<T>(a, l, r, d + 1);
return;
}
if(strfunc(*(a + i), d) < v) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(*(a + k), *(a + j));
for(k = r; k >= q; i++, k--) std::swap(*(a + k), *(a + i));
rquicksort<T>(a, l, j, d);
if((i == r) && (strfunc(*(a + i), d) == v)) ++i;
if(v != '\0') rquicksort<T>(a, j + 1, i - 1, d + 1);
rquicksort<T>(a, i, r, d);
}
template<class T>
void rrquicksort(typename std::deque<T>::iterator& a, int l, int r, int bit, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&))
{
if((r - l) <= 16) { r_insertion<T>(a, l, r, ltfunc); return;}
register int i = l - 1, j = r, d = bit, v = strfunc(*(a + j), d);//speed increase with registers
int p = i, q = j;
while(i < j)
{
while(v < strfunc(*(a + ++i), d)) ;
while(strfunc(*(a + --j), d) < v) if(j == l) break;
if(i > j) break;
std::swap(*(a + i), *(a + j));
if(strfunc(*(a + i), d) == v) {++p; std::swap(*(a + p), *(a + i));}
if(strfunc(*(a + j), d) == v) {--q; std::swap(*(a + q), *(a + j));}
}
if(p == q)
{
if(v != '\0') rrquicksort<T>(a, l, r, d + 1);
return;
}
if(v < strfunc(*(a + i), d)) ++i;
int k = l;
for( ; k <= p; j--, k++) std::swap(*(a + k), *(a + j));
for(k = r; k >= q; i++, k--) std::swap(*(a + k), *(a + i));
rrquicksort<T>(a, l, j, d);
if((i == r) && (strfunc(*(a + i), d) == v)) ++i;
if(v != '\0') rrquicksort<T>(a, j + 1, i - 1, d + 1);
rrquicksort<T>(a, i, r, d);
}
}
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& data, int size, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&)) //normal
{
detail::rquicksort<T>(data, 0, size, 0, strfunc, ltfunc);
}
template<class T>
inline void r_radix_qsort(typename std::deque<T>::iterator& data, int size, unsigned char (*strfunc)(const T&, int), bool(*ltfunc)(const T&, const T&)) //reverse
{
detail::rrquicksort<T>(data, 0, size, 0, strfunc, ltfunc);
}
//////////////////////////////////////////////////////////////////////////variable bytes
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& a, int size, int startbyte)
{
detail::rquicksort<T>(a, 0, size, startbyte);
}
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& a, int start, int size, int startbyte)
{
detail::rquicksort<T>(a, start, size, startbyte);
}
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& a, int size, int startbyte, unsigned char(*strfunc)(const T&, int d), bool(*ltfunc)(const T&, const T&))
{
detail::rquicksort<T>(a, 0, size, startbyte, strfunc, ltfunc);
}
template<class T>
inline void radix_qsort(typename std::deque<T>::iterator& a, int start, int size, int startbyte, unsigned char(*strfunc)(const T&, int d), bool(*ltfunc)(const T&, const T&))
{
detail::rquicksort<T>(a, start, size, startbyte, strfunc, ltfunc);
}
std::size_t create_id_string(const char* fmt, char* dest, ...)
{
va_list ap;
const char* p;
std::size_t n = 0;
va_start(ap, dest);
for(p = fmt; *p; p++)
{
if(*p != '%')
{
dest[n++] = *p;
continue;
}
switch(*++p)
{
case 'd': case 'D': case 'i': case 'I':
{
int itemp = va_arg(ap, int);
_ui64toa(itemp, (char*)(dest+n), 16);
n += strlen(dest+n);
break;
}
case 's': case 'S':
{
const char *ctemp = va_arg(ap, const char*);
strcpy(dest+n, ctemp);
n += strlen(dest+n);
break;
}
case 'e': case 'E': case 'g': case 'G':
{
double dtemp = va_arg(ap, double);
long long dval = *((long long*)&dtemp);
_ui64toa(dval, (char*)(dest+n), 16);
n += strlen(dest+n);
break;
}
default:
{
dest[n++] = *p;
break;
}
}
}
dest[n++] = '\0';
va_end(ap);
return n + 1; //1 compenstates for zero index array
}
}
#endif
#ifndef BOOST_DETAIL_INSERTION_HPP
#define BOOST_DETAIL_INSERTION_HPP
#include <algorithm>
#include <cstring>
#include <deque>
namespace boost
{
namespace detail
{
template<class T>
void insertion(T* ar, int l, int r)
{
register T* a = ar;
register int i;
for(i = r; i > l; i--) if(a[i] < a[i - 1]) std::swap<T>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = a[i];
while(v < a[j - 1])
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
template<>
void insertion<char*>(char** ar, int l, int r)
{
register char** a = ar;
register int i;
for(i = r; i > l; i--) if(strcmp(a[i], a[i - 1]) & 0x80000000) std::swap<char*>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; register char* v = a[i];
while(strcmp(v, a[j - 1]) & 0x80000000)
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
template<class T>
void r_insertion(T* ar, int l, int r)
{
register T* a = ar;
register int i;
for(i = r; i > l; i--) if(a[i - 1] < a[i]) std::swap<T>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = a[i];
while(a[j - 1] < v)
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
template<>
void r_insertion<char*>(char** ar, int l, int r)
{
register char** a = ar;
register int i;
for(i = r; i > l; i--) if(strcmp(a[i - 1], a[i]) & 0x80000000) std::swap<char*>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; char* v = a[i];
while(strcmp(a[j - 1], v) & 0x80000000)
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
//////////////user-defined
template<class T>
void insertion(T* ar, int l, int r, bool(*ltfunc)(const T&, const T&))
{
register T* a = ar;
register int i;
for(i = r; i > l; i--) if(lt(a[i], a[i - 1])) std::swap<T>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = a[i];
while(lt(v, a[j - 1]))
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
template<class T>
void r_insertion(T* ar, int l, int r, bool(*ltfunc)(const T&, const T&))
{
register T* a = ar;
register int i;
for(i = r; i > l; i--) if(lt(a[i - 1], a[i])) std::swap<T>(a[i], a[i - 1]);
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = a[i];
while(lt(a[j - 1], v))
{
a[j] = a[j - 1];
--j;
}
a[j] = v;
}
}
///////////////////////////////////////////////////////////////////////standard library sorters
template<class T>
void insertion(typename std::deque<T>::iterator& a, int l, int r)
{
register int i;
for(i = r; i > l; i--) if(*(a + i) < *(a + i - 1)) std::swap<T>(*(a + i), *(a + i - 1));
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = *(a + i);
while(v < *(a + j - 1))
{
*(a + j) = *(a + j - 1);
--j;
}
*(a + j) = v;
}
}
//template<>
//void insertion<char*>(typename std::deque<char*>::iterator& a, int l, int r)
//{
// register int i;
// for(i = r; i > l; i--) if(strcmp(*(a + i), *(a + i - 1)) & 0x80000000) std::swap<char*>(*(a + i), *(a + i - 1));
// for(i = l + 2; i <= r; i++)
// {
// register int j = i; register char* v = *(a + i);
// while(strcmp(v, *(a + j - 1)) & 0x80000000)
// {
// *(a + j) = *(a + j - 1);
// --j;
// }
// *(a + j) = v;
// }
//}
template<class T>
void r_insertion(typename std::deque<T>::iterator& a, int l, int r)
{
register int i;
for(i = r; i > l; i--) if(*(a + i - 1) < *(a + i)) std::swap<T>(*(a + i), *(a + i - 1));
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = *(a + i);
while(*(a + j - 1) < v)
{
*(a + j) = *(a + j - 1);
--j;
}
*(a + j) = v;
}
}
//template<>
//void r_insertion<char*>(typename std::deque<char*>::iterator& a, int l, int r)
//{
// register int i;
// for(i = r; i > l; i--) if(strcmp(*(a + i - 1), *(a + i)) & 0x80000000) std::swap<char*>(*(a + i), *(a + i - 1));
// for(i = l + 2; i <= r; i++)
// {
// register int j = i; char* v = *(a + i);
// while(strcmp(*(a + j - 1), v) & 0x80000000)
// {
// *(a + j) = *(a + j - 1);
// --j;
// }
// *(a + j) = v;
// }
//}
//////////////user-defined
template<class T>
void insertion(typename std::deque<T>::iterator& a, int l, int r, bool(*ltfunc)(const T&, const T&))
{
register int i;
for(i = r; i > l; i--) if(lt(*(a + i), *(a + i - 1))) std::swap<T>(*(a + i), *(a + i - 1));
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = *(a + i);
while(lt(v, *(a + j - 1)))
{
*(a + j) = *(a + j - 1);
--j;
}
*(a + j) = v;
}
}
template<class T>
void r_insertion(typename std::deque<T>::iterator& a, int l, int r, bool(*ltfunc)(const T&, const T&))
{
register int i;
for(i = r; i > l; i--) if(lt(*(a + i - 1), *(a + i))) std::swap<T>(*(a + i), *(a + i - 1));
for(i = l + 2; i <= r; i++)
{
register int j = i; T v = *(a + i);
while(lt(*(a + j - 1), v))
{
*(a + j) = *(a + j - 1);
--j;
}
*(a + j) = v;
}
}
}
}
#endif
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#define STD_SORT 0
#define RADIX_Q_SORT 1
#define RADIX_SORT 2
// --------------------------------------
// TODO: Set SORT_TYPE to one of:
// STD_SORT, RADIX_Q_SORT, or RADIX_SORT
// --------------------------------------
#define SORT_TYPE RADIX_SORT
#if (SORT_TYPE == RADIX_Q_SORT)
#include <boost/sorting/rquicksort.hpp>
#elif (SORT_TYPE == RADIX_SORT)
#include <boost/sorting/radix.hpp>
#include <boost/sorting/rquicksort.hpp> // for create_id_string
#else // std::sort
#include <algorithm>
#endif
static double doublerand()
{
double a = static_cast<double>(rand());
double b = static_cast<double>(rand());
double c = static_cast<double>(rand());
return (a*b)/c;
}
static std::string stringrand()
{
std::string s;
for(int i=0 ; i<5 ; ++i)
{
s += static_cast<char>(rand() % 26) + 'a';
}
return s;
}
static int intrand() {return rand();}
struct person
{
std::string name;
int iNum;
double fNum;
int order;
#if ((SORT_TYPE == RADIX_Q_SORT) || (SORT_TYPE == RADIX_SORT))
static const int STR_SZ = 30;
char idstring_qs[STR_SZ];
#endif
person(){}
person(int iOrder, int inum, const std::string &n, double w)
{
order = iOrder;
iNum = inum;
name = n;
fNum = w;
#if ((SORT_TYPE == RADIX_Q_SORT) || (SORT_TYPE == RADIX_SORT))
//%s means string, %d means int, and %e means double
boost::create_id_string("%s%e%d", idstring_qs, name.c_str(), fNum, iNum);
#endif
}
#if (SORT_TYPE == RADIX_Q_SORT)
inline int operator<(const person& rhs) const
{
return strcmp(idstring_qs, rhs.idstring_qs) & 0x80000000;
}
#elif (SORT_TYPE == RADIX_SORT)
inline unsigned char operator[](int d) const
{
return idstring_qs[d];
}
#else // std::sort
inline bool operator<(const person& rhs)
{
if(name < rhs.name) return true;
if(rhs.name < name) return false;
if(fNum < rhs.fNum) return true;
if(rhs.fNum < fNum) return false;
return (iNum < rhs.iNum);
}
#endif
};
static void FillData(std::vector<double> &vec_d, std::vector<int> &vec_i,
std::vector<std::string> &vec_s, std::size_t desired_size)
{
vec_d.clear(); vec_d.reserve(desired_size);
vec_i.clear(); vec_i.reserve(desired_size);
vec_s.clear(); vec_s.reserve(desired_size);
for(std::size_t i=0 ; i<desired_size ; ++i)
{
vec_d.push_back(doublerand());
vec_i.push_back(intrand());
vec_s.push_back(stringrand());
}
}
// We want a large number of objects to sort, but we don't
// want it to crash if it can't find enough stack space.
static const std::size_t NUM_PEOPLE = 10000;
static void PrintPeople(const person people[NUM_PEOPLE])
{
for(int x = 0; x < NUM_PEOPLE; x++)
{
std::cout << people[x].name
<< " has floating point value " << people[x].fNum
<< " and is #" << people[x].iNum
<< " originally " << people[x].order
<< std::endl;
}
}
static int GetMin(int a, int b) {return (std::min)(a,b);}
static int GetMax(int a, int b, int c) {return (std::max)(a, (std::max)(b,c));}
static clock_t TestPeopleSorting(int num_loops)
{
static const int I_MOD = 5;
static const int S_MOD = 7;
static const int F_MOD = 3;
//// If I make all objects unique (with the code below), then the
//// sorts are closer, but std::sort still wins.
//static const int I_MOD = NUM_PEOPLE;
//static const int S_MOD = NUM_PEOPLE;
//static const int F_MOD = NUM_PEOPLE;
static const int DATA_MAX = GetMin(NUM_PEOPLE, GetMax(I_MOD, S_MOD, F_MOD));
std::vector<double> fnumbers;
std::vector<int> numbers;
std::vector<std::string> names;
FillData(fnumbers, numbers, names, DATA_MAX);
person people[NUM_PEOPLE];
for(int x = 0; x < NUM_PEOPLE; x++)
{
people[x] = person(x, numbers[x%I_MOD], names[x%S_MOD], fnumbers[x%F_MOD]);
}
//std::cout << "Before sort:\n";
//PrintPeople(people);
std::clock_t start_time = std::clock();
for(int i=0 ; i<num_loops ; ++i)
{
#if (SORT_TYPE == RADIX_Q_SORT)
boost::radix_qsort(people, NUM_PEOPLE-1); // why -1 ???
#elif (SORT_TYPE == RADIX_SORT)
boost::radix_sort(people, NUM_PEOPLE);
#else // std::sort
std::sort(people, people+NUM_PEOPLE);
#endif
}
std::clock_t end_time = std::clock();
//std::cout << "\n\nAfter sort:\n";
//PrintPeople(people);
return end_time - start_time;
}
class radixtest
{
public:
int numbers[2];
#if (SORT_TYPE == RADIX_Q_SORT)
static const int STR_SZ = 30;
char idstring_qs[STR_SZ];
#endif
radixtest()
{
numbers[0] = rand() % 10;
numbers[1] = rand() % 10;
#if (SORT_TYPE == RADIX_Q_SORT)
//%s means string, %d means int, and %e means double
boost::create_id_string("%e%e", idstring_qs, numbers[0], numbers[1]);
#endif
}
inline unsigned char operator[](int num)
{return ((unsigned char*)numbers)[num];}
inline unsigned char operator[](int num) const
{return ((unsigned char*)numbers)[num];}
~radixtest()
{}
#if ((SORT_TYPE == STD_SORT) || (SORT_TYPE == RADIX_Q_SORT))
bool operator<(const radixtest& a) const
{
if(numbers[0] < a.numbers[0])
return true;
else if(numbers[0] == a.numbers[0])
{
if (numbers[1] < a.numbers[1])
return true;
}
return false;
}
#endif
};
// We want a large number of objects to sort, but we don't
// want it to crash if it can't find enough stack space.
static const int NUM_RADIX = 15000;
static clock_t TestRadixSorting(int num_loops)
{
radixtest tests[NUM_RADIX];
std::clock_t start_time = std::clock();
for(int i=0 ; i<num_loops ; ++i)
{
#if (SORT_TYPE == RADIX_Q_SORT)
boost::radix_qsort(tests, NUM_RADIX-1); // why -1 ???
#elif (SORT_TYPE == RADIX_SORT)
boost::radix_sort(tests, NUM_RADIX, sizeof(int)*2);
#else // std::sort
std::sort(tests, tests+NUM_RADIX);
#endif
}
std::clock_t end_time = std::clock();
return end_time - start_time;
}
int main(int argc, char* argv[])
{
//clock_t people_sorting = TestPeopleSorting(10);
//clock_t radix_sorting = TestRadixSorting(100);
clock_t people_sorting = TestPeopleSorting(1);
clock_t radix_sorting = TestRadixSorting(1);
std::cout << "\nTime for "
#if (SORT_TYPE == RADIX_Q_SORT)
<< "radix_qsort "
#elif (SORT_TYPE == RADIX_SORT)
<< "radix_sort "
#else
<< "std::sort "
#endif
<< "sorting:\n"
<< "people: " << static_cast<double>(people_sorting) / CLOCKS_PER_SEC << std::endl
<< "radixtest: " << static_cast<double>(radix_sorting) / CLOCKS_PER_SEC << std::endl;
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk