aboutsummaryrefslogtreecommitdiffstats
path: root/vppinfra/vppinfra/qsort.c
diff options
context:
space:
mode:
Diffstat (limited to 'vppinfra/vppinfra/qsort.c')
-rw-r--r--vppinfra/vppinfra/qsort.c271
1 files changed, 155 insertions, 116 deletions
diff --git a/vppinfra/vppinfra/qsort.c b/vppinfra/vppinfra/qsort.c
index b9732aaa29c..2faa5897eb2 100644
--- a/vppinfra/vppinfra/qsort.c
+++ b/vppinfra/vppinfra/qsort.c
@@ -33,17 +33,18 @@
* bytes. The MTHREShold is where we stop finding a better median.
*/
-#define THRESH 4 /* threshold for insertion */
-#define MTHRESH 6 /* threshold for median */
+#define THRESH 4 /* threshold for insertion */
+#define MTHRESH 6 /* threshold for median */
-typedef struct {
+typedef struct
+{
word qsz; /* size of each record */
word thresh; /* THRESHold in chars */
word mthresh; /* MTHRESHold in chars */
- int (*qcmp) (const void *, const void *); /* the comparison routine */
+ int (*qcmp) (const void *, const void *); /* the comparison routine */
} qst_t;
-static void qst (qst_t * q, char * base, char *max);
+static void qst (qst_t * q, char *base, char *max);
/*
* qqsort: First, set up some global parameters for qst to share.
@@ -52,7 +53,7 @@ static void qst (qst_t * q, char * base, char *max);
*/
void
-qsort (void * base, uword n, uword size,
+qsort (void *base, uword n, uword size,
int (*compar) (const void *, const void *))
{
char *i;
@@ -62,7 +63,7 @@ qsort (void * base, uword n, uword size,
char *min;
char c;
char *max;
- qst_t _q, * q = &_q;
+ qst_t _q, *q = &_q;
if (n <= 1)
return;
@@ -72,29 +73,35 @@ qsort (void * base, uword n, uword size,
q->thresh = q->qsz * THRESH;
q->mthresh = q->qsz * MTHRESH;
max = base + n * q->qsz;
- if (n >= THRESH) {
- qst(q, base, max);
- hi = base + q->thresh;
- } else {
- hi = max;
- }
+ if (n >= THRESH)
+ {
+ qst (q, base, max);
+ hi = base + q->thresh;
+ }
+ else
+ {
+ hi = max;
+ }
/*
* First put smallest element, which must be in the first THRESH, in the
* first position as a sentinel. This is done just by searching the
* first THRESH elements (or the first n if n < THRESH), finding the min,
* and swapping it into the first position.
*/
- for (j = lo = base; (lo += q->qsz) < hi;) {
- if ((*compar) (j, lo) > 0)
- j = lo;
- }
- if (j != base) { /* swap j into place */
- for (i = base, hi = base + q->qsz; i < hi;) {
- c = *j;
- *j++ = *i;
- *i++ = c;
+ for (j = lo = base; (lo += q->qsz) < hi;)
+ {
+ if ((*compar) (j, lo) > 0)
+ j = lo;
+ }
+ if (j != base)
+ { /* swap j into place */
+ for (i = base, hi = base + q->qsz; i < hi;)
+ {
+ c = *j;
+ *j++ = *i;
+ *i++ = c;
+ }
}
- }
/*
* With our sentinel in place, we now run the following hyper-fast
* insertion sort. For each remaining element, min, from [1] to [n-1],
@@ -102,17 +109,20 @@ qsort (void * base, uword n, uword size,
* the standard insertion sort shift on a character at a time basis for
* each element in the frob.
*/
- for (min = base; (hi = min += q->qsz) < max;) {
- while ((*q->qcmp) (hi -= q->qsz, min) > 0);
- if ((hi += q->qsz) != min) {
- for (lo = min + q->qsz; --lo >= min;) {
- c = *lo;
- for (i = j = lo; (j -= q->qsz) >= hi; i = j)
- *i = *j;
- *i = c;
- }
+ for (min = base; (hi = min += q->qsz) < max;)
+ {
+ while ((*q->qcmp) (hi -= q->qsz, min) > 0);
+ if ((hi += q->qsz) != min)
+ {
+ for (lo = min + q->qsz; --lo >= min;)
+ {
+ c = *lo;
+ for (i = j = lo; (j -= q->qsz) >= hi; i = j)
+ *i = *j;
+ *i = c;
+ }
+ }
}
- }
}
@@ -132,7 +142,7 @@ qsort (void * base, uword n, uword size,
*/
static void
-qst(qst_t *q, char *base, char *max)
+qst (qst_t * q, char *base, char *max)
{
char *i;
char *j;
@@ -140,91 +150,120 @@ qst(qst_t *q, char *base, char *max)
char *mid;
int ii;
char c;
- char *tmp;
- int lo;
- int hi;
+ char *tmp;
+ int lo;
+ int hi;
int qsz = q->qsz;
- lo = (int)(max - base); /* number of elements as chars */
- do {
- /*
- * At the top here, lo is the number of characters of elements in the
- * current partition. (Which should be max - base). Find the median
- * of the first, last, and middle element and make that the middle
- * element. Set j to largest of first and middle. If max is larger
- * than that guy, then it's that guy, else compare max with loser of
- * first and take larger. Things are set up to prefer the middle,
- * then the first in case of ties.
- */
- mid = i = base + qsz * ((unsigned) (lo / qsz) >> 1);
- if (lo >= q->mthresh) {
- j = ((*q->qcmp) ((jj = base), i) > 0 ? jj : i);
- if ((*q->qcmp) (j, (tmp = max - qsz)) > 0) {
- /* switch to first loser */
- j = (j == jj ? i : jj);
- if ((*q->qcmp) (j, tmp) < 0)
- j = tmp;
- }
- if (j != i) {
- ii = qsz;
- do {
- c = *i;
- *i++ = *j;
- *j++ = c;
- } while (--ii);
- }
- }
- /* Semi-standard quicksort partitioning/swapping */
- for (i = base, j = max - qsz;;) {
- while (i < mid && (*q->qcmp) (i, mid) <= 0)
- i += qsz;
- while (j > mid) {
- if ((*q->qcmp) (mid, j) <= 0) {
- j -= qsz;
- continue;
+ lo = (int) (max - base); /* number of elements as chars */
+ do
+ {
+ /*
+ * At the top here, lo is the number of characters of elements in the
+ * current partition. (Which should be max - base). Find the median
+ * of the first, last, and middle element and make that the middle
+ * element. Set j to largest of first and middle. If max is larger
+ * than that guy, then it's that guy, else compare max with loser of
+ * first and take larger. Things are set up to prefer the middle,
+ * then the first in case of ties.
+ */
+ mid = i = base + qsz * ((unsigned) (lo / qsz) >> 1);
+ if (lo >= q->mthresh)
+ {
+ j = ((*q->qcmp) ((jj = base), i) > 0 ? jj : i);
+ if ((*q->qcmp) (j, (tmp = max - qsz)) > 0)
+ {
+ /* switch to first loser */
+ j = (j == jj ? i : jj);
+ if ((*q->qcmp) (j, tmp) < 0)
+ j = tmp;
+ }
+ if (j != i)
+ {
+ ii = qsz;
+ do
+ {
+ c = *i;
+ *i++ = *j;
+ *j++ = c;
+ }
+ while (--ii);
+ }
}
- tmp = i + qsz; /* value of i after swap */
- if (i == mid) { /* j <-> mid, new mid is j */
- mid = jj = j;
- } else { /* i <-> j */
- jj = j;
- j -= qsz;
+ /* Semi-standard quicksort partitioning/swapping */
+ for (i = base, j = max - qsz;;)
+ {
+ while (i < mid && (*q->qcmp) (i, mid) <= 0)
+ i += qsz;
+ while (j > mid)
+ {
+ if ((*q->qcmp) (mid, j) <= 0)
+ {
+ j -= qsz;
+ continue;
+ }
+ tmp = i + qsz; /* value of i after swap */
+ if (i == mid)
+ { /* j <-> mid, new mid is j */
+ mid = jj = j;
+ }
+ else
+ { /* i <-> j */
+ jj = j;
+ j -= qsz;
+ }
+ goto swap;
+ }
+ if (i == mid)
+ {
+ break;
+ }
+ else
+ { /* i <-> mid, new mid is i */
+ jj = mid;
+ tmp = mid = i; /* value of i after swap */
+ j -= qsz;
+ }
+ swap:
+ ii = qsz;
+ do
+ {
+ c = *i;
+ *i++ = *jj;
+ *jj++ = c;
+ }
+ while (--ii);
+ i = tmp;
+ }
+ /*
+ * Look at sizes of the two partitions, do the smaller one first by
+ * recursion, then do the larger one by making sure lo is its size,
+ * base and max are update correctly, and branching back. But only
+ * repeat (recursively or by branching) if the partition is of at
+ * least size THRESH.
+ */
+ i = (j = mid) + qsz;
+ if ((lo = (int) (j - base)) <= (hi = (int) (max - i)))
+ {
+ if (lo >= q->thresh)
+ qst (q, base, j);
+ base = i;
+ lo = hi;
+ }
+ else
+ {
+ if (hi >= q->thresh)
+ qst (q, i, max);
+ max = j;
}
- goto swap;
- }
- if (i == mid) {
- break;
- } else { /* i <-> mid, new mid is i */
- jj = mid;
- tmp = mid = i; /* value of i after swap */
- j -= qsz;
- }
- swap:
- ii = qsz;
- do {
- c = *i;
- *i++ = *jj;
- *jj++ = c;
- } while (--ii);
- i = tmp;
- }
- /*
- * Look at sizes of the two partitions, do the smaller one first by
- * recursion, then do the larger one by making sure lo is its size,
- * base and max are update correctly, and branching back. But only
- * repeat (recursively or by branching) if the partition is of at
- * least size THRESH.
- */
- i = (j = mid) + qsz;
- if ((lo = (int)(j - base)) <= (hi = (int)(max - i))) {
- if (lo >= q->thresh)
- qst(q, base, j);
- base = i;
- lo = hi;
- } else {
- if (hi >= q->thresh)
- qst(q, i, max);
- max = j;
}
- } while (lo >= q->thresh);
+ while (lo >= q->thresh);
}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */