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