This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
revised patch to qsort
- From: "djamel anonymous" <djam8193ah at hotmail dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 27 Jun 2006 11:25:21 +0000
- Subject: revised patch to qsort
- Bcc:
hello all, after my last mail i made a search on this mailing list i
discovered that there has already been a proposed version by wolfgang glas
dated 8 Jun 2004.the reason for which the sugestion was rejected
was because the standard requires omparison function be passed only pointers
from the original array.
i revised my own version to call the comparison function with arguments only
from the original array.
by benchmarking on an array of 2 millions 32 bits unsigned integers on
athlon xp 1700+ i found the following results:
random aray:
original qsort 1.93 seconds
modified qsort 1.60 secons
reverse sorted aray:
original qsort 1.32 seconds
modified qsort 0.94 secons
i have attached only the modified version of the file msort.c
best regards.
_________________________________________________________________
MSN Messenger : appels gratuits de PC à PC !
http://www.msn.fr/newhotmail/Default.asp?Ath=f
/* An alternative to qsort, with an identical interface.
This file is part of the GNU C Library.
Copyright (C) 1992,95-97,99,2000,01,02,04 Free Software Foundation, Inc.
Written by Mike Haertel, September 1988.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <alloca.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <memcopy.h>
#include <errno.h>
static void msort_with_tmp (void *b, size_t n, size_t s,
__compar_fn_t cmp, char *t);
static void
msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp,
char *t)
{
char *tmp;
char *b1, *b2;
size_t n1, n2;
if (n <= 2) {
if(n<=1)
return;
b1=b;
b2= (char *) b + s;
if ((*cmp) (b1, b2) > 0) {
if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) {
*((op_t *) t) = *((op_t *) b1);
*((op_t *) b1) = *((op_t *) b2);
*((op_t *) b2) = *((op_t *) t);
} else {
memcpy (t, b1, s);
memcpy (b1, b2, s);
memcpy (b2, t, s);
};
};
return;
};
n1 = n / 2;
n2 = n - n1;
b1 = b;
b2 = (char *) b + (n1 * s);
msort_with_tmp (b1, n1, s, cmp, t);
msort_with_tmp (b2, n2, s, cmp, t);
if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0){
/* We are operating on aligned words. Use direct word stores. */
tmp=t;
while (tmp<t+(n1*s))
{
if ((*cmp) (b1, b2) <= 0)
{
*((op_t *) tmp) = *((op_t *) b1);
tmp += sizeof (op_t);
b1 += sizeof (op_t);
}
else
{
*((op_t *) tmp) = *((op_t *) b2);
tmp += sizeof (op_t);
b2 += sizeof (op_t);
}
};
tmp=(char*)b+(n1*s);
while (b2<(char*)b+(n*s) && b1<(char*)b+(n1*s))
{
if ((*cmp) (b1, b2) <= 0)
{
*((op_t *) tmp) = *((op_t *) b1);
tmp += sizeof (op_t);
b1 += sizeof (op_t);
}
else
{
*((op_t *) tmp) = *((op_t *) b2);
tmp += sizeof (op_t);
b2 += sizeof (op_t);
}
};
}
else {
tmp=t;
while (tmp<t+(n1*s))
{
if ((*cmp) (b1, b2) <= 0)
{
tmp = (char *) __mempcpy (tmp, b1, s);
b1 += s;
}
else
{
tmp = (char *) __mempcpy (tmp, b2, s);
b2 += s;
}
}
tmp=(char*)b+(n1*s);
while (b2<(char*)b+(n*s) && b1<(char*)b+(n1*s))
{
if ((*cmp) (b1, b2) <= 0)
{
tmp = (char *) __mempcpy (tmp, b1, s);
b1 += s;
}
else
{
tmp = (char *) __mempcpy (tmp, b2, s);
b2 += s;
}
}
}
if(tmp<b2)
memcpy(tmp ,b1 , b2 - tmp);
memcpy (b , t, n1 * s);
}
void
qsort (void *b, size_t n, size_t s, __compar_fn_t cmp)
{
const size_t size = n * s;
if (size < 1024)
{
void *buf = __alloca (size/2);
/* The temporary array is small, so put it on the stack. */
msort_with_tmp (b, n, s, cmp, buf);
}
else
{
/* We should avoid allocating too much memory since this might
have to be backed up by swap space. */
static long int phys_pages;
static int pagesize;
if (phys_pages == 0)
{
phys_pages = __sysconf (_SC_PHYS_PAGES);
if (phys_pages == -1)
/* Error while determining the memory size. So let's
assume there is enough memory. Otherwise the
implementer should provide a complete implementation of
the `sysconf' function. */
phys_pages = (long int) (~0ul >> 1);
/* The following determines that we will never use more than
a quarter of the physical memory. */
phys_pages /= 3;
pagesize = __sysconf (_SC_PAGESIZE);
}
/* Just a comment here. We cannot compute
phys_pages * pagesize
and compare the needed amount of memory against this value.
The problem is that some systems might have more physical
memory then can be represented with a `size_t' value (when
measured in bytes. */
/* If the memory requirements are too high don't allocate memory. */
if (size / pagesize) > (size_t) phys_pages)
_quicksort (b, n, s, cmp);
else
{
/* It's somewhat large, so malloc it. */
int save = errno;
char *tmp = malloc (size/2);
if (tmp == NULL)
{
/* Couldn't get space, so use the slower algorithm
that doesn't need a temporary array. */
__set_errno (save);
_quicksort (b, n, s, cmp);
}
else
{
__set_errno (save);
msort_with_tmp (b, n, s, cmp, tmp);
free (tmp);
}
}
}
}
libc_hidden_def (qsort)