This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

revised patch to qsort


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]