aboutsummaryrefslogtreecommitdiff
path: root/src/cube_avx2.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
commit18c9a8b8905304cf5f8fc15825769046a3144866 (patch)
treea7807bb32b0a5d9ded7d3cedccc598f64a9b00fe /src/cube_avx2.h
parentf25a10e19eca294c4e6a99e4f80ce5cfd11a0e5f (diff)
downloadnissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.tar.gz
nissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.zip
Reorganized folder structure
Diffstat (limited to 'src/cube_avx2.h')
-rw-r--r--src/cube_avx2.h341
1 files changed, 0 insertions, 341 deletions
diff --git a/src/cube_avx2.h b/src/cube_avx2.h
deleted file mode 100644
index b189023..0000000
--- a/src/cube_avx2.h
+++ /dev/null
@@ -1,341 +0,0 @@
1typedef __m256i cube_t;
2
3#define _co2_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060))
4#define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020))
5#define _cp_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x0707070707070707))
6#define _ep_avx2 \
7 _mm256_set_epi64x(INT64_C(0x0F0F0F0F), INT64_C(0x0F0F0F0F0F0F0F0F), 0, 0)
8#define _eo_avx2 \
9 _mm256_set_epi64x(INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0)
10
11#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \
12 e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \
13 _mm256_set_epi8(0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, \
14 e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, \
15 0, 0, 0, 0, 0, 0, 0, 0, \
16 c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr)
17#define zero _mm256_set_epi64x(0, 0, 0, 0)
18#define solved static_cube( \
19 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
20
21_static void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]);
22_static_inline bool equal(cube_t, cube_t);
23_static_inline cube_t invertco(cube_t);
24_static_inline cube_t compose_epcpeo(cube_t, cube_t);
25_static_inline cube_t compose_edges(cube_t, cube_t);
26_static_inline cube_t compose_corners(cube_t, cube_t);
27_static_inline cube_t compose(cube_t, cube_t);
28_static_inline cube_t inverse(cube_t);
29
30_static_inline int64_t coord_co(cube_t);
31_static_inline int64_t coord_csep(cube_t);
32_static_inline int64_t coord_cocsep(cube_t);
33_static_inline int64_t coord_eo(cube_t);
34_static_inline int64_t coord_esep(cube_t);
35
36_static_inline void copy_corners(cube_t *, cube_t);
37_static_inline void copy_edges(cube_t *, cube_t);
38_static_inline void set_eo(cube_t *, int64_t);
39_static_inline cube_t invcoord_esep(int64_t);
40
41_static void
42pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
43{
44 uint8_t aux[32];
45
46 _mm256_storeu_si256((__m256i_u *)aux, *cube);
47 memcpy(c, aux, 8);
48 memcpy(e, aux+16, 12);
49}
50
51_static_inline bool
52equal(cube_t c1, cube_t c2)
53{
54 int32_t mask;
55 __m256i cmp;
56
57 cmp = _mm256_cmpeq_epi8(c1, c2);
58 mask = _mm256_movemask_epi8(cmp);
59
60 return mask == ~0;
61}
62
63_static_inline cube_t
64invertco(cube_t c)
65{
66 cube_t co, shleft, shright, summed, newco, cleanco, ret;
67
68 co = _mm256_and_si256(c, _co2_avx2);
69 shleft = _mm256_slli_epi32(co, 1);
70 shright = _mm256_srli_epi32(co, 1);
71 summed = _mm256_or_si256(shleft, shright);
72 newco = _mm256_and_si256(summed, _co2_avx2);
73 cleanco = _mm256_xor_si256(c, co);
74 ret = _mm256_or_si256(cleanco, newco);
75
76 return ret;
77}
78
79_static_inline cube_t
80compose_epcpeo(cube_t c1, cube_t c2)
81{
82 cube_t b, s, eo2;
83
84 /* Permute and clean unused bits */
85 s = _mm256_shuffle_epi8(c1, c2);
86 b = _mm256_set_epi8(
87 ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0
89 );
90 s = _mm256_andnot_si256(b, s);
91
92 /* Change EO */
93 eo2 = _mm256_and_si256(c2, _eo_avx2);
94 s = _mm256_xor_si256(s, eo2);
95
96 return s;
97}
98
99_static_inline cube_t
100compose_edges(cube_t c1, cube_t c2)
101{
102 return compose_epcpeo(c1, c2);
103}
104
105_static_inline cube_t
106compose_corners(cube_t c1, cube_t c2)
107{
108 /*
109 * We do a full compose. Minor optimizations are possible, like
110 * saving one instruction by not doing EO, but it should not
111 * be significant.
112 */
113 return compose(c1, c2);
114}
115
116_static_inline cube_t
117compose(cube_t c1, cube_t c2)
118{
119 cube_t s, co1, co2, aux, auy1, auy2, auz1, auz2;
120
121 s = compose_epcpeo(c1, c2);
122
123 /* Change CO */
124 co1 = _mm256_and_si256(s, _co2_avx2);
125 co2 = _mm256_and_si256(c2, _co2_avx2);
126 aux = _mm256_add_epi8(co1, co2);
127 auy1 = _mm256_add_epi8(aux, _cocw_avx2);
128 auy2 = _mm256_srli_epi32(auy1, 2);
129 auz1 = _mm256_add_epi8(aux, auy2);
130 auz2 = _mm256_and_si256(auz1, _co2_avx2);
131
132 /* Put together */
133 s = _mm256_andnot_si256(_co2_avx2, s);
134 s = _mm256_or_si256(s, auz2);
135
136 return s;
137}
138
139_static_inline cube_t
140cleanaftershuffle(cube_t c)
141{
142 __m256i b;
143
144 b = _mm256_set_epi8(
145 ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0
147 );
148
149 return _mm256_andnot_si256(b, c);
150}
151
152_static_inline cube_t
153inverse(cube_t c)
154{
155 /* Method taken from Andrew Skalski's vcube[1]. The addition sequence
156 * was generated using [2].
157 * [1] https://github.com/Voltara/vcube
158 * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html
159 */
160 cube_t v3, vi, vo, vp, ret;
161
162 v3 = _mm256_shuffle_epi8(c, c);
163 v3 = _mm256_shuffle_epi8(v3, c);
164 vi = _mm256_shuffle_epi8(v3, v3);
165 vi = _mm256_shuffle_epi8(vi, vi);
166 vi = _mm256_shuffle_epi8(vi, vi);
167 vi = _mm256_shuffle_epi8(vi, v3);
168 vi = _mm256_shuffle_epi8(vi, vi);
169 vi = _mm256_shuffle_epi8(vi, vi);
170 vi = _mm256_shuffle_epi8(vi, vi);
171 vi = _mm256_shuffle_epi8(vi, vi);
172 vi = _mm256_shuffle_epi8(vi, c);
173 vi = _mm256_shuffle_epi8(vi, vi);
174 vi = _mm256_shuffle_epi8(vi, vi);
175 vi = _mm256_shuffle_epi8(vi, vi);
176 vi = _mm256_shuffle_epi8(vi, vi);
177 vi = _mm256_shuffle_epi8(vi, vi);
178 vi = _mm256_shuffle_epi8(vi, v3);
179 vi = _mm256_shuffle_epi8(vi, vi);
180 vi = _mm256_shuffle_epi8(vi, c);
181
182 vo = _mm256_and_si256(c, _mm256_or_si256(_eo_avx2, _co2_avx2));
183 vo = _mm256_shuffle_epi8(vo, vi);
184 vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi);
185 ret = _mm256_or_si256(vp, vo);
186 ret = cleanaftershuffle(ret);
187
188 return invertco(ret);
189}
190
191_static_inline int64_t
192coord_co(cube_t c)
193{
194 cube_t co;
195 int64_t mem[4], ret, i, p;
196
197 co = _mm256_and_si256(c, _co2_avx2);
198 _mm256_storeu_si256((__m256i *)mem, co);
199
200 mem[0] >>= 5;
201 for (i = 0, ret = 0, p = 1; i < 7; i++, mem[0] >>= 8, p *= 3)
202 ret += (mem[0] & 3) * p;
203
204 return ret;
205}
206
207_static_inline int64_t
208coord_csep(cube_t c)
209{
210 cube_t cp, shifted;
211 int64_t mask;
212
213 cp = _mm256_and_si256(c, _cp_avx2);
214 shifted = _mm256_slli_epi32(cp, 5);
215 mask = _mm256_movemask_epi8(shifted);
216
217 return mask & 0x7F;
218}
219
220_static_inline int64_t
221coord_cocsep(cube_t c)
222{
223 return (coord_co(c) << 7) + coord_csep(c);
224}
225
226_static_inline int64_t
227coord_eo(cube_t c)
228{
229 cube_t eo, shifted;
230 int64_t mask;
231
232 eo = _mm256_and_si256(c, _eo_avx2);
233 shifted = _mm256_slli_epi32(eo, 3);
234 mask = _mm256_movemask_epi8(shifted);
235
236 return mask >> 17;
237}
238
239_static_inline int64_t
240coord_esep(cube_t c)
241{
242 cube_t ep;
243 int64_t e, mem[4], i, j, jj, k, l, ret1, ret2, bit1, bit2, is1;
244
245 ep = _mm256_and_si256(c, _ep_avx2);
246 _mm256_storeu_si256((__m256i *)mem, ep);
247
248 mem[3] <<= 8;
249 ret1 = ret2 = 0;
250 k = l = 4;
251 for (i = 0, j = 0; i < 12; i++, mem[i/8 + 2] >>= 8) {
252 e = mem[i/8 + 2];
253
254 bit1 = (e & _esepbit1) >> 2;
255 bit2 = (e & _esepbit2) >> 3;
256 is1 = (1 - bit2) * bit1;
257
258 ret1 += bit2 * binomial[11-i][k];
259 k -= bit2;
260
261 jj = j < 8;
262 ret2 += jj * is1 * binomial[7-(j*jj)][l];
263 l -= is1;
264 j += (1-bit2);
265 }
266
267 return ret1 * 70 + ret2;
268}
269
270_static_inline void
271copy_corners(cube_t *dest, cube_t src)
272{
273 *dest = _mm256_blend_epi32(*dest, src, 0x0F);
274}
275
276_static_inline void
277copy_edges(cube_t *dest, cube_t src)
278{
279 *dest = _mm256_blend_epi32(*dest, src, 0xF0);
280}
281
282_static_inline void
283set_eo(cube_t *cube, int64_t eo)
284{
285 int64_t eo12, eotop, eobot;
286 __m256i veo;
287
288 eo12 = (eo << 1) + (_mm_popcnt_u64(eo) % 2);
289 eotop = (eo12 & (1 << 11)) << 17 |
290 (eo12 & (1 << 10)) << 10 |
291 (eo12 & (1 << 9)) << 3 |
292 (eo12 & (1 << 8)) >> 4;
293 eobot = (eo12 & (1 << 7)) << 53 |
294 (eo12 & (1 << 6)) << 46 |
295 (eo12 & (1 << 5)) << 39 |
296 (eo12 & (1 << 4)) << 32 |
297 (eo12 & (1 << 3)) << 25 |
298 (eo12 & (1 << 2)) << 18 |
299 (eo12 & (1 << 1)) << 11 |
300 (eo12 & 1) << 4;
301 veo = _mm256_set_epi64x(eotop, eobot, 0, 0);
302
303 *cube = _mm256_andnot_si256(_eo_avx2, *cube);
304 *cube = _mm256_or_si256(*cube, veo);
305}
306
307_static_inline cube_t
308invcoord_esep(int64_t esep)
309{
310 cube_t eee, ret;
311 int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2;
312 uint8_t mem[32];
313 uint8_t slice[3] = {0};
314
315 set1 = esep % 70;
316 set2 = esep / 70;
317
318 for (i = 0, j = 0, k = 4, l = 4; i < 12; i++) {
319 v = binomial[11-i][k];
320 jj = j < 8;
321 w = jj * binomial[7-(j*jj)][l];
322 bit2 = set2 >= v;
323 bit1 = set1 >= w;
324 is1 = (1 - bit2) * bit1;
325
326 set2 -= bit2 * v;
327 k -= bit2;
328 set1 -= is1 * w;
329 l -= is1;
330 j += (1-bit2);
331 s = 2*bit2 + (1-bit2)*bit1;
332
333 mem[i+16] = (slice[s]++) | (uint8_t)(s << 2);
334 }
335
336 ret = solved;
337 eee = _mm256_loadu_si256((__m256i_u *)&mem);
338 copy_edges(&ret, eee);
339
340 return ret;
341}

Generated with cgit - Back to sebastiano.tronto.net