diff options
Diffstat (limited to 'cube.c')
| -rw-r--r-- | cube.c | 111 |
1 files changed, 80 insertions, 31 deletions
| @@ -277,7 +277,7 @@ _move_U(cube_fast_t c) | |||
| 277 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 1, 0, 3, 2, 4, 5 | 277 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 1, 0, 3, 2, 4, 5 |
| 278 | ); | 278 | ); |
| 279 | 279 | ||
| 280 | return _mm256_shuffle_epi8(c, m); | 280 | return compose_fast(c, m); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static inline cube_fast_t | 283 | static inline cube_fast_t |
| @@ -288,7 +288,7 @@ _move_U2(cube_fast_t c) | |||
| 288 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 4, 5, 3, 2, 0, 1 | 288 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 4, 5, 3, 2, 0, 1 |
| 289 | ); | 289 | ); |
| 290 | 290 | ||
| 291 | return _mm256_shuffle_epi8(c, m); | 291 | return compose_fast(c, m); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | static inline cube_fast_t | 294 | static inline cube_fast_t |
| @@ -299,7 +299,7 @@ _move_U3(cube_fast_t c) | |||
| 299 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 1, 3, 2, 5, 4 | 299 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 1, 3, 2, 5, 4 |
| 300 | ); | 300 | ); |
| 301 | 301 | ||
| 302 | return _mm256_shuffle_epi8(c, m); | 302 | return compose_fast(c, m); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static inline cube_fast_t | 305 | static inline cube_fast_t |
| @@ -310,7 +310,7 @@ _move_D(cube_fast_t c) | |||
| 310 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 4, 6, 7, 1, 0 | 310 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 4, 6, 7, 1, 0 |
| 311 | ); | 311 | ); |
| 312 | 312 | ||
| 313 | return _mm256_shuffle_epi8(c, m); | 313 | return compose_fast(c, m); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static inline cube_fast_t | 316 | static inline cube_fast_t |
| @@ -321,7 +321,7 @@ _move_D2(cube_fast_t c) | |||
| 321 | 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 5, 4, 2, 3, 1, 0 | 321 | 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 5, 4, 2, 3, 1, 0 |
| 322 | ); | 322 | ); |
| 323 | 323 | ||
| 324 | return _mm256_shuffle_epi8(c, m); | 324 | return compose_fast(c, m); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | static inline cube_fast_t | 327 | static inline cube_fast_t |
| @@ -332,7 +332,7 @@ _move_D3(cube_fast_t c) | |||
| 332 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 4, 7, 6, 1, 0 | 332 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 4, 7, 6, 1, 0 |
| 333 | ); | 333 | ); |
| 334 | 334 | ||
| 335 | return _mm256_shuffle_epi8(c, m); | 335 | return compose_fast(c, m); |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | static inline cube_fast_t | 338 | static inline cube_fast_t |
| @@ -354,7 +354,7 @@ _move_R2(cube_fast_t c) | |||
| 354 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 4, 0, 2, 1, 3 | 354 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 4, 0, 2, 1, 3 |
| 355 | ); | 355 | ); |
| 356 | 356 | ||
| 357 | return _mm256_shuffle_epi8(c, m); | 357 | return compose_fast(c, m); |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static inline cube_fast_t | 360 | static inline cube_fast_t |
| @@ -387,7 +387,7 @@ _move_L2(cube_fast_t c) | |||
| 387 | 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 5, 7, 3, 1, 2, 0 | 387 | 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 5, 7, 3, 1, 2, 0 |
| 388 | ); | 388 | ); |
| 389 | 389 | ||
| 390 | return _mm256_shuffle_epi8(c, m); | 390 | return compose_fast(c, m); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static inline cube_fast_t | 393 | static inline cube_fast_t |
| @@ -420,7 +420,7 @@ _move_F2(cube_fast_t c) | |||
| 420 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 5, 6, 3, 0, 1, 2 | 420 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 5, 6, 3, 0, 1, 2 |
| 421 | ); | 421 | ); |
| 422 | 422 | ||
| 423 | return _mm256_shuffle_epi8(c, m); | 423 | return compose_fast(c, m); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | static inline cube_fast_t | 426 | static inline cube_fast_t |
| @@ -453,7 +453,7 @@ _move_B2(cube_fast_t c) | |||
| 453 | 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 4, 1, 2, 3, 0 | 453 | 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 4, 1, 2, 3, 0 |
| 454 | ); | 454 | ); |
| 455 | 455 | ||
| 456 | return _mm256_shuffle_epi8(c, m); | 456 | return compose_fast(c, m); |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static inline cube_fast_t | 459 | static inline cube_fast_t |
| @@ -1479,13 +1479,13 @@ fasttocube(cube_fast_t c) | |||
| 1479 | static inline bool | 1479 | static inline bool |
| 1480 | equal_fast(cube_fast_t c1, cube_fast_t c2) | 1480 | equal_fast(cube_fast_t c1, cube_fast_t c2) |
| 1481 | { | 1481 | { |
| 1482 | uint32_t mask; | 1482 | int32_t mask; |
| 1483 | __m256i cmp; | 1483 | __m256i cmp; |
| 1484 | 1484 | ||
| 1485 | cmp = _mm256_cmpeq_epi8(c1, c2); | 1485 | cmp = _mm256_cmpeq_epi8(c1, c2); |
| 1486 | mask = _mm256_movemask_epi8(cmp); | 1486 | mask = _mm256_movemask_epi8(cmp); |
| 1487 | 1487 | ||
| 1488 | return mask == 0xffffffffU; | 1488 | return mask == ~0; |
| 1489 | } | 1489 | } |
| 1490 | 1490 | ||
| 1491 | static inline bool | 1491 | static inline bool |
| @@ -1511,6 +1511,19 @@ invertco_fast(cube_fast_t c) | |||
| 1511 | } | 1511 | } |
| 1512 | 1512 | ||
| 1513 | static inline cube_fast_t | 1513 | static inline cube_fast_t |
| 1514 | cleanaftershuffle(cube_fast_t c) | ||
| 1515 | { | ||
| 1516 | __m256i b; | ||
| 1517 | |||
| 1518 | b = _mm256_set_epi8( | ||
| 1519 | ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1520 | ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 1521 | ); | ||
| 1522 | |||
| 1523 | return _mm256_andnot_si256(b, c); | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | static inline cube_fast_t | ||
| 1514 | inverse_fast(cube_fast_t c) | 1527 | inverse_fast(cube_fast_t c) |
| 1515 | { | 1528 | { |
| 1516 | /* Method taken from Andrew Skalski's vcube[1]. The addition sequence | 1529 | /* Method taken from Andrew Skalski's vcube[1]. The addition sequence |
| @@ -1544,6 +1557,7 @@ inverse_fast(cube_fast_t c) | |||
| 1544 | vo = _mm256_shuffle_epi8(vo, vi); | 1557 | vo = _mm256_shuffle_epi8(vo, vi); |
| 1545 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi); | 1558 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi); |
| 1546 | ret = _mm256_or_si256(vp, vo); | 1559 | ret = _mm256_or_si256(vp, vo); |
| 1560 | ret = cleanaftershuffle(ret); | ||
| 1547 | 1561 | ||
| 1548 | return invertco_fast(ret); | 1562 | return invertco_fast(ret); |
| 1549 | } | 1563 | } |
| @@ -1557,6 +1571,7 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) | |||
| 1557 | 1571 | ||
| 1558 | eo2 = _mm256_and_si256(c2, _eo_avx2); | 1572 | eo2 = _mm256_and_si256(c2, _eo_avx2); |
| 1559 | s = _mm256_shuffle_epi8(c1, c2); | 1573 | s = _mm256_shuffle_epi8(c1, c2); |
| 1574 | s = cleanaftershuffle(s); | ||
| 1560 | ed = _mm256_xor_si256(s, eo2); | 1575 | ed = _mm256_xor_si256(s, eo2); |
| 1561 | co1 = _mm256_and_si256(s, _co2_avx2); | 1576 | co1 = _mm256_and_si256(s, _co2_avx2); |
| 1562 | co2 = _mm256_and_si256(c2, _co2_avx2); | 1577 | co2 = _mm256_and_si256(c2, _co2_avx2); |
| @@ -2939,6 +2954,8 @@ Some of these routines depend on the efficient functions implemented in the | |||
| 2939 | previous sections, while some other operate directly on the cube. | 2954 | previous sections, while some other operate directly on the cube. |
| 2940 | ******************************************************************************/ | 2955 | ******************************************************************************/ |
| 2941 | 2956 | ||
| 2957 | static inline uint8_t movebase(uint8_t); | ||
| 2958 | static inline uint8_t moveaxis(uint8_t); | ||
| 2942 | static uint8_t readco(char *); | 2959 | static uint8_t readco(char *); |
| 2943 | static uint8_t readcp(char *); | 2960 | static uint8_t readcp(char *); |
| 2944 | static uint8_t readeo(char *); | 2961 | static uint8_t readeo(char *); |
| @@ -2990,6 +3007,18 @@ iserror(cube_t cube) | |||
| 2990 | return equal(cube, zero); | 3007 | return equal(cube, zero); |
| 2991 | } | 3008 | } |
| 2992 | 3009 | ||
| 3010 | static inline uint8_t | ||
| 3011 | movebase(uint8_t move) | ||
| 3012 | { | ||
| 3013 | return move / 3; | ||
| 3014 | } | ||
| 3015 | |||
| 3016 | static inline uint8_t | ||
| 3017 | moveaxis(uint8_t move) | ||
| 3018 | { | ||
| 3019 | return move / 6; | ||
| 3020 | } | ||
| 3021 | |||
| 2993 | static uint8_t | 3022 | static uint8_t |
| 2994 | readco(char *str) | 3023 | readco(char *str) |
| 2995 | { | 3024 | { |
| @@ -3292,6 +3321,9 @@ writemoves(uint8_t *m, int n, char *buf) | |||
| 3292 | b += len; | 3321 | b += len; |
| 3293 | *b = ' '; | 3322 | *b = ' '; |
| 3294 | } | 3323 | } |
| 3324 | |||
| 3325 | if (b != buf) | ||
| 3326 | b--; /* Remove last space */ | ||
| 3295 | *b = '\0'; | 3327 | *b = '\0'; |
| 3296 | 3328 | ||
| 3297 | return b - buf; | 3329 | return b - buf; |
| @@ -3653,8 +3685,8 @@ typedef struct { | |||
| 3653 | cube_fast_t cube; | 3685 | cube_fast_t cube; |
| 3654 | uint8_t depth; | 3686 | uint8_t depth; |
| 3655 | int64_t maxsols; | 3687 | int64_t maxsols; |
| 3656 | char *sols; | 3688 | char **nextsol; |
| 3657 | int64_t nsols; | 3689 | int64_t *nsols; |
| 3658 | uint8_t nmoves; | 3690 | uint8_t nmoves; |
| 3659 | uint8_t moves[20]; | 3691 | uint8_t moves[20]; |
| 3660 | uint8_t (*estimate)(cube_fast_t); | 3692 | uint8_t (*estimate)(cube_fast_t); |
| @@ -3671,10 +3703,10 @@ allowednextmove(dfsarg_generic_t arg, uint8_t m) | |||
| 3671 | if (n == 0) | 3703 | if (n == 0) |
| 3672 | return true; | 3704 | return true; |
| 3673 | 3705 | ||
| 3674 | mbase = m / 3; | 3706 | mbase = movebase(m); |
| 3675 | maxis = mbase / 2; | 3707 | maxis = moveaxis(m); |
| 3676 | l1base = arg.moves[n-1] / 3; | 3708 | l1base = movebase(arg.moves[n-1]); |
| 3677 | l1axis = l1base / 2; | 3709 | l1axis = moveaxis(arg.moves[n-1]); |
| 3678 | 3710 | ||
| 3679 | if (mbase == l1base || (maxis == l1axis && mbase < l1base)) | 3711 | if (mbase == l1base || (maxis == l1axis && mbase < l1base)) |
| 3680 | return false; | 3712 | return false; |
| @@ -3682,12 +3714,25 @@ allowednextmove(dfsarg_generic_t arg, uint8_t m) | |||
| 3682 | if (n == 1) | 3714 | if (n == 1) |
| 3683 | return true; | 3715 | return true; |
| 3684 | 3716 | ||
| 3685 | l2base = arg.moves[n-2] / 3; | 3717 | l2base = movebase(arg.moves[n-2]); |
| 3686 | l2axis = l1base / 2; | 3718 | l2axis = moveaxis(arg.moves[n-2]); |
| 3687 | 3719 | ||
| 3688 | return l1axis != l2axis || mbase != l2base; | 3720 | return l1axis != l2axis || mbase != l2base; |
| 3689 | } | 3721 | } |
| 3690 | 3722 | ||
| 3723 | static void | ||
| 3724 | solve_generic_appendsolution(dfsarg_generic_t arg) | ||
| 3725 | { | ||
| 3726 | int strl; | ||
| 3727 | |||
| 3728 | strl = writemoves(arg.moves, arg.depth, *arg.nextsol); | ||
| 3729 | DBG_LOG("Solution found: %s\n", *arg.nextsol); | ||
| 3730 | *arg.nextsol += strl; | ||
| 3731 | **arg.nextsol = '\n'; | ||
| 3732 | (*arg.nextsol)++; | ||
| 3733 | (*arg.nsols)++; | ||
| 3734 | } | ||
| 3735 | |||
| 3691 | static int | 3736 | static int |
| 3692 | solve_generic_dfs(dfsarg_generic_t arg) | 3737 | solve_generic_dfs(dfsarg_generic_t arg) |
| 3693 | { | 3738 | { |
| @@ -3697,15 +3742,13 @@ solve_generic_dfs(dfsarg_generic_t arg) | |||
| 3697 | 3742 | ||
| 3698 | bound = arg.estimate(arg.cube); | 3743 | bound = arg.estimate(arg.cube); |
| 3699 | 3744 | ||
| 3700 | if (arg.nsols == arg.maxsols || bound + arg.nmoves > arg.depth) | 3745 | if (*arg.nsols == arg.maxsols || bound + arg.nmoves > arg.depth) |
| 3701 | return 0; | 3746 | return 0; |
| 3702 | 3747 | ||
| 3703 | if (bound == 0) { | 3748 | if (bound == 0) { |
| 3704 | if (arg.nmoves != arg.depth) | 3749 | if (arg.nmoves != arg.depth) |
| 3705 | return 0; | 3750 | return 0; |
| 3706 | arg.sols += writemoves(arg.moves, arg.depth, arg.sols); | 3751 | solve_generic_appendsolution(arg); |
| 3707 | *arg.sols = '\n'; | ||
| 3708 | arg.sols++; | ||
| 3709 | return 1; | 3752 | return 1; |
| 3710 | } | 3753 | } |
| 3711 | 3754 | ||
| @@ -3746,6 +3789,13 @@ solve_generic( | |||
| 3746 | return -1; | 3789 | return -1; |
| 3747 | } | 3790 | } |
| 3748 | 3791 | ||
| 3792 | if (issolved(cube)) { | ||
| 3793 | DBG_LOG("solve: cube is already solved\n"); | ||
| 3794 | sols[0] = '\n'; | ||
| 3795 | sols[1] = 0; | ||
| 3796 | return 1; | ||
| 3797 | } | ||
| 3798 | |||
| 3749 | DBG_WARN(!strcmp(nisstype, ""), | 3799 | DBG_WARN(!strcmp(nisstype, ""), |
| 3750 | "solve: NISS not implemented yet, 'nisstype' ignored\n"); | 3800 | "solve: NISS not implemented yet, 'nisstype' ignored\n"); |
| 3751 | 3801 | ||
| @@ -3782,8 +3832,8 @@ solve_generic( | |||
| 3782 | arg = (dfsarg_generic_t) { | 3832 | arg = (dfsarg_generic_t) { |
| 3783 | .cube = cubetofast(cube), | 3833 | .cube = cubetofast(cube), |
| 3784 | .maxsols = maxsols, | 3834 | .maxsols = maxsols, |
| 3785 | .sols = sols, | 3835 | .nextsol = &sols, |
| 3786 | .nsols = 0, | 3836 | .nsols = &ret, |
| 3787 | .nmoves = 0, | 3837 | .nmoves = 0, |
| 3788 | .moves = {0}, | 3838 | .moves = {0}, |
| 3789 | .estimate = estimate, | 3839 | .estimate = estimate, |
| @@ -3793,12 +3843,11 @@ solve_generic( | |||
| 3793 | first = -1; | 3843 | first = -1; |
| 3794 | for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) { | 3844 | for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) { |
| 3795 | tmp = solve_generic_dfs(arg); | 3845 | tmp = solve_generic_dfs(arg); |
| 3796 | ret += tmp; | ||
| 3797 | if (tmp != 0) | 3846 | if (tmp != 0) |
| 3798 | first = arg.depth; | 3847 | first = arg.depth; |
| 3799 | 3848 | ||
| 3800 | DBG_LOG("Found %" PRId64 " solutions at depth %" PRIu8 "\n", | 3849 | DBG_LOG("Found %" PRId64 " solution%s at depth %" PRIu8 "\n", |
| 3801 | tmp, arg.depth); | 3850 | tmp, tmp == 1 ? "" : "s", arg.depth); |
| 3802 | 3851 | ||
| 3803 | if (ret >= maxsols) | 3852 | if (ret >= maxsols) |
| 3804 | break; | 3853 | break; |
| @@ -3864,7 +3913,7 @@ solve( | |||
| 3864 | DBG_WARN(data == NULL, | 3913 | DBG_WARN(data == NULL, |
| 3865 | "solve: 'data' not implemented yet, ignoring\n"); | 3914 | "solve: 'data' not implemented yet, ignoring\n"); |
| 3866 | 3915 | ||
| 3867 | if (!strcmp(solver, "simple")) { | 3916 | if (!strcmp(solver, "optimal") || !strcmp(solver, "simple")) { |
| 3868 | return solve_simple( | 3917 | return solve_simple( |
| 3869 | cube, | 3918 | cube, |
| 3870 | minmoves, | 3919 | minmoves, |
| @@ -3874,7 +3923,7 @@ solve( | |||
| 3874 | solutions | 3923 | solutions |
| 3875 | ); | 3924 | ); |
| 3876 | } else { | 3925 | } else { |
| 3877 | DBG_LOG("solve: unknown solver\n"); | 3926 | DBG_LOG("solve: unknown solver '%s'\n", solver); |
| 3878 | return -1; | 3927 | return -1; |
| 3879 | } | 3928 | } |
| 3880 | 3929 | ||
