@@ -34,124 +34,94 @@ type_t next_value(type_t value)
3434template <typename vtype, typename mm_t >
3535X86_SIMD_SORT_INLINE void COEX (mm_t &a, mm_t &b);
3636
37- template <typename vtype>
38- struct AscendingComparator {
37+ template <typename vtype, bool descend >
38+ struct Comparator {
3939 using reg_t = typename vtype::reg_t ;
4040 using opmask_t = typename vtype::opmask_t ;
4141 using type_t = typename vtype::type_t ;
4242
4343 X86_SIMD_SORT_FINLINE bool STDSortComparator (const type_t &a,
4444 const type_t &b)
4545 {
46- return comparison_func<vtype>(a, b);
46+ if constexpr (descend) { return comparison_func<vtype>(b, a); }
47+ else {
48+ return comparison_func<vtype>(a, b);
49+ }
4750 }
4851
4952 X86_SIMD_SORT_FINLINE opmask_t PartitionComparator (reg_t a, reg_t b)
5053 {
51- return vtype::ge (a, b);
54+ if constexpr (descend) { return vtype::ge (b, a); }
55+ else {
56+ return vtype::ge (a, b);
57+ }
5258 }
5359
5460 X86_SIMD_SORT_FINLINE void COEX (reg_t &a, reg_t &b)
5561 {
56- ::COEX<vtype, reg_t >(a, b);
62+ if constexpr (descend) { ::COEX<vtype, reg_t >(b, a); }
63+ else {
64+ ::COEX<vtype, reg_t >(a, b);
65+ }
5766 }
5867
5968 // Returns a vector of values that would be sorted as far right as possible
6069 // For ascending order, this is the maximum possible value
6170 X86_SIMD_SORT_FINLINE reg_t rightmostPossibleVec ()
6271 {
63- return vtype::zmm_max ();
72+ if constexpr (descend) { return vtype::zmm_min (); }
73+ else {
74+ return vtype::zmm_max ();
75+ }
6476 }
6577
6678 // Returns the value that would be leftmost of the two when sorted
6779 // For ascending order, that is the smaller value
6880 X86_SIMD_SORT_FINLINE type_t leftmost (type_t smaller, type_t larger)
6981 {
70- UNUSED (larger);
71- return smaller;
82+ if constexpr (descend) {
83+ UNUSED (smaller);
84+ return larger;
85+ }
86+ else {
87+ UNUSED (larger);
88+ return smaller;
89+ }
7290 }
7391
7492 // Returns the value that would be rightmost of the two when sorted
7593 // For ascending order, that is the larger value
7694 X86_SIMD_SORT_FINLINE type_t rightmost (type_t smaller, type_t larger)
7795 {
78- UNUSED (smaller);
79- return larger;
96+ if constexpr (descend) {
97+ UNUSED (larger);
98+ return smaller;
99+ }
100+ else {
101+ UNUSED (smaller);
102+ return larger;
103+ }
80104 }
81105
82106 // If median == smallest, that implies approximately half the array is equal to smallest, unless we were very unlucky with our sample
83107 // Try just doing the next largest value greater than this seemingly very common value to seperate them out
84108 X86_SIMD_SORT_FINLINE type_t choosePivotMedianIsSmallest (type_t median)
85109 {
86- return next_value<type_t >(median);
110+ if constexpr (descend) { return median; }
111+ else {
112+ return next_value<type_t >(median);
113+ }
87114 }
88115
89116 // If median == largest, that implies approximately half the array is equal to largest, unless we were very unlucky with our sample
90117 // Thus, median probably is a fine pivot, since it will move all of this common value into its own partition
91118 X86_SIMD_SORT_FINLINE type_t choosePivotMedianIsLargest (type_t median)
92119 {
93- return median;
94- }
95- };
96-
97- template <typename vtype>
98- struct DescendingComparator {
99- using reg_t = typename vtype::reg_t ;
100- using opmask_t = typename vtype::opmask_t ;
101- using type_t = typename vtype::type_t ;
102-
103- X86_SIMD_SORT_FINLINE bool STDSortComparator (const type_t &a,
104- const type_t &b)
105- {
106- return comparison_func<vtype>(b, a);
107- }
108-
109- X86_SIMD_SORT_FINLINE opmask_t PartitionComparator (reg_t a, reg_t b)
110- {
111- return vtype::ge (b, a);
112- }
113-
114- X86_SIMD_SORT_FINLINE void COEX (reg_t &a, reg_t &b)
115- {
116- ::COEX<vtype, reg_t >(b, a);
117- }
118-
119- // Returns a vector of values that would be sorted as far right as possible
120- // For descending order, this is the minimum possible value
121- X86_SIMD_SORT_FINLINE reg_t rightmostPossibleVec ()
122- {
123- return vtype::zmm_min ();
124- }
125-
126- // Returns the value that would be leftmost of the two when sorted
127- // For descending order, that is the larger value
128- X86_SIMD_SORT_FINLINE type_t leftmost (type_t smaller, type_t bigger)
129- {
130- UNUSED (smaller);
131- return bigger;
132- }
133-
134- // Returns the value that would be rightmost of the two when sorted
135- // For descending order, that is the smaller value
136- X86_SIMD_SORT_FINLINE type_t rightmost (type_t smaller, type_t bigger)
137- {
138- UNUSED (bigger);
139- return smaller;
140- }
141-
142- // If median == smallest, that implies approximately half the array is equal to smallest, unless we were very unlucky with our sample
143- // Thus, median probably is a fine pivot, since it will move all of this common value into its own partition
144- X86_SIMD_SORT_FINLINE type_t choosePivotMedianIsSmallest (type_t median)
145- {
146- return median;
147- }
148-
149- // If median == largest, that implies approximately half the array is equal to largest, unless we were very unlucky with our sample
150- // Try just doing the next smallest value less than this seemingly very common value to seperate them out
151- X86_SIMD_SORT_FINLINE type_t choosePivotMedianIsLargest (type_t median)
152- {
153- return prev_value<type_t >(median);
120+ if constexpr (descend) { return prev_value<type_t >(median); }
121+ else {
122+ return median;
123+ }
154124 }
155125};
156126
157- #endif // XSS_COMMON_COMPARATORS
127+ #endif // XSS_COMMON_COMPARATORS
0 commit comments