diff options
Diffstat (limited to 'src/cube_avx2.h')
| -rw-r--r-- | src/cube_avx2.h | 229 |
1 files changed, 229 insertions, 0 deletions
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 @@ | |||
| 1 | typedef __m256i cube_fast_t; | ||
| 2 | |||
| 3 | #define _co2_avx2 _mm256_set_epi64x(0, 0, 0, 0x6060606060606060) | ||
| 4 | #define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020) | ||
| 5 | #define _cp_avx2 _mm256_set_epi64x(0, 0, 0, 0x0707070707070707) | ||
| 6 | #define _ep_avx2 _mm256_set_epi64x(0x0F0F0F0F, 0x0F0F0F0F0F0F0F0F, 0, 0) | ||
| 7 | #define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0) | ||
| 8 | |||
| 9 | _static_inline cube_fast_t fastcube( | ||
| 10 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 11 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 12 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 13 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t | ||
| 14 | ); | ||
| 15 | _static cube_fast_t cubetofast(cube_t); | ||
| 16 | _static cube_t fasttocube(cube_fast_t); | ||
| 17 | _static_inline bool equal_fast(cube_fast_t, cube_fast_t); | ||
| 18 | _static_inline bool issolved_fast(cube_fast_t); | ||
| 19 | _static_inline cube_fast_t invertco_fast(cube_fast_t); | ||
| 20 | _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); | ||
| 21 | |||
| 22 | _static_inline int64_t coord_fast_co(cube_fast_t); | ||
| 23 | _static_inline int64_t coord_fast_csep(cube_fast_t); | ||
| 24 | _static_inline int64_t coord_fast_cocsep(cube_fast_t); | ||
| 25 | _static_inline int64_t coord_fast_eo(cube_fast_t); | ||
| 26 | _static_inline int64_t coord_fast_esep(cube_fast_t); | ||
| 27 | |||
| 28 | _static_inline cube_fast_t | ||
| 29 | fastcube( | ||
| 30 | uint8_t c_ufr, | ||
| 31 | uint8_t c_ubl, | ||
| 32 | uint8_t c_dfl, | ||
| 33 | uint8_t c_dbr, | ||
| 34 | uint8_t c_ufl, | ||
| 35 | uint8_t c_ubr, | ||
| 36 | uint8_t c_dfr, | ||
| 37 | uint8_t c_dbl, | ||
| 38 | |||
| 39 | uint8_t e_uf, | ||
| 40 | uint8_t e_ub, | ||
| 41 | uint8_t e_db, | ||
| 42 | uint8_t e_df, | ||
| 43 | uint8_t e_ur, | ||
| 44 | uint8_t e_ul, | ||
| 45 | uint8_t e_dl, | ||
| 46 | uint8_t e_dr, | ||
| 47 | uint8_t e_fr, | ||
| 48 | uint8_t e_fl, | ||
| 49 | uint8_t e_bl, | ||
| 50 | uint8_t e_br | ||
| 51 | ) | ||
| 52 | { | ||
| 53 | return _mm256_set_epi8( | ||
| 54 | 0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, | ||
| 55 | e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, | ||
| 56 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 57 | c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr | ||
| 58 | ); | ||
| 59 | } | ||
| 60 | |||
| 61 | _static cube_fast_t | ||
| 62 | cubetofast(cube_t a) | ||
| 63 | { | ||
| 64 | uint8_t aux[32]; | ||
| 65 | |||
| 66 | memset(aux, 0, 32); | ||
| 67 | memcpy(aux, &a.corner, 8); | ||
| 68 | memcpy(aux + 16, &a.edge, 12); | ||
| 69 | |||
| 70 | return _mm256_loadu_si256((__m256i_u *)&aux); | ||
| 71 | } | ||
| 72 | |||
| 73 | _static cube_t | ||
| 74 | fasttocube(cube_fast_t c) | ||
| 75 | { | ||
| 76 | cube_t a; | ||
| 77 | uint8_t aux[32]; | ||
| 78 | |||
| 79 | _mm256_storeu_si256((__m256i_u *)aux, c); | ||
| 80 | memcpy(&a.corner, aux, 8); | ||
| 81 | memcpy(&a.edge, aux + 16, 12); | ||
| 82 | |||
| 83 | return a; | ||
| 84 | } | ||
| 85 | |||
| 86 | _static_inline bool | ||
| 87 | equal_fast(cube_fast_t c1, cube_fast_t c2) | ||
| 88 | { | ||
| 89 | int32_t mask; | ||
| 90 | __m256i cmp; | ||
| 91 | |||
| 92 | cmp = _mm256_cmpeq_epi8(c1, c2); | ||
| 93 | mask = _mm256_movemask_epi8(cmp); | ||
| 94 | |||
| 95 | return mask == ~0; | ||
| 96 | } | ||
| 97 | |||
| 98 | _static_inline bool | ||
| 99 | issolved_fast(cube_fast_t cube) | ||
| 100 | { | ||
| 101 | return equal_fast(cube, solved_fast); | ||
| 102 | } | ||
| 103 | |||
| 104 | _static_inline cube_fast_t | ||
| 105 | invertco_fast(cube_fast_t c) | ||
| 106 | { | ||
| 107 | cube_fast_t co, shleft, shright, summed, newco, cleanco, ret; | ||
| 108 | |||
| 109 | co = _mm256_and_si256(c, _co2_avx2); | ||
| 110 | shleft = _mm256_slli_epi32(co, 1); | ||
| 111 | shright = _mm256_srli_epi32(co, 1); | ||
| 112 | summed = _mm256_or_si256(shleft, shright); | ||
| 113 | newco = _mm256_and_si256(summed, _co2_avx2); | ||
| 114 | cleanco = _mm256_xor_si256(c, co); | ||
| 115 | ret = _mm256_or_si256(cleanco, newco); | ||
| 116 | |||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | _static_inline cube_fast_t | ||
| 121 | compose_fast(cube_fast_t c1, cube_fast_t c2) | ||
| 122 | { | ||
| 123 | cube_fast_t s, b, eo2, co1, co2, aux, auy1, auy2, auz1, auz2; | ||
| 124 | |||
| 125 | /* Permute and clean unused bits */ | ||
| 126 | s = _mm256_shuffle_epi8(c1, c2); | ||
| 127 | b = _mm256_set_epi8( | ||
| 128 | ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 129 | ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 130 | ); | ||
| 131 | s = _mm256_andnot_si256(b, s); | ||
| 132 | |||
| 133 | /* Change EO */ | ||
| 134 | eo2 = _mm256_and_si256(c2, _eo_avx2); | ||
| 135 | s = _mm256_xor_si256(s, eo2); | ||
| 136 | |||
| 137 | /* Change CO */ | ||
| 138 | co1 = _mm256_and_si256(s, _co2_avx2); | ||
| 139 | co2 = _mm256_and_si256(c2, _co2_avx2); | ||
| 140 | aux = _mm256_add_epi8(co1, co2); | ||
| 141 | auy1 = _mm256_add_epi8(aux, _cocw_avx2); | ||
| 142 | auy2 = _mm256_srli_epi32(auy1, 2); | ||
| 143 | auz1 = _mm256_add_epi8(aux, auy2); | ||
| 144 | auz2 = _mm256_and_si256(auz1, _co2_avx2); | ||
| 145 | |||
| 146 | /* Put together */ | ||
| 147 | s = _mm256_andnot_si256(_co2_avx2, s); | ||
| 148 | s = _mm256_or_si256(s, auz2); | ||
| 149 | |||
| 150 | return s; | ||
| 151 | } | ||
| 152 | |||
| 153 | _static_inline int64_t | ||
| 154 | coord_fast_co(cube_fast_t c) | ||
| 155 | { | ||
| 156 | cube_fast_t co; | ||
| 157 | int64_t mem[4], ret, i, p; | ||
| 158 | |||
| 159 | co = _mm256_and_si256(c, _co2_avx2); | ||
| 160 | _mm256_storeu_si256((__m256i *)mem, co); | ||
| 161 | |||
| 162 | mem[0] >>= 5L; | ||
| 163 | for (i = 0, ret = 0, p = 1; i < 7; i++, mem[0] >>= 8L, p *= 3) | ||
| 164 | ret += (mem[0] & 3L) * p; | ||
| 165 | |||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | _static_inline int64_t | ||
| 170 | coord_fast_csep(cube_fast_t c) | ||
| 171 | { | ||
| 172 | cube_fast_t cp, shifted; | ||
| 173 | int64_t mask; | ||
| 174 | |||
| 175 | cp = _mm256_and_si256(c, _cp_avx2); | ||
| 176 | shifted = _mm256_slli_epi32(cp, 5); | ||
| 177 | mask = _mm256_movemask_epi8(shifted); | ||
| 178 | |||
| 179 | return mask & 0x7F; | ||
| 180 | } | ||
| 181 | |||
| 182 | _static_inline int64_t | ||
| 183 | coord_fast_cocsep(cube_fast_t c) | ||
| 184 | { | ||
| 185 | return (coord_fast_co(c) << 7) + coord_fast_csep(c); | ||
| 186 | } | ||
| 187 | |||
| 188 | _static_inline int64_t | ||
| 189 | coord_fast_eo(cube_fast_t c) | ||
| 190 | { | ||
| 191 | cube_fast_t eo, shifted; | ||
| 192 | int64_t mask; | ||
| 193 | |||
| 194 | eo = _mm256_and_si256(c, _eo_avx2); | ||
| 195 | shifted = _mm256_slli_epi32(eo, 3); | ||
| 196 | mask = _mm256_movemask_epi8(shifted); | ||
| 197 | |||
| 198 | return mask >> 17; | ||
| 199 | } | ||
| 200 | |||
| 201 | _static_inline int64_t | ||
| 202 | coord_fast_esep(cube_fast_t c) | ||
| 203 | { | ||
| 204 | cube_fast_t ep; | ||
| 205 | int64_t e, mem[4], i, j, k, l, ret1, ret2, bit1, bit2, is1; | ||
| 206 | |||
| 207 | ep = _mm256_and_si256(c, _ep_avx2); | ||
| 208 | _mm256_storeu_si256((__m256i *)mem, ep); | ||
| 209 | |||
| 210 | mem[3] <<= 8L; | ||
| 211 | ret1 = ret2 = 0; | ||
| 212 | k = l = 4; | ||
| 213 | for (i = 0, j = 0; i < 12; i++, mem[i/8 + 2] >>= 8L) { | ||
| 214 | e = mem[i/8 + 2]; | ||
| 215 | |||
| 216 | bit1 = (e & _esepbit1) >> 2L; | ||
| 217 | bit2 = (e & _esepbit2) >> 3L; | ||
| 218 | is1 = (1 - bit2) * bit1; | ||
| 219 | |||
| 220 | ret1 += bit2 * binomial[11-i][k]; | ||
| 221 | k -= bit2; | ||
| 222 | |||
| 223 | ret2 += is1 * binomial[7-j][l]; | ||
| 224 | l -= is1; | ||
| 225 | j += (1-bit2); | ||
| 226 | } | ||
| 227 | |||
| 228 | return ret1 * 70 + ret2; | ||
| 229 | } | ||
