예제 #1
0
/** Sort array using smoothsort.
 *
 * Sort @a N elements from array @a base starting with index @a r with smoothsort.
 *
 * @param base  pointer to array
 * @param r     lowest index to sort
 * @param N     number of elements to sort
 * @param less  comparison function returning nonzero if m[a] < m[b]
 * @param swap  swapper function exchanging elements m[a] and m[b]
 */
void su_smoothsort(void *base, size_t r, size_t N,
		   int (*less)(void *m, size_t a, size_t b),
		   void (*swap)(void *m, size_t a, size_t b))
{
  stretch s = { 1, 1, 1 };
  size_t q;

  array array_i;
  array* const array = &array_i;
  array->less = less;
  array->swap = swap;
  array->m = base;

  assert(less && swap);

  if (base == NULL || N <= 1 || less == NULL || swap == NULL)
    return;

  DEBUG(("\nsmoothsort(%p, %zu)\n", array, nmemb));

  for (q = 1; q != N; q++, r++, s.p++) {
    DEBUG(("loop0 q=%zu, b=%u, p=%s \n", q, s.b, binary(s.p)));

    if ((s.p & 7) == 3) {
      sift(array, r, s), stretch_up(&s), stretch_up(&s);
    }
    else /* if ((s.p & 3) == 1) */ { assert((s.p & 3) == 1);
      if (q + s.c < N)
	sift(array, r, s);
      else
	trinkle(array, r, s);

      while (stretch_down(&s, 0) > 1)
	;
    }
  }

  trinkle(array, r, s);

  for (; q > 1; q--) {
    s.p--;

    DEBUG(("loop1 q=%zu: b=%u p=%s\n", q, s.b, binary(s.p)));

    if (s.b <= 1) {
      while ((s.p & 1) == 0)
	stretch_up(&s);
      --r;
    }
    else /* if b >= 3 */ {
      if (s.p) semitrinkle(array, r - (s.b - s.c), s);
      stretch_down(&s, 1);
      semitrinkle(array, --r, s);
      stretch_down(&s, 1);
    }
  }
}
예제 #2
0
/** Trinkles the stretches when the adjacent stretches are already trusty.
 *
 * @param array   description of array to sort
 * @param r       root of the stretch
 * @param stretch description of stretches to trinkle
 */
static void semitrinkle(array const *array, size_t r, stretch s)
{
  size_t r1 = r - s.c;

  DEBUG(("semitrinkle(%p, %zu, (%u, %s))\n", array, r, s.b, binary(s.p)));

  if (array->less(array->m, r, r1)) {
    DEBUG(("\tswap(%p @%zu <=> @%zu b=%u)\n", array, r, r1, s.b));
    array->swap(array->m, r, r1);
    trinkle(array, r1, s);
  }
}
예제 #3
0
파일: qsort.c 프로젝트: KGG814/AOS
void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
{
	size_t lp[12*sizeof(size_t)];
	size_t i, size = width * nel;
	unsigned char *head, *high;
	size_t p[2] = {1, 0};
	int pshift = 1;
	int trail;

	if (!size) return;

	head = base;
	high = head + size - width;

	/* Precompute Leonardo numbers, scaled by element width */
	for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);

	while(head < high) {
		if((p[0] & 3) == 3) {
			sift(head, width, cmp, pshift, lp);
			shr(p, 2);
			pshift += 2;
		} else {
			if(lp[pshift - 1] >= high - head) {
				trinkle(head, width, cmp, p, pshift, 0, lp);
			} else {
				sift(head, width, cmp, pshift, lp);
			}
			
			if(pshift == 1) {
				shl(p, 1);
				pshift = 0;
			} else {
				shl(p, pshift - 1);
				pshift = 1;
			}
		}
		
		p[0] |= 1;
		head += width;
	}

	trinkle(head, width, cmp, p, pshift, 0, lp);

	while(pshift != 1 || p[0] != 1 || p[1] != 0) {
		if(pshift <= 1) {
			trail = pntz(p);
			shr(p, trail);
			pshift += trail;
		} else {
			shl(p, 2);
			pshift -= 2;
			p[0] ^= 7;
			shr(p, 1);
			trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp);
			shl(p, 1);
			p[0] |= 1;
			trinkle(head - width, width, cmp, p, pshift, 1, lp);
		}
		head -= width;
	}
}