Blender  V2.93
list_sort_impl.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
46 /* -------------------------------------------------------------------- */
47 /* Handle External Defines */
48 
49 /* check we're not building directly */
50 #if !defined(SORT_IMPL_LINKTYPE) || !defined(SORT_IMPL_FUNC)
51 # error "This file can't be compiled directly, include in another source file"
52 #endif
53 
54 #define list_node SORT_IMPL_LINKTYPE
55 #define list_sort_do SORT_IMPL_FUNC
56 
57 #ifdef SORT_IMPL_LINKTYPE_DATA
58 # define SORT_ARG(n) ((n)->SORT_IMPL_LINKTYPE_DATA)
59 #else
60 # define SORT_ARG(n) (n)
61 #endif
62 
63 #ifdef SORT_IMPL_USE_THUNK
64 # define THUNK_APPEND1(a, thunk) a, thunk
65 # define THUNK_PREPEND2(thunk, a, b) thunk, a, b
66 #else
67 # define THUNK_APPEND1(a, thunk) a
68 # define THUNK_PREPEND2(thunk, a, b) a, b
69 #endif
70 
71 #define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
72 #define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
73 #define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id)
74 
75 /* local identifiers */
76 #define SortInfo _SORT_PREFIX(SortInfo)
77 #define CompareFn _SORT_PREFIX(CompareFn)
78 #define init_sort_info _SORT_PREFIX(init_sort_info)
79 #define merge_lists _SORT_PREFIX(merge_lists)
80 #define sweep_up _SORT_PREFIX(sweep_up)
81 #define insert_list _SORT_PREFIX(insert_list)
82 
83 typedef int (*CompareFn)(
84 #ifdef SORT_IMPL_USE_THUNK
85  void *thunk,
86 #endif
87  const void *,
88  const void *);
89 
90 /* -------------------------------------------------------------------- */
91 /* MIT license from original source */
92 
93 /*
94  * Permission is hereby granted, free of charge, to any person obtaining
95  * a copy of this software and associated documentation files (the
96  * "Software"), to deal in the Software without restriction, including
97  * without limitation the rights to use, copy, modify, merge, publish,
98  * distribute, sublicense, and/or sell copies of the Software, and to
99  * permit persons to whom the Software is furnished to do so, subject to
100  * the following conditions:
101  *
102  * The above copyright notice and this permission notice shall be
103  * included in all copies or substantial portions of the Software.
104  *
105  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
106  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
107  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
108  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
109  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
110  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
111  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
112  *
113  * Author:
114  * Raja R Harinath <rharinath@novell.com>
115  */
116 
126 #define FLOOR_LOG2(x) \
127  (((x) >= 2) + ((x) >= 4) + ((x) >= 8) + ((x) >= 16) + ((x) >= 32) + ((x) >= 64) + ((x) >= 128))
128 #define MAX_RANKS ((sizeof(size_t) * 8) - FLOOR_LOG2(sizeof(list_node)) - 1)
129 
130 struct SortInfo {
131  unsigned int min_rank, n_ranks;
133 
134 #ifdef SORT_IMPL_USE_THUNK
135  void *thunk;
136 #endif
137 
143 };
144 
146  CompareFn func
147 #ifdef SORT_IMPL_USE_THUNK
148  ,
149  void *thunk
150 #endif
151 )
152 {
153  si->min_rank = si->n_ranks = 0;
154  si->func = func;
155  /* we don't need to initialize si->ranks,
156  * since we never lookup past si->n_ranks. */
157 
158 #ifdef SORT_IMPL_USE_THUNK
159  si->thunk = thunk;
160 #endif
161 }
162 
164  list_node *second,
165  CompareFn func
166 #ifdef SORT_IMPL_USE_THUNK
167  ,
168  void *thunk
169 #endif
170 )
171 {
172  /* merge the two lists */
173  list_node *list = NULL;
174  list_node **pos = &list;
175  while (first && second) {
176  if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
177  *pos = second;
178  second = second->next;
179  }
180  else {
181  *pos = first;
182  first = first->next;
183  }
184  pos = &((*pos)->next);
185  }
186  *pos = first ? first : second;
187  return list;
188 }
189 
194 BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned int upto)
195 {
196  unsigned int i;
197  for (i = si->min_rank; i < upto; i++) {
198  list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
199  si->ranks[i] = NULL;
200  }
201  return list;
202 }
203 
233 BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int rank)
234 {
235  unsigned int i;
236 
237  if (rank > si->n_ranks) {
238  if (UNLIKELY(rank > MAX_RANKS)) {
239  // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank);
240  rank = MAX_RANKS;
241  }
242  list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk));
243  for (i = si->n_ranks; i < rank; i++) {
244  si->ranks[i] = NULL;
245  }
246  }
247  else {
248  if (rank) {
249  list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk));
250  }
251  for (i = rank; i < si->n_ranks && si->ranks[i]; i++) {
252  list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
253  si->ranks[i] = NULL;
254  }
255  }
256 
257  /* Will _never_ happen: so we can just devolve into quadratic ;-) */
258  if (UNLIKELY(i == MAX_RANKS)) {
259  i--;
260  }
261 
262  if (i >= si->n_ranks) {
263  si->n_ranks = i + 1;
264  }
265 
266  si->min_rank = i;
267  si->ranks[i] = list;
268 }
269 
270 #undef MAX_RANKS
271 #undef FLOOR_LOG2
272 
277  CompareFn func
278 #ifdef SORT_IMPL_USE_THUNK
279  ,
280  void *thunk
281 #endif
282 )
283 {
284  struct SortInfo si;
285 
286  init_sort_info(&si,
287  func
288 #ifdef SORT_IMPL_USE_THUNK
289  ,
290  thunk
291 #endif
292  );
293 
294  while (list && list->next) {
295  list_node *next = list->next;
296  list_node *tail = next->next;
297 
298  if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
299  next->next = list;
300  next = list;
301  list = list->next;
302  }
303  next->next = NULL;
304 
305  insert_list(&si, list, 0);
306 
307  list = tail;
308  }
309 
310  return sweep_up(&si, list, si.n_ranks);
311 }
312 
313 #undef _CONCAT_AUX
314 #undef _CONCAT
315 #undef _SORT_PREFIX
316 
317 #undef SortInfo
318 #undef CompareFn
319 #undef init_sort_info
320 #undef merge_lists
321 #undef sweep_up
322 #undef insert_list
323 
324 #undef list_node
325 #undef list_sort_do
326 
327 #undef THUNK_APPEND1
328 #undef THUNK_PREPEND2
329 #undef SORT_ARG
#define BLI_INLINE
#define UNLIKELY(x)
uint pos
#define SORT_ARG(n)
#define merge_lists
#define list_node
#define list_sort_do
#define init_sort_info
#define CompareFn
#define THUNK_PREPEND2(thunk, a, b)
#define insert_list
#define MAX_RANKS
#define THUNK_APPEND1(a, thunk)
#define sweep_up
static ulong * next
CompareFn func
list_node * ranks[MAX_RANKS]
unsigned int min_rank
unsigned int n_ranks