diff options
Diffstat (limited to '')
| -rw-r--r-- | src/_trans_avx2.c | 2 | ||||
| -rw-r--r-- | src/cube.c | 146 | ||||
| -rw-r--r-- | src/cube.h | 1 |
3 files changed, 94 insertions, 55 deletions
diff --git a/src/_trans_avx2.c b/src/_trans_avx2.c index 29ee942..e80bf79 100644 --- a/src/_trans_avx2.c +++ b/src/_trans_avx2.c | |||
| @@ -7,7 +7,7 @@ flipallcorners(cube_t c) | |||
| 7 | shright = _mm256_srli_si256(c, 1); | 7 | shright = _mm256_srli_si256(c, 1); |
| 8 | summed = _mm256_or_si256(shleft, shright); | 8 | summed = _mm256_or_si256(shleft, shright); |
| 9 | newco = _mm256_and_si256(summed, _co_avx2); | 9 | newco = _mm256_and_si256(summed, _co_avx2); |
| 10 | cleanco = _mm256_andnot_si256_(c, _co_avx2); | 10 | cleanco = _mm256_andnot_si256(c, _co_avx2); |
| 11 | ret = _mm256_and_si256(cleanco, newco); | 11 | ret = _mm256_and_si256(cleanco, newco); |
| 12 | 12 | ||
| 13 | return ret; | 13 | return ret; |
| @@ -6,10 +6,6 @@ | |||
| 6 | #include <stdio.h> | 6 | #include <stdio.h> |
| 7 | #endif | 7 | #endif |
| 8 | 8 | ||
| 9 | #ifdef AVX2 | ||
| 10 | #include <immintrin.h> | ||
| 11 | #endif | ||
| 12 | |||
| 13 | #include "cube.h" | 9 | #include "cube.h" |
| 14 | 10 | ||
| 15 | #define U 0U | 11 | #define U 0U |
| @@ -118,6 +114,11 @@ | |||
| 118 | #define _eflip 0x10U | 114 | #define _eflip 0x10U |
| 119 | #define _error 0xFFU | 115 | #define _error 0xFFU |
| 120 | 116 | ||
| 117 | #define get_edge(cube, i) (cube).e[(i)] | ||
| 118 | #define get_corner(cube, i) (cube).c[(i)] | ||
| 119 | #define set_edge(cube, i, p) (cube).e[(i)] = (p) | ||
| 120 | #define set_corner(cube, i, p) (cube).c[(i)] = (p) | ||
| 121 | |||
| 121 | cube_arr_t solvedcube_arr = { | 122 | cube_arr_t solvedcube_arr = { |
| 122 | .c = {0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, | 123 | .c = {0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, |
| 123 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0} | 124 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0} |
| @@ -126,40 +127,54 @@ cube_arr_t zerocube_arr = { .e = {0}, .c = {0} }; | |||
| 126 | 127 | ||
| 127 | #ifdef CUBE_AVX2 | 128 | #ifdef CUBE_AVX2 |
| 128 | 129 | ||
| 129 | #define _co_avx2 _mm256_set_epi64x(0, 0xF0F0F0F0F0F0F0F0, 0, 0) | 130 | #define _co_avx2 _mm256_set_epi8( \ |
| 130 | #define _eo_avx2 _mm256_set_epi64x(0, 0, 0xF0F0F0F0, 0xF0F0F0F0F0F0F0F0) | 131 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ |
| 131 | #define _c _mm256_set_epi64x(0, 0, 0, 0xFF) | 132 | 0, 0, 0, 0, 0, 0, 0, 0, \ |
| 132 | #define _e _mm256_set_epi64x(0, 0xFF, 0, 0) | 133 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70) |
| 134 | #define _eo_avx2 _mm256_set_epi8( \ | ||
| 135 | 0, 0, 0, 0, 0x70, 0x70, 0x70, 0x70, \ | ||
| 136 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, \ | ||
| 137 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | ||
| 133 | #define setsolved(cube) cube = _mm256_loadu_si256((__m256i_u *)&solvedcube_arr) | 138 | #define setsolved(cube) cube = _mm256_loadu_si256((__m256i_u *)&solvedcube_arr) |
| 134 | #define setzero(cube) cube = _mm256_setzero_si256() | 139 | #define setzero(cube) cube = _mm256_setzero_si256() |
| 135 | /* TODO: in the next 4 macros, all 0 should be i, but must be constant! */ | ||
| 136 | #define get_edge(cube, i) _mm256_extract_epi8(cube, 0+16) | ||
| 137 | #define get_corner(cube, i) _mm256_extract_epi8(cube, 0) | ||
| 138 | #define set_edge(cube, i, p) _mm256_or_si256( \ | ||
| 139 | _mm256_andnot_si256(cube, _mm256_slli_si256(_e, 0)), \ | ||
| 140 | _mm256_and_si256(_mm256_set1_epi8(p), _mm256_slli_si256(_e, 0))) | ||
| 141 | #define set_corner(cube, i, p) _mm256_or_si256( \ | ||
| 142 | _mm256_andnot_si256(cube, _mm256_slli_si256(_c, 0)), \ | ||
| 143 | _mm256_and_si256(_mm256_set1_epi8(p), _mm256_slli_si256(_c, 0))) | ||
| 144 | 140 | ||
| 145 | #include "_moves_avx2.c" | 141 | #include "_moves_avx2.c" |
| 146 | #include "_trans_avx2.c" | 142 | #include "_trans_avx2.c" |
| 147 | 143 | ||
| 144 | static cube_t | ||
| 145 | arrtocube(cube_arr_t a) | ||
| 146 | { | ||
| 147 | return _mm256_loadu_si256((__m256i_u *)&a); | ||
| 148 | } | ||
| 149 | |||
| 150 | static void | ||
| 151 | cubetoarr(cube_t c, cube_arr_t *a) | ||
| 152 | { | ||
| 153 | _mm256_storeu_si256((__m256i_u *)a, c); | ||
| 154 | } | ||
| 155 | |||
| 148 | #else | 156 | #else |
| 149 | 157 | ||
| 150 | #define setsolved(cube) cube = solvedcube_arr | 158 | #define setsolved(cube) cube = solvedcube_arr |
| 151 | #define setzero(cube) cube = zerocube_arr | 159 | #define setzero(cube) cube = zerocube_arr |
| 152 | #define get_edge(cube, i) (cube).e[(i)] | 160 | |
| 153 | #define get_corner(cube, i) (cube).c[(i)] | 161 | static cube_t |
| 154 | #define set_edge(cube, i, p) (cube).e[(i)] = (p) | 162 | arrtocube(cube_arr_t a) |
| 155 | #define set_corner(cube, i, p) (cube).c[(i)] = (p) | 163 | { |
| 164 | return a; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void | ||
| 168 | cubetoarr(cube_t c, cube_arr_t *a) | ||
| 169 | { | ||
| 170 | memcpy(a, &c, sizeof(cube_t)); | ||
| 171 | } | ||
| 156 | 172 | ||
| 157 | #include "_moves_arr.c" | 173 | #include "_moves_arr.c" |
| 158 | #include "_trans_arr.c" | 174 | #include "_trans_arr.c" |
| 159 | 175 | ||
| 160 | #endif | 176 | #endif |
| 161 | 177 | ||
| 162 | |||
| 163 | static char *cornerstr[] = { | 178 | static char *cornerstr[] = { |
| 164 | [_c_ufr] = "UFR", | 179 | [_c_ufr] = "UFR", |
| 165 | [_c_ubl] = "UBL", | 180 | [_c_ubl] = "UBL", |
| @@ -279,10 +294,10 @@ static uint8_t readep(char *); | |||
| 279 | static uint8_t readmove(char); | 294 | static uint8_t readmove(char); |
| 280 | static uint8_t readmodifier(char); | 295 | static uint8_t readmodifier(char); |
| 281 | static cube_t readcube_H48(char *); | 296 | static cube_t readcube_H48(char *); |
| 282 | static void writecube_AVX(cube_t, char *); | 297 | static void writecube_AVX(cube_arr_t, char *); |
| 283 | static void writecube_H48(cube_t, char *); | 298 | static void writecube_H48(cube_arr_t, char *); |
| 284 | static int writepiece_SRC(uint8_t, char *); | 299 | static int writepiece_SRC(uint8_t, char *); |
| 285 | static void writecube_SRC(cube_t, char *); | 300 | static void writecube_SRC(cube_arr_t, char *); |
| 286 | static int permsign(uint8_t *, int); | 301 | static int permsign(uint8_t *, int); |
| 287 | 302 | ||
| 288 | cube_t | 303 | cube_t |
| @@ -367,10 +382,10 @@ readcube_H48(char *buf) | |||
| 367 | { | 382 | { |
| 368 | int i; | 383 | int i; |
| 369 | uint8_t piece, orient; | 384 | uint8_t piece, orient; |
| 370 | cube_t ret, err; | 385 | cube_arr_t ret = {0}; |
| 386 | cube_t err; | ||
| 371 | char *b; | 387 | char *b; |
| 372 | 388 | ||
| 373 | setzero(ret); | ||
| 374 | setzero(err); | 389 | setzero(err); |
| 375 | b = buf; | 390 | b = buf; |
| 376 | 391 | ||
| @@ -397,7 +412,7 @@ readcube_H48(char *buf) | |||
| 397 | set_corner(ret, i, piece | orient); | 412 | set_corner(ret, i, piece | orient); |
| 398 | } | 413 | } |
| 399 | 414 | ||
| 400 | return ret; | 415 | return arrtocube(ret); |
| 401 | } | 416 | } |
| 402 | 417 | ||
| 403 | cube_t | 418 | cube_t |
| @@ -424,7 +439,7 @@ readcube(format_t format, char *buf) | |||
| 424 | } | 439 | } |
| 425 | 440 | ||
| 426 | static void | 441 | static void |
| 427 | writecube_AVX(cube_t cube, char *buf) | 442 | writecube_AVX(cube_arr_t cube, char *buf) |
| 428 | { | 443 | { |
| 429 | int i, ptr; | 444 | int i, ptr; |
| 430 | uint8_t piece; | 445 | uint8_t piece; |
| @@ -448,9 +463,8 @@ writecube_AVX(cube_t cube, char *buf) | |||
| 448 | memcpy(buf+ptr-2, "\n)\0", 3); | 463 | memcpy(buf+ptr-2, "\n)\0", 3); |
| 449 | } | 464 | } |
| 450 | 465 | ||
| 451 | |||
| 452 | static void | 466 | static void |
| 453 | writecube_H48(cube_t cube, char *buf) | 467 | writecube_H48(cube_arr_t cube, char *buf) |
| 454 | { | 468 | { |
| 455 | uint8_t piece, perm, orient; | 469 | uint8_t piece, perm, orient; |
| 456 | int i; | 470 | int i; |
| @@ -502,7 +516,7 @@ writepiece_SRC(uint8_t piece, char *buf) | |||
| 502 | } | 516 | } |
| 503 | 517 | ||
| 504 | static void | 518 | static void |
| 505 | writecube_SRC(cube_t cube, char *buf) | 519 | writecube_SRC(cube_arr_t cube, char *buf) |
| 506 | { | 520 | { |
| 507 | int i, ptr; | 521 | int i, ptr; |
| 508 | uint8_t piece; | 522 | uint8_t piece; |
| @@ -529,6 +543,7 @@ writecube_SRC(cube_t cube, char *buf) | |||
| 529 | void | 543 | void |
| 530 | writecube(format_t format, cube_t cube, char *buf) | 544 | writecube(format_t format, cube_t cube, char *buf) |
| 531 | { | 545 | { |
| 546 | cube_arr_t a; | ||
| 532 | char *errormsg; | 547 | char *errormsg; |
| 533 | size_t len; | 548 | size_t len; |
| 534 | 549 | ||
| @@ -537,15 +552,17 @@ writecube(format_t format, cube_t cube, char *buf) | |||
| 537 | goto writecube_error; | 552 | goto writecube_error; |
| 538 | } | 553 | } |
| 539 | 554 | ||
| 555 | cubetoarr(cube, &a); | ||
| 556 | |||
| 540 | switch (format) { | 557 | switch (format) { |
| 541 | case AVX: | 558 | case AVX: |
| 542 | writecube_AVX(cube, buf); | 559 | writecube_AVX(a, buf); |
| 543 | break; | 560 | break; |
| 544 | case H48: | 561 | case H48: |
| 545 | writecube_H48(cube, buf); | 562 | writecube_H48(a, buf); |
| 546 | break; | 563 | break; |
| 547 | case SRC: | 564 | case SRC: |
| 548 | writecube_SRC(cube, buf); | 565 | writecube_SRC(a, buf); |
| 549 | break; | 566 | break; |
| 550 | default: | 567 | default: |
| 551 | errormsg = "ERROR: cannot write cube in the given format"; | 568 | errormsg = "ERROR: cannot write cube in the given format"; |
| @@ -687,11 +704,14 @@ permsign(uint8_t *a, int n) | |||
| 687 | } | 704 | } |
| 688 | 705 | ||
| 689 | static bool | 706 | static bool |
| 690 | isconsistent(cube_t c) | 707 | isconsistent(cube_t cube) |
| 691 | { | 708 | { |
| 709 | cube_arr_t c; | ||
| 692 | uint8_t i, p, e, piece; | 710 | uint8_t i, p, e, piece; |
| 693 | bool found[12]; | 711 | bool found[12]; |
| 694 | 712 | ||
| 713 | cubetoarr(cube, &c); | ||
| 714 | |||
| 695 | for (i = 0; i < 12; i++) | 715 | for (i = 0; i < 12; i++) |
| 696 | found[i] = false; | 716 | found[i] = false; |
| 697 | for (i = 0; i < 12; i++) { | 717 | for (i = 0; i < 12; i++) { |
| @@ -751,7 +771,8 @@ inconsistent_co: | |||
| 751 | bool | 771 | bool |
| 752 | issolvable(cube_t cube) | 772 | issolvable(cube_t cube) |
| 753 | { | 773 | { |
| 754 | uint8_t i, eo, co, piece, e[12], c[8]; | 774 | cube_arr_t c; |
| 775 | uint8_t i, eo, co, piece, edges[12], corners[8]; | ||
| 755 | 776 | ||
| 756 | #ifdef DEBUG | 777 | #ifdef DEBUG |
| 757 | if (!isconsistent(cube)) { | 778 | if (!isconsistent(cube)) { |
| @@ -760,17 +781,19 @@ issolvable(cube_t cube) | |||
| 760 | } | 781 | } |
| 761 | #endif | 782 | #endif |
| 762 | 783 | ||
| 784 | cubetoarr(cube, &c); | ||
| 785 | |||
| 763 | for (i = 0; i < 12; i++) | 786 | for (i = 0; i < 12; i++) |
| 764 | e[i] = get_edge(cube, i) & _pbits; | 787 | edges[i] = get_edge(c, i) & _pbits; |
| 765 | for (i = 0; i < 8; i++) | 788 | for (i = 0; i < 8; i++) |
| 766 | c[i] = get_corner(cube, i) & _pbits; | 789 | corners[i] = get_corner(c, i) & _pbits; |
| 767 | 790 | ||
| 768 | if (permsign(e, 12) != permsign(c, 8)) | 791 | if (permsign(edges, 12) != permsign(corners, 8)) |
| 769 | goto issolvable_parity; | 792 | goto issolvable_parity; |
| 770 | 793 | ||
| 771 | eo = 0; | 794 | eo = 0; |
| 772 | for (i = 0; i < 12; i++) { | 795 | for (i = 0; i < 12; i++) { |
| 773 | piece = get_edge(cube, i); | 796 | piece = get_edge(c, i); |
| 774 | eo += (piece & _eobit) >> _eoshift; | 797 | eo += (piece & _eobit) >> _eoshift; |
| 775 | } | 798 | } |
| 776 | if (eo % 2 != 0) | 799 | if (eo % 2 != 0) |
| @@ -778,7 +801,7 @@ issolvable(cube_t cube) | |||
| 778 | 801 | ||
| 779 | co = 0; | 802 | co = 0; |
| 780 | for (i = 0; i < 8; i++) { | 803 | for (i = 0; i < 8; i++) { |
| 781 | piece = get_corner(cube, i); | 804 | piece = get_corner(c, i); |
| 782 | co += (piece & _cobits) >> _coshift; | 805 | co += (piece & _cobits) >> _coshift; |
| 783 | } | 806 | } |
| 784 | if (co % 3 != 0) | 807 | if (co % 3 != 0) |
| @@ -909,7 +932,6 @@ move_error: | |||
| 909 | cube_t | 932 | cube_t |
| 910 | inverse(cube_t c) | 933 | inverse(cube_t c) |
| 911 | { | 934 | { |
| 912 | /* TODO: optimize for avx2 */ | ||
| 913 | cube_t ret; | 935 | cube_t ret; |
| 914 | 936 | ||
| 915 | #ifdef DEBUG | 937 | #ifdef DEBUG |
| @@ -926,7 +948,7 @@ inverse(cube_t c) | |||
| 926 | * [1] https://github.com/Voltara/vcube | 948 | * [1] https://github.com/Voltara/vcube |
| 927 | * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html | 949 | * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html |
| 928 | */ | 950 | */ |
| 929 | cube_t v3, vi; | 951 | cube_t v3, vi, vo, vp; |
| 930 | 952 | ||
| 931 | v3 = _mm256_shuffle_epi8(c, c); | 953 | v3 = _mm256_shuffle_epi8(c, c); |
| 932 | v3 = _mm256_shuffle_epi8(v3, c); | 954 | v3 = _mm256_shuffle_epi8(v3, c); |
| @@ -945,7 +967,12 @@ inverse(cube_t c) | |||
| 945 | vi = _mm256_shuffle_epi8(vi, vi); | 967 | vi = _mm256_shuffle_epi8(vi, vi); |
| 946 | vi = _mm256_shuffle_epi8(vi, v3); | 968 | vi = _mm256_shuffle_epi8(vi, v3); |
| 947 | vi = _mm256_shuffle_epi8(vi, vi); | 969 | vi = _mm256_shuffle_epi8(vi, vi); |
| 948 | ret = _mm256_shuffle_epi8(vi, c); | 970 | vi = _mm256_shuffle_epi8(vi, c); |
| 971 | |||
| 972 | vo = _mm256_and_si256(c, _mm256_or_si256(_eo_avx2, _co_avx2)); | ||
| 973 | vo = _mm256_shuffle_epi8(vo, vi); | ||
| 974 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co_avx2), vi); | ||
| 975 | ret = _mm256_or_si256(vp, vo); | ||
| 949 | 976 | ||
| 950 | return flipallcorners(ret); | 977 | return flipallcorners(ret); |
| 951 | #else | 978 | #else |
| @@ -983,19 +1010,30 @@ inline_compose(cube_t c1, cube_t c2) | |||
| 983 | #endif | 1010 | #endif |
| 984 | 1011 | ||
| 985 | #ifdef CUBE_AVX2 | 1012 | #ifdef CUBE_AVX2 |
| 986 | cube_t shuf, eo, eodone, co2, aux, auy1, auy2, cw, auz1, auz2, coclean; | 1013 | cube_t s, eo2, ed, co1, co2, aux, auy1, auy2, cw, cwccw, auz1, auz2, |
| 1014 | coclean; | ||
| 987 | 1015 | ||
| 1016 | eo2 = _mm256_and_si256(c2, _eo_avx2); | ||
| 1017 | s = _mm256_shuffle_epi8(c1, c2); | ||
| 1018 | ed = _mm256_xor_si256(s, eo2); | ||
| 1019 | co1 = _mm256_and_si256(s, _co_avx2); | ||
| 988 | co2 = _mm256_and_si256(c2, _co_avx2); | 1020 | co2 = _mm256_and_si256(c2, _co_avx2); |
| 989 | eo = _mm256_and_si256(c2, _eo_avx2); | 1021 | aux = _mm256_add_epi8(co1, co2); |
| 990 | shufd = _mm256_shuffle_epi8(c1, c2); | 1022 | cw = _mm256_set_epi8( |
| 991 | eodone = _mm256_(shufd, eo); | 1023 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 992 | aux = _mm256_add_epi8(c1, co2); | 1024 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 993 | cw = _mm256_set_epi64x(0, 0x2020202020202020, 0, 0); | 1025 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 |
| 1026 | ); | ||
| 994 | auy1 = _mm256_add_epi8(aux, cw); | 1027 | auy1 = _mm256_add_epi8(aux, cw); |
| 995 | auy2 = _mm256_srli_si256(auy1, 2); | 1028 | auy2 = _mm256_srli_epi32(auy1, 2); |
| 996 | auz1 = _mm256_add_epi8(aux, auy2); | 1029 | auz1 = _mm256_add_epi8(aux, auy2); |
| 997 | auz2 = _mm256_and_si256(auz1, _co_avx2); | 1030 | cwccw = _mm256_set_epi8( |
| 998 | coclean = _mm256_andnot_si256(eodone, _co_avx2); | 1031 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 1032 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1033 | 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 | ||
| 1034 | ); | ||
| 1035 | auz2 = _mm256_and_si256(auz1, cwccw); | ||
| 1036 | coclean = _mm256_andnot_si256(_co_avx2, ed); | ||
| 999 | ret = _mm256_or_si256(coclean, auz2); | 1037 | ret = _mm256_or_si256(coclean, auz2); |
| 1000 | #else | 1038 | #else |
| 1001 | uint8_t i, piece1, piece2, p, orien, aux, auy; | 1039 | uint8_t i, piece1, piece2, p, orien, aux, auy; |
| @@ -3,6 +3,7 @@ typedef struct { | |||
| 3 | uint8_t e[16]; | 3 | uint8_t e[16]; |
| 4 | } cube_arr_t; | 4 | } cube_arr_t; |
| 5 | #ifdef CUBE_AVX2 | 5 | #ifdef CUBE_AVX2 |
| 6 | #include <immintrin.h> | ||
| 6 | typedef __m256i cube_t; | 7 | typedef __m256i cube_t; |
| 7 | #else | 8 | #else |
| 8 | typedef cube_arr_t cube_t; | 9 | typedef cube_arr_t cube_t; |
