diff options
| -rw-r--r-- | TODO.txt | 3 | ||||
| -rw-r--r-- | cube.c | 95 | ||||
| -rw-r--r-- | test/074_coord_esep/00_solved.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/00_solved.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/01_U.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/01_U.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/02_U2.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/02_U2.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/20_scrambled.in | 3 | ||||
| -rw-r--r-- | test/074_coord_esep/20_scrambled.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/21_swapaxis_FB.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/21_swapaxis_FB.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/22_swapaxis_RL.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/22_swapaxis_RL.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/23_swapaxis_UD.in | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/23_swapaxis_UD.out | 1 | ||||
| -rw-r--r-- | test/074_coord_esep/coord_esep_tests.c | 21 |
17 files changed, 133 insertions, 2 deletions
| @@ -1,6 +1,7 @@ | |||
| 1 | ## (find better name) H48 solver, ideas | 1 | ## (find better name) H48 solver, ideas |
| 2 | 2 | ||
| 3 | TODO next: epsep, precise coordinate unlike cpsep which is redundant | 3 | TODO implement lookup tables |
| 4 | TODO alternative: ARM NEON part | ||
| 4 | 5 | ||
| 5 | First compute co + csep. Use csep as a binary number (2^7 instead of 70, | 6 | First compute co + csep. Use csep as a binary number (2^7 instead of 70, |
| 6 | loose a factor of 1.8 but still fits in a few megabytes or less). Use | 7 | loose a factor of 1.8 but still fits in a few megabytes or less). Use |
| @@ -126,6 +126,9 @@ Section: constants, strings and other stuff | |||
| 126 | #define _coshift 5U | 126 | #define _coshift 5U |
| 127 | 127 | ||
| 128 | #define _pbits 0xFU | 128 | #define _pbits 0xFU |
| 129 | #define _esepbit1 0x4U | ||
| 130 | #define _esepbit2 0x8U | ||
| 131 | #define _csepbit 0x4U | ||
| 129 | #define _eobit 0x10U | 132 | #define _eobit 0x10U |
| 130 | #define _cobits 0xF0U | 133 | #define _cobits 0xF0U |
| 131 | #define _cobits2 0x60U | 134 | #define _cobits2 0x60U |
| @@ -484,6 +487,21 @@ static char *transstr[] = { | |||
| 484 | [BLm] = "mirrored BL", | 487 | [BLm] = "mirrored BL", |
| 485 | }; | 488 | }; |
| 486 | 489 | ||
| 490 | static int64_t binomial[12][12] = { | ||
| 491 | {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
| 492 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
| 493 | {1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
| 494 | {1, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
| 495 | {1, 4, 6, 4, 1, 0, 0, 0, 0, 0, 0, 0}, | ||
| 496 | {1, 5, 10, 10, 5, 1, 0, 0, 0, 0, 0, 0}, | ||
| 497 | {1, 6, 15, 20, 15, 6, 1, 0, 0, 0, 0, 0}, | ||
| 498 | {1, 7, 21, 35, 35, 21, 7, 1, 0, 0, 0, 0}, | ||
| 499 | {1, 8, 28, 56, 70, 56, 28, 8, 1, 0, 0, 0}, | ||
| 500 | {1, 9, 36, 84, 126, 126, 84, 36, 9, 1, 0, 0}, | ||
| 501 | {1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1, 0}, | ||
| 502 | {1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1}, | ||
| 503 | }; | ||
| 504 | |||
| 487 | /****************************************************************************** | 505 | /****************************************************************************** |
| 488 | Section: AVX2 fast methods | 506 | Section: AVX2 fast methods |
| 489 | 507 | ||
| @@ -500,6 +518,7 @@ typedef __m256i cube_fast_t; | |||
| 500 | #define _co2_avx2 _mm256_set_epi64x(0, 0, 0, 0x6060606060606060) | 518 | #define _co2_avx2 _mm256_set_epi64x(0, 0, 0, 0x6060606060606060) |
| 501 | #define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020) | 519 | #define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020) |
| 502 | #define _cp_avx2 _mm256_set_epi64x(0, 0, 0, 0x0707070707070707) | 520 | #define _cp_avx2 _mm256_set_epi64x(0, 0, 0, 0x0707070707070707) |
| 521 | #define _ep_avx2 _mm256_set_epi64x(0x0F0F0F0F, 0x0F0F0F0F0F0F0F0F, 0, 0) | ||
| 503 | #define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0) | 522 | #define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0) |
| 504 | 523 | ||
| 505 | _static_inline cube_fast_t fastcube( | 524 | _static_inline cube_fast_t fastcube( |
| @@ -518,6 +537,7 @@ _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); | |||
| 518 | _static_inline int64_t coord_fast_co(cube_fast_t); | 537 | _static_inline int64_t coord_fast_co(cube_fast_t); |
| 519 | _static_inline int64_t coord_fast_csep(cube_fast_t); | 538 | _static_inline int64_t coord_fast_csep(cube_fast_t); |
| 520 | _static_inline int64_t coord_fast_eo(cube_fast_t); | 539 | _static_inline int64_t coord_fast_eo(cube_fast_t); |
| 540 | _static_inline int64_t coord_fast_esep(cube_fast_t); | ||
| 521 | 541 | ||
| 522 | _static_inline cube_fast_t | 542 | _static_inline cube_fast_t |
| 523 | fastcube( | 543 | fastcube( |
| @@ -686,6 +706,36 @@ coord_fast_eo(cube_fast_t c) | |||
| 686 | return mask >> 17; | 706 | return mask >> 17; |
| 687 | } | 707 | } |
| 688 | 708 | ||
| 709 | _static_inline int64_t | ||
| 710 | coord_fast_esep(cube_fast_t c) | ||
| 711 | { | ||
| 712 | cube_fast_t ep; | ||
| 713 | int64_t e, mem[4], i, j, k, l, ret1, ret2, bit1, bit2, is1; | ||
| 714 | |||
| 715 | ep = _mm256_and_si256(c, _ep_avx2); | ||
| 716 | _mm256_storeu_si256((__m256i *)mem, ep); | ||
| 717 | |||
| 718 | mem[3] <<= 8L; | ||
| 719 | ret1 = ret2 = 0; | ||
| 720 | k = l = 4; | ||
| 721 | for (i = 0, j = 0; i < 12; i++, mem[i/8 + 2] >>= 8L) { | ||
| 722 | e = mem[i/8 + 2]; | ||
| 723 | |||
| 724 | bit1 = (e & _esepbit1) >> 2L; | ||
| 725 | bit2 = (e & _esepbit2) >> 3L; | ||
| 726 | is1 = (1 - bit2) * bit1; | ||
| 727 | |||
| 728 | ret1 += bit2 * binomial[11-i][k]; | ||
| 729 | k -= bit2; | ||
| 730 | |||
| 731 | ret2 += is1 * binomial[7-j][l]; | ||
| 732 | l -= is1; | ||
| 733 | j += (1-bit2); | ||
| 734 | } | ||
| 735 | |||
| 736 | return ret1 * 70 + ret2; | ||
| 737 | } | ||
| 738 | |||
| 689 | /****************************************************************************** | 739 | /****************************************************************************** |
| 690 | Section: ARM NEON fast methods | 740 | Section: ARM NEON fast methods |
| 691 | 741 | ||
| @@ -730,6 +780,7 @@ _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); | |||
| 730 | _static_inline int64_t coord_fast_co(cube_fast_t); | 780 | _static_inline int64_t coord_fast_co(cube_fast_t); |
| 731 | _static_inline int64_t coord_fast_csep(cube_fast_t); | 781 | _static_inline int64_t coord_fast_csep(cube_fast_t); |
| 732 | _static_inline int64_t coord_fast_eo(cube_fast_t); | 782 | _static_inline int64_t coord_fast_eo(cube_fast_t); |
| 783 | _static_inline int64_t coord_fast_esep(cube_fast_t); | ||
| 733 | 784 | ||
| 734 | _static_inline cube_fast_t | 785 | _static_inline cube_fast_t |
| 735 | fastcube( | 786 | fastcube( |
| @@ -863,6 +914,13 @@ coord_fast_co(cube_fast_t c) | |||
| 863 | return ret; | 914 | return ret; |
| 864 | } | 915 | } |
| 865 | 916 | ||
| 917 | /* | ||
| 918 | For corner separation, we consider the axis (a.k.a. tetrad) each | ||
| 919 | corner belongs to as 0 or 1 and we translate this sequence into binary. | ||
| 920 | Ignoring the last bit, we have a value up to 2^7, but not all values are | ||
| 921 | possible. Encoding this as a number from 0 to C(8,4) would save about 40% | ||
| 922 | of space, but we are not going to use this coordinate in large tables. | ||
| 923 | */ | ||
| 866 | _static_inline int64_t | 924 | _static_inline int64_t |
| 867 | coord_fast_csep(cube_fast_t c) | 925 | coord_fast_csep(cube_fast_t c) |
| 868 | { | 926 | { |
| @@ -870,7 +928,7 @@ coord_fast_csep(cube_fast_t c) | |||
| 870 | int64_t ret; | 928 | int64_t ret; |
| 871 | 929 | ||
| 872 | for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2) | 930 | for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2) |
| 873 | ret += p * ((c.corner[i] & _pbits) >> 2U); | 931 | ret += p * ((c.corner[i] & _csepbit) >> 2U); |
| 874 | 932 | ||
| 875 | return ret; | 933 | return ret; |
| 876 | } | 934 | } |
| @@ -887,6 +945,41 @@ coord_fast_eo(cube_fast_t c) | |||
| 887 | return ret; | 945 | return ret; |
| 888 | } | 946 | } |
| 889 | 947 | ||
| 948 | /* | ||
| 949 | We encode the edge separation as a number from 0 to C(12,4)*C(8,4). | ||
| 950 | It can be seen as the composition of two "subset index" coordinates. | ||
| 951 | */ | ||
| 952 | _static_inline int64_t | ||
| 953 | coord_fast_esep(cube_fast_t c) | ||
| 954 | { | ||
| 955 | int64_t i, j, k, l, ret1, ret2, bit1, bit2, is1; | ||
| 956 | |||
| 957 | for (i = 0, j = 0, k = 4, l = 4, ret1 = 0, ret2 = 0; i < 12; i++) { | ||
| 958 | /* Simple version: | ||
| 959 | if (c.edge[i] & _esepbit2) { | ||
| 960 | ret1 += binomial[11-i][k--]; | ||
| 961 | } else { | ||
| 962 | if (c.edge[i] & _esepbit1) | ||
| 963 | ret2 += binomial[7-j][l--]; | ||
| 964 | j++; | ||
| 965 | } | ||
| 966 | */ | ||
| 967 | |||
| 968 | bit1 = (c.edge[i] & _esepbit1) >> 2U; | ||
| 969 | bit2 = (c.edge[i] & _esepbit2) >> 3U; | ||
| 970 | is1 = (1 - bit2) * bit1; | ||
| 971 | |||
| 972 | ret1 += bit2 * binomial[11-i][k]; | ||
| 973 | k -= bit2; | ||
| 974 | |||
| 975 | ret2 += is1 * binomial[7-j][l]; | ||
| 976 | l -= is1; | ||
| 977 | j += (1-bit2); | ||
| 978 | } | ||
| 979 | |||
| 980 | return ret1 * 70 + ret2; | ||
| 981 | } | ||
| 982 | |||
| 890 | #endif | 983 | #endif |
| 891 | 984 | ||
| 892 | /****************************************************************************** | 985 | /****************************************************************************** |
diff --git a/test/074_coord_esep/00_solved.in b/test/074_coord_esep/00_solved.in new file mode 100644 index 0000000..dff224d --- /dev/null +++ b/test/074_coord_esep/00_solved.in | |||
| @@ -0,0 +1 @@ | |||
| UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/00_solved.out b/test/074_coord_esep/00_solved.out new file mode 100644 index 0000000..573541a --- /dev/null +++ b/test/074_coord_esep/00_solved.out | |||
| @@ -0,0 +1 @@ | |||
| 0 | |||
diff --git a/test/074_coord_esep/01_U.in b/test/074_coord_esep/01_U.in new file mode 100644 index 0000000..b5b36ad --- /dev/null +++ b/test/074_coord_esep/01_U.in | |||
| @@ -0,0 +1 @@ | |||
| UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/01_U.out b/test/074_coord_esep/01_U.out new file mode 100644 index 0000000..c3f407c --- /dev/null +++ b/test/074_coord_esep/01_U.out | |||
| @@ -0,0 +1 @@ | |||
| 55 | |||
diff --git a/test/074_coord_esep/02_U2.in b/test/074_coord_esep/02_U2.in new file mode 100644 index 0000000..316ad57 --- /dev/null +++ b/test/074_coord_esep/02_U2.in | |||
| @@ -0,0 +1 @@ | |||
| UB0 UF0 DB0 DF0 UL0 UR0 DL0 DR0 FR0 FL0 BL0 BR0 UBL0 UFR0 DFL0 DBR0 UBR0 UFL0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/02_U2.out b/test/074_coord_esep/02_U2.out new file mode 100644 index 0000000..573541a --- /dev/null +++ b/test/074_coord_esep/02_U2.out | |||
| @@ -0,0 +1 @@ | |||
| 0 | |||
diff --git a/test/074_coord_esep/20_scrambled.in b/test/074_coord_esep/20_scrambled.in new file mode 100644 index 0000000..274d30b --- /dev/null +++ b/test/074_coord_esep/20_scrambled.in | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | UL0 BL0 BR1 DL0 FR0 DF0 DB1 DR1 UB0 FL0 UF0 UR1 DFL0 UFR1 DBR1 UBR2 DBL2 DFR0 UFL1 UBL2 | ||
| 2 | |||
| 3 | // Scramble: U R D' L D' F L2 D L F B D2 B' L2 F U2 L2 D2 R2 L2 B' | ||
diff --git a/test/074_coord_esep/20_scrambled.out b/test/074_coord_esep/20_scrambled.out new file mode 100644 index 0000000..b204ff8 --- /dev/null +++ b/test/074_coord_esep/20_scrambled.out | |||
| @@ -0,0 +1 @@ | |||
| 22248 | |||
diff --git a/test/074_coord_esep/21_swapaxis_FB.in b/test/074_coord_esep/21_swapaxis_FB.in new file mode 100644 index 0000000..d06e331 --- /dev/null +++ b/test/074_coord_esep/21_swapaxis_FB.in | |||
| @@ -0,0 +1 @@ | |||
| FR0 BR0 BL0 FL0 UR0 UL0 DL0 DR0 DF0 UF0 UB0 DB0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/21_swapaxis_FB.out b/test/074_coord_esep/21_swapaxis_FB.out new file mode 100644 index 0000000..cb33fb1 --- /dev/null +++ b/test/074_coord_esep/21_swapaxis_FB.out | |||
| @@ -0,0 +1 @@ | |||
| 34649 | |||
diff --git a/test/074_coord_esep/22_swapaxis_RL.in b/test/074_coord_esep/22_swapaxis_RL.in new file mode 100644 index 0000000..cb1ea4e --- /dev/null +++ b/test/074_coord_esep/22_swapaxis_RL.in | |||
| @@ -0,0 +1 @@ | |||
| UF0 UB0 DB0 DF0 FR0 FL0 BL0 BR0 DR0 DL0 UL0 UR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/22_swapaxis_RL.out b/test/074_coord_esep/22_swapaxis_RL.out new file mode 100644 index 0000000..ddeb3cf --- /dev/null +++ b/test/074_coord_esep/22_swapaxis_RL.out | |||
| @@ -0,0 +1 @@ | |||
| 4830 | |||
diff --git a/test/074_coord_esep/23_swapaxis_UD.in b/test/074_coord_esep/23_swapaxis_UD.in new file mode 100644 index 0000000..9c57408 --- /dev/null +++ b/test/074_coord_esep/23_swapaxis_UD.in | |||
| @@ -0,0 +1 @@ | |||
| UR0 UL0 DL0 DR0 UB0 UF0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 | |||
diff --git a/test/074_coord_esep/23_swapaxis_UD.out b/test/074_coord_esep/23_swapaxis_UD.out new file mode 100644 index 0000000..b5489e5 --- /dev/null +++ b/test/074_coord_esep/23_swapaxis_UD.out | |||
| @@ -0,0 +1 @@ | |||
| 69 | |||
diff --git a/test/074_coord_esep/coord_esep_tests.c b/test/074_coord_esep/coord_esep_tests.c new file mode 100644 index 0000000..8276dc0 --- /dev/null +++ b/test/074_coord_esep/coord_esep_tests.c | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #include "../test.h" | ||
| 2 | |||
| 3 | int64_t coord_fast_esep(cube_fast_t); | ||
| 4 | cube_fast_t cubetofast(cube_t); | ||
| 5 | |||
| 6 | int main(void) { | ||
| 7 | char str[STRLENMAX]; | ||
| 8 | cube_t cube; | ||
| 9 | cube_fast_t fast; | ||
| 10 | int64_t result; | ||
| 11 | |||
| 12 | fgets(str, STRLENMAX, stdin); | ||
| 13 | cube = readcube("H48", str); | ||
| 14 | fast = cubetofast(cube); | ||
| 15 | |||
| 16 | result = coord_fast_esep(fast); | ||
| 17 | |||
| 18 | printf("%" PRId64 "\n", result); | ||
| 19 | |||
| 20 | return 0; | ||
| 21 | } | ||
