164 lines
4.1 KiB
C
Raw Normal View History

2022-08-30 15:42:35 +08:00
#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