From a660922d738b78b11fc78207daabea031058f710 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Fri, 10 May 2024 09:10:12 +0200 Subject: Split into .h files --- src/cube_avx2.h | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/cube_avx2.h (limited to 'src/cube_avx2.h') diff --git a/src/cube_avx2.h b/src/cube_avx2.h new file mode 100644 index 0000000..c61813f --- /dev/null +++ b/src/cube_avx2.h @@ -0,0 +1,229 @@ +typedef __m256i cube_fast_t; + +#define _co2_avx2 _mm256_set_epi64x(0, 0, 0, 0x6060606060606060) +#define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020) +#define _cp_avx2 _mm256_set_epi64x(0, 0, 0, 0x0707070707070707) +#define _ep_avx2 _mm256_set_epi64x(0x0F0F0F0F, 0x0F0F0F0F0F0F0F0F, 0, 0) +#define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0) + +_static_inline cube_fast_t fastcube( + uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, + uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, + uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, + uint8_t, uint8_t, uint8_t, uint8_t, uint8_t +); +_static cube_fast_t cubetofast(cube_t); +_static cube_t fasttocube(cube_fast_t); +_static_inline bool equal_fast(cube_fast_t, cube_fast_t); +_static_inline bool issolved_fast(cube_fast_t); +_static_inline cube_fast_t invertco_fast(cube_fast_t); +_static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); + +_static_inline int64_t coord_fast_co(cube_fast_t); +_static_inline int64_t coord_fast_csep(cube_fast_t); +_static_inline int64_t coord_fast_cocsep(cube_fast_t); +_static_inline int64_t coord_fast_eo(cube_fast_t); +_static_inline int64_t coord_fast_esep(cube_fast_t); + +_static_inline cube_fast_t +fastcube( + uint8_t c_ufr, + uint8_t c_ubl, + uint8_t c_dfl, + uint8_t c_dbr, + uint8_t c_ufl, + uint8_t c_ubr, + uint8_t c_dfr, + uint8_t c_dbl, + + uint8_t e_uf, + uint8_t e_ub, + uint8_t e_db, + uint8_t e_df, + uint8_t e_ur, + uint8_t e_ul, + uint8_t e_dl, + uint8_t e_dr, + uint8_t e_fr, + uint8_t e_fl, + uint8_t e_bl, + uint8_t e_br +) +{ + return _mm256_set_epi8( + 0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, + e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, + 0, 0, 0, 0, 0, 0, 0, 0, + c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr + ); +} + +_static cube_fast_t +cubetofast(cube_t a) +{ + uint8_t aux[32]; + + memset(aux, 0, 32); + memcpy(aux, &a.corner, 8); + memcpy(aux + 16, &a.edge, 12); + + return _mm256_loadu_si256((__m256i_u *)&aux); +} + +_static cube_t +fasttocube(cube_fast_t c) +{ + cube_t a; + uint8_t aux[32]; + + _mm256_storeu_si256((__m256i_u *)aux, c); + memcpy(&a.corner, aux, 8); + memcpy(&a.edge, aux + 16, 12); + + return a; +} + +_static_inline bool +equal_fast(cube_fast_t c1, cube_fast_t c2) +{ + int32_t mask; + __m256i cmp; + + cmp = _mm256_cmpeq_epi8(c1, c2); + mask = _mm256_movemask_epi8(cmp); + + return mask == ~0; +} + +_static_inline bool +issolved_fast(cube_fast_t cube) +{ + return equal_fast(cube, solved_fast); +} + +_static_inline cube_fast_t +invertco_fast(cube_fast_t c) +{ + cube_fast_t co, shleft, shright, summed, newco, cleanco, ret; + + co = _mm256_and_si256(c, _co2_avx2); + shleft = _mm256_slli_epi32(co, 1); + shright = _mm256_srli_epi32(co, 1); + summed = _mm256_or_si256(shleft, shright); + newco = _mm256_and_si256(summed, _co2_avx2); + cleanco = _mm256_xor_si256(c, co); + ret = _mm256_or_si256(cleanco, newco); + + return ret; +} + +_static_inline cube_fast_t +compose_fast(cube_fast_t c1, cube_fast_t c2) +{ + cube_fast_t s, b, eo2, co1, co2, aux, auy1, auy2, auz1, auz2; + + /* Permute and clean unused bits */ + s = _mm256_shuffle_epi8(c1, c2); + b = _mm256_set_epi8( + ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 + ); + s = _mm256_andnot_si256(b, s); + + /* Change EO */ + eo2 = _mm256_and_si256(c2, _eo_avx2); + s = _mm256_xor_si256(s, eo2); + + /* Change CO */ + co1 = _mm256_and_si256(s, _co2_avx2); + co2 = _mm256_and_si256(c2, _co2_avx2); + aux = _mm256_add_epi8(co1, co2); + auy1 = _mm256_add_epi8(aux, _cocw_avx2); + auy2 = _mm256_srli_epi32(auy1, 2); + auz1 = _mm256_add_epi8(aux, auy2); + auz2 = _mm256_and_si256(auz1, _co2_avx2); + + /* Put together */ + s = _mm256_andnot_si256(_co2_avx2, s); + s = _mm256_or_si256(s, auz2); + + return s; +} + +_static_inline int64_t +coord_fast_co(cube_fast_t c) +{ + cube_fast_t co; + int64_t mem[4], ret, i, p; + + co = _mm256_and_si256(c, _co2_avx2); + _mm256_storeu_si256((__m256i *)mem, co); + + mem[0] >>= 5L; + for (i = 0, ret = 0, p = 1; i < 7; i++, mem[0] >>= 8L, p *= 3) + ret += (mem[0] & 3L) * p; + + return ret; +} + +_static_inline int64_t +coord_fast_csep(cube_fast_t c) +{ + cube_fast_t cp, shifted; + int64_t mask; + + cp = _mm256_and_si256(c, _cp_avx2); + shifted = _mm256_slli_epi32(cp, 5); + mask = _mm256_movemask_epi8(shifted); + + return mask & 0x7F; +} + +_static_inline int64_t +coord_fast_cocsep(cube_fast_t c) +{ + return (coord_fast_co(c) << 7) + coord_fast_csep(c); +} + +_static_inline int64_t +coord_fast_eo(cube_fast_t c) +{ + cube_fast_t eo, shifted; + int64_t mask; + + eo = _mm256_and_si256(c, _eo_avx2); + shifted = _mm256_slli_epi32(eo, 3); + mask = _mm256_movemask_epi8(shifted); + + return mask >> 17; +} + +_static_inline int64_t +coord_fast_esep(cube_fast_t c) +{ + cube_fast_t ep; + int64_t e, mem[4], i, j, k, l, ret1, ret2, bit1, bit2, is1; + + ep = _mm256_and_si256(c, _ep_avx2); + _mm256_storeu_si256((__m256i *)mem, ep); + + mem[3] <<= 8L; + ret1 = ret2 = 0; + k = l = 4; + for (i = 0, j = 0; i < 12; i++, mem[i/8 + 2] >>= 8L) { + e = mem[i/8 + 2]; + + bit1 = (e & _esepbit1) >> 2L; + bit2 = (e & _esepbit2) >> 3L; + is1 = (1 - bit2) * bit1; + + ret1 += bit2 * binomial[11-i][k]; + k -= bit2; + + ret2 += is1 * binomial[7-j][l]; + l -= is1; + j += (1-bit2); + } + + return ret1 * 70 + ret2; +} -- cgit v1.3