Blender V4.3
sort.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <stdlib.h>
10
11#include "BLI_utildefines.h"
12
13#include "BLI_sort.h"
14
15#ifdef min /* For MSVC. */
16# undef min
17#endif
18
19/* Maintained by FreeBSD. */
20/* clang-format off */
21
29BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk);
30BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype);
31
32#define min(a, b) (a) < (b) ? (a) : (b)
33#define swapcode(TYPE, parmi, parmj, n) \
34{ \
35 long i = (n) / sizeof(TYPE); \
36 TYPE *pi = (TYPE *) (parmi); \
37 TYPE *pj = (TYPE *) (parmj); \
38 do { \
39 TYPE t = *pi; \
40 *pi++ = *pj; \
41 *pj++ = t; \
42 } while (--i > 0); \
43}
44#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
45 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
46
47BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype)
48{
49 if (swaptype <= 1)
50 swapcode(long, a, b, n)
51 else
52 swapcode(char, a, b, n)
53}
54
55#define swap(a, b) \
56 if (swaptype == 0) { \
57 long t = *(long *)(a); \
58 *(long *)(a) = *(long *)(b);\
59 *(long *)(b) = t; \
60 } else \
61 swapfunc(a, b, es, swaptype)
62
63#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
64#define CMP(t, x, y) (cmp((x), (y), (t)))
65
66BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk)
67{
68 return CMP(thunk, a, b) < 0 ?
69 (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) :
70 (CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
71}
72
76void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
77{
78 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
79 int d, r, swaptype, swap_cnt;
80
81loop:
82 SWAPINIT(a, es);
83 swap_cnt = 0;
84 if (n < 7) {
85 for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) {
86 for (pl = pm;
87 pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
88 pl -= es)
89 {
90 swap(pl, pl - es);
91 }
92 }
93 return;
94 }
95 pm = (char *)a + (n / 2) * es;
96 if (n > 7) {
97 pl = (char *)a;
98 pn = (char *)a + (n - 1) * es;
99 if (n > 40) {
100 d = (n / 8) * es;
101 pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
102 pm = med3(pm - d, pm, pm + d, cmp, thunk);
103 pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
104 }
105 pm = med3(pl, pm, pn, cmp, thunk);
106 }
107 swap((char *)a, pm);
108 pa = pb = (char *)a + es;
109
110 pc = pd = (char *)a + (n - 1) * es;
111 for (;;) {
112 while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
113 if (r == 0) {
114 swap_cnt = 1;
115 swap(pa, pb);
116 pa += es;
117 }
118 pb += es;
119 }
120 while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
121 if (r == 0) {
122 swap_cnt = 1;
123 swap(pc, pd);
124 pd -= es;
125 }
126 pc -= es;
127 }
128 if (pb > pc) {
129 break;
130 }
131 swap(pb, pc);
132 swap_cnt = 1;
133 pb += es;
134 pc -= es;
135 }
136 if (swap_cnt == 0) { /* Switch to insertion sort */
137 for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) {
138 for (pl = pm;
139 pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
140 pl -= es)
141 {
142 swap(pl, pl - es);
143 }
144 }
145 return;
146 }
147
148 pn = (char *)a + n * es;
149 r = min(pa - (char *)a, pb - pa);
150 vecswap((char *)a, pb - r, r);
151 r = min(pd - pc, pn - pd - es);
152 vecswap(pb, pn - r, r);
153 if ((r = pb - pa) > es) {
154 BLI_qsort_r(a, r / es, es, cmp, thunk);
155 }
156 if ((r = pd - pc) > es) {
157 /* Iterate rather than recurse to save stack space */
158 a = pn - r;
159 n = r / es;
160 goto loop;
161 }
162}
163
164/* clang-format on */
#define BLI_INLINE
int(* BLI_sort_cmp_t)(const void *a, const void *b, void *ctx)
Definition BLI_sort.h:18
local_group_size(16, 16) .push_constant(Type b
BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype)
Definition sort.c:47
#define swap(a, b)
Definition sort.c:55
#define vecswap(a, b, n)
Definition sort.c:63
#define CMP(t, x, y)
Definition sort.c:64
#define swapcode(TYPE, parmi, parmj, n)
Definition sort.c:33
#define min(a, b)
Definition sort.c:32
BLI_INLINE char * med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk)
Definition sort.c:66
#define SWAPINIT(a, es)
Definition sort.c:44
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition sort.c:76