Add qsort_r() implementation to the C library.
NOTE: This replaces qsort.c with the FreeBSD version. While the patch changes the source, it should not alter the implementation that should use the exact same algorithm.
This commit is contained in:
parent
e1e684920f
commit
754c178ae5
@ -154,6 +154,7 @@ libc_common_src_files := \
|
|||||||
stdlib/nrand48.c \
|
stdlib/nrand48.c \
|
||||||
stdlib/putenv.c \
|
stdlib/putenv.c \
|
||||||
stdlib/qsort.c \
|
stdlib/qsort.c \
|
||||||
|
stdlib/qsort_r.c \
|
||||||
stdlib/seed48.c \
|
stdlib/seed48.c \
|
||||||
stdlib/setenv.c \
|
stdlib/setenv.c \
|
||||||
stdlib/setjmperr.c \
|
stdlib/setjmperr.c \
|
||||||
|
@ -101,6 +101,7 @@ extern void * bsearch(const void *key, const void *base0,
|
|||||||
int (*compar)(const void *, const void *));
|
int (*compar)(const void *, const void *));
|
||||||
|
|
||||||
extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
|
extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
|
||||||
|
extern void qsort_r(void *a, size_t n, size_t es, void *thunk, int (*)(void *, const void *, const void *));
|
||||||
|
|
||||||
extern long jrand48(unsigned short *);
|
extern long jrand48(unsigned short *);
|
||||||
extern long mrand48(void);
|
extern long mrand48(void);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1992, 1993
|
* Copyright (c) 1992, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
@ -11,7 +10,7 @@
|
|||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
@ -28,11 +27,16 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/cdefs.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
|
#ifdef I_AM_QSORT_R
|
||||||
static __inline void swapfunc(char *, char *, int, int);
|
typedef int cmp_t(void *, const void *, const void *);
|
||||||
|
#else
|
||||||
|
typedef int cmp_t(const void *, const void *);
|
||||||
|
#endif
|
||||||
|
static inline char *med3(char *, char *, char *, cmp_t *, void *);
|
||||||
|
static inline void swapfunc(char *, char *, int, int);
|
||||||
|
|
||||||
#define min(a, b) (a) < (b) ? a : b
|
#define min(a, b) (a) < (b) ? a : b
|
||||||
|
|
||||||
@ -53,10 +57,12 @@ static __inline void swapfunc(char *, char *, int, int);
|
|||||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||||
|
|
||||||
static __inline void
|
static inline void
|
||||||
swapfunc(char *a, char *b, int n, int swaptype)
|
swapfunc(a, b, n, swaptype)
|
||||||
|
char *a, *b;
|
||||||
|
int n, swaptype;
|
||||||
{
|
{
|
||||||
if (swaptype <= 1)
|
if(swaptype <= 1)
|
||||||
swapcode(long, a, b, n)
|
swapcode(long, a, b, n)
|
||||||
else
|
else
|
||||||
swapcode(char, a, b, n)
|
swapcode(char, a, b, n)
|
||||||
@ -72,57 +78,75 @@ swapfunc(char *a, char *b, int n, int swaptype)
|
|||||||
|
|
||||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||||
|
|
||||||
static __inline char *
|
#ifdef I_AM_QSORT_R
|
||||||
med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
|
#define CMP(t, x, y) (cmp((t), (x), (y)))
|
||||||
|
#else
|
||||||
|
#define CMP(t, x, y) (cmp((x), (y)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
|
||||||
|
#ifndef I_AM_QSORT_R
|
||||||
|
__unused
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return cmp(a, b) < 0 ?
|
return CMP(thunk, a, b) < 0 ?
|
||||||
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
|
(CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
|
||||||
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
|
:(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef I_AM_QSORT_R
|
||||||
void
|
void
|
||||||
qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
|
qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
|
||||||
|
#else
|
||||||
|
#define thunk NULL
|
||||||
|
void
|
||||||
|
qsort(void *a, size_t n, size_t es, cmp_t *cmp)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||||
int d, r, swaptype, swap_cnt;
|
size_t d, r;
|
||||||
char *a = aa;
|
int cmp_result;
|
||||||
|
int swaptype, swap_cnt;
|
||||||
|
|
||||||
loop: SWAPINIT(a, es);
|
loop: SWAPINIT(a, es);
|
||||||
swap_cnt = 0;
|
swap_cnt = 0;
|
||||||
if (n < 7) {
|
if (n < 7) {
|
||||||
for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
|
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||||
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
|
for (pl = pm;
|
||||||
|
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||||
pl -= es)
|
pl -= es)
|
||||||
swap(pl, pl - es);
|
swap(pl, pl - es);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pm = (char *)a + (n / 2) * es;
|
pm = (char *)a + (n / 2) * es;
|
||||||
if (n > 7) {
|
if (n > 7) {
|
||||||
pl = (char *)a;
|
pl = a;
|
||||||
pn = (char *)a + (n - 1) * es;
|
pn = (char *)a + (n - 1) * es;
|
||||||
if (n > 40) {
|
if (n > 40) {
|
||||||
d = (n / 8) * es;
|
d = (n / 8) * es;
|
||||||
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
|
||||||
pm = med3(pm - d, pm, pm + d, cmp);
|
pm = med3(pm - d, pm, pm + d, cmp, thunk);
|
||||||
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
|
||||||
}
|
}
|
||||||
pm = med3(pl, pm, pn, cmp);
|
pm = med3(pl, pm, pn, cmp, thunk);
|
||||||
}
|
}
|
||||||
swap(a, pm);
|
swap(a, pm);
|
||||||
pa = pb = (char *)a + es;
|
pa = pb = (char *)a + es;
|
||||||
|
|
||||||
pc = pd = (char *)a + (n - 1) * es;
|
pc = pd = (char *)a + (n - 1) * es;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
|
while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
|
||||||
if (r == 0) {
|
if (cmp_result == 0) {
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pa, pb);
|
swap(pa, pb);
|
||||||
pa += es;
|
pa += es;
|
||||||
}
|
}
|
||||||
pb += es;
|
pb += es;
|
||||||
}
|
}
|
||||||
while (pb <= pc && (r = cmp(pc, a)) >= 0) {
|
while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
|
||||||
if (r == 0) {
|
if (cmp_result == 0) {
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pc, pd);
|
swap(pc, pd);
|
||||||
pd -= es;
|
pd -= es;
|
||||||
@ -137,8 +161,9 @@ loop: SWAPINIT(a, es);
|
|||||||
pc -= es;
|
pc -= es;
|
||||||
}
|
}
|
||||||
if (swap_cnt == 0) { /* Switch to insertion sort */
|
if (swap_cnt == 0) { /* Switch to insertion sort */
|
||||||
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
|
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||||
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
|
for (pl = pm;
|
||||||
|
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||||
pl -= es)
|
pl -= es)
|
||||||
swap(pl, pl - es);
|
swap(pl, pl - es);
|
||||||
return;
|
return;
|
||||||
@ -149,9 +174,13 @@ loop: SWAPINIT(a, es);
|
|||||||
vecswap(a, pb - r, r);
|
vecswap(a, pb - r, r);
|
||||||
r = min(pd - pc, pn - pd - (int)es);
|
r = min(pd - pc, pn - pd - (int)es);
|
||||||
vecswap(pb, pn - r, r);
|
vecswap(pb, pn - r, r);
|
||||||
if ((r = pb - pa) > (int)es)
|
if ((r = pb - pa) > es)
|
||||||
|
#ifdef I_AM_QSORT_R
|
||||||
|
qsort_r(a, r / es, es, thunk, cmp);
|
||||||
|
#else
|
||||||
qsort(a, r / es, es, cmp);
|
qsort(a, r / es, es, cmp);
|
||||||
if ((r = pd - pc) > (int)es) {
|
#endif
|
||||||
|
if ((r = pd - pc) > es) {
|
||||||
/* Iterate rather than recurse to save stack space */
|
/* Iterate rather than recurse to save stack space */
|
||||||
a = pn - r;
|
a = pn - r;
|
||||||
n = r / es;
|
n = r / es;
|
||||||
|
8
libc/stdlib/qsort_r.c
Normal file
8
libc/stdlib/qsort_r.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* This file is in the public domain. Originally written by Garrett
|
||||||
|
* A. Wollman.
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/lib/libc/stdlib/qsort_r.c,v 1.1.36.1.2.1 2009/10/25 01:10:29 kensmith Exp $
|
||||||
|
*/
|
||||||
|
#define I_AM_QSORT_R
|
||||||
|
#include "qsort.c"
|
Loading…
x
Reference in New Issue
Block a user