1 /****************************************************************************
2 **
3 ** DQt - D bindings for the Qt Toolkit
4 **
5 ** GNU Lesser General Public License Usage
6 ** This file may be used under the terms of the GNU Lesser
7 ** General Public License version 3 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 ** packaging of this file. Please review the following information to
10 ** ensure the GNU Lesser General Public License version 3 requirements
11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 **
13 ****************************************************************************/
14 module qt.core.algorithms;
15 extern(C++):
16 
17 import qt.config;
18 import qt.helpers;
19 
20 /+ #ifdef Q_CC_MSVC
21 #endif
22 
23 QT_WARNING_PUSH
24 QT_WARNING_DISABLE_DEPRECATED
25 
26 /*
27     Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
28     and may be changed from version to version or even be completely removed.
29 */
30 namespace QAlgorithmsPrivate {
31 
32 #if QT_DEPRECATED_SINCE(5, 2)
33 template <typename RandomAccessIterator, typename T, typename LessThan>
34 QT_DEPRECATED_X("Use std::sort") void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
35 template <typename RandomAccessIterator, typename T>
36 QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy);
37 template <typename RandomAccessIterator, typename T, typename LessThan>
38 QT_DEPRECATED_X("Use std::stable_sort") void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
39 template <typename RandomAccessIterator, typename T>
40 QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &);
41 template <typename RandomAccessIterator, typename T, typename LessThan>
42 QT_DEPRECATED_X("Use std::lower_bound") RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
43 template <typename RandomAccessIterator, typename T, typename LessThan>
44 QT_DEPRECATED_X("Use std::upper_bound") RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
45 template <typename RandomAccessIterator, typename T, typename LessThan>
46 QT_DEPRECATED_X("Use std::binary_search") RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
47 #endif // QT_DEPRECATED_SINCE(5, 2)
48 
49 }
50 
51 #if QT_DEPRECATED_SINCE(5, 2) +/
52 /+ QT_DEPRECATED_X("Use std::copy") +/ pragma(inline, true) OutputIterator qCopy(InputIterator, OutputIterator)(InputIterator begin, InputIterator end, OutputIterator dest)
53 {
54     while (begin != end)
55         *dest++ = *begin++;
56     return dest;
57 }
58 
59 /+ QT_DEPRECATED_X("Use std::copy_backward") +/ pragma(inline, true) BiIterator2 qCopyBackward(BiIterator1, BiIterator2)(BiIterator1 begin, BiIterator1 end, BiIterator2 dest)
60 {
61     while (begin != end)
62         *--dest = *--end;
63     return dest;
64 }
65 
66 /+ QT_DEPRECATED_X("Use std::equal") +/ pragma(inline, true) bool qEqual(InputIterator1, InputIterator2)(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
67 {
68     for (; first1 != last1; ++first1, ++first2)
69         if (!(*first1 == *first2))
70             return false;
71     return true;
72 }
73 
74 /+ QT_DEPRECATED_X("Use std::fill") +/ pragma(inline, true) void qFill(ForwardIterator, T)(ForwardIterator first, ForwardIterator last, ref const(T) val)
75 {
76     for (; first != last; ++first)
77         *first = val;
78 }
79 
80 /+ QT_DEPRECATED_X("Use std::fill") +/ pragma(inline, true) void qFill(Container, T)(ref Container container, ref const(T) val)
81 {
82     qFill(container.begin(), container.end(), val);
83 }
84 
85 /+ QT_DEPRECATED_X("Use std::find") +/ pragma(inline, true) InputIterator qFind(InputIterator, T)(InputIterator first, InputIterator last, ref const(T) val)
86 {
87     while (first != last && !(*first == val))
88         ++first;
89     return first;
90 }
91 
92 /+ QT_DEPRECATED_X("Use std::find") +/ /+ typename Container::const_iterator +/pragma(inline, true) UnknownType!q{} qFind(Container, T)(ref const(Container) container, ref const(T) val)
93 {
94     return qFind(container.constBegin(), container.constEnd(), val);
95 }
96 
97 /+ QT_DEPRECATED_X("Use std::count") +/ pragma(inline, true) void qCount(InputIterator, T, Size)(InputIterator first, InputIterator last, ref const(T) value, ref Size n)
98 {
99     for (; first != last; ++first)
100         if (*first == value)
101             ++n;
102 }
103 
104 /+ QT_DEPRECATED_X("Use std::count") +/ pragma(inline, true) void qCount(Container, T, Size)(ref const(Container) container, ref const(T) value, ref Size n)
105 {
106     qCount(container.constBegin(), container.constEnd(), value, n);
107 }
108 
109 /+ #ifdef Q_QDOC
110 typedef void* LessThan;
111 template <typename T> LessThan qLess();
112 template <typename T> LessThan qGreater();
113 #else +/
114 class /+ QT_DEPRECATED_X("Use std::less") +/ qLess(T)
115 {
116 public:
117     /+pragma(inline, true) final bool operator ()(ref const(T) t1, ref const(T) t2) const
118     {
119         return (t1 < t2);
120     }+/
121 }
122 
123 class /+ QT_DEPRECATED_X("Use std::greater") +/ qGreater(T)
124 {
125 public:
126     /+pragma(inline, true) final bool operator ()(ref const(T) t1, ref const(T) t2) const
127     {
128         return (t2 < t1);
129     }+/
130 }
131 /+ #endif +/
132 
133 /+ QT_DEPRECATED_X("Use std::sort") +/ pragma(inline, true) void qSort(RandomAccessIterator)(RandomAccessIterator start, RandomAccessIterator end)
134 {
135     if (start != end)
136         /+ QAlgorithmsPrivate:: +/qSortHelper(start, end, *start);
137 }
138 
139 /+ QT_DEPRECATED_X("Use std::sort") +/ pragma(inline, true) void qSort(RandomAccessIterator, LessThan)(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
140 {
141     if (start != end)
142         /+ QAlgorithmsPrivate:: +/qSortHelper(start, end, *start, lessThan);
143 }
144 
145 /+ QT_DEPRECATED_X("Use std::sort") +/ pragma(inline, true) void qSort(Container)(ref Container c)
146 {
147 /+ #ifdef Q_CC_BOR
148     // Work around Borland 5.5 optimizer bug
149     c.detach();
150 #endif +/
151     if (!c.empty())
152         /+ QAlgorithmsPrivate:: +/qSortHelper(c.begin(), c.end(), *c.begin());
153 }
154 
155 /+ QT_DEPRECATED_X("Use std::stable_sort") +/ pragma(inline, true) void qStableSort(RandomAccessIterator)(RandomAccessIterator start, RandomAccessIterator end)
156 {
157     if (start != end)
158         /+ QAlgorithmsPrivate:: +/qStableSortHelper(start, end, *start);
159 }
160 
161 /+ QT_DEPRECATED_X("Use std::stable_sort") +/ pragma(inline, true) void qStableSort(RandomAccessIterator, LessThan)(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
162 {
163     if (start != end)
164         /+ QAlgorithmsPrivate:: +/qStableSortHelper(start, end, *start, lessThan);
165 }
166 
167 /+ QT_DEPRECATED_X("Use std::stable_sort") +/ pragma(inline, true) void qStableSort(Container)(ref Container c)
168 {
169 /+ #ifdef Q_CC_BOR
170     // Work around Borland 5.5 optimizer bug
171     c.detach();
172 #endif +/
173     if (!c.empty())
174         /+ QAlgorithmsPrivate:: +/qStableSortHelper(c.begin(), c.end(), *c.begin());
175 }
176 
177 /+ QT_DEPRECATED_X("Use std::lower_bound") +/ RandomAccessIterator qLowerBound(RandomAccessIterator, T)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value)
178 {
179     // Implementation is duplicated from QAlgorithmsPrivate to keep existing code
180     // compiling. We have to allow using *begin and value with different types,
181     // and then implementing operator< for those types.
182     RandomAccessIterator middle;
183     int n = end - begin;
184     int half;
185 
186     while (n > 0) {
187         half = n >> 1;
188         middle = begin + half;
189         if (*middle < value) {
190             begin = middle + 1;
191             n -= half + 1;
192         } else {
193             n = half;
194         }
195     }
196     return begin;
197 }
198 
199 /+ QT_DEPRECATED_X("Use std::lower_bound") +/ RandomAccessIterator qLowerBound(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
200 {
201     return /+ QAlgorithmsPrivate:: +/qLowerBoundHelper(begin, end, value, lessThan);
202 }
203 
204 /+ QT_DEPRECATED_X("Use std::lower_bound") +/ /+ typename Container::const_iterator +/UnknownType!q{} qLowerBound(Container, T)(ref const(Container) container, ref const(T) value)
205 {
206     return /+ QAlgorithmsPrivate:: +/qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess!(T)());
207 }
208 
209 /+ QT_DEPRECATED_X("Use std::upper_bound") +/ RandomAccessIterator qUpperBound(RandomAccessIterator, T)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value)
210 {
211     // Implementation is duplicated from QAlgorithmsPrivate.
212     RandomAccessIterator middle;
213     int n = end - begin;
214     int half;
215 
216     while (n > 0) {
217         half = n >> 1;
218         middle = begin + half;
219         if (value < *middle) {
220             n = half;
221         } else {
222             begin = middle + 1;
223             n -= half + 1;
224         }
225     }
226     return begin;
227 }
228 
229 /+ QT_DEPRECATED_X("Use std::upper_bound") +/ RandomAccessIterator qUpperBound(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
230 {
231     return /+ QAlgorithmsPrivate:: +/qUpperBoundHelper(begin, end, value, lessThan);
232 }
233 
234 /+ QT_DEPRECATED_X("Use std::upper_bound") +/ /+ typename Container::const_iterator +/UnknownType!q{} qUpperBound(Container, T)(ref const(Container) container, ref const(T) value)
235 {
236     return /+ QAlgorithmsPrivate:: +/qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess!(T)());
237 }
238 
239 /+ QT_DEPRECATED_X("Use std::binary_search") +/ RandomAccessIterator qBinaryFind(RandomAccessIterator, T)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value)
240 {
241     // Implementation is duplicated from QAlgorithmsPrivate.
242     RandomAccessIterator it = qLowerBound(begin, end, value);
243 
244     if (it == end || value < *it)
245         return end;
246 
247     return it;
248 }
249 
250 /+ QT_DEPRECATED_X("Use std::binary_search") +/ RandomAccessIterator qBinaryFind(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
251 {
252     return /+ QAlgorithmsPrivate:: +/qBinaryFindHelper(begin, end, value, lessThan);
253 }
254 
255 /+ QT_DEPRECATED_X("Use std::binary_search") +/ /+ typename Container::const_iterator +/UnknownType!q{} qBinaryFind(Container, T)(ref const(Container) container, ref const(T) value)
256 {
257     return /+ QAlgorithmsPrivate:: +/qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess!(T)());
258 }
259 /+ #endif +/ // QT_DEPRECATED_SINCE(5, 2)
260 
261 void qDeleteAll(ForwardIterator)(ForwardIterator begin, ForwardIterator end)
262 {
263     import core.stdcpp.new_;
264 
265     while (begin != end) {
266         cpp_delete(*begin);
267         ++begin;
268     }
269 }
270 
271 pragma(inline, true) void qDeleteAll(Container)(ref Container c)
272 {
273     qDeleteAll(c.begin(), c.end());
274 }
275 
276 /*
277     Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
278     and may be changed from version to version or even be completely removed.
279 */
280 extern(C++, "QAlgorithmsPrivate") {
281 
282 /+ #if QT_DEPRECATED_SINCE(5, 2) +/
283 
284 /+ QT_DEPRECATED_X("Use std::sort") +/ void qSortHelper(RandomAccessIterator, T, LessThan)(RandomAccessIterator start, RandomAccessIterator end, ref const(T) t, LessThan lessThan)
285 {
286     import qt.core.global;
287 
288 top:
289     int span = int(end - start);
290     if (span < 2)
291         return;
292 
293     --end;
294     RandomAccessIterator low = start; RandomAccessIterator high = end - 1;
295     RandomAccessIterator pivot = start + span / 2;
296 
297     if (lessThan(*end, *start))
298         qSwap(*end, *start);
299     if (span == 2)
300         return;
301 
302     if (lessThan(*pivot, *start))
303         qSwap(*pivot, *start);
304     if (lessThan(*end, *pivot))
305         qSwap(*end, *pivot);
306     if (span == 3)
307         return;
308 
309     qSwap(*pivot, *end);
310 
311     while (low < high) {
312         while (low < high && lessThan(*low, *end))
313             ++low;
314 
315         while (high > low && lessThan(*end, *high))
316             --high;
317 
318         if (low < high) {
319             qSwap(*low, *high);
320             ++low;
321             --high;
322         } else {
323             break;
324         }
325     }
326 
327     if (lessThan(*low, *end))
328         ++low;
329 
330     qSwap(*end, *low);
331     qSortHelper(start, low, t, lessThan);
332 
333     start = low + 1;
334     ++end;
335     goto top;
336 }
337 
338 /+ QT_DEPRECATED_X("Use std::sort") +/ pragma(inline, true) void qSortHelper(RandomAccessIterator, T)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) dummy)
339 {
340     qSortHelper(begin, end, dummy, qLess!(T)());
341 }
342 
343 /+ QT_DEPRECATED_X("Use std::reverse") +/ void qReverse(RandomAccessIterator)(RandomAccessIterator begin, RandomAccessIterator end)
344 {
345     import qt.core.global;
346 
347     --end;
348     while (begin < end)
349         qSwap(*begin++, *end--);
350 }
351 
352 /+ QT_DEPRECATED_X("Use std::rotate") +/ void qRotate(RandomAccessIterator)(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end)
353 {
354     qReverse(begin, middle);
355     qReverse(middle, end);
356     qReverse(begin, end);
357 }
358 
359 /+ QT_DEPRECATED_X("Use std::merge") +/ void qMerge(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, ref T t, LessThan lessThan)
360 {
361     import qt.core.global;
362 
363     const(int) len1 = pivot - begin;
364     const(int) len2 = end - pivot;
365 
366     if (len1 == 0 || len2 == 0)
367         return;
368 
369     if (len1 + len2 == 2) {
370         if (lessThan(*(begin + 1), *(begin)))
371             qSwap(*begin, *(begin + 1));
372         return;
373     }
374 
375     RandomAccessIterator firstCut;
376     RandomAccessIterator secondCut;
377     int len2Half;
378     if (len1 > len2) {
379         const(int) len1Half = len1 / 2;
380         firstCut = begin + len1Half;
381         secondCut = qLowerBound(pivot, end, *firstCut, lessThan);
382         len2Half = secondCut - pivot;
383     } else {
384         len2Half = len2 / 2;
385         secondCut = pivot + len2Half;
386         firstCut = qUpperBound(begin, pivot, *secondCut, lessThan);
387     }
388 
389     qRotate(firstCut, pivot, secondCut);
390     const(RandomAccessIterator) newPivot = firstCut + len2Half;
391     qMerge(begin, firstCut, newPivot, t, lessThan);
392     qMerge(newPivot, secondCut, end, t, lessThan);
393 }
394 
395 /+ QT_DEPRECATED_X("Use std::stable_sort") +/ void qStableSortHelper(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) t, LessThan lessThan)
396 {
397     const(int) span = end - begin;
398     if (span < 2)
399        return;
400 
401     const(RandomAccessIterator) middle = begin + span / 2;
402     qStableSortHelper(begin, middle, t, lessThan);
403     qStableSortHelper(middle, end, t, lessThan);
404     qMerge(begin, middle, end, t, lessThan);
405 }
406 
407 /+ QT_DEPRECATED_X("Use std::stable_sort") +/ pragma(inline, true) void qStableSortHelper(RandomAccessIterator, T)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) dummy)
408 {
409     qStableSortHelper(begin, end, dummy, qLess!(T)());
410 }
411 
412 /+ QT_DEPRECATED_X("Use std::lower_bound") +/ RandomAccessIterator qLowerBoundHelper(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
413 {
414     RandomAccessIterator middle;
415     int n = int(end - begin);
416     int half;
417 
418     while (n > 0) {
419         half = n >> 1;
420         middle = begin + half;
421         if (lessThan(*middle, value)) {
422             begin = middle + 1;
423             n -= half + 1;
424         } else {
425             n = half;
426         }
427     }
428     return begin;
429 }
430 
431 
432 /+ QT_DEPRECATED_X("Use std::upper_bound") +/ RandomAccessIterator qUpperBoundHelper(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
433 {
434     RandomAccessIterator middle;
435     int n = end - begin;
436     int half;
437 
438     while (n > 0) {
439         half = n >> 1;
440         middle = begin + half;
441         if (lessThan(value, *middle)) {
442             n = half;
443         } else {
444             begin = middle + 1;
445             n -= half + 1;
446         }
447     }
448     return begin;
449 }
450 
451 /+ QT_DEPRECATED_X("Use std::binary_search") +/ RandomAccessIterator qBinaryFindHelper(RandomAccessIterator, T, LessThan)(RandomAccessIterator begin, RandomAccessIterator end, ref const(T) value, LessThan lessThan)
452 {
453     RandomAccessIterator it = qLowerBoundHelper(begin, end, value, lessThan);
454 
455     if (it == end || lessThan(value, *it))
456         return end;
457 
458     return it;
459 }
460 
461 /+ #endif // QT_DEPRECATED_SINCE(5, 2)
462 
463 #ifdef Q_CC_CLANG
464 // Clang had a bug where __builtin_ctz/clz/popcount were not marked as constexpr.
465 #  if (defined __apple_build_version__ &&  __clang_major__ >= 7) || (Q_CC_CLANG >= 307)
466 #    define QT_HAS_CONSTEXPR_BUILTINS
467 #  endif
468 #elif defined(Q_CC_MSVC) && !defined(Q_CC_INTEL) && !defined(Q_PROCESSOR_ARM)
469 #  define QT_HAS_CONSTEXPR_BUILTINS
470 #elif defined(Q_CC_GNU)
471 #  define QT_HAS_CONSTEXPR_BUILTINS
472 #endif
473 
474 #if defined QT_HAS_CONSTEXPR_BUILTINS
475 #if defined(Q_CC_GNU) || defined(Q_CC_CLANG)
476 #  define QT_HAS_BUILTIN_CTZS
477 Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
478 {
479 #  if __has_builtin(__builtin_ctzs)
480     return __builtin_ctzs(v);
481 #  else
482     return __builtin_ctz(v);
483 #  endif
484 }
485 #define QT_HAS_BUILTIN_CLZS
486 Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
487 {
488 #  if __has_builtin(__builtin_clzs)
489     return __builtin_clzs(v);
490 #  else
491     return __builtin_clz(v) - 16U;
492 #  endif
493 }
494 #define QT_HAS_BUILTIN_CTZ
495 Q_ALWAYS_INLINE uint qt_builtin_ctz(quint32 v) noexcept
496 {
497     return __builtin_ctz(v);
498 }
499 #define QT_HAS_BUILTIN_CLZ
500 Q_ALWAYS_INLINE uint qt_builtin_clz(quint32 v) noexcept
501 {
502     return __builtin_clz(v);
503 }
504 #define QT_HAS_BUILTIN_CTZLL
505 Q_ALWAYS_INLINE uint qt_builtin_ctzll(quint64 v) noexcept
506 {
507     return __builtin_ctzll(v);
508 }
509 #define QT_HAS_BUILTIN_CLZLL
510 Q_ALWAYS_INLINE uint qt_builtin_clzll(quint64 v) noexcept
511 {
512     return __builtin_clzll(v);
513 }
514 #define QALGORITHMS_USE_BUILTIN_POPCOUNT
515 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
516 {
517     return __builtin_popcount(v);
518 }
519 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
520 {
521     return __builtin_popcount(v);
522 }
523 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
524 {
525     return __builtin_popcount(v);
526 }
527 #define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
528 Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
529 {
530     return __builtin_popcountll(v);
531 }
532 #elif defined(Q_CC_MSVC) && !defined(Q_PROCESSOR_ARM)
533 #define QT_POPCOUNT_CONSTEXPR
534 #define QT_POPCOUNT_RELAXED_CONSTEXPR
535 #define QT_HAS_BUILTIN_CTZ
536 Q_ALWAYS_INLINE unsigned long qt_builtin_ctz(quint32 val)
537 {
538     unsigned long result;
539     _BitScanForward(&result, val);
540     return result;
541 }
542 #define QT_HAS_BUILTIN_CLZ
543 Q_ALWAYS_INLINE unsigned long qt_builtin_clz(quint32 val)
544 {
545     unsigned long result;
546     _BitScanReverse(&result, val);
547     // Now Invert the result: clz will count *down* from the msb to the lsb, so the msb index is 31
548     // and the lsb index is 0. The result for the index when counting up: msb index is 0 (because it
549     // starts there), and the lsb index is 31.
550     result ^= sizeof(quint32) * 8 - 1;
551     return result;
552 }
553 #if Q_PROCESSOR_WORDSIZE == 8
554 // These are only defined for 64bit builds.
555 #define QT_HAS_BUILTIN_CTZLL
556 Q_ALWAYS_INLINE unsigned long qt_builtin_ctzll(quint64 val)
557 {
558     unsigned long result;
559     _BitScanForward64(&result, val);
560     return result;
561 }
562 // MSVC calls it _BitScanReverse and returns the carry flag, which we don't need
563 #define QT_HAS_BUILTIN_CLZLL
564 Q_ALWAYS_INLINE unsigned long qt_builtin_clzll(quint64 val)
565 {
566     unsigned long result;
567     _BitScanReverse64(&result, val);
568     // see qt_builtin_clz
569     result ^= sizeof(quint64) * 8 - 1;
570     return result;
571 }
572 #endif // MSVC 64bit
573 #  define QT_HAS_BUILTIN_CTZS
574 Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
575 {
576     return qt_builtin_ctz(v);
577 }
578 #define QT_HAS_BUILTIN_CLZS
579 Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
580 {
581     return qt_builtin_clz(v) - 16U;
582 }
583 
584 // Neither MSVC nor the Intel compiler define a macro for the POPCNT processor
585 // feature, so we're using either the SSE4.2 or the AVX macro as a proxy (Clang
586 // does define the macro). It's incorrect for two reasons:
587 // 1. It's a separate bit in CPUID, so a processor could implement SSE4.2 and
588 //    not POPCNT, but that's unlikely to happen.
589 // 2. There are processors that support POPCNT but not AVX (Intel Nehalem
590 //    architecture), but unlike the other compilers, MSVC has no option
591 //    to generate code for those processors.
592 // So it's an acceptable compromise.
593 #if defined(__AVX__) || defined(__SSE4_2__) || defined(__POPCNT__)
594 #define QALGORITHMS_USE_BUILTIN_POPCOUNT
595 #define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
596 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
597 {
598     return __popcnt(v);
599 }
600 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
601 {
602     return __popcnt16(v);
603 }
604 Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
605 {
606     return __popcnt16(v);
607 }
608 Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
609 {
610 #if Q_PROCESSOR_WORDSIZE == 8
611     return __popcnt64(v);
612 #else
613     return __popcnt(quint32(v)) + __popcnt(quint32(v >> 32));
614 #endif // MSVC 64bit
615 }
616 
617 #endif // __AVX__ || __SSE4_2__ || __POPCNT__
618 
619 #endif // MSVC
620 #endif // QT_HAS_CONSTEXPR_BUILTINS
621 
622 #ifndef QT_POPCOUNT_CONSTEXPR
623 #define QT_POPCOUNT_CONSTEXPR Q_DECL_CONSTEXPR
624 #define QT_POPCOUNT_RELAXED_CONSTEXPR Q_DECL_RELAXED_CONSTEXPR
625 #endif +/
626 
627 } //namespace QAlgorithmsPrivate
628 
629 /+ Q_DECL_CONST_FUNCTION inline uint qPopulationCount(quint32 v) noexcept
630 {
631 #ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
632     return QAlgorithmsPrivate::qt_builtin_popcount(v);
633 #else
634     // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
635     return
636         (((v      ) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
637         (((v >> 12) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
638         (((v >> 24) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
639 #endif
640 }
641 
642 Q_DECL_CONST_FUNCTION inline uint qPopulationCount(quint8 v) noexcept
643 {
644 #ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
645     return QAlgorithmsPrivate::qt_builtin_popcount(v);
646 #else
647     return
648         (((v      ) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
649 #endif
650 }
651 
652 Q_DECL_CONST_FUNCTION inline uint qPopulationCount(quint16 v) noexcept
653 {
654 #ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
655     return QAlgorithmsPrivate::qt_builtin_popcount(v);
656 #else
657     return
658         (((v      ) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
659         (((v >> 12) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
660 #endif
661 }
662 
663 Q_DECL_CONST_FUNCTION inline uint qPopulationCount(quint64 v) noexcept
664 {
665 #ifdef QALGORITHMS_USE_BUILTIN_POPCOUNTLL
666     return QAlgorithmsPrivate::qt_builtin_popcountll(v);
667 #else
668     return
669         (((v      ) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
670         (((v >> 12) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
671         (((v >> 24) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
672         (((v >> 36) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
673         (((v >> 48) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
674         (((v >> 60) & 0xfff)    * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
675 #endif
676 }
677 
678 Q_DECL_CONST_FUNCTION inline uint qPopulationCount(long unsigned int v) noexcept
679 {
680     return qPopulationCount(static_cast<quint64>(v));
681 }
682 
683 #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
684 #undef QALGORITHMS_USE_BUILTIN_POPCOUNT
685 #endif
686 #undef QT_POPCOUNT_CONSTEXPR
687 
688 inline uint qCountTrailingZeroBits(quint32 v) noexcept
689 {
690 #if defined(QT_HAS_BUILTIN_CTZ)
691     return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 32U;
692 #else
693     // see http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel
694     unsigned int c = 32; // c will be the number of zero bits on the right
695     v &= -signed(v);
696     if (v) c--;
697     if (v & 0x0000FFFF) c -= 16;
698     if (v & 0x00FF00FF) c -= 8;
699     if (v & 0x0F0F0F0F) c -= 4;
700     if (v & 0x33333333) c -= 2;
701     if (v & 0x55555555) c -= 1;
702     return c;
703 #endif
704 }
705 
706 inline uint qCountTrailingZeroBits(quint8 v) noexcept
707 {
708 #if defined(QT_HAS_BUILTIN_CTZ)
709     return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 8U;
710 #else
711     unsigned int c = 8; // c will be the number of zero bits on the right
712     v &= -signed(v);
713     if (v) c--;
714     if (v & 0x0000000F) c -= 4;
715     if (v & 0x00000033) c -= 2;
716     if (v & 0x00000055) c -= 1;
717     return c;
718 #endif
719 }
720 
721 inline uint qCountTrailingZeroBits(quint16 v) noexcept
722 {
723 #if defined(QT_HAS_BUILTIN_CTZS)
724     return v ? QAlgorithmsPrivate::qt_builtin_ctzs(v) : 16U;
725 #else
726     unsigned int c = 16; // c will be the number of zero bits on the right
727     v &= -signed(v);
728     if (v) c--;
729     if (v & 0x000000FF) c -= 8;
730     if (v & 0x00000F0F) c -= 4;
731     if (v & 0x00003333) c -= 2;
732     if (v & 0x00005555) c -= 1;
733     return c;
734 #endif
735 }
736 
737 inline uint qCountTrailingZeroBits(quint64 v) noexcept
738 {
739 #if defined(QT_HAS_BUILTIN_CTZLL)
740     return v ? QAlgorithmsPrivate::qt_builtin_ctzll(v) : 64;
741 #else
742     quint32 x = static_cast<quint32>(v);
743     return x ? qCountTrailingZeroBits(x)
744              : 32 + qCountTrailingZeroBits(static_cast<quint32>(v >> 32));
745 #endif
746 }
747 
748 inline uint qCountTrailingZeroBits(unsigned long v) noexcept
749 {
750     return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
751 }
752 
753 inline uint qCountLeadingZeroBits(quint32 v) noexcept
754 {
755 #if defined(QT_HAS_BUILTIN_CLZ)
756     return v ? QAlgorithmsPrivate::qt_builtin_clz(v) : 32U;
757 #else
758     // Hacker's Delight, 2nd ed. Fig 5-16, p. 102
759     v = v | (v >> 1);
760     v = v | (v >> 2);
761     v = v | (v >> 4);
762     v = v | (v >> 8);
763     v = v | (v >> 16);
764     return qPopulationCount(~v);
765 #endif
766 }
767 
768 inline uint qCountLeadingZeroBits(quint8 v) noexcept
769 {
770 #if defined(QT_HAS_BUILTIN_CLZ)
771     return v ? QAlgorithmsPrivate::qt_builtin_clz(v)-24U : 8U;
772 #else
773     v = v | (v >> 1);
774     v = v | (v >> 2);
775     v = v | (v >> 4);
776     return qPopulationCount(static_cast<quint8>(~v));
777 #endif
778 }
779 
780 inline uint qCountLeadingZeroBits(quint16 v) noexcept
781 {
782 #if defined(QT_HAS_BUILTIN_CLZS)
783     return v ? QAlgorithmsPrivate::qt_builtin_clzs(v) : 16U;
784 #else
785     v = v | (v >> 1);
786     v = v | (v >> 2);
787     v = v | (v >> 4);
788     v = v | (v >> 8);
789     return qPopulationCount(static_cast<quint16>(~v));
790 #endif
791 }
792 
793 inline uint qCountLeadingZeroBits(quint64 v) noexcept
794 {
795 #if defined(QT_HAS_BUILTIN_CLZLL)
796     return v ? QAlgorithmsPrivate::qt_builtin_clzll(v) : 64U;
797 #else
798     v = v | (v >> 1);
799     v = v | (v >> 2);
800     v = v | (v >> 4);
801     v = v | (v >> 8);
802     v = v | (v >> 16);
803     v = v | (v >> 32);
804     return qPopulationCount(~v);
805 #endif
806 }
807 
808 inline uint qCountLeadingZeroBits(unsigned long v) noexcept
809 {
810     return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
811 }
812 
813 QT_WARNING_POP +/
814