Embedded Artistry libc
C Standard Library Support for Bare-metal Systems
qsort.c File Reference
#include <stdlib.h>
#include <string.h>
#include <strings.h>
Include dependency graph for qsort.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define min(a, b)   (a) < (b) ? a : b
 
#define swapcode(TYPE, parmi, parmj, n)
 
#define SWAPINIT(a, es)   swaptype = (uintptr_t)a % sizeof(long) || es % sizeof(long) ? 2 : es == sizeof(long) ? 0 : 1;
 
#define swap(a, b)   swapfunc(a, b, (size_t)es, (size_t)swaptype)
 
#define vecswap(a, b, n)
 
#define CMP(t, x, y)   (cmp((x), (y)))
 
#define DEPTH(x)   (2 * (fls((int)(x)) - 1))
 
#define thunk   NULL
 

Typedefs

typedef int cmp_t(const void *, const void *)
 

Functions

static char * med3 (char *a, char *b, char *c, cmp_t *cmd, void *thunk) __attribute__((always_inline))
 
static void swapfunc (char *a, char *b, size_t n, size_t swaptype) __attribute__((always_inline))
 
static char * med3 (char *a, char *b, char *c, cmp_t *cmp, void *thunk __attribute__((unused)))
 
static void _qsort (void *a, size_t n, size_t es, #define thunk cmp_t *cmp, int depth_limit)
 
void qsort (void *a, size_t n, size_t es, cmp_t *cmp)
 

Macro Definition Documentation

◆ CMP

#define CMP (   t,
  x,
 
)    (cmp((x), (y)))

Definition at line 95 of file qsort.c.

◆ DEPTH

#define DEPTH (   x)    (2 * (fls((int)(x)) - 1))

Definition at line 112 of file qsort.c.

◆ min

#define min (   a,
 
)    (a) < (b) ? a : b

Definition at line 44 of file qsort.c.

◆ swap

#define swap (   a,
 
)    swapfunc(a, b, (size_t)es, (size_t)swaptype)

Definition at line 83 of file qsort.c.

◆ swapcode

#define swapcode (   TYPE,
  parmi,
  parmj,
 
)
Value:
{ \
size_t i = (n) / sizeof(TYPE); \
TYPE* pi = (TYPE*)(parmi); \
TYPE* pj = (TYPE*)(parmj); \
do \
{ \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while(--i > 0); \
}

Definition at line 49 of file qsort.c.

◆ SWAPINIT

#define SWAPINIT (   a,
  es 
)    swaptype = (uintptr_t)a % sizeof(long) || es % sizeof(long) ? 2 : es == sizeof(long) ? 0 : 1;

Definition at line 62 of file qsort.c.

◆ thunk

#define thunk   NULL

◆ vecswap

#define vecswap (   a,
  b,
 
)
Value:
if((n) > 0) \
swapfunc(a, b, n, swaptype ? (size_t)swaptype : 1)

Definition at line 88 of file qsort.c.

Typedef Documentation

◆ cmp_t

typedef int cmp_t(const void *, const void *)

Definition at line 37 of file qsort.c.

Function Documentation

◆ _qsort()

static void _qsort ( void *  a,
size_t  n,
size_t  es,
#define thunk cmp_t cmp,
int  depth_limit 
)
static

Definition at line 115 of file qsort.c.

122 {
123  char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
124  size_t d, r, swap_cnt;
125  int cmp_result;
126  int swaptype;
127 
128 loop:
129  if(depth_limit-- <= 0)
130  {
131 #ifdef I_AM_QSORT_R
132  heapsort_r(a, n, es, thunk, cmp);
133 #else
134  heapsort(a, n, es, cmp);
135 #endif
136  return;
137  }
138  SWAPINIT(a, es);
139  swap_cnt = 0;
140  if(n < 7)
141  {
142  for(pm = (char*)a + es; pm < (char*)a + n * es; pm += es)
143  {
144  for(pl = pm; pl > (char*)a && CMP(thunk, pl - es, pl) > 0; pl -= es)
145  {
146  swap(pl, pl - es);
147  }
148  }
149  return;
150  }
151  pm = (char*)a + (n / 2) * es;
152  if(n > 7)
153  {
154  pl = a;
155  pn = (char*)a + (n - 1) * es;
156  if(n > 40)
157  {
158  d = (n / 8) * es;
159  pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
160  pm = med3(pm - d, pm, pm + d, cmp, thunk);
161  pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
162  }
163  pm = med3(pl, pm, pn, cmp, thunk);
164  }
165  swap(a, (void*)pm);
166  pa = pb = (char*)a + es;
167 
168  pc = pd = (char*)a + (n - 1) * es;
169  for(;;)
170  {
171  while(pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0)
172  {
173  if(cmp_result == 0)
174  {
175  swap_cnt = 1;
176  swap(pa, pb);
177  pa += es;
178  }
179  pb += es;
180  }
181  while(pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0)
182  {
183  if(cmp_result == 0)
184  {
185  swap_cnt = 1;
186  swap(pc, pd);
187  pd -= es;
188  }
189  pc -= es;
190  }
191  if(pb > pc)
192  {
193  break;
194  }
195  swap(pb, pc);
196  swap_cnt = 1;
197  pb += es;
198  pc -= es;
199  }
200 
201  pn = (char*)a + n * es;
202  r = min((uintptr_t)pa - (uintptr_t)a, (uintptr_t)pb - (uintptr_t)pa);
203  vecswap(a, pb - r, r);
204  r = min((uintptr_t)pd - (uintptr_t)pc, (uintptr_t)pn - (uintptr_t)pd - (uintptr_t)es);
205  vecswap(pb, pn - r, r);
206 
207  if(swap_cnt == 0)
208  { /* Switch to insertion sort */
209  r = 1 + n / 4; /* n >= 7, so r >= 2 */
210  for(pm = (char*)a + es; pm < (char*)a + n * es; pm += es)
211  {
212  for(pl = pm; pl > (char*)a && CMP(thunk, pl - es, pl) > 0; pl -= es)
213  {
214  swap(pl, pl - es);
215  if(++swap_cnt > r)
216  {
217  goto nevermind;
218  }
219  }
220  }
221  return;
222  }
223 
224 nevermind:
225  if((r = (uintptr_t)pb - (uintptr_t)pa) > es)
226  {
227 #ifdef I_AM_QSORT_R
228  _qsort(a, r / es, es, thunk, cmp, depth_limit);
229 #else
230  _qsort(a, r / es, es, cmp, depth_limit);
231 #endif
232  }
233  if((r = (uintptr_t)pd - (uintptr_t)pc) > es)
234  {
235  /* Iterate rather than recurse to save stack space */
236  a = pn - r;
237  n = r / es;
238  goto loop;
239  }
240  /* qsort(pn - r, r / es, es, cmp);*/
241 }
#define swap(a, b)
Definition: qsort.c:83
#define SWAPINIT(a, es)
Definition: qsort.c:62
#define CMP(t, x, y)
Definition: qsort.c:95
static char * med3(char *a, char *b, char *c, cmp_t *cmd, void *thunk) __attribute__((always_inline))
#define vecswap(a, b, n)
Definition: qsort.c:88
int cmp(Bigint *a, Bigint *b)
Definition: misc.c:570
int heapsort(void *vbase, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Sorts the given array pointed to by vbase in ascending order.
#define min(a, b)
Definition: qsort.c:44
static void _qsort(void *a, size_t n, size_t es, #define thunk cmp_t *cmp, int depth_limit)
Definition: qsort.c:115
#define thunk
int heapsort_r(void *vbase, size_t nmemb, size_t size, void *thunk, int(*compar)(void *, const void *, const void *))
Sorts the given array pointed to by vbase in ascending order.

References CMP, cmp(), heapsort(), heapsort_r(), med3(), min, swap, SWAPINIT, thunk, and vecswap.

Referenced by qsort().

◆ med3() [1/2]

static char* med3 ( char *  a,
char *  b,
char *  c,
cmp_t cmd,
void *  thunk 
)
inlinestatic

Referenced by _qsort().

◆ med3() [2/2]

static char* med3 ( char *  a,
char *  b,
char *  c,
cmp_t cmp,
void *thunk   __attribute__(unused) 
)
inlinestatic

Definition at line 98 of file qsort.c.

104 {
105  return CMP(thunk, a, b) < 0 ? (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a))
106  : (CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c));
107 }
#define CMP(t, x, y)
Definition: qsort.c:95
#define thunk

References CMP, and thunk.

◆ qsort()

void qsort ( void *  a,
size_t  n,
size_t  es,
cmp_t cmp 
)

Definition at line 247 of file qsort.c.

249 {
250  _qsort(a, n, es,
251 #ifdef I_AM_QSORT_R
252  thunk,
253 #endif
254  cmp, DEPTH(n));
255 }
#define I_AM_QSORT_R
Definition: qsort_r.c:7
int cmp(Bigint *a, Bigint *b)
Definition: misc.c:570
#define DEPTH(x)
Definition: qsort.c:112
static void _qsort(void *a, size_t n, size_t es, #define thunk cmp_t *cmp, int depth_limit)
Definition: qsort.c:115
#define thunk

References _qsort(), cmp(), DEPTH, I_AM_QSORT_R, and thunk.

◆ swapfunc()

static void swapfunc ( char *  a,
char *  b,
size_t  n,
size_t  swaptype 
)
inlinestatic

Definition at line 65 of file qsort.c.

66 {
67  if(swaptype == 0)
68  {
69  long t = *(long*)(void*)(a);
70  *(long*)(void*)(a) = *(long*)(void*)(b);
71  *(long*)(void*)(b) = t;
72  }
73  else if(swaptype == 1)
74  {
75  swapcode(long, (void*)a, (void*)b, n)
76  }
77  else
78  {
79  swapcode(char, a, b, n)
80  }
81 }
#define swapcode(TYPE, parmi, parmj, n)
Definition: qsort.c:49

References swapcode.