/* sorttemplates.c version 2.0, Mar 13, 2018.
* Author: Brendan McKay; brendan.mckay@anu.edu.au
*
* This file contains templates for creating in-place sorting procedures
* for different data types. It cannot be compiled separately but
* should be #included after defining a few preprocessor variables.
* SORT_OF_SORT, SORT_NAME and SORT_TYPE1 are always required, and
* SORT_TYPE2 is needed for SORT_OF_SORT = 3,
* SORT_COMPARE is needed for SORT_OF_SORT = 4.
*
* SORT_OF_SORT = 1: Creates a procedure
* static void SORT_NAME(SORT_TYPE1 *x, int n)
* which permutes x[0..n-1] so that x[0] <= ... <= x[n-1].
* SORT_OF_SORT = 2: Creates a procedure
* static void SORT_NAME(SORT_TYPE1 *x, SORT_TYPE2 *y, int n)
* which permutes x[0..n-1] so that x[0] <= ... <= x[n-1]
* and also permutes y[0..n-1] by the same permutation.
* SORT_OF_SORT = 3: Creates a procedure
* static void SORT_NAME(SORT_TYPE1 *x, SORT_TYPE2 *y, int n)
* which permutes x[0..n-1] so that y[x[0]] <= ... <= y[x[n-1]].
* SORT_OF_SORT = 4: Creates a procedure
* static void SORT_NAME(SORT_TYPE1 *x, int n)
* which permutes x[0..n-1] so that
* SORT_COMPARE(x[i],x[j]) <= 0 for i<j.
* SORT_COMPARE(x,y) is an expression <0,0,>0 for x<y,x=y,x>y.
*
* SORT_NAME = the name of the procedure to be created
*
* SORT_TYPE1 = type of the first or only array (no default)
* This can be any numeric type for SORT_OF_SORT=1,2, but
* should be an integer type for SORT_OF_SORT=3.
* For SORT_OF_SORT=4, SORT_TYPE1 should be assignable;
* such as a simple type or a structure.
* SORT_TYPE2 = type of the second array if needed (no default)
* This can be any assignable type (including a structure) for
* SORT_OF_SORT=2, but must be a numeric type for SORT_OF_SORT=3.
*
* Note that C doesn't like SORT_TYPE1 and SORT_TYPE2 to be defined
* as explicit pointer types like int*. The simplest work-around
* is to define a type, e.g. typedef intptr int* then use that.
*
* SORT_MINPARTITION = least number of elements for using quicksort
* partitioning, otherwise insertion sort is used (default "11")
* SORT_MINMEDIAN9 = least number of elements for using the median of 3
* medians of 3 for partitioning (default "320")
* SORT_FUNCTYPE = type of sort function (default "static void")
*
* This file can be included any number of times provided the value
* of SORT_NAME is different each time.
*/
#define SORT_MEDIAN_OF_3(a,b,c) \
((a) <= (b) ? ((b) <= (c) ? (b) : (c) <= (a) ? (a) : (c)) \
: ((a) <= (c) ? (a) : (c) <= (b) ? (b) : (c)))
#define F_SORT_MEDIAN_OF_3(f,a,b,c) \
(f(a,b) <= 0 ? (f(b,c) <= 0 ? (b) : f(c,a) <= 0 ? (a) : (c)) \
: (f(a,c) <= 0 ? (a) : f(c,b) <= 0 ? (b) : (c)))
#if !defined(SORT_OF_SORT) || !defined(SORT_NAME)
#error Either SORT_OF_SORT or SORT_NAME is undefined
#endif
#if (SORT_OF_SORT < 1) || (SORT_OF_SORT > 4)
#error Unknown value of SORT_OF_SORT
#endif
#ifndef SORT_TYPE1
#error "SORT_TYPE1 must be defined before including sorttemplates.c"
#endif
#ifndef SORT_MINPARTITION
#define SORT_MINPARTITION 11
#endif
#ifndef SORT_MINMEDIAN9
#define SORT_MINMEDIAN9 320
#endif
#ifndef SORT_FUNCTYPE
#define SORT_FUNCTYPE static void
#endif
#define SORT_SWAP1(x,y) tmp1 = x; x = y; y = tmp1;
#define SORT_SWAP2(x,y) tmp2 = x; x = y; y = tmp2;
/*******************************************************************/
#if SORT_OF_SORT == 1
SORT_FUNCTYPE
SORT_NAME(SORT_TYPE1 *x, int n)
{
int i,j;
int a,d,ba,dc,s,nn;
SORT_TYPE1 tmp1,v,v1,v2,v3;
SORT_TYPE1 *x0,*xa,*xb,*xc,*xd,*xh,*xl;
struct {SORT_TYPE1 *addr; int len;} stack[40];
int top;
top = 0;
if (n > 1)
{
stack[top].addr = x;
stack[top].len = n;
++top;
}
while (top > 0)
{
--top;
x0 = stack[top].addr;
nn = stack[top].len;
if (nn < SORT_MINPARTITION)
{
for (i = 1; i < nn; ++i)
{
tmp1 = x0[i];
for (j = i; x0[j-1] > tmp1; )
{
x0[j] = x0[j-1];
if (--j == 0) break;
}
x0[j] = tmp1;
}
continue;
}
if (nn < SORT_MINMEDIAN9)
v = SORT_MEDIAN_OF_3(x0[0],x0[nn/2],x0[nn-1]);
else
{
v1 = SORT_MEDIAN_OF_3(x0[0],x0[1],x0[2]);
v2 = SORT_MEDIAN_OF_3(x0[nn/2-1],x0[nn/2],x0[nn/2+1]);
v3 = SORT_MEDIAN_OF_3(x0[nn-3],x0[nn-2],x0[nn-1]);
v = SORT_MEDIAN_OF_3(v1,v2,v3);
}
xa = xb = x0; xc = xd = x0+(nn-1);
for (;;)
{
while (xb <= xc && *xb <= v)
{
if (*xb == v)
{
*xb = *xa; *xa = v; ++xa;
}
++xb;
}
while (xc >= xb && *xc >= v)
{
if (*xc == v)
{
*xc = *xd; *xd = v; --xd;
}
--xc;
}
if (xb > xc) break;
SORT_SWAP1(*xb,*xc);
++xb;
--xc;
}
a = xa - x0;
ba = xb - xa;
if (ba > a) s = a; else s = ba;
for (xl = x0, xh = xb-s; s > 0; --s)
{
*xl = *xh; *xh = v; ++xl; ++xh;
}
d = xd - x0;
dc = xd - xc;
if (dc > nn-1-d) s = nn-1-d; else s = dc;
for (xl = xb, xh = x0 + (nn-s); s > 0; --s)
{
*xh = *xl; *xl = v; ++xl; ++xh;
}
if (ba > dc)
{
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
}
else
{
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
}
}
}
#endif
#if SORT_OF_SORT == 2
#ifndef SORT_TYPE2
#error "SORT_TYPE2 must be defined before including sorttemplates.c"
#endif
SORT_FUNCTYPE
SORT_NAME(SORT_TYPE1 *x, SORT_TYPE2 *y, int n)
{
int i,j;
int a,d,ba,dc,s,nn;
SORT_TYPE2 tmp2,*y0,*ya,*yb,*yc,*yd,*yl,*yh;
SORT_TYPE1 tmp1,v,v1,v2,v3;
SORT_TYPE1 *x0,*xa,*xb,*xc,*xd,*xh,*xl;
struct {SORT_TYPE1 *addr; int len;} stack[40];
int top;
top = 0;
if (n > 1)
{
stack[top].addr = x;
stack[top].len = n;
++top;
}
while (top > 0)
{
--top;
x0 = stack[top].addr;
y0 = y + (x0-x);
nn = stack[top].len;
if (nn < SORT_MINPARTITION)
{
for (i = 1; i < nn; ++i)
{
tmp1 = x0[i];
tmp2 = y0[i];
for (j = i; x0[j-1] > tmp1; )
{
x0[j] = x0[j-1];
y0[j] = y0[j-1];
if (--j == 0) break;
}
x0[j] = tmp1;
y0[j] = tmp2;
}
continue;
}
if (nn < SORT_MINMEDIAN9)
v = SORT_MEDIAN_OF_3(x0[0],x0[nn/2],x0[nn-1]);
else
{
v1 = SORT_MEDIAN_OF_3(x0[0],x0[1],x0[2]);
v2 = SORT_MEDIAN_OF_3(x0[nn/2-1],x0[nn/2],x0[nn/2+1]);
v3 = SORT_MEDIAN_OF_3(x0[nn-3],x0[nn-2],x0[nn-1]);
v = SORT_MEDIAN_OF_3(v1,v2,v3);
}
xa = xb = x0; xc = xd = x0+(nn-1);
ya = yb = y0; yc = yd = y0+(nn-1);
for (;;)
{
while (xb <= xc && *xb <= v)
{
if (*xb == v)
{
*xb = *xa; *xa = v; ++xa;
SORT_SWAP2(*ya,*yb); ++ya;
}
++xb; ++yb;
}
while (xc >= xb && *xc >= v)
{
if (*xc == v)
{
*xc = *xd; *xd = v; --xd;
SORT_SWAP2(*yc,*yd); --yd;
}
--xc; --yc;
}
if (xb > xc) break;
SORT_SWAP1(*xb,*xc);
SORT_SWAP2(*yb,*yc);
++xb; ++yb;
--xc; --yc;
}
a = xa - x0;
ba = xb - xa;
if (ba > a) s = a; else s = ba;
for (xl = x0, xh = xb-s, yl = y0, yh = yb-s; s > 0; --s)
{
*xl = *xh; *xh = v; ++xl; ++xh;
SORT_SWAP2(*yl,*yh); ++yl; ++yh;
}
d = xd - x0;
dc = xd - xc;
if (dc > nn-1-d) s = nn-1-d; else s = dc;
for (xl = xb, xh = x0+(nn-s), yl = yb, yh = y0+(nn-s); s > 0; --s)
{
*xh = *xl; *xl = v; ++xl; ++xh;
SORT_SWAP2(*yl,*yh); ++yl; ++yh;
}
if (ba > dc)
{
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
}
else
{
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
}
}
}
#endif
#if SORT_OF_SORT == 3
#ifndef SORT_TYPE2
#error "SORT_TYPE2 must be defined before including sorttemplates.c"
#endif
SORT_FUNCTYPE
SORT_NAME(SORT_TYPE1 *x, SORT_TYPE2 *y, int n)
{
int i,j;
int a,d,ba,dc,s,nn;
SORT_TYPE2 tmp2,v,v1,v2,v3;
SORT_TYPE1 tmp1,*x0,*xa,*xb,*xc,*xd,*xh,*xl;
struct {SORT_TYPE1 *addr; int len;} stack[40];
int top;
top = 0;
if (n > 1)
{
stack[top].addr = x;
stack[top].len = n;
++top;
}
while (top > 0)
{
--top;
x0 = stack[top].addr;
nn = stack[top].len;
if (nn < SORT_MINPARTITION)
{
for (i = 1; i < nn; ++i)
{
tmp1 = x0[i];
tmp2 = y[tmp1];
for (j = i; y[x0[j-1]] > tmp2; )
{
x0[j] = x0[j-1];
if (--j == 0) break;
}
x0[j] = tmp1;
}
continue;
}
if (nn < SORT_MINMEDIAN9)
v = SORT_MEDIAN_OF_3(y[x0[0]],y[x0[nn/2]],y[x0[nn-1]]);
else
{
v1 = SORT_MEDIAN_OF_3(y[x0[0]],y[x0[1]],y[x0[2]]);
v2 = SORT_MEDIAN_OF_3(y[x0[nn/2-1]],y[x0[nn/2]],y[x0[nn/2+1]]);
v3 = SORT_MEDIAN_OF_3(y[x0[nn-3]],y[x0[nn-2]],y[x0[nn-1]]);
v = SORT_MEDIAN_OF_3(v1,v2,v3);
}
xa = xb = x0; xc = xd = x0+(nn-1);
for (;;)
{
while (xb <= xc && y[*xb] <= v)
{
if (y[*xb] == v)
{
SORT_SWAP1(*xa,*xb); ++xa;
}
++xb;
}
while (xc >= xb && y[*xc] >= v)
{
if (y[*xc] == v)
{
SORT_SWAP1(*xc,*xd); --xd;
}
--xc;
}
if (xb > xc) break;
SORT_SWAP1(*xb,*xc);
++xb;
--xc;
}
a = xa - x0;
ba = xb - xa;
if (ba > a) s = a; else s = ba;
for (xl = x0, xh = xb-s; s > 0; --s)
{
SORT_SWAP1(*xl,*xh); ++xl; ++xh;
}
d = xd - x0;
dc = xd - xc;
if (dc > nn-1-d) s = nn-1-d; else s = dc;
for (xl = xb, xh = x0 + (nn-s); s > 0; --s)
{
SORT_SWAP1(*xl,*xh); ++xl; ++xh;
}
if (ba > dc)
{
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
}
else
{
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
}
}
}
#endif
#if SORT_OF_SORT == 4
#ifndef SORT_COMPARE
#error "SORT_COMPARE must be defined before including sorttemplates.c"
#endif
SORT_FUNCTYPE
SORT_NAME(SORT_TYPE1 *x, int n)
{
int i,j;
int a,d,ba,dc,s,nn;
SORT_TYPE1 tmp2,v,v1,v2,v3;
SORT_TYPE1 tmp1,*x0,*xa,*xb,*xc,*xd,*xh,*xl;
struct {SORT_TYPE1 *addr; int len;} stack[40];
int top;
top = 0;
if (n > 1)
{
stack[top].addr = x;
stack[top].len = n;
++top;
}
while (top > 0)
{
--top;
x0 = stack[top].addr;
nn = stack[top].len;
if (nn < SORT_MINPARTITION)
{
for (i = 1; i < nn; ++i)
{
tmp1 = x0[i];
for (j = i; SORT_COMPARE(tmp1,x0[j-1]) < 0; )
{
x0[j] = x0[j-1];
if (--j == 0) break;
}
x0[j] = tmp1;
}
continue;
}
if (nn < SORT_MINMEDIAN9)
v = F_SORT_MEDIAN_OF_3(SORT_COMPARE,x0[0],x0[nn/2],x0[nn-1]);
else
{
v1 = F_SORT_MEDIAN_OF_3(SORT_COMPARE,x0[0],x0[1],x0[2]);
v2 = F_SORT_MEDIAN_OF_3(SORT_COMPARE,x0[nn/2-1],x0[nn/2],x0[nn/2+1]);
v3 = F_SORT_MEDIAN_OF_3(SORT_COMPARE,x0[nn-3],x0[nn-2],x0[nn-1]);
v = F_SORT_MEDIAN_OF_3(SORT_COMPARE,v1,v2,v3);
}
xa = xb = x0; xc = xd = x0+(nn-1);
for (;;)
{
while (xb <= xc && SORT_COMPARE(*xb,v) <= 0)
{
if (SORT_COMPARE(*xb,v) == 0)
{
SORT_SWAP1(*xa,*xb); ++xa;
}
++xb;
}
while (xc >= xb && SORT_COMPARE(*xc,v) >= 0)
{
if (SORT_COMPARE(*xc,v) == 0)
{
SORT_SWAP1(*xc,*xd); --xd;
}
--xc;
}
if (xb > xc) break;
SORT_SWAP1(*xb,*xc);
++xb;
--xc;
}
a = xa - x0;
ba = xb - xa;
if (ba > a) s = a; else s = ba;
for (xl = x0, xh = xb-s; s > 0; --s)
{
SORT_SWAP1(*xl,*xh); ++xl; ++xh;
}
d = xd - x0;
dc = xd - xc;
if (dc > nn-1-d) s = nn-1-d; else s = dc;
for (xl = xb, xh = x0 + (nn-s); s > 0; --s)
{
SORT_SWAP1(*xl,*xh); ++xl; ++xh;
}
if (ba > dc)
{
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
}
else
{
if (dc > 1)
{
stack[top].addr = x0+(nn-dc); stack[top].len = dc; ++top;
}
if (ba > 1)
{
stack[top].addr = x0; stack[top].len = ba; ++top;
}
}
}
}
#endif
#undef SORT_NAME
#undef SORT_OF_SORT
#undef SORT_TYPE1
#undef SORT_TYPE2
#undef SORT_COMPARE
¤ Dauer der Verarbeitung: 0.11 Sekunden
¤
*© Formatika GbR, Deutschland
|
|