Skip to content

Latest commit

 

History

History
216 lines (187 loc) · 6.4 KB

SDL_qsort.c

File metadata and controls

216 lines (187 loc) · 6.4 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "../SDL_internal.h"
#include "SDL_stdinc.h"
#include "SDL_assert.h"
#if defined(HAVE_QSORT)
void
SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *))
{
qsort(base, nmemb, size, compare);
}
#else
Feb 15, 2016
Feb 15, 2016
14
15
#ifdef REGTEST
#undef REGTEST
Feb 15, 2016
Feb 15, 2016
18
19
20
#ifdef TEST
#undef TEST
#endif
Feb 15, 2016
Feb 15, 2016
22
23
24
#ifndef _PDCLIB_memswp
#define _PDCLIB_memswp( i, j, size ) char tmp; do { tmp = *i; *i++ = *j; *j++ = tmp; } while ( --size );
#endif
Feb 15, 2016
Feb 15, 2016
26
27
28
#ifndef _PDCLIB_size_t
#define _PDCLIB_size_t size_t
#endif
Feb 15, 2016
Feb 15, 2016
30
31
32
#ifdef qsort
#undef qsort
#endif
Feb 15, 2016
Feb 15, 2016
33
#define qsort SDL_qsort
Feb 15, 2016
Feb 15, 2016
35
#define inline SDL_INLINE
Feb 15, 2016
Feb 15, 2016
37
38
39
40
41
/*
This code came from PDCLib, under the public domain. Specifically this:
https://bitbucket.org/pdclib/pdclib/raw/a82b02d0c7d4ed633b97f2a7639d9a10b1c92ec8/functions/stdlib/qsort.c
The _PDCLIB_memswp macro was from
https://bitbucket.org/pdclib/pdclib/src/a82b02d0c7d4ed633b97f2a7639d9a10b1c92ec8/platform/posix/internals/_PDCLIB_config.h?at=default&fileviewer=file-view-default#_PDCLIB_config.h-28
Feb 15, 2016
Feb 15, 2016
43
44
45
Everything below this comment until the HAVE_QSORT #endif was from PDCLib.
--ryan.
*/
Feb 15, 2016
Feb 15, 2016
47
/* $Id$ */
Feb 15, 2016
Feb 15, 2016
49
/* qsort( void *, size_t, size_t, int(*)( const void *, const void * ) )
Feb 15, 2016
Feb 15, 2016
51
52
53
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
Feb 15, 2016
Feb 15, 2016
55
#include <stdlib.h>
Feb 15, 2016
Feb 15, 2016
57
#ifndef REGTEST
Feb 15, 2016
Feb 15, 2016
59
/* This implementation is taken from Paul Edward's PDPCLIB.
Feb 15, 2016
Feb 15, 2016
61
62
63
64
65
Original code is credited to Raymond Gardner, Englewood CO.
Minor mods are credited to Paul Edwards.
Some reformatting and simplification done by Martin Baute.
All code is still Public Domain.
*/
Feb 15, 2016
Feb 15, 2016
67
68
/* Wrapper for _PDCLIB_memswp protects against multiple argument evaluation. */
static inline void memswp( char * i, char * j, size_t size )
Feb 15, 2016
Feb 15, 2016
70
_PDCLIB_memswp( i, j, size );
Feb 15, 2016
Feb 15, 2016
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* For small sets, insertion sort is faster than quicksort.
T is the threshold below which insertion sort will be used.
Must be 3 or larger.
*/
#define T 7
/* Macros for handling the QSort stack */
#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]
/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case).
Worst-case nmemb is platform dependent and should probably be
configured through _PDCLIB_config.h.
*/
#define STACKSIZE 64
Feb 15, 2016
Feb 15, 2016
89
void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) )
Feb 15, 2016
Feb 15, 2016
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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 ) /* QSort for more than T elements. */
{
/* We work from second to last - first will be pivot element. */
i = base_ + size;
j = limit - size;
/* We swap first with middle element, then sort that with second
and last element so that eventually first element is the median
of the three - avoiding pathological pivots.
TODO: Instead of middle element, chose one randomly.
*/
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 );
/* Now we have the median for pivot element, entering main Quicksort. */
for ( ;; )
Feb 15, 2016
Feb 15, 2016
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
do
{
/* move i right until *i >= pivot */
i += size;
} while ( compar( i, base_ ) < 0 );
do
{
/* move j left until *j <= pivot */
j -= size;
} while ( compar( j, base_ ) > 0 );
if ( i > j )
{
/* break loop if pointers crossed */
break;
}
/* else swap elements, keep scanning */
memswp( i, j, size );
Feb 15, 2016
Feb 15, 2016
135
136
137
138
/* move pivot into correct place */
memswp( base_, j, size );
/* larger subfile base / limit to stack, sort smaller */
if ( j - base_ > limit - i )
Feb 15, 2016
Feb 15, 2016
140
141
142
/* left is larger */
PUSH( base_, j );
base_ = i;
Feb 15, 2016
Feb 15, 2016
144
else
Feb 15, 2016
Feb 15, 2016
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* right is larger */
PUSH( i, limit );
limit = j;
}
}
else /* insertion sort for less than T elements */
{
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 ) /* if any entries on stack */
{
POP( base_, limit );
}
else /* else stack empty, done */
{
break;
171
172
173
174
175
}
}
}
}
Feb 15, 2016
Feb 15, 2016
176
#endif
Feb 15, 2016
Feb 15, 2016
178
179
180
181
182
183
#ifdef TEST
#include <_PDCLIB_test.h>
#include <string.h>
#include <limits.h>
static int compare( const void * left, const void * right )
Feb 15, 2016
Feb 15, 2016
185
186
return *( (unsigned char *)left ) - *( (unsigned char *)right );
}
Feb 15, 2016
Feb 15, 2016
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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;
Feb 15, 2016
Feb 15, 2016
212
213
214
#endif
#endif /* HAVE_QSORT */
215
216
/* vi: set ts=4 sw=4 expandtab: */