#include <stdlib.h>
#ifndef REGTEST
static inline void memswp( char * i, char * j, size_t size )
{
_PDCLIB_memswp( i, j, size );
}
#define T 7
#define PREPARE_STACK char * stack[STACKSIZE]; char * * stackptr = stack
#define PUSH( base, limit ) stackptr[0] = base; stackptr[1] = limit; stackptr += 2
#define POP( base, limit ) stackptr -= 2; base = stackptr[0]; limit = stackptr[1]
#define STACKSIZE 64
void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) )
{
char * i;
char * j;
_PDCLIB_size_t thresh = T * size;
char * base_ = (char *)base;
char * limit = base_ + nmemb * size;
PREPARE_STACK;
for ( ;; )
{
if ( (size_t)( limit - base_ ) > thresh )
{
i = base_ + size;
j = limit - size;
memswp( ( ( ( (size_t)( limit - base_ ) ) / size ) / 2 ) * size + base_, base_, size );
if ( compar( i, j ) > 0 ) memswp( i, j, size );
if ( compar( base_, j ) > 0 ) memswp( base_, j, size );
if ( compar( i, base_ ) > 0 ) memswp( i, base_, size );
for ( ;; )
{
do
{
i += size;
} while ( compar( i, base_ ) < 0 );
do
{
j -= size;
} while ( compar( j, base_ ) > 0 );
if ( i > j )
{
break;
}
memswp( i, j, size );
}
memswp( base_, j, size );
if ( j - base_ > limit - i )
{
PUSH( base_, j );
base_ = i;
}
else
{
PUSH( i, limit );
limit = j;
}
}
else
{
for ( j = base_, i = j + size; i < limit; j = i, i += size )
{
for ( ; compar( j, j + size ) > 0; j -= size )
{
memswp( j, j + size, size );
if ( j == base_ )
{
break;
}
}
}
if ( stackptr != stack )
{
POP( base_, limit );
}
else
{
break;
}
}
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <string.h>
#include <limits.h>
static int compare( const void * left, const void * right )
{
return *( (unsigned char *)left ) - *( (unsigned char *)right );
}
int main( void )
{
char presort[] = { "shreicnyjqpvozxmbt" };
char sorted1[] = { "bcehijmnopqrstvxyz" };
char sorted2[] = { "bticjqnyozpvreshxm" };
char s[19];
strcpy( s, presort );
qsort( s, 18, 1, compare );
TESTCASE( strcmp( s, sorted1 ) == 0 );
strcpy( s, presort );
qsort( s, 9, 2, compare );
TESTCASE( strcmp( s, sorted2 ) == 0 );
strcpy( s, presort );
qsort( s, 1, 1, compare );
TESTCASE( strcmp( s, presort ) == 0 );
#if defined(REGTEST) && (__BSD_VISIBLE || __APPLE__)
puts( "qsort.c: Skipping test #4 for BSD as it goes into endless loop here." );
#else
qsort( s, 100, 0, compare );
TESTCASE( strcmp( s, presort ) == 0 );
#endif
return TEST_RESULTS;
}
#endif