164 lines
4.1 KiB
C
164 lines
4.1 KiB
C
#ifndef _sort_h_INCLUDED
|
|
#define _sort_h_INCLUDED
|
|
|
|
#include "utilities.h"
|
|
|
|
#define GREATER_SWAP(TYPE,P,Q,LESS) \
|
|
do { \
|
|
if (LESS (Q, P)) \
|
|
SWAP (TYPE, P, Q); \
|
|
} while(0)
|
|
|
|
#define SORTER (solver->sorter)
|
|
|
|
#define PARTITION(TYPE,L,R,A,LESS) \
|
|
do { \
|
|
const size_t L_PARTITION = (L); \
|
|
I_QUICK_SORT = L_PARTITION - 1; \
|
|
\
|
|
size_t J_PARTITION = (R); \
|
|
\
|
|
TYPE PIVOT_PARTITION = A[J_PARTITION]; \
|
|
\
|
|
for (;;) \
|
|
{ \
|
|
while (LESS (A[++I_QUICK_SORT], PIVOT_PARTITION)) \
|
|
; \
|
|
while (LESS (PIVOT_PARTITION, A[--J_PARTITION])) \
|
|
if (J_PARTITION == L_PARTITION) \
|
|
break; \
|
|
\
|
|
if (I_QUICK_SORT >= J_PARTITION) \
|
|
break; \
|
|
\
|
|
SWAP (TYPE, A[I_QUICK_SORT], A[J_PARTITION]); \
|
|
} \
|
|
\
|
|
SWAP (TYPE, A[I_QUICK_SORT], A[R]); \
|
|
} while(0)
|
|
|
|
#define QUICK_SORT_LIMIT 10
|
|
|
|
#define QUICK_SORT(TYPE,N,A,LESS) \
|
|
do { \
|
|
assert (N); \
|
|
assert (EMPTY_STACK (SORTER)); \
|
|
\
|
|
size_t L_QUICK_SORT = 0; \
|
|
size_t R_QUICK_SORT = N - 1; \
|
|
\
|
|
if (R_QUICK_SORT - L_QUICK_SORT <= QUICK_SORT_LIMIT) \
|
|
break; \
|
|
\
|
|
for (;;) \
|
|
{ \
|
|
const size_t M = L_QUICK_SORT + (R_QUICK_SORT - L_QUICK_SORT) / 2; \
|
|
\
|
|
SWAP (TYPE, A[M], A[R_QUICK_SORT - 1]); \
|
|
\
|
|
GREATER_SWAP (TYPE, A[L_QUICK_SORT], A[R_QUICK_SORT - 1], LESS); \
|
|
GREATER_SWAP (TYPE, A[L_QUICK_SORT], A[R_QUICK_SORT], LESS); \
|
|
GREATER_SWAP (TYPE, A[R_QUICK_SORT - 1], A[R_QUICK_SORT], LESS); \
|
|
\
|
|
size_t I_QUICK_SORT; \
|
|
\
|
|
PARTITION (TYPE, L_QUICK_SORT + 1, R_QUICK_SORT - 1, A, LESS); \
|
|
assert (L_QUICK_SORT < I_QUICK_SORT); \
|
|
assert (I_QUICK_SORT <= R_QUICK_SORT); \
|
|
\
|
|
size_t LL_QUICK_SORT; \
|
|
size_t RR_QUICK_SORT; \
|
|
\
|
|
if (I_QUICK_SORT - L_QUICK_SORT < R_QUICK_SORT - I_QUICK_SORT) \
|
|
{ \
|
|
LL_QUICK_SORT = I_QUICK_SORT + 1; \
|
|
RR_QUICK_SORT = R_QUICK_SORT; \
|
|
R_QUICK_SORT = I_QUICK_SORT - 1; \
|
|
} \
|
|
else \
|
|
{ \
|
|
LL_QUICK_SORT = L_QUICK_SORT; \
|
|
RR_QUICK_SORT = I_QUICK_SORT - 1; \
|
|
L_QUICK_SORT = I_QUICK_SORT + 1; \
|
|
} \
|
|
if (R_QUICK_SORT - L_QUICK_SORT > QUICK_SORT_LIMIT) \
|
|
{ \
|
|
assert (RR_QUICK_SORT - LL_QUICK_SORT > QUICK_SORT_LIMIT); \
|
|
PUSH_STACK (SORTER, LL_QUICK_SORT); \
|
|
PUSH_STACK (SORTER, RR_QUICK_SORT); \
|
|
} \
|
|
else if (RR_QUICK_SORT - LL_QUICK_SORT > QUICK_SORT_LIMIT) \
|
|
{ \
|
|
L_QUICK_SORT = LL_QUICK_SORT; \
|
|
R_QUICK_SORT = RR_QUICK_SORT; \
|
|
} \
|
|
else if (!EMPTY_STACK (SORTER)) \
|
|
{ \
|
|
R_QUICK_SORT = POP_STACK (SORTER); \
|
|
L_QUICK_SORT = POP_STACK (SORTER); \
|
|
} else break; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define INSERTION_SORT(TYPE,N,A,LESS) \
|
|
do { \
|
|
size_t L_INSERTION_SORT = 0; \
|
|
size_t R_INSERTION_SORT = N - 1; \
|
|
\
|
|
for (size_t I_INSERTION_SORT = R_INSERTION_SORT; \
|
|
I_INSERTION_SORT > L_INSERTION_SORT; \
|
|
I_INSERTION_SORT--) \
|
|
GREATER_SWAP (TYPE, A[I_INSERTION_SORT - 1], A[I_INSERTION_SORT], LESS); \
|
|
\
|
|
for (size_t I_INSERTION_SORT = L_INSERTION_SORT + 2; \
|
|
I_INSERTION_SORT <= R_INSERTION_SORT; \
|
|
I_INSERTION_SORT++) \
|
|
{ \
|
|
TYPE PIVOT_INSERTION_SORT = A[I_INSERTION_SORT]; \
|
|
\
|
|
size_t J_INSERTION_SORT = I_INSERTION_SORT; \
|
|
\
|
|
while (LESS (PIVOT_INSERTION_SORT, A[J_INSERTION_SORT - 1])) \
|
|
{ \
|
|
A[J_INSERTION_SORT] = A[J_INSERTION_SORT - 1]; \
|
|
J_INSERTION_SORT--; \
|
|
} \
|
|
\
|
|
A[J_INSERTION_SORT] = PIVOT_INSERTION_SORT; \
|
|
} \
|
|
} while (0)
|
|
|
|
#ifdef NDEBUG
|
|
#define CHECK_SORTED(...) do { } while(0)
|
|
#else
|
|
#define CHECK_SORTED(N,A,LESS) \
|
|
do { \
|
|
for (size_t I_CHECK_SORTED = 0; I_CHECK_SORTED < N - 1; I_CHECK_SORTED++) \
|
|
assert (!LESS (A[I_CHECK_SORTED+1], A[I_CHECK_SORTED])); \
|
|
} while(0)
|
|
#endif
|
|
|
|
#define SORT(TYPE,N,A,LESS) \
|
|
do { \
|
|
const size_t N_SORT = (N); \
|
|
if (!N_SORT) \
|
|
break; \
|
|
START (sort); \
|
|
TYPE * A_SORT = (A); \
|
|
QUICK_SORT (TYPE, N_SORT, A_SORT, LESS); \
|
|
INSERTION_SORT (TYPE, N_SORT, A_SORT, LESS); \
|
|
CHECK_SORTED (N_SORT, A_SORT, LESS); \
|
|
STOP (sort); \
|
|
} while (0)
|
|
|
|
#define SORT_STACK(TYPE,S,LESS) \
|
|
do { \
|
|
const size_t N_SORT_STACK = SIZE_STACK (S); \
|
|
if (N_SORT_STACK <= 1) \
|
|
break; \
|
|
TYPE * A_SORT_STACK = BEGIN_STACK (S); \
|
|
SORT (TYPE, N_SORT_STACK, A_SORT_STACK, LESS); \
|
|
} while (0)
|
|
|
|
#endif
|