Blender V5.0
list_sort_impl.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
33
34/* -------------------------------------------------------------------- */
35/* Handle External Defines */
36
37#include "BLI_compiler_compat.h"
38#include "BLI_utildefines.h"
39
40/* check we're not building directly */
41#if !defined(SORT_IMPL_LINKTYPE) || !defined(SORT_IMPL_FUNC)
42# error "This file can't be compiled directly, include in another source file"
43#endif
44
45#define list_node SORT_IMPL_LINKTYPE
46#define list_sort_do SORT_IMPL_FUNC
47
48#ifdef SORT_IMPL_LINKTYPE_DATA
49# define SORT_ARG(n) ((n)->SORT_IMPL_LINKTYPE_DATA)
50#else
51# define SORT_ARG(n) (n)
52#endif
53
54#ifdef SORT_IMPL_USE_THUNK
55# define BLI_LIST_THUNK_APPEND1(a, thunk) a, thunk
56# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) thunk, a, b
57#else
58# define BLI_LIST_THUNK_APPEND1(a, thunk) a
59# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) a, b
60#endif
61
62#define _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
63#define _BLI_LIST_SORT_CONCAT(MACRO_ARG1, MACRO_ARG2) \
64 _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
65#define _BLI_LIST_SORT_PREFIX(id) _BLI_LIST_SORT_CONCAT(SORT_IMPL_FUNC, _##id)
66
67/* local identifiers */
68#define SortInfo _BLI_LIST_SORT_PREFIX(SortInfo)
69#define CompareFn _BLI_LIST_SORT_PREFIX(CompareFn)
70#define init_sort_info _BLI_LIST_SORT_PREFIX(init_sort_info)
71#define merge_lists _BLI_LIST_SORT_PREFIX(merge_lists)
72#define sweep_up _BLI_LIST_SORT_PREFIX(sweep_up)
73#define insert_list _BLI_LIST_SORT_PREFIX(insert_list)
74
75typedef int (*CompareFn)(
76#ifdef SORT_IMPL_USE_THUNK
77 void *thunk,
78#endif
79 const void *,
80 const void *);
81
82/* -------------------------------------------------------------------- */
83/* MIT license from original source */
84
85/*
86 * Permission is hereby granted, free of charge, to any person obtaining
87 * a copy of this software and associated documentation files (the
88 * "Software"), to deal in the Software without restriction, including
89 * without limitation the rights to use, copy, modify, merge, publish,
90 * distribute, sublicense, and/or sell copies of the Software, and to
91 * permit persons to whom the Software is furnished to do so, subject to
92 * the following conditions:
93 *
94 * The above copyright notice and this permission notice shall be
95 * included in all copies or substantial portions of the Software.
96 *
97 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
98 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
99 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
100 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
101 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
102 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
103 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
104 *
105 * Author:
106 * Raja R Harinath <rharinath@novell.com>
107 */
108
118#define FLOOR_LOG2(x) \
119 (((x) >= 2) + ((x) >= 4) + ((x) >= 8) + ((x) >= 16) + ((x) >= 32) + ((x) >= 64) + ((x) >= 128))
120#define MAX_RANKS ((sizeof(size_t) * 8) - FLOOR_LOG2(sizeof(list_node)) - 1)
121
122struct SortInfo {
123 unsigned int min_rank, n_ranks;
125
126#ifdef SORT_IMPL_USE_THUNK
127 void *thunk;
128#endif
129
130 /* Invariant: `ranks[i] == NULL || length(ranks[i]) >= 2**(i+1)`.
131 * ~ 128 bytes on 32bit, ~ 512 bytes on 64bit. */
133};
134
135inline void init_sort_info(struct SortInfo *si,
136 CompareFn func
138 ,
139 void *thunk
140#endif
141)
142{
143 si->min_rank = si->n_ranks = 0;
144 si->func = func;
145 /* we don't need to initialize si->ranks,
146 * since we never lookup past si->n_ranks. */
147
148#ifdef SORT_IMPL_USE_THUNK
149 si->thunk = thunk;
150#endif
151}
152
154 list_node *second,
155 CompareFn func
157 ,
158 void *thunk
159#endif
160)
161{
162 /* merge the two lists */
163 list_node *list = NULL;
164 list_node **pos = &list;
165 while (first && second) {
166 if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
167 *pos = second;
168 second = second->next;
169 }
170 else {
171 *pos = first;
172 first = first->next;
173 }
174 pos = &((*pos)->next);
175 }
176 *pos = first ? first : second;
177 return list;
178}
179
184BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned int upto)
185{
186 unsigned int i;
187 for (i = si->min_rank; i < upto; i++) {
188 list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
189 si->ranks[i] = NULL;
190 }
191 return list;
192}
193
217
223BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int rank)
224{
225 unsigned int i;
226
227 if (rank > si->n_ranks) {
228 if (UNLIKELY(rank > MAX_RANKS)) {
229 // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank);
230 rank = MAX_RANKS;
231 }
232 list = merge_lists(
233 sweep_up(si, NULL, si->n_ranks), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
234 for (i = si->n_ranks; i < rank; i++) {
235 si->ranks[i] = NULL;
236 }
237 }
238 else {
239 if (rank) {
240 list = merge_lists(
241 sweep_up(si, NULL, rank), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
242 }
243 for (i = rank; i < si->n_ranks && si->ranks[i]; i++) {
244 list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
245 si->ranks[i] = NULL;
246 }
247 }
248
249 /* Will _never_ happen: so we can just devolve into quadratic ;-) */
250 if (UNLIKELY(i == MAX_RANKS)) {
251 i--;
252 }
253
254 if (i >= si->n_ranks) {
255 si->n_ranks = i + 1;
256 }
257
258 si->min_rank = i;
259 si->ranks[i] = list;
260}
261
262#undef MAX_RANKS
263#undef FLOOR_LOG2
264
269 CompareFn func
271 ,
272 void *thunk
273#endif
274)
275{
276 struct SortInfo si;
277
278 init_sort_info(&si,
279 func
281 ,
282 thunk
283#endif
284 );
285
286 while (list && list->next) {
287 list_node *next = list->next;
288 list_node *tail = next->next;
289
290 if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
291 next->next = list;
292 next = list;
293 list = list->next;
294 }
295 next->next = NULL;
296
297 insert_list(&si, list, 0);
298
299 list = tail;
300 }
301
302 return sweep_up(&si, list, si.n_ranks);
303}
304
305#undef _BLI_LIST_SORT_CONCAT_AUX
306#undef _BLI_LIST_SORT_CONCAT
307#undef _SORT_PREFIX
308
309#undef SortInfo
310#undef CompareFn
311#undef init_sort_info
312#undef merge_lists
313#undef sweep_up
314#undef insert_list
315
316#undef list_node
317#undef list_sort_do
318
319#undef BLI_LIST_THUNK_APPEND1
320#undef BLI_LIST_THUNK_PREPEND2
321#undef SORT_ARG
#define BLI_INLINE
#define UNLIKELY(x)
uint pos
#define BLI_LIST_THUNK_PREPEND2(thunk, a, b)
#define SORT_ARG(n)
#define BLI_LIST_THUNK_APPEND1(a, thunk)
#define merge_lists
#define SortInfo
#define list_node
#define list_sort_do
#define init_sort_info
#define CompareFn
#define insert_list
#define MAX_RANKS
#define sweep_up
static ulong * next
CompareFn func
list_node * ranks[MAX_RANKS]
unsigned int min_rank
unsigned int n_ranks
i
Definition text_draw.cc:230