Adding a generic merge sort if container has both _splice_back & _splice_at

methods
This commit is contained in:
Patrick Pelissier committed 2018-05-28 23:51:41 +02:00
1 parent e62ae9fb94
commit 38cd8847a2
1 file changed
+86
+86
View File
@@ -373,6 +373,7 @@
\
/* Sort can be generated from 3 algorithms: */ \
/* - a specialized version defined by the container */ \
/* - an unstable merge sort (need 'splice_back' method) */ \
/* - an insertion sort (need 'previous' method) */ \
/* - a selection sort */ \
M_IF_METHOD(SORT, cont_oplist)( \
@@ -382,6 +383,90 @@
M_GET_SORT cont_oplist(l, M_C3(name,sort_name,_cmp)); \
} \
, \
M_IF_METHOD2(SPLICE_BACK, SPLICE_AT, cont_oplist)( \
/* MERGE SORT (unstable) */ \
static inline void M_C3(name,sort_name,_split)(container_t l1, container_t l2, container_t l) \
{ \
it_t it; \
bool b = false; \
for (M_GET_IT_FIRST cont_oplist(it, l); \
!M_GET_IT_END_P cont_oplist (it);) { \
M_GET_SPLICE_BACK cont_oplist(b ? l1 : l2, l, it); \
b = !b; \
} \
/* assert(M_GET_EMPTY_P cont_oplist(l)); */ \
} \
\
static inline void M_C3(name,sort_name,_merge)(container_t l, container_t l1, container_t l2) \
{ \
/* assert(M_GET_EMPTY_P cont_oplist(l)); */ \
it_t it; \
it_t it1; \
it_t it2; \
M_GET_IT_END cont_oplist (it, l); \
M_GET_IT_FIRST cont_oplist(it1, l1); \
M_GET_IT_FIRST cont_oplist(it2, l2); \
while (true) { \
int c = M_C3(name,sort_name,_cmp)(M_GET_IT_CREF cont_oplist (it1), \
M_GET_IT_CREF cont_oplist (it2)); \
if (c <= 0) { \
M_GET_SPLICE_AT cont_oplist (l, it, l1, it1); \
if (M_UNLIKELY (M_GET_IT_END_P cont_oplist (it1))) { \
while (!M_GET_IT_END_P cont_oplist (it2)) { \
M_GET_SPLICE_AT cont_oplist (l, it, l2, it2); \
} \
return; \
} \
} else { \
M_GET_SPLICE_AT cont_oplist (l, it, l2, it2); \
if (M_UNLIKELY (M_GET_IT_END_P cont_oplist (it2))) { \
while (!M_GET_IT_END_P cont_oplist (it1)) { \
M_GET_SPLICE_AT cont_oplist (l, it, l1, it1); \
} \
return; \
} \
} \
} \
} \
\
static inline void M_C(name,sort_name)(container_t l) \
{ \
container_t l1; \
container_t l2; \
it_t it; \
it_t it1; \
it_t it2; \
/* First deal with 0, 1, or 2 size container */ \
M_GET_IT_FIRST cont_oplist (it, l); \
if (M_UNLIKELY (M_GET_IT_END_P cont_oplist(it))) \
return; \
M_GET_IT_SET cont_oplist (it1, it); \
M_GET_IT_NEXT cont_oplist (it); \
if (M_UNLIKELY (M_GET_IT_END_P cont_oplist(it))) \
return; \
M_GET_IT_SET cont_oplist (it2, it); \
M_GET_IT_NEXT cont_oplist (it); \
if (M_UNLIKELY (M_GET_IT_END_P cont_oplist(it))) { \
/* Two elements */ \
int c = M_C3(name,sort_name,_cmp)(M_GET_IT_CREF cont_oplist (it1), \
M_GET_IT_CREF cont_oplist (it2)); \
if (c > 0) { \
/* SWAP */ \
M_GET_SPLICE_BACK cont_oplist (l, l, it2); \
} \
return; \
} \
/* Container length is greater than 2: split, sort & merge */ \
M_GET_INIT cont_oplist(l1); \
M_GET_INIT cont_oplist(l2); \
M_C3(name,sort_name,_split)(l1, l2, l); \
M_C(name,sort_name)(l1); \
M_C(name,sort_name)(l2); \
M_C3(name,sort_name,_merge)(l, l1, l2); \
M_GET_CLEAR cont_oplist(l2); \
M_GET_CLEAR cont_oplist(l1); \
} \
, \
M_IF_METHOD(IT_PREVIOUS, cont_oplist)( \
/* generic insertion sort */ \
static inline void M_C(name,sort_name)(container_t l) \
@@ -438,6 +523,7 @@
} \
} \
) /* IF IT_PREVIOUS METHOD */ \
) /* SPLICE BACK METHOD */ \
) /* IF SORT METHOD */ \
/* Compute the union of two ***sorted*** containers */ \
M_IF_METHOD(IT_INSERT, cont_oplist)( \