|
-
November 26th, 2002, 08:55 PM
#1
The Qsort challenge
A while ago, I posted my Qsort code and explained why it can be used to sort any object arrays or vectors, just like any POD data types. The code works on all compilers I can lay my hands on. And it is much faster than std::sort when the object is none trivial.
There was one, unsubstantiate claim that when a specific compiler was used, and when sorting a specific type of objects, Qsort does not give the right result. That claim was un-substantiated because it was not verified by any one else that uses that specific compiler, nor did the original poster provide any file to back it up.
So here is the challenge, I am posting my Qsort code again. And if the original challenge do believe it doesn't work for a specific object type on a specific compiler, please compile the stuff with assembly output enabled, and zip all the file up, and post it here. So every one can verify the result.
Here is my Qsort code:
Code:
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#define ELEMENT_COUNT 10000 //00
#define BUFF_SIZE 4096
#define CUTOFF 8 /* testing shows that this is good value */
using namespace std;
class SomeClass
{
public:
SomeClass();
~SomeClass();
SomeClass(const SomeClass& src);
SomeClass& operator=(const SomeClass& src);
std::string fld1;
char* m_pBuff;
};
SomeClass::SomeClass()
{
m_pBuff = new char[BUFF_SIZE];
}
SomeClass::~SomeClass()
{
delete [] m_pBuff;
}
SomeClass::SomeClass(const SomeClass& src) :
fld1(src.fld1)
{
m_pBuff = new char[BUFF_SIZE];
memcpy(m_pBuff, src.m_pBuff, BUFF_SIZE);
}
SomeClass& SomeClass::operator=(const SomeClass& src)
{
fld1 = src.fld1;
memcpy(m_pBuff, src.m_pBuff, BUFF_SIZE);
return *this;
}
struct SortFld
{
inline bool operator() (const SomeClass& first, const SomeClass& second)
{
return strcmp(first.fld1.c_str(), second.fld1.c_str())<0?true:false;
}
};
typedef vector<SomeClass> intvec;
void randomise_vector(intvec& v)
{
srand(time(0));
char szBuf[15];
for (intvec::iterator i = v.begin(); i != v.end(); ++i)
{
sprintf(szBuf, "%d", 100 + (((unsigned int)rand())%999));
(*i).fld1 = szBuf;
strcpy((*i).m_pBuff, szBuf);
}
}
inline bool stllessfunc(const SomeClass& lhs, const SomeClass& rhs)
{
return strcmp(lhs.fld1.c_str(), rhs.fld1.c_str())<0?true:false;
}
inline int qscompare(const void* lhs, const void* rhs)
{
return strcmp(((SomeClass *)lhs)->fld1.c_str(), ((SomeClass *)rhs)->fld1.c_str());
}
void __cdecl Qsort (
void *base,
unsigned num,
unsigned width,
int (__cdecl *comp)(const void *, const void *)
);
int main()
{
srand(clock());
intvec v(ELEMENT_COUNT);
randomise_vector(v);
cout << "std::sort using functor: ";
clock_t start = clock();
sort(v.begin(), v.end(), SortFld());
clock_t stop = clock();
cout << stop - start << " ticks" << endl;
randomise_vector(v);
cout << "std::sort using function: ";
start = clock();
sort(v.begin(), v.end(), stllessfunc);
stop = clock();
cout << stop - start << " ticks" << endl;
randomise_vector(v);
cout << "Qsort: ";
start = clock();
Qsort(static_cast<void*>(&v[0]), ELEMENT_COUNT, sizeof(SomeClass), qscompare);
stop = clock();
cout << stop - start << " ticks" << endl;
char c;
cin >> c;
return 0;
}
// This is Anthony's improved version of qsort -A.Mai 7/18/2002
void __cdecl Qsort (
void *base,
unsigned num,
unsigned width,
int (__cdecl *comp)(const void *, const void *)
)
{
char *lo, *hi;
char *mid;
char *loguy, *higuy;
unsigned size;
char *lostk[30], *histk[30];
int stkptr;
if (num < 2 || width == 0)
{
return;
}
stkptr = 0;
lo = (char*)base;
hi = (char *)base + width * (num-1);
recurse:
size = (hi - lo) / width + 1;
if (size > CUTOFF)
{
mid = lo + (size / 2) * width;
{
register int w2 = width;
if (w2 < 4)
{
do
{
char tmp;
w2 --;
tmp = mid[w2];
mid[w2] = lo[w2];
lo[w2] = tmp;
} while (w2 > 0);
}
else
{
int tmp;
tmp = *(int*)(&mid[w2-4]);
*(int*)(&mid[w2-4]) = *(int*)(&lo[w2-4]);
*(int*)(&lo[w2-4]) = tmp;
w2--;
w2 &= -4;
while (w2 >= 4)
{
w2 -= 4;
tmp = *(int*)(&mid[w2]);
*(int*)(&mid[w2]) = *(int*)(&lo[w2]);
*(int*)(&lo[w2]) = tmp;
}
}
}
loguy = lo;
higuy = hi + width;
for (;;)
{
do {
loguy += width;
} while (loguy <= hi && comp(loguy, lo) < 0); // <=
do {
higuy -= width;
} while (higuy > lo && comp(higuy, lo) > 0); // >=
if (higuy < loguy)
{
break;
}
{
register int w2 = width;
if (w2 < 4)
{
do
{
char tmp;
w2 --;
tmp = loguy[w2];
loguy[w2] = higuy[w2];
higuy[w2] = tmp;
} while (w2 > 0);
}
else
{
int tmp;
tmp = *(int*)(&loguy[w2-4]);
*(int*)(&loguy[w2-4]) = *(int*)(&higuy[w2-4]);
*(int*)(&higuy[w2-4]) = tmp;
w2--;
w2 &= -4;
while (w2 >= 4)
{
w2 -= 4;
tmp = *(int*)(&loguy[w2]);
*(int*)(&loguy[w2]) = *(int*)(&higuy[w2]);
*(int*)(&higuy[w2]) = tmp;
}
}
}
}
{
register int w2 = width;
if (w2 < 4)
{
do
{
char tmp;
w2 --;
tmp = lo[w2];
lo[w2] = higuy[w2];
higuy[w2] = tmp;
} while (w2 > 0);
}
else
{
int tmp;
tmp = *(int*)(&lo[w2-4]);
*(int*)(&lo[w2-4]) = *(int*)(&higuy[w2-4]);
*(int*)(&higuy[w2-4]) = tmp;
w2--;
w2 &= -4;
while (w2 >= 4)
{
w2 -= 4;
int tmp = *(int*)(&lo[w2]);
*(int*)(&lo[w2]) = *(int*)(&higuy[w2]);
*(int*)(&higuy[w2]) = tmp;
}
}
}
if ( higuy - 1 - lo >= hi - loguy )
{
if (lo + width < higuy)
{
lostk[stkptr] = lo;
histk[stkptr] = higuy - width;
++stkptr;
}
if (loguy < hi)
{
lo = loguy;
goto recurse;
}
}
else
{
if (loguy < hi)
{
lostk[stkptr] = loguy;
histk[stkptr] = hi;
++stkptr;
}
if (lo + width < higuy)
{
hi = higuy - width;
goto recurse;
}
}
}
else
{
char *p, *max;
while (hi > lo)
{
max = lo;
for (p = lo+width; p <= hi; p += width)
{
if (comp(p, max) > 0)
{
max = p;
}
}
if ( max != hi )
{
register int w2 = width;
if (w2 < 4)
{
do {
char tmp;
w2 --;
tmp = max[w2];
max[w2] = hi[w2];
hi[w2] = tmp;
} while (w2 > 0);
}
else
{
int tmp;
tmp = *(int*)(&max[w2-4]);
*(int*)(&max[w2-4]) = *(int*)(&hi[w2-4]);
*(int*)(&hi[w2-4]) = tmp;
w2--;
w2 &= -4;
while (w2 >= 4)
{
w2 -= 4;
tmp = *(int*)(&max[w2]);
*(int*)(&max[w2]) = *(int*)(&hi[w2]);
*(int*)(&hi[w2]) = tmp;
}
}
}
hi -= width;
}
}
--stkptr;
if (stkptr >= 0)
{
lo = lostk[stkptr];
hi = histk[stkptr];
goto recurse;
}
return;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|