]> git.uio.no Git - u/mrichter/AliRoot.git/blob - Vc/src/avx_sorthelper.cpp
allow also comma as delimiter
[u/mrichter/AliRoot.git] / Vc / src / avx_sorthelper.cpp
1 /*  This file is part of the Vc library.
2
3     Copyright (C) 2011 Matthias Kretz <kretz@kde.org>
4
5     Vc is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as
7     published by the Free Software Foundation, either version 3 of
8     the License, or (at your option) any later version.
9
10     Vc is distributed in the hope that it will be useful, but
11     WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with Vc.  If not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20 #include <Vc/avx/intrinsics.h>
21 #include <Vc/avx/casts.h>
22 #include <Vc/avx/sorthelper.h>
23 #include <Vc/avx/macros.h>
24
25 namespace AliRoot {
26 namespace Vc
27 {
28 namespace AVX
29 {
30
31 template<> m128i SortHelper<short>::sort(VTArg _x)
32 {
33     m128i lo, hi, y, x = _x;
34     // sort pairs
35     y = _mm_shufflelo_epi16(_mm_shufflehi_epi16(x, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
36     lo = _mm_min_epi16(x, y);
37     hi = _mm_max_epi16(x, y);
38     x = _mm_blend_epi16(lo, hi, 0xaa);
39
40     // merge left and right quads
41     y = _mm_shufflelo_epi16(_mm_shufflehi_epi16(x, _MM_SHUFFLE(0, 1, 2, 3)), _MM_SHUFFLE(0, 1, 2, 3));
42     lo = _mm_min_epi16(x, y);
43     hi = _mm_max_epi16(x, y);
44     x = _mm_blend_epi16(lo, hi, 0xcc);
45     y = _mm_srli_si128(x, 2);
46     lo = _mm_min_epi16(x, y);
47     hi = _mm_max_epi16(x, y);
48     x = _mm_blend_epi16(lo, _mm_slli_si128(hi, 2), 0xaa);
49
50     // merge quads into octs
51     y = _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2));
52     y = _mm_shufflelo_epi16(y, _MM_SHUFFLE(0, 1, 2, 3));
53     lo = _mm_min_epi16(x, y);
54     hi = _mm_max_epi16(x, y);
55
56     x = _mm_unpacklo_epi16(lo, hi);
57     y = _mm_srli_si128(x, 8);
58     lo = _mm_min_epi16(x, y);
59     hi = _mm_max_epi16(x, y);
60
61     x = _mm_unpacklo_epi16(lo, hi);
62     y = _mm_srli_si128(x, 8);
63     lo = _mm_min_epi16(x, y);
64     hi = _mm_max_epi16(x, y);
65
66     return _mm_unpacklo_epi16(lo, hi);
67 }
68 template<> m128i SortHelper<unsigned short>::sort(VTArg _x)
69 {
70     m128i lo, hi, y, x = _x;
71     // sort pairs
72     y = _mm_shufflelo_epi16(_mm_shufflehi_epi16(x, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
73     lo = _mm_min_epu16(x, y);
74     hi = _mm_max_epu16(x, y);
75     x = _mm_blend_epi16(lo, hi, 0xaa);
76
77     // merge left and right quads
78     y = _mm_shufflelo_epi16(_mm_shufflehi_epi16(x, _MM_SHUFFLE(0, 1, 2, 3)), _MM_SHUFFLE(0, 1, 2, 3));
79     lo = _mm_min_epu16(x, y);
80     hi = _mm_max_epu16(x, y);
81     x = _mm_blend_epi16(lo, hi, 0xcc);
82     y = _mm_srli_si128(x, 2);
83     lo = _mm_min_epu16(x, y);
84     hi = _mm_max_epu16(x, y);
85     x = _mm_blend_epi16(lo, _mm_slli_si128(hi, 2), 0xaa);
86
87     // merge quads into octs
88     y = _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2));
89     y = _mm_shufflelo_epi16(y, _MM_SHUFFLE(0, 1, 2, 3));
90     lo = _mm_min_epu16(x, y);
91     hi = _mm_max_epu16(x, y);
92
93     x = _mm_unpacklo_epi16(lo, hi);
94     y = _mm_srli_si128(x, 8);
95     lo = _mm_min_epu16(x, y);
96     hi = _mm_max_epu16(x, y);
97
98     x = _mm_unpacklo_epi16(lo, hi);
99     y = _mm_srli_si128(x, 8);
100     lo = _mm_min_epu16(x, y);
101     hi = _mm_max_epu16(x, y);
102
103     return _mm_unpacklo_epi16(lo, hi);
104 }
105
106 template<> m256i SortHelper<int>::sort(VTArg _hgfedcba)
107 {
108     VectorType hgfedcba = _hgfedcba;
109     const m128i hgfe = hi128(hgfedcba);
110     const m128i dcba = lo128(hgfedcba);
111     m128i l = _mm_min_epi32(hgfe, dcba); // ↓hd ↓gc ↓fb ↓ea
112     m128i h = _mm_max_epi32(hgfe, dcba); // ↑hd ↑gc ↑fb ↑ea
113
114     m128i x = _mm_unpacklo_epi32(l, h); // ↑fb ↓fb ↑ea ↓ea
115     m128i y = _mm_unpackhi_epi32(l, h); // ↑hd ↓hd ↑gc ↓gc
116
117     l = _mm_min_epi32(x, y); // ↓(↑fb,↑hd) ↓hfdb ↓(↑ea,↑gc) ↓geca
118     h = _mm_max_epi32(x, y); // ↑hfdb ↑(↓fb,↓hd) ↑geca ↑(↓ea,↓gc)
119
120     x = _mm_min_epi32(l, Reg::permute<X2, X2, X0, X0>(h)); // 2(hfdb) 1(hfdb) 2(geca) 1(geca)
121     y = _mm_max_epi32(h, Reg::permute<X3, X3, X1, X1>(l)); // 4(hfdb) 3(hfdb) 4(geca) 3(geca)
122
123     m128i b = Reg::shuffle<Y0, Y1, X0, X1>(y, x); // b3 <= b2 <= b1 <= b0
124     m128i a = _mm_unpackhi_epi64(x, y);           // a3 >= a2 >= a1 >= a0
125
126     if (VC_IS_UNLIKELY(_mm_extract_epi32(x, 2) >= _mm_extract_epi32(y, 1))) {
127         return concat(Reg::permute<X0, X1, X2, X3>(b), a);
128     } else if (VC_IS_UNLIKELY(_mm_extract_epi32(x, 0) >= _mm_extract_epi32(y, 3))) {
129         return concat(a, Reg::permute<X0, X1, X2, X3>(b));
130     }
131
132     // merge
133     l = _mm_min_epi32(a, b); // ↓a3b3 ↓a2b2 ↓a1b1 ↓a0b0
134     h = _mm_max_epi32(a, b); // ↑a3b3 ↑a2b2 ↑a1b1 ↑a0b0
135
136     a = _mm_unpacklo_epi32(l, h); // ↑a1b1 ↓a1b1 ↑a0b0 ↓a0b0
137     b = _mm_unpackhi_epi32(l, h); // ↑a3b3 ↓a3b3 ↑a2b2 ↓a2b2
138     l = _mm_min_epi32(a, b);      // ↓(↑a1b1,↑a3b3) ↓a1b3 ↓(↑a0b0,↑a2b2) ↓a0b2
139     h = _mm_max_epi32(a, b);      // ↑a3b1 ↑(↓a1b1,↓a3b3) ↑a2b0 ↑(↓a0b0,↓a2b2)
140
141     a = _mm_unpacklo_epi32(l, h); // ↑a2b0 ↓(↑a0b0,↑a2b2) ↑(↓a0b0,↓a2b2) ↓a0b2
142     b = _mm_unpackhi_epi32(l, h); // ↑a3b1 ↓(↑a1b1,↑a3b3) ↑(↓a1b1,↓a3b3) ↓a1b3
143     l = _mm_min_epi32(a, b); // ↓(↑a2b0,↑a3b1) ↓(↑a0b0,↑a2b2,↑a1b1,↑a3b3) ↓(↑(↓a0b0,↓a2b2) ↑(↓a1b1,↓a3b3)) ↓a0b3
144     h = _mm_max_epi32(a, b); // ↑a3b0 ↑(↓(↑a0b0,↑a2b2) ↓(↑a1b1,↑a3b3)) ↑(↓a0b0,↓a2b2,↓a1b1,↓a3b3) ↑(↓a0b2,↓a1b3)
145
146     return concat(_mm_unpacklo_epi32(l, h), _mm_unpackhi_epi32(l, h));
147 }
148
149 template<> m256i SortHelper<unsigned int>::sort(VTArg _hgfedcba)
150 {
151     VectorType hgfedcba = _hgfedcba;
152     const m128i hgfe = hi128(hgfedcba);
153     const m128i dcba = lo128(hgfedcba);
154     m128i l = _mm_min_epu32(hgfe, dcba); // ↓hd ↓gc ↓fb ↓ea
155     m128i h = _mm_max_epu32(hgfe, dcba); // ↑hd ↑gc ↑fb ↑ea
156
157     m128i x = _mm_unpacklo_epi32(l, h); // ↑fb ↓fb ↑ea ↓ea
158     m128i y = _mm_unpackhi_epi32(l, h); // ↑hd ↓hd ↑gc ↓gc
159
160     l = _mm_min_epu32(x, y); // ↓(↑fb,↑hd) ↓hfdb ↓(↑ea,↑gc) ↓geca
161     h = _mm_max_epu32(x, y); // ↑hfdb ↑(↓fb,↓hd) ↑geca ↑(↓ea,↓gc)
162
163     x = _mm_min_epu32(l, Reg::permute<X2, X2, X0, X0>(h)); // 2(hfdb) 1(hfdb) 2(geca) 1(geca)
164     y = _mm_max_epu32(h, Reg::permute<X3, X3, X1, X1>(l)); // 4(hfdb) 3(hfdb) 4(geca) 3(geca)
165
166     m128i b = Reg::shuffle<Y0, Y1, X0, X1>(y, x); // b3 <= b2 <= b1 <= b0
167     m128i a = _mm_unpackhi_epi64(x, y);           // a3 >= a2 >= a1 >= a0
168
169     if (VC_IS_UNLIKELY(_mm_extract_epu32(x, 2) >= _mm_extract_epu32(y, 1))) {
170         return concat(Reg::permute<X0, X1, X2, X3>(b), a);
171     } else if (VC_IS_UNLIKELY(_mm_extract_epu32(x, 0) >= _mm_extract_epu32(y, 3))) {
172         return concat(a, Reg::permute<X0, X1, X2, X3>(b));
173     }
174
175     // merge
176     l = _mm_min_epu32(a, b); // ↓a3b3 ↓a2b2 ↓a1b1 ↓a0b0
177     h = _mm_max_epu32(a, b); // ↑a3b3 ↑a2b2 ↑a1b1 ↑a0b0
178
179     a = _mm_unpacklo_epi32(l, h); // ↑a1b1 ↓a1b1 ↑a0b0 ↓a0b0
180     b = _mm_unpackhi_epi32(l, h); // ↑a3b3 ↓a3b3 ↑a2b2 ↓a2b2
181     l = _mm_min_epu32(a, b);      // ↓(↑a1b1,↑a3b3) ↓a1b3 ↓(↑a0b0,↑a2b2) ↓a0b2
182     h = _mm_max_epu32(a, b);      // ↑a3b1 ↑(↓a1b1,↓a3b3) ↑a2b0 ↑(↓a0b0,↓a2b2)
183
184     a = _mm_unpacklo_epi32(l, h); // ↑a2b0 ↓(↑a0b0,↑a2b2) ↑(↓a0b0,↓a2b2) ↓a0b2
185     b = _mm_unpackhi_epi32(l, h); // ↑a3b1 ↓(↑a1b1,↑a3b3) ↑(↓a1b1,↓a3b3) ↓a1b3
186     l = _mm_min_epu32(a, b); // ↓(↑a2b0,↑a3b1) ↓(↑a0b0,↑a2b2,↑a1b1,↑a3b3) ↓(↑(↓a0b0,↓a2b2) ↑(↓a1b1,↓a3b3)) ↓a0b3
187     h = _mm_max_epu32(a, b); // ↑a3b0 ↑(↓(↑a0b0,↑a2b2) ↓(↑a1b1,↑a3b3)) ↑(↓a0b0,↓a2b2,↓a1b1,↓a3b3) ↑(↓a0b2,↓a1b3)
188
189     return concat(_mm_unpacklo_epi32(l, h), _mm_unpackhi_epi32(l, h));
190 }
191
192 template<> m256 SortHelper<float>::sort(VTArg _hgfedcba)
193 {
194     VectorType hgfedcba = _hgfedcba;
195     const m128 hgfe = hi128(hgfedcba);
196     const m128 dcba = lo128(hgfedcba);
197     m128 l = _mm_min_ps(hgfe, dcba); // ↓hd ↓gc ↓fb ↓ea
198     m128 h = _mm_max_ps(hgfe, dcba); // ↑hd ↑gc ↑fb ↑ea
199
200     m128 x = _mm_unpacklo_ps(l, h); // ↑fb ↓fb ↑ea ↓ea
201     m128 y = _mm_unpackhi_ps(l, h); // ↑hd ↓hd ↑gc ↓gc
202
203     l = _mm_min_ps(x, y); // ↓(↑fb,↑hd) ↓hfdb ↓(↑ea,↑gc) ↓geca
204     h = _mm_max_ps(x, y); // ↑hfdb ↑(↓fb,↓hd) ↑geca ↑(↓ea,↓gc)
205
206     x = _mm_min_ps(l, Reg::permute<X2, X2, X0, X0>(h)); // 2(hfdb) 1(hfdb) 2(geca) 1(geca)
207     y = _mm_max_ps(h, Reg::permute<X3, X3, X1, X1>(l)); // 4(hfdb) 3(hfdb) 4(geca) 3(geca)
208
209     m128 a = _mm_castpd_ps(_mm_unpackhi_pd(_mm_castps_pd(x), _mm_castps_pd(y))); // a3 >= a2 >= a1 >= a0
210     m128 b = Reg::shuffle<Y0, Y1, X0, X1>(y, x); // b3 <= b2 <= b1 <= b0
211
212     // merge
213     l = _mm_min_ps(a, b); // ↓a3b3 ↓a2b2 ↓a1b1 ↓a0b0
214     h = _mm_max_ps(a, b); // ↑a3b3 ↑a2b2 ↑a1b1 ↑a0b0
215
216     a = _mm_unpacklo_ps(l, h); // ↑a1b1 ↓a1b1 ↑a0b0 ↓a0b0
217     b = _mm_unpackhi_ps(l, h); // ↑a3b3 ↓a3b3 ↑a2b2 ↓a2b2
218     l = _mm_min_ps(a, b);      // ↓(↑a1b1,↑a3b3) ↓a1b3 ↓(↑a0b0,↑a2b2) ↓a0b2
219     h = _mm_max_ps(a, b);      // ↑a3b1 ↑(↓a1b1,↓a3b3) ↑a2b0 ↑(↓a0b0,↓a2b2)
220
221     a = _mm_unpacklo_ps(l, h); // ↑a2b0 ↓(↑a0b0,↑a2b2) ↑(↓a0b0,↓a2b2) ↓a0b2
222     b = _mm_unpackhi_ps(l, h); // ↑a3b1 ↓(↑a1b1,↑a3b3) ↑(↓a1b1,↓a3b3) ↓a1b3
223     l = _mm_min_ps(a, b); // ↓(↑a2b0,↑a3b1) ↓(↑a0b0,↑a2b2,↑a1b1,↑a3b3) ↓(↑(↓a0b0,↓a2b2) ↑(↓a1b1,↓a3b3)) ↓a0b3
224     h = _mm_max_ps(a, b); // ↑a3b0 ↑(↓(↑a0b0,↑a2b2) ↓(↑a1b1,↑a3b3)) ↑(↓a0b0,↓a2b2,↓a1b1,↓a3b3) ↑(↓a0b2,↓a1b3)
225
226     return concat(_mm_unpacklo_ps(l, h), _mm_unpackhi_ps(l, h));
227 }
228
229 template<> m256 SortHelper<sfloat>::sort(VTArg hgfedcba)
230 {
231     return SortHelper<float>::sort(hgfedcba);
232 }
233
234 template<> void SortHelper<double>::sort(m256d &VC_RESTRICT x, m256d &VC_RESTRICT y)
235 {
236     m256d l = _mm256_min_pd(x, y); // ↓x3y3 ↓x2y2 ↓x1y1 ↓x0y0
237     m256d h = _mm256_max_pd(x, y); // ↑x3y3 ↑x2y2 ↑x1y1 ↑x0y0
238     x = _mm256_unpacklo_pd(l, h); // ↑x2y2 ↓x2y2 ↑x0y0 ↓x0y0
239     y = _mm256_unpackhi_pd(l, h); // ↑x3y3 ↓x3y3 ↑x1y1 ↓x1y1
240     l = _mm256_min_pd(x, y); // ↓(↑x2y2,↑x3y3) ↓x3x2y3y2 ↓(↑x0y0,↑x1y1) ↓x1x0y1y0
241     h = _mm256_max_pd(x, y); // ↑x3x2y3y2 ↑(↓x2y2,↓x3y3) ↑x1x0y1y0 ↑(↓x0y0,↓x1y1)
242     x = _mm256_unpacklo_pd(l, h); // ↑(↓x2y2,↓x3y3) ↓x3x2y3y2 ↑(↓x0y0,↓x1y1) ↓x1x0y1y0
243     y = _mm256_unpackhi_pd(h, l); // ↓(↑x2y2,↑x3y3) ↑x3x2y3y2 ↓(↑x0y0,↑x1y1) ↑x1x0y1y0
244     l = _mm256_min_pd(x, y); // ↓(↑(↓x2y2,↓x3y3) ↓(↑x2y2,↑x3y3)) ↓x3x2y3y2 ↓(↑(↓x0y0,↓x1y1) ↓(↑x0y0,↑x1y1)) ↓x1x0y1y0
245     h = _mm256_max_pd(x, y); // ↑(↑(↓x2y2,↓x3y3) ↓(↑x2y2,↑x3y3)) ↑x3x2y3y2 ↑(↑(↓x0y0,↓x1y1) ↓(↑x0y0,↑x1y1)) ↑x1x0y1y0
246     m256d a = Reg::permute<X2, X3, X1, X0>(Reg::permute128<X0, X1>(h, h)); // h0 h1 h3 h2
247     m256d b = Reg::permute<X2, X3, X1, X0>(l);                             // l2 l3 l1 l0
248
249     // a3 >= a2 >= b1 >= b0
250     // b3 <= b2 <= a1 <= a0
251
252     // merge
253     l = _mm256_min_pd(a, b); // ↓a3b3 ↓a2b2 ↓a1b1 ↓a0b0
254     h = _mm256_min_pd(a, b); // ↑a3b3 ↑a2b2 ↑a1b1 ↑a0b0
255
256     x = _mm256_unpacklo_pd(l, h); // ↑a2b2 ↓a2b2 ↑a0b0 ↓a0b0
257     y = _mm256_unpackhi_pd(l, h); // ↑a3b3 ↓a3b3 ↑a1b1 ↓a1b1
258     l = _mm256_min_pd(x, y);      // ↓(↑a2b2,↑a3b3) ↓a2b3 ↓(↑a0b0,↑a1b1) ↓a1b0
259     h = _mm256_min_pd(x, y);      // ↑a3b2 ↑(↓a2b2,↓a3b3) ↑a0b1 ↑(↓a0b0,↓a1b1)
260
261     x = Reg::permute128<Y0, X0>(l, h); // ↑a0b1 ↑(↓a0b0,↓a1b1) ↓(↑a0b0,↑a1b1) ↓a1b0
262     y = Reg::permute128<Y1, X1>(l, h); // ↑a3b2 ↑(↓a2b2,↓a3b3) ↓(↑a2b2,↑a3b3) ↓a2b3
263     l = _mm256_min_pd(x, y);      // ↓(↑a0b1,↑a3b2) ↓(↑(↓a0b0,↓a1b1) ↑(↓a2b2,↓a3b3)) ↓(↑a0b0,↑a1b1,↑a2b2,↑a3b3) ↓b0b3
264     h = _mm256_min_pd(x, y);      // ↑a0a3 ↑(↓a0b0,↓a1b1,↓a2b2,↓a3b3) ↑(↓(↑a0b0,↑a1b1) ↓(↑a2b2,↑a3b3)) ↑(↓a1b0,↓a2b3)
265
266     x = _mm256_unpacklo_pd(l, h); // h2 l2 h0 l0
267     y = _mm256_unpackhi_pd(l, h); // h3 l3 h1 l1
268 }
269 template<> m256d SortHelper<double>::sort(VTArg _dcba)
270 {
271     VectorType dcba = _dcba;
272     /*
273      * to find the second largest number find
274      * max(min(max(ab),max(cd)), min(max(ad),max(bc)))
275      *  or
276      * max(max(min(ab),min(cd)), min(max(ab),max(cd)))
277      *
278     const m256d adcb = avx_cast<m256d>(concat(_mm_alignr_epi8(avx_cast<m128i>(dc), avx_cast<m128i>(ba), 8), _mm_alignr_epi8(avx_cast<m128i>(ba), avx_cast<m128i>(dc), 8)));
279     const m256d l = _mm256_min_pd(dcba, adcb); // min(ad cd bc ab)
280     const m256d h = _mm256_max_pd(dcba, adcb); // max(ad cd bc ab)
281     // max(h3, h1)
282     // max(min(h0,h2), min(h3,h1))
283     // min(max(l0,l2), max(l3,l1))
284     // min(l3, l1)
285
286     const m256d ll = _mm256_min_pd(h, Reg::permute128<X0, X1>(h, h)); // min(h3h1 h2h0 h1h3 h0h2)
287     //const m256d hh = _mm256_max_pd(h3 ll1_3 l1 l0, h1 ll0_2 l3 l2);
288     const m256d hh = _mm256_max_pd(
289             Reg::permute128<X1, Y0>(_mm256_unpackhi_pd(ll, h), l),
290             Reg::permute128<X0, Y1>(_mm256_blend_pd(h ll, 0x1), l));
291     _mm256_min_pd(hh0, hh1
292      */
293
294     //////////////////////////////////////////////////////////////////////////////////
295     // max(max(ac), max(bd))
296     // max(max(min(ac),min(bd)), min(max(ac),max(bd)))
297     // min(max(min(ac),min(bd)), min(max(ac),max(bd)))
298     // min(min(ac), min(bd))
299     m128d l = _mm_min_pd(lo128(dcba), hi128(dcba)); // min(bd) min(ac)
300     m128d h = _mm_max_pd(lo128(dcba), hi128(dcba)); // max(bd) max(ac)
301     m128d h0_l0 = _mm_unpacklo_pd(l, h);
302     m128d h1_l1 = _mm_unpackhi_pd(l, h);
303     l = _mm_min_pd(h0_l0, h1_l1);
304     h = _mm_max_pd(h0_l0, h1_l1);
305     return concat(
306         _mm_min_pd(l, Reg::permute<X0, X0>(h)),
307         _mm_max_pd(h, Reg::permute<X1, X1>(l))
308             );
309     // extract: 1 cycle
310     // min/max: 4 cycles
311     // unpacklo/hi: 2 cycles
312     // min/max: 4 cycles
313     // permute: 1 cycle
314     // min/max: 4 cycles
315     // insert:  1 cycle
316     // ----------------------
317     // total:   17 cycles
318
319     /*
320     m256d cdab = Reg::permute<X2, X3, X0, X1>(dcba);
321     m256d l = _mm256_min_pd(dcba, cdab);
322     m256d h = _mm256_max_pd(dcba, cdab);
323     m256d maxmin_ba = Reg::permute128<X0, Y0>(l, h);
324     m256d maxmin_dc = Reg::permute128<X1, Y1>(l, h);
325
326     l = _mm256_min_pd(maxmin_ba, maxmin_dc);
327     h = _mm256_max_pd(maxmin_ba, maxmin_dc);
328
329     return _mm256_blend_pd(h, l, 0x55);
330     */
331
332     /*
333     // a b c d
334     // b a d c
335     // sort pairs
336     m256d y, l, h;
337     m128d l2, h2;
338     y = shuffle<X1, Y0, X3, Y2>(x, x);
339     l = _mm256_min_pd(x, y); // min[ab ab cd cd]
340     h = _mm256_max_pd(x, y); // max[ab ab cd cd]
341
342     // 1 of 2 is at [0]
343     // 1 of 4 is at [1]
344     // 1 of 4 is at [2]
345     // 1 of 2 is at [3]
346
347     // don't be fooled by unpack here. It works differently for AVX pd than for SSE ps
348     x = _mm256_unpacklo_pd(l, h); // l_ab h_ab l_cd h_cd
349     l2 = _mm_min_pd(lo128(x), hi128(x)); // l_abcd l(h_ab hcd)
350     h2 = _mm_max_pd(lo128(x), hi128(x)); // h(l_ab l_cd) h_abcd
351
352     // either it is:
353     return concat(l2, h2);
354     // or:
355     // concat(_mm_unpacklo_pd(l2, h2), _mm_unpackhi_pd(l2, h2));
356
357     // I'd like to have four useful compares
358     const m128d dc = hi128(dcba);
359     const m128d ba = lo128(dcba);
360     const m256d adcb = avx_cast<m256d>(concat(_mm_alignr_epi8(avx_cast<m128i>(dc), avx_cast<m128i>(ba), 8), _mm_alignr_epi8(avx_cast<m128i>(ba), avx_cast<m128i>(dc), 8)));
361
362     const int extraCmp = _mm_movemask_pd(_mm_cmpgt_pd(dc, ba));
363     // 0x0: d <= b && c <= a
364     // 0x1: d <= b && c >  a
365     // 0x2: d >  b && c <= a
366     // 0x3: d >  b && c >  a
367
368     switch (_mm256_movemask_pd(_mm256_cmpgt_pd(dcba, adcb))) {
369     // impossible: 0x0, 0xf
370     case 0x1: // a <= b && b <= c && c <= d && d >  a
371         // abcd
372         return Reg::permute<X2, X3, X0, X1>(Reg::permute<X0, X1>(dcba, dcba));
373     case 0x2: // a <= b && b <= c && c >  d && d <= a
374         // dabc
375         return Reg::permute<X2, X3, X0, X1>(adcb);
376     case 0x3: // a <= b && b <= c && c >  d && d >  a
377         // a[bd]c
378         if (extraCmp & 2) {
379             // abdc
380             return Reg::permute<X2, X3, X1, X0>(Reg::permute<X0, X1>(dcba, dcba));
381         } else {
382             // adbc
383             return Reg::permute<X3, X2, X0, X1>(adcb);
384         }
385     case 0x4: // a <= b && b >  c && c <= d && d <= a
386         // cdab;
387         return Reg::permute<X2, X3, X0, X1>(dcba);
388     case 0x5: // a <= b && b >  c && c <= d && d >  a
389         // [ac] < [bd]
390         switch (extraCmp) {
391         case 0x0: // d <= b && c <= a
392             // cadb
393             return shuffle<>(dcba, bcda);
394         case 0x1: // d <= b && c >  a
395         case 0x2: // d >  b && c <= a
396         case 0x3: // d >  b && c >  a
397         }
398     case 0x6: // a <= b && b >  c && c >  d && d <= a
399         // d[ac]b
400     case 0x7: // a <= b && b >  c && c >  d && d >  a
401         // adcb;
402         return permute<X1, X0, X3, X2>(permute128<X1, X0>(bcda, bcda));
403     case 0x8: // a >  b && b <= c && c <= d && d <= a
404         return bcda;
405     case 0x9: // a >  b && b <= c && c <= d && d >  a
406         // b[ac]d;
407     case 0xa: // a >  b && b <= c && c >  d && d <= a
408         // [ac] > [bd]
409     case 0xb: // a >  b && b <= c && c >  d && d >  a
410         // badc;
411         return permute128<X1, X0>(dcba);
412     case 0xc: // a >  b && b >  c && c <= d && d <= a
413         // c[bd]a;
414     case 0xd: // a >  b && b >  c && c <= d && d >  a
415         // cbad;
416         return permute<X1, X0, X3, X2>(bcda);
417     case 0xe: // a >  b && b >  c && c >  d && d <= a
418         return dcba;
419     }
420     */
421 }
422
423 } // namespace AVX
424 } // namespace Vc
425 } // namespace AliRoot