Beispiel #1
0
void qsort_s(void *Base,
			size_t NumOfElements,
			size_t SizeOfElements,
			int (__cdecl *FuncCompare)(void *,const void *,const void *),
			void *Context)
{
	if (!FuncCompare)
		return;

	const size_t size = NumOfElements * SizeOfElements;
	char buf[1024];

	if (size < sizeof(buf))
	{
		/* The temporary array fits on the small on-stack buffer. */
		msort_with_tmp(Base, NumOfElements, SizeOfElements, FuncCompare, Context, buf);
	}
	else
	{
		/* It's somewhat large, so malloc it.  */
		char *tmp = malloc(size);
		if (tmp)
		{
			msort_with_tmp(Base, NumOfElements, SizeOfElements, FuncCompare, Context, tmp);
			free(tmp);
		}
	}
}
Beispiel #2
0
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 <= 1)
    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);

  tmp = t;

  if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0)
    /* We are operating on aligned words.  Use direct word stores.  */
    while (n1 > 0 && n2 > 0)
      {
	if ((*cmp) (b1, b2) <= 0)
	  {
	    --n1;
	    *((op_t *) tmp)++ = *((op_t *) b1)++;
	  }
	else
	  {
	    --n2;
	    *((op_t *) tmp)++ = *((op_t *) b2)++;
	  }
      }
  else
    while (n1 > 0 && n2 > 0)
      {
	if ((*cmp) (b1, b2) <= 0)
	  {
	    tmp = (char *) __mempcpy (tmp, b1, s);
	    b1 += s;
	    --n1;
	  }
	else
	  {
	    tmp = (char *) __mempcpy (tmp, b2, s);
	    b2 += s;
	    --n2;
	  }
      }
  if (n1 > 0)
    memcpy (tmp, b1, n1 * s);
  memcpy (b, t, (n - n2) * s);
}
Beispiel #3
0
static
void
msort_with_tmp(	void *Base,
				size_t NumElem,
				size_t SizeElem,
				int (*FuncCmp)(void *Ctx, const void *, const void *),
				void *Context,
				char *ExtTmp)
{
	char *LocalTmp;
	char *b1, *b2;
	size_t n1, n2;

	if (NumElem <= 1)
		return;

	n1 = NumElem / 2;
	n2 = NumElem - n1;
	b1 = Base;
	b2 = (char *)Base + (n1 * SizeElem);

	msort_with_tmp(b1, n1, SizeElem, FuncCmp, Context, ExtTmp);
	msort_with_tmp(b2, n2, SizeElem, FuncCmp, Context, ExtTmp);

	LocalTmp = ExtTmp;

	while (n1 > 0 && n2 > 0)
	{
		if (FuncCmp(Context, b1, b2) <= 0)
		{
			memcpy(LocalTmp, b1, SizeElem);
			LocalTmp += SizeElem;
			b1 += SizeElem;
			--n1;
		}
		else
		{
			memcpy(LocalTmp, b2, SizeElem);
			LocalTmp += SizeElem;
			b2 += SizeElem;
			--n2;
		}
	}
	
	if (n1 > 0)
		memcpy(LocalTmp, b1, n1 * SizeElem);
	
	memcpy(Base, ExtTmp, (NumElem - n2) * SizeElem);
}
Beispiel #4
0
void git_qsort(void *b, size_t n, size_t s,
	       int (*cmp)(const void *, const void *))
{
	const size_t size = n * s;
	char buf[1024];

	if (size < sizeof(buf)) {
		/* The temporary array fits on the small on-stack buffer. */
		msort_with_tmp(b, n, s, cmp, buf);
	} else {
		/* It's somewhat large, so malloc it.  */
		char *tmp = xmalloc(size);
		msort_with_tmp(b, n, s, cmp, tmp);
		free(tmp);
	}
}
Beispiel #5
0
static void msort_with_tmp(void *b, size_t n, size_t s,
			   int (*cmp)(const void *, const void *),
			   char *t)
{
	char *tmp;
	char *b1, *b2;
	size_t n1, n2;

	if (n <= 1)
		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);

	tmp = t;

	while (n1 > 0 && n2 > 0) {
		if (cmp(b1, b2) <= 0) {
			memcpy(tmp, b1, s);
			tmp += s;
			b1 += s;
			--n1;
		} else {
			memcpy(tmp, b2, s);
			tmp += s;
			b2 += s;
			--n2;
		}
	}
	if (n1 > 0)
		memcpy(tmp, b1, n1 * s);
	memcpy(b, t, (n - n2) * s);
}
Beispiel #6
0
void qsort(void *base, size_t total_num, size_t size, 
	       int (*cmp)(const void *, const void *))
{
	size_t total_size = size * total_num;
	if(total_size < 1024)
	{
		msort_with_tmp(base, total_num, size, cmp, (char*)alloca(total_size) );
	}
	else
	{
		char *tmp = (char*)malloc(size);
		if(tmp == NULL)
		{
			extern void _quicksort(void *base, size_t total_num, size_t size, int (*compare)(const void *, const void *) );
			_quicksort(base, total_num, size, cmp);
		}
		else
		{
			msort_with_tmp(base, total_num, size, cmp, tmp );
			free( tmp );
		}
	}
}
Beispiel #7
0
void msort_with_tmp(void *base, size_t num, size_t size,
                    int (*compare)(const void *, const void *),
					char *t)
{
	if( num <= 1)
		return;

	int num1    = num / 2;
	char *base1 = (char*)base;
	int num2    = num - num1;
	char *base2 = (char*)base + size * num1;

	msort_with_tmp(base1, num1, size, compare, t);
	msort_with_tmp(base2, num2, size, compare, t);

	char *tmp = t;
	while(num1 > 0 && num2 > 0)
	{
		if( (*compare)(base1, base2) <= 0)
		{
			memcpy(tmp, base1, size);
			base1 += size;
			--num1;
		}
		else
		{
			memcpy(tmp, base2, size);
			base2 += size;
			 --num2;
		}
		tmp += size;
	}
	if(num1 > 0)                             
		memcpy(tmp, base1, num1 * size);   //base1 | base2, base2's elem is tail and sorted
	memcpy(base, t, (num - num2) * size);
}
Beispiel #8
0
static void
msort_with_tmp (const struct msort_param *p, void *b, size_t n)
{
  char *b1, *b2;
  size_t n1, n2;

  if (n <= 1)
    return;

  n1 = n / 2;
  n2 = n - n1;
  b1 = b;
  b2 = (char *) b + (n1 * p->s);

  msort_with_tmp (p, b1, n1);
  msort_with_tmp (p, b2, n2);

  char *tmp = p->t;
  const size_t s = p->s;
  __compar_d_fn_t cmp = p->cmp;
  void *arg = p->arg;
  switch (p->var)
    {
    case 0:
      while (n1 > 0 && n2 > 0)
	{
	  if ((*cmp) (b1, b2, arg) <= 0)
	    {
	      *(uint32_t *) tmp = *(uint32_t *) b1;
	      b1 += sizeof (uint32_t);
	      --n1;
	    }
	  else
	    {
	      *(uint32_t *) tmp = *(uint32_t *) b2;
	      b2 += sizeof (uint32_t);
	      --n2;
	    }
	  tmp += sizeof (uint32_t);
	}
      break;
    case 1:
      while (n1 > 0 && n2 > 0)
	{
	  if ((*cmp) (b1, b2, arg) <= 0)
	    {
	      *(uint64_t *) tmp = *(uint64_t *) b1;
	      b1 += sizeof (uint64_t);
	      --n1;
	    }
	  else
	    {
	      *(uint64_t *) tmp = *(uint64_t *) b2;
	      b2 += sizeof (uint64_t);
	      --n2;
	    }
	  tmp += sizeof (uint64_t);
	}
      break;
    case 2:
      while (n1 > 0 && n2 > 0)
	{
	  unsigned long *tmpl = (unsigned long *) tmp;
	  unsigned long *bl;

	  tmp += s;
	  if ((*cmp) (b1, b2, arg) <= 0)
	    {
	      bl = (unsigned long *) b1;
	      b1 += s;
	      --n1;
	    }
	  else
	    {
	      bl = (unsigned long *) b2;
	      b2 += s;
	      --n2;
	    }
	  while (tmpl < (unsigned long *) tmp)
	    *tmpl++ = *bl++;
	}
      break;
    case 3:
      while (n1 > 0 && n2 > 0)
	{
	  if ((*cmp) (*(const void **) b1, *(const void **) b2, arg) <= 0)
	    {
	      *(void **) tmp = *(void **) b1;
	      b1 += sizeof (void *);
	      --n1;
	    }
	  else
	    {
	      *(void **) tmp = *(void **) b2;
	      b2 += sizeof (void *);
	      --n2;
	    }
	  tmp += sizeof (void *);
	}
      break;
    default:
      while (n1 > 0 && n2 > 0)
	{
	  if ((*cmp) (b1, b2, arg) <= 0)
	    {
	      tmp = (char *) __mempcpy (tmp, b1, s);
	      b1 += s;
	      --n1;
	    }
	  else
	    {
	      tmp = (char *) __mempcpy (tmp, b2, s);
	      b2 += s;
	      --n2;
	    }
	}
      break;
    }

  if (n1 > 0)
    memcpy (tmp, b1, n1 * s);
  memcpy (b, p->t, (n - n2) * s);
}
Beispiel #9
0
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);
      
      /* 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 /= 4;

	  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 > phys_pages)
	_quicksort (b, n, s, cmp);
      else
	{
	  /* It's somewhat large, so malloc it.  */
	  int save = errno;
	  char *tmp = malloc (size);
	  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);
	    }
	}
    }