diff options
Diffstat (limited to 'cube.c')
| -rw-r--r-- | cube.c | 95 |
1 files changed, 94 insertions, 1 deletions
| @@ -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 | /****************************************************************************** |
