From: Martin Mares Date: Sat, 4 Jan 2003 15:25:06 +0000 (+0000) Subject: Added generic array sorter. X-Git-Tag: holmes-import~1310 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=c08795753ea2d9a9b12d857f7b22b69c757b66e1;p=libucw.git Added generic array sorter. Benchmark results on my K6/400MHz: mj@albireo:~/src/sherlock/run$ bin/asort-test qsort: 19209 ms asort: 7544 ms --- diff --git a/lib/Makefile b/lib/Makefile index ad93507d..e8b60206 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -# Makefile for the Sherlock Library (c) 1997--2002 Martin Mares +# Makefile for the Sherlock Library (c) 1997--2003 Martin Mares DIRS+=lib PROGS+=obj/lib/db-tool obj/lib/buckettool @@ -25,6 +25,7 @@ obj/lib/lfs-test: obj/lib/lfs-test.o obj/lib/libsh.$(LS) obj/lib/regex-test: obj/lib/regex-test.o obj/lib/libsh.$(LS) obj/lib/hash-test: obj/lib/hash-test.o obj/lib/libsh.$(LS) obj/lib/str-test: obj/lib/str-test.o obj/lib/libsh.$(LS) +obj/lib/asort-test: obj/lib/asort-test.o obj/lib/libsh.$(LS) include lib/perl/Makefile include lib/shell/Makefile diff --git a/lib/arraysort.h b/lib/arraysort.h new file mode 100644 index 00000000..316bcd20 --- /dev/null +++ b/lib/arraysort.h @@ -0,0 +1,167 @@ +/* + * Sherlock Library -- Universal Array Sorter + * + * (c) 2003 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +/* + * This is not a normal header file, it's a generator of sorting + * routines. Each time you include it with parameters set in the + * corresponding preprocessor macros, it generates an array sorter + * with the parameters given. + * + * You might wonder why the heck do we implement our own array sorter + * instead of using qsort(). The primary reason is that qsort handles + * only continuous arrays, but we need to sort array-like data structures + * where the only way to access elements is by using an indexing macro. + * Besides that, we are more than 2 times faster. + * + * So much for advocacy, there are the parameters (those marked with [*] + * are mandatory): + * + * ASORT_PREFIX(x) [*] add a name prefix (used on all global names + * defined by the sorter) + * ASORT_KEY_TYPE [*] data type of a single array entry key + * ASORT_ELT(i) [*] returns the key of i-th element + * ASORT_LT(x,y) x < y for ASORT_TYPE (default: "x ASORT_THRESHOLD && (right - l) > ASORT_THRESHOLD) + { + /* Both partitions ok => push the larger one */ + if ((r - left) > (right - l)) + { + stack[sp].l = left; + stack[sp].r = r; + left = l; + } + else + { + stack[sp].l = l; + stack[sp].r = right; + right = r; + } + sp++; + } + else if ((r - left) > ASORT_THRESHOLD) + { + /* Left partition OK, right undersize */ + right = r; + } + else if ((right - l) > ASORT_THRESHOLD) + { + /* Right partition OK, left undersize */ + left = l; + } + else + { + /* Both partitions undersize => pop */ + if (!sp) + break; + sp--; + left = stack[sp].l; + right = stack[sp].r; + } + } + + /* + * We have a partially sorted array, finish by insertsort. Inspired + * by qsort() in GNU libc. + */ + + /* Find minimal element which will serve as a barrier */ + r = MIN(array_size, ASORT_THRESHOLD); + m = 0; + for (l=1; l + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include "lib/lib.h" + +#include +#include + +#define N 4000037 /* a prime */ + +struct elt { + u32 key; + u32 x, y; +}; + +static struct elt array[N]; + +#define ASORT_KEY_TYPE u32 +#define ASORT_ELT(i) array[i].key +#define ASORT_SWAP(i,j) do { struct elt e=array[j]; array[j]=array[i]; array[i]=e; } while(0) + +static void generate(void) +{ + uns i; + for (i=0; ikey < Y->key) + return -1; + else if (X->key > Y->key) + return 1; + else + return 0; +} + +#define ASORT_PREFIX(x) as_##x +#include "lib/arraysort.h" + +int main(void) +{ + generate(); + init_timer(); + qsort(array, N, sizeof(array[0]), (int (*)(const void *, const void *)) qs_comp); + printf("qsort: %d ms\n", get_timer()); + check(); + generate(); + init_timer(); + as_sort(N); + printf("asort: %d ms\n", get_timer()); + check(); + return 0; +}