UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Sorting.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Algo/BinarySearch.h"
7#include "Algo/Sort.h"
8#include "HAL/PlatformMath.h"
9#include "Templates/Less.h"
10
14template<typename T, class PREDICATE_CLASS>
16{
18
21
23 UE_FORCEINLINE_HINT bool operator()( T& A, T& B ) { return Predicate( A, B ); }
24 UE_FORCEINLINE_HINT bool operator()( const T& A, const T& B ) const { return Predicate( A, B ); }
25};
27template<typename T, class PREDICATE_CLASS>
29{
31
34
36 UE_FORCEINLINE_HINT bool operator()( T* A, T* B ) const
37 {
38 return Predicate( *A, *B );
39 }
40};
41
46template <typename T>
48{
50 : Begin(InPtr)
51 , Size(InSize)
52 {
53 }
54
55 T* GetData() const { return Begin; }
56 int32 Num() const { return Size; }
57
58private:
59 T* Begin;
60 int32 Size;
61};
62
63template <typename T>
65{
66 enum { Value = true };
67};
68
76template<class T, class PREDICATE_CLASS>
77UE_DEPRECATED(5.3, "Sort is deprecated, please use Algo::Sort. Algo::Sort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
78void Sort( T* First, const int32 Num, const PREDICATE_CLASS& Predicate )
79{
80 TArrayRange<T> ArrayRange( First, Num );
81 Algo::Sort( ArrayRange, TDereferenceWrapper<T, PREDICATE_CLASS>( Predicate ) );
82}
83
91template<class T, class PREDICATE_CLASS>
92UE_DEPRECATED(5.3, "Sort is deprecated, please use Algo::Sort. Algo::Sort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
93void Sort( T** First, const int32 Num, const PREDICATE_CLASS& Predicate )
94{
95 TArrayRange<T*> ArrayRange( First, Num );
96 Algo::Sort( ArrayRange, TDereferenceWrapper<T*, PREDICATE_CLASS>( Predicate ) );
97}
98
106template<class T>
107UE_DEPRECATED(5.3, "Sort is deprecated, please use Algo::Sort. Algo::Sort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
108void Sort( T* First, const int32 Num )
109{
110 TArrayRange<T> ArrayRange( First, Num );
111 Algo::Sort( ArrayRange, TDereferenceWrapper<T, TLess<T> >( TLess<T>() ) );
112}
113
120template<class T>
121UE_DEPRECATED(5.3, "Sort is deprecated, please use Algo::Sort. Algo::Sort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
122void Sort( T** First, const int32 Num )
123{
124 TArrayRange<T*> ArrayRange( First, Num );
125 Algo::Sort( ArrayRange, TDereferenceWrapper<T*, TLess<T> >( TLess<T>() ) );
126}
127
138template<class T, class PREDICATE_CLASS>
139void Merge(T* Out, T* In, const int32 Mid, const int32 Num, const PREDICATE_CLASS& Predicate)
140{
141 int32 Merged = 0;
143 int32 A = 0, B = Mid;
144
145 while (Merged < Num)
146 {
147 if (Merged != B && (B >= Num || !Predicate(In[B], In[A])))
148 {
149 Picked = A++;
150 }
151 else
152 {
153 Picked = B++;
154 }
155
156 Out[Merged] = In[Picked];
157
158 ++Merged;
159 }
160}
161
166{
167public:
177 {
178 while (B != 0)
179 {
180 int32 Temp = B;
181 B = A % B;
182 A = Temp;
183 }
184
185 return A;
186 }
187};
188
194template <class TGCDPolicy>
196{
197public:
206 template <class T>
207 static void Rotate(T* First, const int32 From, const int32 To, const int32 Amount)
208 {
209 if (Amount == 0)
210 {
211 return;
212 }
213
214 auto Num = To - From;
215 auto GCD = TGCDPolicy::GCD(Num, Amount);
216 auto CycleSize = Num / GCD;
217
218 for (int32 Index = 0; Index < GCD; ++Index)
219 {
220 T BufferObject = MoveTemp(First[From + Index]);
221 int32 IndexToFill = Index;
222
224 {
225 IndexToFill = (IndexToFill + Amount) % Num;
226 Exchange(First[From + IndexToFill], BufferObject);
227 }
228 }
229 }
230};
231
237template <class TRotationPolicy>
239{
240public:
249 template <class T, class PREDICATE_CLASS>
250 static void Merge(T* First, const int32 Mid, const int32 Num, const PREDICATE_CLASS& Predicate)
251 {
252 int32 AStart = 0;
253 int32 BStart = Mid;
254
255 while (AStart < BStart && BStart < Num)
256 {
257 // Index after the last value == First[BStart]
260
261 if (AStart >= BStart) // done
262 break;
263
264 // Index of the first value == First[AStart]
266 TRotationPolicy::Rotate(First, AStart, BStart + NewBOffset, NewBOffset);
268 AStart += NewBOffset + 1;
269 }
270 }
271};
272
279template <class TMergePolicy, int32 MinMergeSubgroupSize = 2>
281{
282public:
290 template<class T, class PREDICATE_CLASS>
291 static void Sort(T* First, const int32 Num, const PREDICATE_CLASS& Predicate)
292 {
294
295 if (MinMergeSubgroupSize > 1)
296 {
297 if (MinMergeSubgroupSize > 2)
298 {
299 // First pass with simple bubble-sort.
300 do
301 {
302 int32 GroupEnd = FPlatformMath::Min(SubgroupStart + MinMergeSubgroupSize, Num);
303 do
304 {
305 for (int32 It = SubgroupStart; It < GroupEnd - 1; ++It)
306 {
307 if (Predicate(First[It + 1], First[It]))
308 {
309 Exchange(First[It], First[It + 1]);
310 }
311 }
312 GroupEnd--;
313 } while (GroupEnd - SubgroupStart > 1);
314
315 SubgroupStart += MinMergeSubgroupSize;
316 } while (SubgroupStart < Num);
317 }
318 else
319 {
320 for (int32 Subgroup = 0; Subgroup < Num; Subgroup += 2)
321 {
322 if (Subgroup + 1 < Num && Predicate(First[Subgroup + 1], First[Subgroup]))
323 {
325 }
326 }
327 }
328 }
329
330 int32 SubgroupSize = MinMergeSubgroupSize;
331 while (SubgroupSize < Num)
332 {
333 SubgroupStart = 0;
334 do
335 {
336 TMergePolicy::Merge(
339 FPlatformMath::Min(SubgroupSize << 1, Num - SubgroupStart),
340 Predicate);
342 } while (SubgroupStart < Num);
343
344 SubgroupSize <<= 1;
345 }
346 }
347};
348
360template<class T, class PREDICATE_CLASS>
365
375template<class T, class PREDICATE_CLASS>
376UE_DEPRECATED(5.3, "StableSort is deprecated, please use Algo::StableSort. Algo::StableSort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
381
390template<class T, class PREDICATE_CLASS>
391UE_DEPRECATED(5.3, "StableSort is deprecated, please use Algo::StableSort. Algo::StableSort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
396
406template<class T>
407UE_DEPRECATED(5.3, "StableSort is deprecated, please use Algo::StableSort. Algo::StableSort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
412
420template<class T>
421UE_DEPRECATED(5.3, "StableSort is deprecated, please use Algo::StableSort. Algo::StableSort supports ranges with index types other than int32, and doesn't automatically dereference pointers.")
426
427
434template< typename ValueType, typename CountType, class SortKeyClass >
435void RadixSort32( ValueType* RESTRICT Dst, ValueType* RESTRICT Src, CountType Num, const SortKeyClass& SortKey )
436{
437 CountType Histograms[ 1024 + 2048 + 2048 ];
438 CountType* RESTRICT Histogram0 = Histograms + 0;
441
442 FMemory::Memzero( Histograms, sizeof( Histograms ) );
443
444 {
445 // Parallel histogram generation pass
446 const ValueType* RESTRICT s = (const ValueType* RESTRICT)Src;
447 for( CountType i = 0; i < Num; i++ )
448 {
449 uint32 Key = SortKey( s[i] );
450 Histogram0[ ( Key >> 0 ) & 1023 ]++;
451 Histogram1[ ( Key >> 10 ) & 2047 ]++;
452 Histogram2[ ( Key >> 21 ) & 2047 ]++;
453 }
454 }
455 {
456 // Prefix sum
457 // Set each histogram entry to the sum of entries preceding it
458 CountType Sum0 = 0;
459 CountType Sum1 = 0;
460 CountType Sum2 = 0;
461 for( CountType i = 0; i < 1024; i++ )
462 {
463 CountType t;
464 t = Histogram0[i] + Sum0; Histogram0[i] = Sum0 - 1; Sum0 = t;
465 t = Histogram1[i] + Sum1; Histogram1[i] = Sum1 - 1; Sum1 = t;
466 t = Histogram2[i] + Sum2; Histogram2[i] = Sum2 - 1; Sum2 = t;
467 }
468 for( CountType i = 1024; i < 2048; i++ )
469 {
470 CountType t;
471 t = Histogram1[i] + Sum1; Histogram1[i] = Sum1 - 1; Sum1 = t;
472 t = Histogram2[i] + Sum2; Histogram2[i] = Sum2 - 1; Sum2 = t;
473 }
474 }
475 {
476 // Sort pass 1
477 const ValueType* RESTRICT s = (const ValueType* RESTRICT)Src;
478 ValueType* RESTRICT d = Dst;
479 for( CountType i = 0; i < Num; i++ )
480 {
481 ValueType Value = s[i];
482 uint32 Key = SortKey( Value );
483 d[ ++Histogram0[ ( (Key >> 0) & 1023 ) ] ] = Value;
484 }
485 }
486 {
487 // Sort pass 2
488 const ValueType* RESTRICT s = (const ValueType* RESTRICT)Dst;
489 ValueType* RESTRICT d = Src;
490 for( CountType i = 0; i < Num; i++ )
491 {
492 ValueType Value = s[i];
493 uint32 Key = SortKey( Value );
494 d[ ++Histogram1[ ( (Key >> 10) & 2047 ) ] ] = Value;
495 }
496 }
497 {
498 // Sort pass 3
499 const ValueType* RESTRICT s = (const ValueType* RESTRICT)Src;
500 ValueType* RESTRICT d = Dst;
501 for( CountType i = 0; i < Num; i++ )
502 {
503 ValueType Value = s[i];
504 uint32 Key = SortKey( Value );
505 d[ ++Histogram2[ ( (Key >> 21) & 2047 ) ] ] = Value;
506 }
507 }
508}
509
510
511template< typename T >
513{
515 {
516 return (uint32)Value;
517 }
518};
519
520template< typename ValueType, typename CountType >
521void RadixSort32( ValueType* RESTRICT Dst, ValueType* RESTRICT Src, CountType Num )
522{
524}
525
526// float cast to uint32 which maintains sorted order
527// http://codercorner.com/RadixSortRevisited.htm
529{
530 inline uint32 operator()( float Value ) const
531 {
532 union { float f; uint32 i; } v;
533 v.f = Value;
534
535 uint32 mask = -int32( v.i >> 31 ) | 0x80000000;
536 return v.i ^ mask;
537 }
538};
539
540template< typename CountType >
541void RadixSort32( float* RESTRICT Dst, float* RESTRICT Src, CountType Num )
542{
543 RadixSort32( Dst, Src, Num, FRadixSortKeyFloat() );
544}
545
551
559template< ERadixSortBufferState BufferState, typename ValueType, typename CountType, class SortKeyClass >
560void RadixSort64(ValueType* RESTRICT Array, ValueType* RESTRICT Buffer, CountType Num, const SortKeyClass& SortKey)
561{
562 CountType Histograms[(1024 * 2) + (2048 * 4)];
563 CountType* RESTRICT Histogram0 = Histograms + 0;
569 FMemory::Memzero(Histograms, sizeof(Histograms));
570
571 {
572 // Parallel histogram generation pass
573 ValueType* RESTRICT s = Array;
574 for (CountType i = 0; i < Num; i++)
575 {
576 uint64 Key = SortKey( *s++ );
577 Histogram0[(Key >> 0) & 1023]++;
578 Histogram1[(Key >> 10) & 1023]++;
579 Histogram2[(Key >> 20) & 2047]++;
580 Histogram3[(Key >> 31) & 2047]++;
581 Histogram4[(Key >> 42) & 2047]++;
582 Histogram5[(Key >> 53) & 2047]++;
583 }
584 }
585 {
586 // Prefix sum
587 // Set each histogram entry to the sum of entries preceding it
588 CountType Sum0 = 0;
589 CountType Sum1 = 0;
590 CountType Sum2 = 0;
591 CountType Sum3 = 0;
592 CountType Sum4 = 0;
593 CountType Sum5 = 0;
594 CountType i = 0;
595 for (; i < 1024; i++)
596 {
603 }
604 for (; i < 2048; i++)
605 {
610 }
611 }
612 {
613 // Sort pass 1
614 ValueType* RESTRICT Source = Array;
615 ValueType* RESTRICT Destination = Buffer;
616 for (CountType i = 0; i < Num; i++)
617 {
618 uint64 Value = SortKey(*Source);
619 SIZE_T Index = Histogram0[((Value >> 0) & 1023)]++;
621 {
622 Destination[Index] = MoveTemp(*Source++);
623 }
624 else
625 {
626 new(Destination + Index) ValueType(MoveTemp(*Source++));
627 }
628 }
629 }
630 {
631 // Sort pass 2
632 ValueType* RESTRICT Source = Buffer;
633 ValueType* RESTRICT Destination = Array;
634 for (CountType i = 0; i < Num; i++)
635 {
636 uint64 Value = SortKey(*Source);
637 Destination[Histogram1[((Value >> 10) & 1023)]++] = MoveTemp(*Source++);
638 }
639 }
640 {
641 // Sort pass 3
642 ValueType* RESTRICT Source = Array;
643 ValueType* RESTRICT Destination = Buffer;
644 for (CountType i = 0; i < Num; i++)
645 {
646 uint64 Value = SortKey(*Source);
647 Destination[Histogram2[((Value >> 20) & 2047)]++] = MoveTemp(*Source++);
648 }
649 }
650 {
651 // Sort pass 4
652 ValueType* RESTRICT Source = Buffer;
653 ValueType* RESTRICT Destination = Array;
654 for (CountType i = 0; i < Num; i++)
655 {
656 uint64 Value = SortKey(*Source);
657 Destination[Histogram3[((Value >> 31) & 2047)]++] = MoveTemp(*Source++);
658 }
659 }
660 {
661 // Sort pass 5
662 ValueType* RESTRICT Source = Array;
663 ValueType* RESTRICT Destination = Buffer;
664 for (CountType i = 0; i < Num; i++)
665 {
666 uint64 Value = SortKey(*Source);
667 Destination[Histogram4[((Value >> 42) & 2047)]++] = MoveTemp(*Source++);
668 }
669 }
670 {
671 // Sort pass 6
672 ValueType* RESTRICT Source = Buffer;
673 ValueType* RESTRICT Destination = Array;
674 for (CountType i = 0; i < Num; i++)
675 {
676 uint64 Value = SortKey(*Source);
677 Destination[Histogram5[((Value >> 53) & 2047)]++] = MoveTemp(*Source++);
678 }
679 }
680}
681
682template< typename T >
684{
686 {
687 return (uint64)Value;
688 }
689};
690
691template< ERadixSortBufferState BufferState, typename ValueType, typename CountType >
696
697template< typename ValueType, typename CountType, class SortKeyClass >
704
705template< typename ValueType, typename CountType >
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
#define RESTRICT
Definition Platform.h:706
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
void StableSort(T *First, const int32 Num, const PREDICATE_CLASS &Predicate)
Definition Sorting.h:377
void StableSortInternal(T *First, const int32 Num, const PREDICATE_CLASS &Predicate)
Definition Sorting.h:361
void RadixSort64(ValueType *RESTRICT Array, ValueType *RESTRICT Buffer, CountType Num, const SortKeyClass &SortKey)
Definition Sorting.h:560
ERadixSortBufferState
Definition Sorting.h:547
void RadixSort32(ValueType *RESTRICT Dst, ValueType *RESTRICT Src, CountType Num, const SortKeyClass &SortKey)
Definition Sorting.h:435
void Sort(T *First, const int32 Num, const PREDICATE_CLASS &Predicate)
Definition Sorting.h:78
@ Num
Definition MetalRHIPrivate.h:234
UE_REWRITE constexpr void Exchange(T &A, T &B)
Definition UnrealTemplate.h:627
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Sorting.h:166
static int32 GCD(int32 A, int32 B)
Definition Sorting.h:176
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
Definition Sorting.h:196
static void Rotate(T *First, const int32 From, const int32 To, const int32 Amount)
Definition Sorting.h:207
Definition Sorting.h:281
static void Sort(T *First, const int32 Num, const PREDICATE_CLASS &Predicate)
Definition Sorting.h:291
Definition Sorting.h:239
static void Merge(T *First, const int32 Mid, const int32 Num, const PREDICATE_CLASS &Predicate)
Definition Sorting.h:250
SizeType UpperBoundInternal(RangeValueType *First, const SizeType Num, const PredicateValueType &Value, ProjectionType Projection, SortPredicateType SortPredicate)
Definition BinarySearch.h:56
SizeType LowerBoundInternal(RangeValueType *First, const SizeType Num, const PredicateValueType &Value, ProjectionType Projection, SortPredicateType SortPredicate)
Definition BinarySearch.h:23
UE_REWRITE void Sort(RangeType &&Range)
Definition Sort.h:16
float v
Definition radaudio_mdct.cpp:62
U16 Index
Definition radfft.cpp:71
Definition IdentityFunctor.h:11
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131
Definition Sorting.h:529
uint32 operator()(float Value) const
Definition Sorting.h:530
Definition Sorting.h:48
int32 Num() const
Definition Sorting.h:56
T * GetData() const
Definition Sorting.h:55
TArrayRange(T *InPtr, int32 InSize)
Definition Sorting.h:49
TDereferenceWrapper(const PREDICATE_CLASS &InPredicate)
Definition Sorting.h:32
const PREDICATE_CLASS & Predicate
Definition Sorting.h:30
UE_FORCEINLINE_HINT bool operator()(T *A, T *B) const
Definition Sorting.h:36
Definition Sorting.h:16
TDereferenceWrapper(const PREDICATE_CLASS &InPredicate)
Definition Sorting.h:19
UE_FORCEINLINE_HINT bool operator()(const T &A, const T &B) const
Definition Sorting.h:24
UE_FORCEINLINE_HINT bool operator()(T &A, T &B)
Definition Sorting.h:23
const PREDICATE_CLASS & Predicate
Definition Sorting.h:17
Definition IsContiguousContainer.h:16
static constexpr bool Value
Definition IsContiguousContainer.h:20
Definition Less.h:19
Definition Sorting.h:513
UE_FORCEINLINE_HINT uint32 operator()(const T &Value) const
Definition Sorting.h:514
Definition Sorting.h:684
UE_FORCEINLINE_HINT uint64 operator()(const T &Value) const
Definition Sorting.h:685