diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2023-10-28 20:42:24 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2023-10-28 20:42:24 +0200 |
| commit | b05fa355c49c619cce1226716a395381a944f578 (patch) | |
| tree | b46416e2fbbc70f3d780f4e0ea3de7763115efe0 | |
| parent | fabb1ae495c4404af0f26380c97d0bca7e881a27 (diff) | |
| download | nissy-core-b05fa355c49c619cce1226716a395381a944f578.tar.gz nissy-core-b05fa355c49c619cce1226716a395381a944f578.zip | |
Started working on AVX2 (not working yet)
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | README.md | 22 | ||||
| -rw-r--r-- | config.mk | 7 | ||||
| -rwxr-xr-x | configure.sh | 18 | ||||
| -rw-r--r-- | src/_base_arr.c | 30 | ||||
| -rw-r--r-- | src/_base_avx2.c | 28 | ||||
| -rw-r--r-- | src/_constants.c | 7 | ||||
| -rw-r--r-- | src/_move_logic_arr.c | 149 | ||||
| -rw-r--r-- | src/_move_logic_avx2.c | 3 | ||||
| -rw-r--r-- | src/_trans_move_avx2.c | 2 | ||||
| -rw-r--r-- | src/cube.c | 296 | ||||
| -rw-r--r-- | src/cube.h | 10 |
12 files changed, 359 insertions, 223 deletions
| @@ -1,15 +1,5 @@ | |||
| 1 | # See LICENSE file for copyright and license details. | ||
| 2 | |||
| 3 | include config.mk | 1 | include config.mk |
| 4 | 2 | ||
| 5 | CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \ | ||
| 6 | -Wno-unused-parameter -O3 | ||
| 7 | DBGFLAGS = -DDEBUG -std=c99 -pthread -pedantic -Wall -Wextra \ | ||
| 8 | -Wno-unused-parameter -Wno-unused-function -g3 \ | ||
| 9 | -fsanitize=address -fsanitize=undefined | ||
| 10 | |||
| 11 | CC = cc | ||
| 12 | |||
| 13 | all: cube.o debugcube.o | 3 | all: cube.o debugcube.o |
| 14 | 4 | ||
| 15 | cube.o: clean | 5 | cube.o: clean |
| @@ -2,18 +2,32 @@ | |||
| 2 | 2 | ||
| 3 | Work in progress. | 3 | Work in progress. |
| 4 | 4 | ||
| 5 | TODO: | 5 | ## Running tests |
| 6 | |||
| 7 | ``` | ||
| 8 | $ ./configure.sh # Run 'TYPE=AVX2 ./configure.sh' to use AVX2 instead | ||
| 9 | $ make test | ||
| 10 | ``` | ||
| 11 | |||
| 12 | ## TODO: | ||
| 13 | |||
| 14 | ### AVX2 | ||
| 15 | |||
| 16 | * static `solvedcube` and co don't work, turn into functions? | ||
| 17 | * implement missing stuff (moves, transform) | ||
| 18 | * optimize things that use _base functions | ||
| 19 | |||
| 20 | ### More features | ||
| 6 | 21 | ||
| 7 | * AVX2 compile-time switch | ||
| 8 | * coordinates: co, eo, epsep, cpsep_sym, cocpsep_sym, cphtr_sym, cocphtr_sym | 22 | * coordinates: co, eo, epsep, cpsep_sym, cocpsep_sym, cphtr_sym, cocphtr_sym |
| 9 | * pruning tables (1 bit per entry + fallback) | 23 | * pruning tables (1 bit per entry + fallback) |
| 10 | * solve.c | 24 | * solve.c |
| 11 | 25 | ||
| 12 | Optimizations: | 26 | ### Optimizations: |
| 13 | 27 | ||
| 14 | * multi-move (up to 4/5 moves at once) | 28 | * multi-move (up to 4/5 moves at once) |
| 15 | 29 | ||
| 16 | Things I need to learn: | 30 | ### Things I need to learn: |
| 17 | 31 | ||
| 18 | * Use AVX2 instructions, in particular | 32 | * Use AVX2 instructions, in particular |
| 19 | [_mm256_shuffle_epi8](https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-10/mm256-shuffle-epi8.html)) | 33 | [_mm256_shuffle_epi8](https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-10/mm256-shuffle-epi8.html)) |
| @@ -1 +1,6 @@ | |||
| 1 | CUBETYPE = CUBE_$(TYPE) | 1 | CUBETYPE = CUBE_ |
| 2 | |||
| 3 | CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -O3 | ||
| 4 | DBGFLAGS = -DDEBUG -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -g3 -fsanitize=address -fsanitize=undefined | ||
| 5 | |||
| 6 | CC = cc | ||
diff --git a/configure.sh b/configure.sh new file mode 100755 index 0000000..17673fc --- /dev/null +++ b/configure.sh | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | CFLAGS="-std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -O3" | ||
| 4 | DBGFLAGS="-DDEBUG -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -g3 -fsanitize=address -fsanitize=undefined" | ||
| 5 | |||
| 6 | if [ "$TYPE" = "AVX2" ]; then | ||
| 7 | CFLAGS="$CFLAGS -mavx2" | ||
| 8 | DBGFLAGS="$DBGFLAGS -mavx2" | ||
| 9 | fi | ||
| 10 | |||
| 11 | { | ||
| 12 | echo "CUBETYPE = CUBE_$TYPE"; | ||
| 13 | echo ""; | ||
| 14 | echo "CFLAGS = $CFLAGS"; | ||
| 15 | echo "DBGFLAGS = $DBGFLAGS"; | ||
| 16 | echo ""; | ||
| 17 | echo "CC = cc" | ||
| 18 | } > config.mk | ||
diff --git a/src/_base_arr.c b/src/_base_arr.c new file mode 100644 index 0000000..2169cd5 --- /dev/null +++ b/src/_base_arr.c | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | cube_t solvedcube = { | ||
| 2 | .c = {0, 1, 2, 3, 4, 5, 6, 7}, | ||
| 3 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} | ||
| 4 | }; | ||
| 5 | static cube_t errorcube = { .e = {0}, .c = {0} }; | ||
| 6 | static cube_t zerocube = { .e = {0}, .c = {0} }; | ||
| 7 | |||
| 8 | static uint8_t | ||
| 9 | get_edge(cube_t c, uint8_t i) | ||
| 10 | { | ||
| 11 | return c.e[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | static uint8_t | ||
| 15 | get_corner(cube_t c, uint8_t i) | ||
| 16 | { | ||
| 17 | return c.c[i]; | ||
| 18 | } | ||
| 19 | |||
| 20 | static void | ||
| 21 | set_edge(cube_t *c, uint8_t i, uint8_t p) | ||
| 22 | { | ||
| 23 | c->e[i] = p; | ||
| 24 | } | ||
| 25 | |||
| 26 | static void | ||
| 27 | set_corner(cube_t *c, uint8_t i, uint8_t p) | ||
| 28 | { | ||
| 29 | c->c[i] = p; | ||
| 30 | } | ||
diff --git a/src/_base_avx2.c b/src/_base_avx2.c new file mode 100644 index 0000000..7af88eb --- /dev/null +++ b/src/_base_avx2.c | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #define solvedcube _mm256_set_epi8( \ | ||
| 2 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0, /* Corners */ \ | ||
| 3 | 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 /* Edges */ \ | ||
| 4 | ) | ||
| 5 | #define errorcube _mm256_setzero_si256() | ||
| 6 | #define zerocube _mm256_setzero_si256() | ||
| 7 | |||
| 8 | static uint8_t | ||
| 9 | get_edge(cube_t c, uint8_t i) | ||
| 10 | { | ||
| 11 | return 0; | ||
| 12 | } | ||
| 13 | |||
| 14 | static uint8_t | ||
| 15 | get_corner(cube_t c, uint8_t i) | ||
| 16 | { | ||
| 17 | return 0; | ||
| 18 | } | ||
| 19 | |||
| 20 | static void | ||
| 21 | set_edge(cube_t *c, uint8_t i, uint8_t p) | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | static void | ||
| 26 | set_corner(cube_t *c, uint8_t i, uint8_t p) | ||
| 27 | { | ||
| 28 | } | ||
diff --git a/src/_constants.c b/src/_constants.c index 90deffe..3121e3b 100644 --- a/src/_constants.c +++ b/src/_constants.c | |||
| @@ -104,13 +104,6 @@ trans_t inverse_trans[] = { | |||
| 104 | [BRm] = RDm, | 104 | [BRm] = RDm, |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | cube_t solvedcube = { | ||
| 108 | .c = {0, 1, 2, 3, 4, 5, 6, 7}, | ||
| 109 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} | ||
| 110 | }; | ||
| 111 | |||
| 112 | static cube_t errorcube = { .e = {0}, .c = {0} }; | ||
| 113 | |||
| 114 | static char *cornerstr[] = { | 107 | static char *cornerstr[] = { |
| 115 | [_c_ufr] = "UFR", | 108 | [_c_ufr] = "UFR", |
| 116 | [_c_ubl] = "UBL", | 109 | [_c_ubl] = "UBL", |
diff --git a/src/_move_logic_arr.c b/src/_move_logic_arr.c new file mode 100644 index 0000000..d8aec10 --- /dev/null +++ b/src/_move_logic_arr.c | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | #define PERM4(r, i, j, k, l) \ | ||
| 2 | aux = r[i]; \ | ||
| 3 | r[i] = r[l]; \ | ||
| 4 | r[l] = r[k]; \ | ||
| 5 | r[k] = r[j]; \ | ||
| 6 | r[j] = aux; | ||
| 7 | #define PERM22(r, i, j, k, l) \ | ||
| 8 | aux = r[i]; \ | ||
| 9 | r[i] = r[j]; \ | ||
| 10 | r[j] = aux; \ | ||
| 11 | aux = r[k]; \ | ||
| 12 | r[k] = r[l]; \ | ||
| 13 | r[l] = aux; | ||
| 14 | #define CO(a, b) \ | ||
| 15 | aux = (a & _cobits) + (b & _cobits); \ | ||
| 16 | auy = (aux + _ctwist_cw) >> 2U; \ | ||
| 17 | auz = (aux + auy) & _cobits2; \ | ||
| 18 | a = (a & _pbits) | auz; | ||
| 19 | #define CO4(r, i, j, k, l) \ | ||
| 20 | CO(r[i], _ctwist_cw) \ | ||
| 21 | CO(r[j], _ctwist_cw) \ | ||
| 22 | CO(r[k], _ctwist_ccw) \ | ||
| 23 | CO(r[l], _ctwist_ccw) | ||
| 24 | #define EO4(r, i, j, k, l) \ | ||
| 25 | r[i] ^= _eobit; \ | ||
| 26 | r[j] ^= _eobit; \ | ||
| 27 | r[k] ^= _eobit; \ | ||
| 28 | r[l] ^= _eobit; | ||
| 29 | |||
| 30 | uint8_t aux, auy, auz; | ||
| 31 | cube_t ret = c; | ||
| 32 | |||
| 33 | switch (m) { | ||
| 34 | case U: | ||
| 35 | PERM4(ret.e, _e_uf, _e_ul, _e_ub, _e_ur) | ||
| 36 | PERM4(ret.c, _c_ufr, _c_ufl, _c_ubl, _c_ubr) | ||
| 37 | |||
| 38 | return ret; | ||
| 39 | case U2: | ||
| 40 | PERM22(ret.e, _e_uf, _e_ub, _e_ul, _e_ur) | ||
| 41 | PERM22(ret.c, _c_ufr, _c_ubl, _c_ufl, _c_ubr) | ||
| 42 | |||
| 43 | return ret; | ||
| 44 | case U3: | ||
| 45 | PERM4(ret.e, _e_uf, _e_ur, _e_ub, _e_ul) | ||
| 46 | PERM4(ret.c, _c_ufr, _c_ubr, _c_ubl, _c_ufl) | ||
| 47 | |||
| 48 | return ret; | ||
| 49 | case D: | ||
| 50 | PERM4(ret.e, _e_df, _e_dr, _e_db, _e_dl) | ||
| 51 | PERM4(ret.c, _c_dfr, _c_dbr, _c_dbl, _c_dfl) | ||
| 52 | |||
| 53 | return ret; | ||
| 54 | case D2: | ||
| 55 | PERM22(ret.e, _e_df, _e_db, _e_dr, _e_dl) | ||
| 56 | PERM22(ret.c, _c_dfr, _c_dbl, _c_dbr, _c_dfl) | ||
| 57 | |||
| 58 | return ret; | ||
| 59 | case D3: | ||
| 60 | PERM4(ret.e, _e_df, _e_dl, _e_db, _e_dr) | ||
| 61 | PERM4(ret.c, _c_dfr, _c_dfl, _c_dbl, _c_dbr) | ||
| 62 | |||
| 63 | return ret; | ||
| 64 | case R: | ||
| 65 | PERM4(ret.e, _e_ur, _e_br, _e_dr, _e_fr) | ||
| 66 | PERM4(ret.c, _c_ufr, _c_ubr, _c_dbr, _c_dfr) | ||
| 67 | |||
| 68 | CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr) | ||
| 69 | |||
| 70 | return ret; | ||
| 71 | case R2: | ||
| 72 | PERM22(ret.e, _e_ur, _e_dr, _e_fr, _e_br) | ||
| 73 | PERM22(ret.c, _c_ufr, _c_dbr, _c_ubr, _c_dfr) | ||
| 74 | |||
| 75 | return ret; | ||
| 76 | case R3: | ||
| 77 | PERM4(ret.e, _e_ur, _e_fr, _e_dr, _e_br) | ||
| 78 | PERM4(ret.c, _c_ufr, _c_dfr, _c_dbr, _c_ubr) | ||
| 79 | |||
| 80 | CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr) | ||
| 81 | |||
| 82 | return ret; | ||
| 83 | case L: | ||
| 84 | PERM4(ret.e, _e_ul, _e_fl, _e_dl, _e_bl) | ||
| 85 | PERM4(ret.c, _c_ufl, _c_dfl, _c_dbl, _c_ubl) | ||
| 86 | |||
| 87 | CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl) | ||
| 88 | |||
| 89 | return ret; | ||
| 90 | case L2: | ||
| 91 | PERM22(ret.e, _e_ul, _e_dl, _e_fl, _e_bl) | ||
| 92 | PERM22(ret.c, _c_ufl, _c_dbl, _c_ubl, _c_dfl) | ||
| 93 | |||
| 94 | return ret; | ||
| 95 | case L3: | ||
| 96 | PERM4(ret.e, _e_ul, _e_bl, _e_dl, _e_fl) | ||
| 97 | PERM4(ret.c, _c_ufl, _c_ubl, _c_dbl, _c_dfl) | ||
| 98 | |||
| 99 | CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl) | ||
| 100 | |||
| 101 | return ret; | ||
| 102 | case F: | ||
| 103 | PERM4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 104 | PERM4(ret.c, _c_ufr, _c_dfr, _c_dfl, _c_ufl) | ||
| 105 | |||
| 106 | EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 107 | CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl) | ||
| 108 | |||
| 109 | return ret; | ||
| 110 | case F2: | ||
| 111 | PERM22(ret.e, _e_uf, _e_df, _e_fr, _e_fl) | ||
| 112 | PERM22(ret.c, _c_ufr, _c_dfl, _c_ufl, _c_dfr) | ||
| 113 | |||
| 114 | return ret; | ||
| 115 | case F3: | ||
| 116 | PERM4(ret.e, _e_uf, _e_fl, _e_df, _e_fr) | ||
| 117 | PERM4(ret.c, _c_ufr, _c_ufl, _c_dfl, _c_dfr) | ||
| 118 | |||
| 119 | EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 120 | CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl) | ||
| 121 | |||
| 122 | return ret; | ||
| 123 | case B: | ||
| 124 | PERM4(ret.e, _e_ub, _e_bl, _e_db, _e_br) | ||
| 125 | PERM4(ret.c, _c_ubr, _c_ubl, _c_dbl, _c_dbr) | ||
| 126 | |||
| 127 | EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 128 | CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr) | ||
| 129 | |||
| 130 | return ret; | ||
| 131 | case B2: | ||
| 132 | PERM22(ret.e, _e_ub, _e_db, _e_br, _e_bl) | ||
| 133 | PERM22(ret.c, _c_ubr, _c_dbl, _c_ubl, _c_dbr) | ||
| 134 | |||
| 135 | return ret; | ||
| 136 | case B3: | ||
| 137 | PERM4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 138 | PERM4(ret.c, _c_ubr, _c_dbr, _c_dbl, _c_ubl) | ||
| 139 | |||
| 140 | EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 141 | CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr) | ||
| 142 | |||
| 143 | return ret; | ||
| 144 | default: | ||
| 145 | #ifdef DEBUG | ||
| 146 | fprintf(stderr, "mover error, unknown move\n"); | ||
| 147 | #endif | ||
| 148 | goto move_error; | ||
| 149 | } | ||
diff --git a/src/_move_logic_avx2.c b/src/_move_logic_avx2.c new file mode 100644 index 0000000..7bf881c --- /dev/null +++ b/src/_move_logic_avx2.c | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | static cube_t move_cube[18]; /* TODO */ | ||
| 2 | |||
| 3 | return compose(move_cube[m], c); | ||
diff --git a/src/_trans_move_avx2.c b/src/_trans_move_avx2.c new file mode 100644 index 0000000..38b825e --- /dev/null +++ b/src/_trans_move_avx2.c | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | static cube_t trans_move_cube[48]; | ||
| 2 | static cube_t trans_move_cube_inverse[48]; | ||
| @@ -2,6 +2,10 @@ | |||
| 2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
| 3 | #include <string.h> | 3 | #include <string.h> |
| 4 | 4 | ||
| 5 | #ifdef CUBE_AVX2 | ||
| 6 | #include <immintrin.h> | ||
| 7 | #endif | ||
| 8 | |||
| 5 | #ifdef DEBUG | 9 | #ifdef DEBUG |
| 6 | #include <stdio.h> | 10 | #include <stdio.h> |
| 7 | #endif | 11 | #endif |
| @@ -10,6 +14,12 @@ | |||
| 10 | 14 | ||
| 11 | #include "_constants.c" | 15 | #include "_constants.c" |
| 12 | 16 | ||
| 17 | #ifdef CUBE_AVX2 | ||
| 18 | #include "_base_avx2.c" | ||
| 19 | #else | ||
| 20 | #include "_base_arr.c" | ||
| 21 | #endif | ||
| 22 | |||
| 13 | static bool isconsistent(cube_t); | 23 | static bool isconsistent(cube_t); |
| 14 | static cube_t flipallcorners(cube_t); | 24 | static cube_t flipallcorners(cube_t); |
| 15 | static uint8_t readco(char *); | 25 | static uint8_t readco(char *); |
| @@ -90,7 +100,7 @@ readcube_H48(char *buf) | |||
| 90 | { | 100 | { |
| 91 | int i; | 101 | int i; |
| 92 | uint8_t piece, orient; | 102 | uint8_t piece, orient; |
| 93 | cube_t ret = {0}; | 103 | cube_t ret = zerocube; |
| 94 | char *b = buf; | 104 | char *b = buf; |
| 95 | 105 | ||
| 96 | for (i = 0; i < 12; i++) { | 106 | for (i = 0; i < 12; i++) { |
| @@ -102,7 +112,7 @@ readcube_H48(char *buf) | |||
| 102 | if ((orient = readeo(b)) == _error) | 112 | if ((orient = readeo(b)) == _error) |
| 103 | return errorcube; | 113 | return errorcube; |
| 104 | b++; | 114 | b++; |
| 105 | ret.e[i] = piece | orient; | 115 | set_edge(&ret, i, piece | orient); |
| 106 | } | 116 | } |
| 107 | for (i = 0; i < 8; i++) { | 117 | for (i = 0; i < 8; i++) { |
| 108 | while (*b == ' ' || *b == '\t' || *b == '\n') | 118 | while (*b == ' ' || *b == '\t' || *b == '\n') |
| @@ -113,7 +123,7 @@ readcube_H48(char *buf) | |||
| 113 | if ((orient = readco(b)) == _error) | 123 | if ((orient = readco(b)) == _error) |
| 114 | return errorcube; | 124 | return errorcube; |
| 115 | b++; | 125 | b++; |
| 116 | ret.c[i] = piece | orient; | 126 | set_corner(&ret, i, piece | orient); |
| 117 | } | 127 | } |
| 118 | 128 | ||
| 119 | return ret; | 129 | return ret; |
| @@ -145,23 +155,25 @@ readcube(format_t format, char *buf) | |||
| 145 | static void | 155 | static void |
| 146 | writecube_H48(cube_t cube, char *buf) | 156 | writecube_H48(cube_t cube, char *buf) |
| 147 | { | 157 | { |
| 148 | uint8_t piece, orient; | 158 | uint8_t piece, perm, orient; |
| 149 | int i; | 159 | int i; |
| 150 | 160 | ||
| 151 | for (i = 0; i < 12; i++) { | 161 | for (i = 0; i < 12; i++) { |
| 152 | piece = cube.e[i] & _pbits; | 162 | piece = get_edge(cube, i); |
| 153 | orient = (cube.e[i] & _eobit) >> _eoshift; | 163 | perm = piece & _pbits; |
| 154 | buf[4*i ] = edgestr[piece][0]; | 164 | orient = (piece & _eobit) >> _eoshift; |
| 155 | buf[4*i + 1] = edgestr[piece][1]; | 165 | buf[4*i ] = edgestr[perm][0]; |
| 166 | buf[4*i + 1] = edgestr[perm][1]; | ||
| 156 | buf[4*i + 2] = orient + '0'; | 167 | buf[4*i + 2] = orient + '0'; |
| 157 | buf[4*i + 3] = ' '; | 168 | buf[4*i + 3] = ' '; |
| 158 | } | 169 | } |
| 159 | for (i = 0; i < 8; i++) { | 170 | for (i = 0; i < 8; i++) { |
| 160 | piece = cube.c[i] & _pbits; | 171 | piece = get_corner(cube, i); |
| 161 | orient = (cube.c[i] & _cobits) >> _coshift; | 172 | perm = piece & _pbits; |
| 162 | buf[48 + 5*i ] = cornerstr[piece][0]; | 173 | orient = (piece & _cobits) >> _coshift; |
| 163 | buf[48 + 5*i + 1] = cornerstr[piece][1]; | 174 | buf[48 + 5*i ] = cornerstr[perm][0]; |
| 164 | buf[48 + 5*i + 2] = cornerstr[piece][2]; | 175 | buf[48 + 5*i + 1] = cornerstr[perm][1]; |
| 176 | buf[48 + 5*i + 2] = cornerstr[perm][2]; | ||
| 165 | buf[48 + 5*i + 3] = orient + '0'; | 177 | buf[48 + 5*i + 3] = orient + '0'; |
| 166 | buf[48 + 5*i + 4] = ' '; | 178 | buf[48 + 5*i + 4] = ' '; |
| 167 | } | 179 | } |
| @@ -196,18 +208,23 @@ static void | |||
| 196 | writecube_SRC(cube_t cube, char *buf) | 208 | writecube_SRC(cube_t cube, char *buf) |
| 197 | { | 209 | { |
| 198 | int i, ptr; | 210 | int i, ptr; |
| 211 | uint8_t piece; | ||
| 199 | 212 | ||
| 200 | memcpy(buf, "{\n\t.c = {", 9); | 213 | memcpy(buf, "{\n\t.c = {", 9); |
| 201 | ptr = 9; | 214 | ptr = 9; |
| 202 | 215 | ||
| 203 | for (i = 0; i < 8; i++) | 216 | for (i = 0; i < 8; i++) { |
| 204 | ptr += writepiece_SRC(cube.c[i], buf + ptr); | 217 | piece = get_corner(cube, i); |
| 218 | ptr += writepiece_SRC(piece, buf + ptr); | ||
| 219 | } | ||
| 205 | 220 | ||
| 206 | memcpy(buf+ptr-2, "},\n\t.e = {", 10); | 221 | memcpy(buf+ptr-2, "},\n\t.e = {", 10); |
| 207 | ptr += 8; | 222 | ptr += 8; |
| 208 | 223 | ||
| 209 | for (i = 0; i < 12; i++) | 224 | for (i = 0; i < 12; i++) { |
| 210 | ptr += writepiece_SRC(cube.e[i], buf + ptr); | 225 | piece = get_edge(cube, i); |
| 226 | ptr += writepiece_SRC(piece, buf + ptr); | ||
| 227 | } | ||
| 211 | 228 | ||
| 212 | memcpy(buf+ptr-2, "}\n}\0", 4); | 229 | memcpy(buf+ptr-2, "}\n}\0", 4); |
| 213 | } | 230 | } |
| @@ -364,7 +381,7 @@ permsign(uint8_t *a, int n) | |||
| 364 | 381 | ||
| 365 | for (i = 0; i < n; i++) | 382 | for (i = 0; i < n; i++) |
| 366 | for (j = i+1; j < n; j++) | 383 | for (j = i+1; j < n; j++) |
| 367 | ret += (a[i] & _pbits) > (a[j] & _pbits) ? 1 : 0; | 384 | ret += a[i] > a[j] ? 1 : 0; |
| 368 | 385 | ||
| 369 | return ret % 2; | 386 | return ret % 2; |
| 370 | } | 387 | } |
| @@ -372,14 +389,15 @@ permsign(uint8_t *a, int n) | |||
| 372 | static bool | 389 | static bool |
| 373 | isconsistent(cube_t c) | 390 | isconsistent(cube_t c) |
| 374 | { | 391 | { |
| 375 | uint8_t i, p, e; | 392 | uint8_t i, p, e, piece; |
| 376 | bool found[12]; | 393 | bool found[12]; |
| 377 | 394 | ||
| 378 | for (i = 0; i < 12; i++) | 395 | for (i = 0; i < 12; i++) |
| 379 | found[i] = false; | 396 | found[i] = false; |
| 380 | for (i = 0; i < 12; i++) { | 397 | for (i = 0; i < 12; i++) { |
| 381 | p = c.e[i] & _pbits; | 398 | piece = get_edge(c, i); |
| 382 | e = c.e[i] & ~_pbits; | 399 | p = piece & _pbits; |
| 400 | e = piece & _eobit; | ||
| 383 | if (p >= 12) | 401 | if (p >= 12) |
| 384 | goto inconsistent_ep; | 402 | goto inconsistent_ep; |
| 385 | if (e != 0 && e != _eobit) | 403 | if (e != 0 && e != _eobit) |
| @@ -393,8 +411,9 @@ isconsistent(cube_t c) | |||
| 393 | for (i = 0; i < 8; i++) | 411 | for (i = 0; i < 8; i++) |
| 394 | found[i] = false; | 412 | found[i] = false; |
| 395 | for (i = 0; i < 8; i++) { | 413 | for (i = 0; i < 8; i++) { |
| 396 | p = c.c[i] & _pbits; | 414 | piece = get_corner(c, i); |
| 397 | e = c.c[i] & ~_pbits; | 415 | p = piece & _pbits; |
| 416 | e = piece & _cobits; | ||
| 398 | if (p >= 8) | 417 | if (p >= 8) |
| 399 | goto inconsistent_cp; | 418 | goto inconsistent_cp; |
| 400 | if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw) | 419 | if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw) |
| @@ -432,7 +451,7 @@ inconsistent_co: | |||
| 432 | bool | 451 | bool |
| 433 | issolvable(cube_t cube) | 452 | issolvable(cube_t cube) |
| 434 | { | 453 | { |
| 435 | int8_t i, eo, co; | 454 | uint8_t i, eo, co, piece, e[12], c[8]; |
| 436 | 455 | ||
| 437 | #ifdef DEBUG | 456 | #ifdef DEBUG |
| 438 | if (!isconsistent(cube)) { | 457 | if (!isconsistent(cube)) { |
| @@ -441,18 +460,27 @@ issolvable(cube_t cube) | |||
| 441 | } | 460 | } |
| 442 | #endif | 461 | #endif |
| 443 | 462 | ||
| 444 | if (permsign(cube.e, 12) != permsign(cube.c, 8)) | 463 | for (i = 0; i < 12; i++) |
| 464 | e[i] = get_edge(cube, i) & _pbits; | ||
| 465 | for (i = 0; i < 8; i++) | ||
| 466 | c[i] = get_corner(cube, i) & _pbits; | ||
| 467 | |||
| 468 | if (permsign(e, 12) != permsign(c, 8)) | ||
| 445 | goto issolvable_parity; | 469 | goto issolvable_parity; |
| 446 | 470 | ||
| 447 | eo = 0; | 471 | eo = 0; |
| 448 | for (i = 0; i < 12; i++) | 472 | for (i = 0; i < 12; i++) { |
| 449 | eo += (cube.e[i] & _eobit) >> _eoshift; | 473 | piece = get_edge(cube, i); |
| 474 | eo += (piece & _eobit) >> _eoshift; | ||
| 475 | } | ||
| 450 | if (eo % 2 != 0) | 476 | if (eo % 2 != 0) |
| 451 | goto issolvable_eo; | 477 | goto issolvable_eo; |
| 452 | 478 | ||
| 453 | co = 0; | 479 | co = 0; |
| 454 | for (i = 0; i < 8; i++) | 480 | for (i = 0; i < 8; i++) { |
| 455 | co += (cube.c[i] & _cobits) >> _coshift; | 481 | piece = get_corner(cube, i); |
| 482 | co += (piece & _cobits) >> _coshift; | ||
| 483 | } | ||
| 456 | if (co % 3 != 0) | 484 | if (co % 3 != 0) |
| 457 | goto issolvable_co; | 485 | goto issolvable_co; |
| 458 | 486 | ||
| @@ -478,6 +506,15 @@ issolvable_co: | |||
| 478 | bool | 506 | bool |
| 479 | equal(cube_t cube1, cube_t cube2) | 507 | equal(cube_t cube1, cube_t cube2) |
| 480 | { | 508 | { |
| 509 | #ifdef CUBE_AVX2 | ||
| 510 | uint32_t mask; | ||
| 511 | __m256i cmp; | ||
| 512 | |||
| 513 | cmp = _mm256_cmpeq_epi8(cube1, cube2); | ||
| 514 | mask = _mm256_movemask_epi8(cmp); | ||
| 515 | |||
| 516 | return mask == 0xffffffffU; | ||
| 517 | #else | ||
| 481 | uint8_t i; | 518 | uint8_t i; |
| 482 | 519 | ||
| 483 | for (i = 0; i < 12; i++) | 520 | for (i = 0; i < 12; i++) |
| @@ -489,6 +526,7 @@ equal(cube_t cube1, cube_t cube2) | |||
| 489 | return false; | 526 | return false; |
| 490 | 527 | ||
| 491 | return true; | 528 | return true; |
| 529 | #endif | ||
| 492 | } | 530 | } |
| 493 | 531 | ||
| 494 | bool | 532 | bool |
| @@ -506,9 +544,6 @@ iserror(cube_t cube) | |||
| 506 | cube_t | 544 | cube_t |
| 507 | move(cube_t c, move_t m) | 545 | move(cube_t c, move_t m) |
| 508 | { | 546 | { |
| 509 | cube_t ret; | ||
| 510 | uint8_t aux, auy, auz; | ||
| 511 | |||
| 512 | #ifdef DEBUG | 547 | #ifdef DEBUG |
| 513 | if (!isconsistent(c)) { | 548 | if (!isconsistent(c)) { |
| 514 | fprintf(stderr, "move error, inconsistent cube\n"); | 549 | fprintf(stderr, "move error, inconsistent cube\n"); |
| @@ -516,154 +551,11 @@ move(cube_t c, move_t m) | |||
| 516 | } | 551 | } |
| 517 | #endif | 552 | #endif |
| 518 | 553 | ||
| 519 | #define PERM4(r, i, j, k, l) \ | 554 | #ifdef CUBE_AVX2 |
| 520 | aux = r[i]; \ | 555 | #include "_move_logic_avx2.c" |
| 521 | r[i] = r[l]; \ | 556 | #else |
| 522 | r[l] = r[k]; \ | 557 | #include "_move_logic_arr.c" |
| 523 | r[k] = r[j]; \ | ||
| 524 | r[j] = aux; | ||
| 525 | #define PERM22(r, i, j, k, l) \ | ||
| 526 | aux = r[i]; \ | ||
| 527 | r[i] = r[j]; \ | ||
| 528 | r[j] = aux; \ | ||
| 529 | aux = r[k]; \ | ||
| 530 | r[k] = r[l]; \ | ||
| 531 | r[l] = aux; | ||
| 532 | #define CO(a, b) \ | ||
| 533 | aux = (a & _cobits) + (b & _cobits); \ | ||
| 534 | auy = (aux + _ctwist_cw) >> 2U; \ | ||
| 535 | auz = (aux + auy) & _cobits2; \ | ||
| 536 | a = (a & _pbits) | auz; | ||
| 537 | #define CO4(r, i, j, k, l) \ | ||
| 538 | CO(r[i], _ctwist_cw) \ | ||
| 539 | CO(r[j], _ctwist_cw) \ | ||
| 540 | CO(r[k], _ctwist_ccw) \ | ||
| 541 | CO(r[l], _ctwist_ccw) | ||
| 542 | #define EO4(r, i, j, k, l) \ | ||
| 543 | r[i] ^= _eobit; \ | ||
| 544 | r[j] ^= _eobit; \ | ||
| 545 | r[k] ^= _eobit; \ | ||
| 546 | r[l] ^= _eobit; | ||
| 547 | |||
| 548 | ret = c; | ||
| 549 | |||
| 550 | switch (m) { | ||
| 551 | case U: | ||
| 552 | PERM4(ret.e, _e_uf, _e_ul, _e_ub, _e_ur) | ||
| 553 | PERM4(ret.c, _c_ufr, _c_ufl, _c_ubl, _c_ubr) | ||
| 554 | |||
| 555 | return ret; | ||
| 556 | case U2: | ||
| 557 | PERM22(ret.e, _e_uf, _e_ub, _e_ul, _e_ur) | ||
| 558 | PERM22(ret.c, _c_ufr, _c_ubl, _c_ufl, _c_ubr) | ||
| 559 | |||
| 560 | return ret; | ||
| 561 | case U3: | ||
| 562 | PERM4(ret.e, _e_uf, _e_ur, _e_ub, _e_ul) | ||
| 563 | PERM4(ret.c, _c_ufr, _c_ubr, _c_ubl, _c_ufl) | ||
| 564 | |||
| 565 | return ret; | ||
| 566 | case D: | ||
| 567 | PERM4(ret.e, _e_df, _e_dr, _e_db, _e_dl) | ||
| 568 | PERM4(ret.c, _c_dfr, _c_dbr, _c_dbl, _c_dfl) | ||
| 569 | |||
| 570 | return ret; | ||
| 571 | case D2: | ||
| 572 | PERM22(ret.e, _e_df, _e_db, _e_dr, _e_dl) | ||
| 573 | PERM22(ret.c, _c_dfr, _c_dbl, _c_dbr, _c_dfl) | ||
| 574 | |||
| 575 | return ret; | ||
| 576 | case D3: | ||
| 577 | PERM4(ret.e, _e_df, _e_dl, _e_db, _e_dr) | ||
| 578 | PERM4(ret.c, _c_dfr, _c_dfl, _c_dbl, _c_dbr) | ||
| 579 | |||
| 580 | return ret; | ||
| 581 | case R: | ||
| 582 | PERM4(ret.e, _e_ur, _e_br, _e_dr, _e_fr) | ||
| 583 | PERM4(ret.c, _c_ufr, _c_ubr, _c_dbr, _c_dfr) | ||
| 584 | |||
| 585 | CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr) | ||
| 586 | |||
| 587 | return ret; | ||
| 588 | case R2: | ||
| 589 | PERM22(ret.e, _e_ur, _e_dr, _e_fr, _e_br) | ||
| 590 | PERM22(ret.c, _c_ufr, _c_dbr, _c_ubr, _c_dfr) | ||
| 591 | |||
| 592 | return ret; | ||
| 593 | case R3: | ||
| 594 | PERM4(ret.e, _e_ur, _e_fr, _e_dr, _e_br) | ||
| 595 | PERM4(ret.c, _c_ufr, _c_dfr, _c_dbr, _c_ubr) | ||
| 596 | |||
| 597 | CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr) | ||
| 598 | |||
| 599 | return ret; | ||
| 600 | case L: | ||
| 601 | PERM4(ret.e, _e_ul, _e_fl, _e_dl, _e_bl) | ||
| 602 | PERM4(ret.c, _c_ufl, _c_dfl, _c_dbl, _c_ubl) | ||
| 603 | |||
| 604 | CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl) | ||
| 605 | |||
| 606 | return ret; | ||
| 607 | case L2: | ||
| 608 | PERM22(ret.e, _e_ul, _e_dl, _e_fl, _e_bl) | ||
| 609 | PERM22(ret.c, _c_ufl, _c_dbl, _c_ubl, _c_dfl) | ||
| 610 | |||
| 611 | return ret; | ||
| 612 | case L3: | ||
| 613 | PERM4(ret.e, _e_ul, _e_bl, _e_dl, _e_fl) | ||
| 614 | PERM4(ret.c, _c_ufl, _c_ubl, _c_dbl, _c_dfl) | ||
| 615 | |||
| 616 | CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl) | ||
| 617 | |||
| 618 | return ret; | ||
| 619 | case F: | ||
| 620 | PERM4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 621 | PERM4(ret.c, _c_ufr, _c_dfr, _c_dfl, _c_ufl) | ||
| 622 | |||
| 623 | EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 624 | CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl) | ||
| 625 | |||
| 626 | return ret; | ||
| 627 | case F2: | ||
| 628 | PERM22(ret.e, _e_uf, _e_df, _e_fr, _e_fl) | ||
| 629 | PERM22(ret.c, _c_ufr, _c_dfl, _c_ufl, _c_dfr) | ||
| 630 | |||
| 631 | return ret; | ||
| 632 | case F3: | ||
| 633 | PERM4(ret.e, _e_uf, _e_fl, _e_df, _e_fr) | ||
| 634 | PERM4(ret.c, _c_ufr, _c_ufl, _c_dfl, _c_dfr) | ||
| 635 | |||
| 636 | EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl) | ||
| 637 | CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl) | ||
| 638 | |||
| 639 | return ret; | ||
| 640 | case B: | ||
| 641 | PERM4(ret.e, _e_ub, _e_bl, _e_db, _e_br) | ||
| 642 | PERM4(ret.c, _c_ubr, _c_ubl, _c_dbl, _c_dbr) | ||
| 643 | |||
| 644 | EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 645 | CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr) | ||
| 646 | |||
| 647 | return ret; | ||
| 648 | case B2: | ||
| 649 | PERM22(ret.e, _e_ub, _e_db, _e_br, _e_bl) | ||
| 650 | PERM22(ret.c, _c_ubr, _c_dbl, _c_ubl, _c_dbr) | ||
| 651 | |||
| 652 | return ret; | ||
| 653 | case B3: | ||
| 654 | PERM4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 655 | PERM4(ret.c, _c_ubr, _c_dbr, _c_dbl, _c_ubl) | ||
| 656 | |||
| 657 | EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl) | ||
| 658 | CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr) | ||
| 659 | |||
| 660 | return ret; | ||
| 661 | default: | ||
| 662 | #ifdef DEBUG | ||
| 663 | fprintf(stderr, "mover error, unknown move\n"); | ||
| 664 | #endif | 558 | #endif |
| 665 | goto move_error; | ||
| 666 | } | ||
| 667 | 559 | ||
| 668 | move_error: | 560 | move_error: |
| 669 | return errorcube; | 561 | return errorcube; |
| @@ -672,8 +564,9 @@ move_error: | |||
| 672 | cube_t | 564 | cube_t |
| 673 | inverse(cube_t c) | 565 | inverse(cube_t c) |
| 674 | { | 566 | { |
| 567 | /* TODO: optimize for avx2 */ | ||
| 675 | uint8_t i, piece, orien; | 568 | uint8_t i, piece, orien; |
| 676 | cube_t ret = {0}; | 569 | cube_t ret = zerocube; |
| 677 | 570 | ||
| 678 | #ifdef DEBUG | 571 | #ifdef DEBUG |
| 679 | if (!isconsistent(c)) { | 572 | if (!isconsistent(c)) { |
| @@ -683,15 +576,15 @@ inverse(cube_t c) | |||
| 683 | #endif | 576 | #endif |
| 684 | 577 | ||
| 685 | for (i = 0; i < 12; i++) { | 578 | for (i = 0; i < 12; i++) { |
| 686 | piece = c.e[i & _pbits]; | 579 | piece = get_edge(c, i); |
| 687 | orien = piece & _eobit; | 580 | orien = piece & _eobit; |
| 688 | ret.e[piece & _pbits] = i | orien; | 581 | set_edge(&ret, piece & _pbits, i | orien); |
| 689 | } | 582 | } |
| 690 | 583 | ||
| 691 | for (i = 0; i < 8; i++) { | 584 | for (i = 0; i < 8; i++) { |
| 692 | piece = c.c[i & _pbits]; | 585 | piece = get_corner(c, i); |
| 693 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | 586 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; |
| 694 | ret.c[piece & _pbits] = i | orien; | 587 | set_corner(&ret, piece & _pbits, i | orien); |
| 695 | } | 588 | } |
| 696 | 589 | ||
| 697 | return ret; | 590 | return ret; |
| @@ -700,8 +593,9 @@ inverse(cube_t c) | |||
| 700 | cube_t | 593 | cube_t |
| 701 | compose(cube_t c1, cube_t c2) | 594 | compose(cube_t c1, cube_t c2) |
| 702 | { | 595 | { |
| 703 | uint8_t i, piece, orien, aux, auy; | 596 | /* TODO: optimize for avx2 */ |
| 704 | cube_t ret = {0}; | 597 | uint8_t i, piece1, piece2, p, orien, aux, auy; |
| 598 | cube_t ret = zerocube; | ||
| 705 | 599 | ||
| 706 | #ifdef DEBUG | 600 | #ifdef DEBUG |
| 707 | if (!isconsistent(c1) || !isconsistent(c2)) { | 601 | if (!isconsistent(c1) || !isconsistent(c2)) { |
| @@ -711,17 +605,21 @@ compose(cube_t c1, cube_t c2) | |||
| 711 | #endif | 605 | #endif |
| 712 | 606 | ||
| 713 | for (i = 0; i < 12; i++) { | 607 | for (i = 0; i < 12; i++) { |
| 714 | piece = c2.e[i] & _pbits; | 608 | piece2 = get_edge(c2, i); |
| 715 | orien = (c2.e[i] ^ c1.e[piece]) & _eobit; | 609 | p = piece2 & _pbits; |
| 716 | ret.e[i] = (c1.e[piece] & _pbits) | orien; | 610 | piece1 = get_edge(c1, p); |
| 611 | orien = (piece2 ^ piece1) & _eobit; | ||
| 612 | set_edge(&ret, i, (piece1 & _pbits) | orien); | ||
| 717 | } | 613 | } |
| 718 | 614 | ||
| 719 | for (i = 0; i < 8; i++) { | 615 | for (i = 0; i < 8; i++) { |
| 720 | piece = c2.c[i] & _pbits; | 616 | piece2 = get_corner(c2, i); |
| 721 | aux = (c2.c[i] & _cobits) + (c1.c[piece] & _cobits); | 617 | p = piece2 & _pbits; |
| 618 | piece1 = get_corner(c1, p); | ||
| 619 | aux = (piece2 & _cobits) + (piece1 & _cobits); | ||
| 722 | auy = (aux + _ctwist_cw) >> 2U; | 620 | auy = (aux + _ctwist_cw) >> 2U; |
| 723 | orien = (aux + auy) & _cobits2; | 621 | orien = (aux + auy) & _cobits2; |
| 724 | ret.c[i] = (c1.c[piece] & _pbits) | orien; | 622 | set_corner(&ret, i, (piece1 & _pbits) | orien); |
| 725 | } | 623 | } |
| 726 | 624 | ||
| 727 | return ret; | 625 | return ret; |
| @@ -730,14 +628,16 @@ compose(cube_t c1, cube_t c2) | |||
| 730 | static cube_t | 628 | static cube_t |
| 731 | flipallcorners(cube_t c) | 629 | flipallcorners(cube_t c) |
| 732 | { | 630 | { |
| 631 | /* TODO: optimize for avx2, can be a couple of instructions */ | ||
| 632 | |||
| 733 | uint8_t i, piece, orien; | 633 | uint8_t i, piece, orien; |
| 734 | cube_t ret; | 634 | cube_t ret; |
| 735 | 635 | ||
| 736 | ret = c; | 636 | ret = c; |
| 737 | for (i = 0; i < 8; i++) { | 637 | for (i = 0; i < 8; i++) { |
| 738 | piece = ret.c[i]; | 638 | piece = get_corner(c, i); |
| 739 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | 639 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; |
| 740 | ret.c[i] = (piece & _pbits) | orien; | 640 | set_corner(&ret, i, (piece & _pbits) | orien); |
| 741 | } | 641 | } |
| 742 | 642 | ||
| 743 | return ret; | 643 | return ret; |
| @@ -746,8 +646,6 @@ flipallcorners(cube_t c) | |||
| 746 | cube_t | 646 | cube_t |
| 747 | transform(cube_t c, trans_t t) | 647 | transform(cube_t c, trans_t t) |
| 748 | { | 648 | { |
| 749 | #include "_trans_move_arr.c" | ||
| 750 | |||
| 751 | cube_t ret; | 649 | cube_t ret; |
| 752 | 650 | ||
| 753 | #ifdef DEBUG | 651 | #ifdef DEBUG |
| @@ -761,6 +659,12 @@ transform(cube_t c, trans_t t) | |||
| 761 | } | 659 | } |
| 762 | #endif | 660 | #endif |
| 763 | 661 | ||
| 662 | #ifdef CUBE_AVX2 | ||
| 663 | #include "_trans_move_avx2.c" | ||
| 664 | #else | ||
| 665 | #include "_trans_move_arr.c" | ||
| 666 | #endif | ||
| 667 | |||
| 764 | ret = compose(solvedcube, trans_move_cube[t]); | 668 | ret = compose(solvedcube, trans_move_cube[t]); |
| 765 | ret = compose(ret, c); | 669 | ret = compose(ret, c); |
| 766 | ret = compose(ret, trans_move_cube_inverse[t]); | 670 | ret = compose(ret, trans_move_cube_inverse[t]); |
| @@ -1,11 +1,11 @@ | |||
| 1 | /* Types *********************************************************************/ | 1 | /* Types *********************************************************************/ |
| 2 | 2 | ||
| 3 | /* TODO: ifdef for different implementations */ | ||
| 4 | /* See doc/CUBE_INTERNAL.md for a description of the cube format */ | 3 | /* See doc/CUBE_INTERNAL.md for a description of the cube format */ |
| 5 | typedef struct { | 4 | #ifdef CUBE_AVX2 |
| 6 | uint8_t c[8]; | 5 | typedef __m256i cube_t; |
| 7 | uint8_t e[12]; | 6 | #else |
| 8 | } cube_t; | 7 | typedef struct { uint8_t c[8]; uint8_t e[12]; } cube_t; |
| 8 | #endif | ||
| 9 | 9 | ||
| 10 | typedef uint8_t move_t; | 10 | typedef uint8_t move_t; |
| 11 | typedef uint8_t trans_t; | 11 | typedef uint8_t trans_t; |
