h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit c5c5017a335208881e27fc8f72c1d0145a04622a
parent 28ad019d62583b7e89b4e76922aa73857d5876eb
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sun,  9 Jun 2024 12:43:49 +0200

Remvoed cube_fast_t and more. More cleaning up to do.

Diffstat:
MTODO.txt | 28+++++++++++-----------------
Asrc/constant_cubes.h | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/constants.h | 241-------------------------------------------------------------------------------
Msrc/cube.c | 14+++++++++++---
Msrc/cube.h | 17-----------------
Msrc/cube_avx2.h | 212++++++++++++++++++++++++++-----------------------------------------------------
Asrc/cube_generic.h | 702+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cube_neon.h | 2+-
Msrc/cube_portable.h | 197++++++++++++++++++++++++++-----------------------------------------------------
Dsrc/cube_routines.h | 668-------------------------------------------------------------------------------
Msrc/cube_transform.h | 470++++++++++++++++++++++++++-----------------------------------------------------
Asrc/cube_transform_with_switch.h | 336+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solve_generic.h | 16++++++++--------
Msrc/solve_h48.h | 56++++++++++++++++++++++++++++----------------------------
Mtest/001_pieces/pieces_tests.c | 11+++++------
Dtest/002_cube_conversion/00_solved.in | 1-
Dtest/002_cube_conversion/00_solved.out | 1-
Dtest/002_cube_conversion/01_scrambled.in | 1-
Dtest/002_cube_conversion/01_scrambled.out | 1-
Dtest/002_cube_conversion/cube_conversion_tests.c | 25-------------------------
Mtest/071_coord_eo/coord_eo_tests.c | 6++----
Mtest/072_coord_co/coord_co_tests.c | 6++----
Mtest/073_coord_csep/coord_csep_tests.c | 6++----
Mtest/074_coord_esep/coord_esep_tests.c | 6++----
Mtest/075_set_eo/set_eo_tests.c | 16++++++++--------
Mtest/076_copy_corners/copy_corners_tests.c | 8++------
Mtest/077_copy_edges/copy_edges_tests.c | 8++------
Mtest/078_invcoord_esep/invcoord_esep_tests.c | 12+++++-------
Mtest/100_gendata_cocsep/gendata_cocsep_tests.c | 4++--
Mtest/101_cocsep_selfsim/cocsep_selfsim_tests.c | 10+++++-----
Mtest/102_coord_invcoord_h48/coord_invcoord_h48_tests.c | 18++++++++----------
Mtest/test.h | 12++++--------
32 files changed, 1663 insertions(+), 1677 deletions(-)

diff --git a/TODO.txt b/TODO.txt @@ -1,25 +1,19 @@ Refactoring: remove cube_fast_t and add b32 format - x added b32 converter by piece (not tested, will be tested automatically) - x added piece functions (e.g. corner(cube, i)) - (would be more efficient to just convert the whole thing to arrays...) - - replace all usages of cube_t with cube_fast_t and piece functions - (this is mainly in cube_routines) - (fix tests in tandem with main code) - cubetofast fasttocube - zero and solved - solvedcube(void) - [cube.h] isconsistent, issolvable, issolved, equal, iserror - [cube.h] compose, inverse - [cube.h] applymoves, applytrans - [cube.h] readcube writecube - [cube.h] solve - - add b32 i/o format as default - - remove cube_t type - - rename cube_fast_t to cube_t + - fix all public functions in cube.h + and their implementations in cube_generic + - cube i/o format + move all formats other than b32 to convert.{c,h} + add tests for conversion + convert test files (?) + make b32 default + replace utils/*.c with a generic convert utility - if all public functions work with strings, always use return value as error code (solve already does this), and use string as buffer to print error +Transform with big table + - make static cube actually static (how?) + Solver - write a solver (how many tricks? some, but not all are needed) diff --git a/src/constant_cubes.h b/src/constant_cubes.h @@ -0,0 +1,229 @@ +#define _move_cube_U static_cube( \ + 5, 4, 2, 3, 0, 1, 6, 7, 4, 5, 2, 3, 1, 0, 6, 7, 8, 9, 10, 11) +#define _move_cube_U2 static_cube( \ + 1, 0, 2, 3, 5, 4, 6, 7, 1, 0, 2, 3, 5, 4, 6, 7, 8, 9, 10, 11) +#define _move_cube_U3 static_cube( \ + 4, 5, 2, 3, 1, 0, 6, 7, 5, 4, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11) +#define _move_cube_D static_cube( \ + 0, 1, 7, 6, 4, 5, 2, 3, 0, 1, 7, 6, 4, 5, 2, 3, 8, 9, 10, 11) +#define _move_cube_D2 static_cube( \ + 0, 1, 3, 2, 4, 5, 7, 6, 0, 1, 3, 2, 4, 5, 7, 6, 8, 9, 10, 11) +#define _move_cube_D3 static_cube( \ + 0, 1, 6, 7, 4, 5, 3, 2, 0, 1, 6, 7, 4, 5, 3, 2, 8, 9, 10, 11) +#define _move_cube_R static_cube( \ + 70, 1, 2, 69, 4, 32, 35, 7, 0, 1, 2, 3, 8, 5, 6, 11, 7, 9, 10, 4) +#define _move_cube_R2 static_cube( \ + 3, 1, 2, 0, 4, 6, 5, 7, 0, 1, 2, 3, 7, 5, 6, 4, 11, 9, 10, 8) +#define _move_cube_R3 static_cube( \ + 69, 1, 2, 70, 4, 35, 32, 7, 0, 1, 2, 3, 11, 5, 6, 8, 4, 9, 10, 7) +#define _move_cube_L static_cube( \ + 0, 71, 68, 3, 33, 5, 6, 34, 0, 1, 2, 3, 4, 10, 9, 7, 8, 5, 6, 11) +#define _move_cube_L2 static_cube( \ + 0, 2, 1, 3, 7, 5, 6, 4, 0, 1, 2, 3, 4, 6, 5, 7, 8, 10, 9, 11) +#define _move_cube_L3 static_cube( \ + 0, 68, 71, 3, 34, 5, 6, 33, 0, 1, 2, 3, 4, 9, 10, 7, 8, 6, 5, 11) +#define _move_cube_F static_cube( \ + 36, 1, 38, 3, 66, 5, 64, 7, 25, 1, 2, 24, 4, 5, 6, 7, 16, 19, 10, 11) +#define _move_cube_F2 static_cube( \ + 2, 1, 0, 3, 6, 5, 4, 7, 3, 1, 2, 0, 4, 5, 6, 7, 9, 8, 10, 11) +#define _move_cube_F3 static_cube( \ + 38, 1, 36, 3, 64, 5, 66, 7, 24, 1, 2, 25, 4, 5, 6, 7, 19, 16, 10, 11) +#define _move_cube_B static_cube( \ + 0, 37, 2, 39, 4, 67, 6, 65, 0, 27, 26, 3, 4, 5, 6, 7, 8, 9, 17, 18) +#define _move_cube_B2 static_cube( \ + 0, 3, 2, 1, 4, 7, 6, 5, 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 11, 10) +#define _move_cube_B3 static_cube( \ + 0, 39, 2, 37, 4, 65, 6, 67, 0, 26, 27, 3, 4, 5, 6, 7, 8, 9, 18, 17) + +#define _trans_cube_UFr static_cube( \ + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) +#define _trans_cube_UFr_inverse static_cube( \ + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) +#define _trans_cube_ULr static_cube( \ + 4, 5, 7, 6, 1, 0, 2, 3, 5, 4, 7, 6, 0, 1, 2, 3, 25, 26, 27, 24) +#define _trans_cube_ULr_inverse static_cube( \ + 5, 4, 6, 7, 0, 1, 3, 2, 4, 5, 6, 7, 1, 0, 3, 2, 27, 24, 25, 26) +#define _trans_cube_UBr static_cube( \ + 1, 0, 3, 2, 5, 4, 7, 6, 1, 0, 3, 2, 5, 4, 7, 6, 10, 11, 8, 9) +#define _trans_cube_UBr_inverse static_cube( \ + 1, 0, 3, 2, 5, 4, 7, 6, 1, 0, 3, 2, 5, 4, 7, 6, 10, 11, 8, 9) +#define _trans_cube_URr static_cube( \ + 5, 4, 6, 7, 0, 1, 3, 2, 4, 5, 6, 7, 1, 0, 3, 2, 27, 24, 25, 26) +#define _trans_cube_URr_inverse static_cube( \ + 4, 5, 7, 6, 1, 0, 2, 3, 5, 4, 7, 6, 0, 1, 2, 3, 25, 26, 27, 24) +#define _trans_cube_DFr static_cube( \ + 2, 3, 0, 1, 6, 7, 4, 5, 3, 2, 1, 0, 6, 7, 4, 5, 9, 8, 11, 10) +#define _trans_cube_DFr_inverse static_cube( \ + 2, 3, 0, 1, 6, 7, 4, 5, 3, 2, 1, 0, 6, 7, 4, 5, 9, 8, 11, 10) +#define _trans_cube_DLr static_cube( \ + 7, 6, 4, 5, 2, 3, 1, 0, 6, 7, 4, 5, 2, 3, 0, 1, 26, 25, 24, 27) +#define _trans_cube_DLr_inverse static_cube( \ + 7, 6, 4, 5, 2, 3, 1, 0, 6, 7, 4, 5, 2, 3, 0, 1, 26, 25, 24, 27) +#define _trans_cube_DBr static_cube( \ + 3, 2, 1, 0, 7, 6, 5, 4, 2, 3, 0, 1, 7, 6, 5, 4, 11, 10, 9, 8) +#define _trans_cube_DBr_inverse static_cube( \ + 3, 2, 1, 0, 7, 6, 5, 4, 2, 3, 0, 1, 7, 6, 5, 4, 11, 10, 9, 8) +#define _trans_cube_DRr static_cube( \ + 6, 7, 5, 4, 3, 2, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0, 24, 27, 26, 25) +#define _trans_cube_DRr_inverse static_cube( \ + 6, 7, 5, 4, 3, 2, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0, 24, 27, 26, 25) +#define _trans_cube_RUr static_cube( \ + 64, 67, 65, 66, 37, 38, 36, 39, 20, 23, 22, 21, 24, 27, 26, 25, 0, 1, 2, 3) +#define _trans_cube_RUr_inverse static_cube( \ + 32, 34, 35, 33, 70, 68, 69, 71, 8, 9, 10, 11, 16, 19, 18, 17, 20, 23, 22, 21) +#define _trans_cube_RFr static_cube( \ + 38, 37, 36, 39, 64, 67, 66, 65, 24, 27, 26, 25, 23, 20, 21, 22, 19, 16, 17, 18) +#define _trans_cube_RFr_inverse static_cube( \ + 36, 39, 38, 37, 66, 65, 64, 67, 25, 26, 27, 24, 21, 22, 23, 20, 16, 19, 18, 17) +#define _trans_cube_RDr static_cube( \ + 67, 64, 66, 65, 38, 37, 39, 36, 23, 20, 21, 22, 27, 24, 25, 26, 2, 3, 0, 1) +#define _trans_cube_RDr_inverse static_cube( \ + 33, 35, 34, 32, 71, 69, 68, 70, 10, 11, 8, 9, 17, 18, 19, 16, 21, 22, 23, 20) +#define _trans_cube_RBr static_cube( \ + 37, 38, 39, 36, 67, 64, 65, 66, 27, 24, 25, 26, 20, 23, 22, 21, 17, 18, 19, 16) +#define _trans_cube_RBr_inverse static_cube( \ + 37, 38, 39, 36, 67, 64, 65, 66, 27, 24, 25, 26, 20, 23, 22, 21, 17, 18, 19, 16) +#define _trans_cube_LUr static_cube( \ + 65, 66, 64, 67, 36, 39, 37, 38, 21, 22, 23, 20, 26, 25, 24, 27, 1, 0, 3, 2) +#define _trans_cube_LUr_inverse static_cube( \ + 34, 32, 33, 35, 68, 70, 71, 69, 9, 8, 11, 10, 19, 16, 17, 18, 22, 21, 20, 23) +#define _trans_cube_LFr static_cube( \ + 36, 39, 38, 37, 66, 65, 64, 67, 25, 26, 27, 24, 21, 22, 23, 20, 16, 19, 18, 17) +#define _trans_cube_LFr_inverse static_cube( \ + 38, 37, 36, 39, 64, 67, 66, 65, 24, 27, 26, 25, 23, 20, 21, 22, 19, 16, 17, 18) +#define _trans_cube_LDr static_cube( \ + 66, 65, 67, 64, 39, 36, 38, 37, 22, 21, 20, 23, 25, 26, 27, 24, 3, 2, 1, 0) +#define _trans_cube_LDr_inverse static_cube( \ + 35, 33, 32, 34, 69, 71, 70, 68, 11, 10, 9, 8, 18, 17, 16, 19, 23, 20, 21, 22) +#define _trans_cube_LBr static_cube( \ + 39, 36, 37, 38, 65, 66, 67, 64, 26, 25, 24, 27, 22, 21, 20, 23, 18, 17, 16, 19) +#define _trans_cube_LBr_inverse static_cube( \ + 39, 36, 37, 38, 65, 66, 67, 64, 26, 25, 24, 27, 22, 21, 20, 23, 18, 17, 16, 19) +#define _trans_cube_FUr static_cube( \ + 68, 70, 69, 71, 32, 34, 33, 35, 16, 19, 18, 17, 9, 8, 11, 10, 5, 4, 7, 6) +#define _trans_cube_FUr_inverse static_cube( \ + 68, 70, 69, 71, 32, 34, 33, 35, 16, 19, 18, 17, 9, 8, 11, 10, 5, 4, 7, 6) +#define _trans_cube_FRr static_cube( \ + 32, 34, 35, 33, 70, 68, 69, 71, 8, 9, 10, 11, 16, 19, 18, 17, 20, 23, 22, 21) +#define _trans_cube_FRr_inverse static_cube( \ + 64, 67, 65, 66, 37, 38, 36, 39, 20, 23, 22, 21, 24, 27, 26, 25, 0, 1, 2, 3) +#define _trans_cube_FDr static_cube( \ + 70, 68, 71, 69, 34, 32, 35, 33, 19, 16, 17, 18, 8, 9, 10, 11, 7, 6, 5, 4) +#define _trans_cube_FDr_inverse static_cube( \ + 69, 71, 68, 70, 33, 35, 32, 34, 17, 18, 19, 16, 11, 10, 9, 8, 4, 5, 6, 7) +#define _trans_cube_FLr static_cube( \ + 34, 32, 33, 35, 68, 70, 71, 69, 9, 8, 11, 10, 19, 16, 17, 18, 22, 21, 20, 23) +#define _trans_cube_FLr_inverse static_cube( \ + 65, 66, 64, 67, 36, 39, 37, 38, 21, 22, 23, 20, 26, 25, 24, 27, 1, 0, 3, 2) +#define _trans_cube_BUr static_cube( \ + 69, 71, 68, 70, 33, 35, 32, 34, 17, 18, 19, 16, 11, 10, 9, 8, 4, 5, 6, 7) +#define _trans_cube_BUr_inverse static_cube( \ + 70, 68, 71, 69, 34, 32, 35, 33, 19, 16, 17, 18, 8, 9, 10, 11, 7, 6, 5, 4) +#define _trans_cube_BRr static_cube( \ + 35, 33, 32, 34, 69, 71, 70, 68, 11, 10, 9, 8, 18, 17, 16, 19, 23, 20, 21, 22) +#define _trans_cube_BRr_inverse static_cube( \ + 66, 65, 67, 64, 39, 36, 38, 37, 22, 21, 20, 23, 25, 26, 27, 24, 3, 2, 1, 0) +#define _trans_cube_BDr static_cube( \ + 71, 69, 70, 68, 35, 33, 34, 32, 18, 17, 16, 19, 10, 11, 8, 9, 6, 7, 4, 5) +#define _trans_cube_BDr_inverse static_cube( \ + 71, 69, 70, 68, 35, 33, 34, 32, 18, 17, 16, 19, 10, 11, 8, 9, 6, 7, 4, 5) +#define _trans_cube_BLr static_cube( \ + 33, 35, 34, 32, 71, 69, 68, 70, 10, 11, 8, 9, 17, 18, 19, 16, 21, 22, 23, 20) +#define _trans_cube_BLr_inverse static_cube( \ + 67, 64, 66, 65, 38, 37, 39, 36, 23, 20, 21, 22, 27, 24, 25, 26, 2, 3, 0, 1) +#define _trans_cube_UFm static_cube( \ + 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 7, 6, 9, 8, 11, 10) +#define _trans_cube_UFm_inverse static_cube( \ + 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 7, 6, 9, 8, 11, 10) +#define _trans_cube_ULm static_cube( \ + 0, 1, 3, 2, 5, 4, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 24, 27, 26, 25) +#define _trans_cube_ULm_inverse static_cube( \ + 0, 1, 3, 2, 5, 4, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 24, 27, 26, 25) +#define _trans_cube_UBm static_cube( \ + 5, 4, 7, 6, 1, 0, 3, 2, 1, 0, 3, 2, 4, 5, 6, 7, 11, 10, 9, 8) +#define _trans_cube_UBm_inverse static_cube( \ + 5, 4, 7, 6, 1, 0, 3, 2, 1, 0, 3, 2, 4, 5, 6, 7, 11, 10, 9, 8) +#define _trans_cube_URm static_cube( \ + 1, 0, 2, 3, 4, 5, 7, 6, 5, 4, 7, 6, 1, 0, 3, 2, 26, 25, 24, 27) +#define _trans_cube_URm_inverse static_cube( \ + 1, 0, 2, 3, 4, 5, 7, 6, 5, 4, 7, 6, 1, 0, 3, 2, 26, 25, 24, 27) +#define _trans_cube_DFm static_cube( \ + 6, 7, 4, 5, 2, 3, 0, 1, 3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10, 11) +#define _trans_cube_DFm_inverse static_cube( \ + 6, 7, 4, 5, 2, 3, 0, 1, 3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10, 11) +#define _trans_cube_DLm static_cube( \ + 3, 2, 0, 1, 6, 7, 5, 4, 7, 6, 5, 4, 2, 3, 0, 1, 27, 24, 25, 26) +#define _trans_cube_DLm_inverse static_cube( \ + 2, 3, 1, 0, 7, 6, 4, 5, 6, 7, 4, 5, 3, 2, 1, 0, 25, 26, 27, 24) +#define _trans_cube_DBm static_cube( \ + 7, 6, 5, 4, 3, 2, 1, 0, 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9) +#define _trans_cube_DBm_inverse static_cube( \ + 7, 6, 5, 4, 3, 2, 1, 0, 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9) +#define _trans_cube_DRm static_cube( \ + 2, 3, 1, 0, 7, 6, 4, 5, 6, 7, 4, 5, 3, 2, 1, 0, 25, 26, 27, 24) +#define _trans_cube_DRm_inverse static_cube( \ + 3, 2, 0, 1, 6, 7, 5, 4, 7, 6, 5, 4, 2, 3, 0, 1, 27, 24, 25, 26) +#define _trans_cube_RUm static_cube( \ + 68, 71, 69, 70, 33, 34, 32, 35, 21, 22, 23, 20, 25, 26, 27, 24, 0, 1, 2, 3) +#define _trans_cube_RUm_inverse static_cube( \ + 70, 68, 69, 71, 32, 34, 35, 33, 8, 9, 10, 11, 19, 16, 17, 18, 23, 20, 21, 22) +#define _trans_cube_RFm static_cube( \ + 34, 33, 32, 35, 68, 71, 70, 69, 25, 26, 27, 24, 22, 21, 20, 23, 19, 16, 17, 18) +#define _trans_cube_RFm_inverse static_cube( \ + 66, 65, 64, 67, 36, 39, 38, 37, 25, 26, 27, 24, 22, 21, 20, 23, 19, 16, 17, 18) +#define _trans_cube_RDm static_cube( \ + 71, 68, 70, 69, 34, 33, 35, 32, 22, 21, 20, 23, 26, 25, 24, 27, 2, 3, 0, 1) +#define _trans_cube_RDm_inverse static_cube( \ + 71, 69, 68, 70, 33, 35, 34, 32, 10, 11, 8, 9, 18, 17, 16, 19, 22, 21, 20, 23) +#define _trans_cube_RBm static_cube( \ + 33, 34, 35, 32, 71, 68, 69, 70, 26, 25, 24, 27, 21, 22, 23, 20, 17, 18, 19, 16) +#define _trans_cube_RBm_inverse static_cube( \ + 67, 64, 65, 66, 37, 38, 39, 36, 27, 24, 25, 26, 23, 20, 21, 22, 18, 17, 16, 19) +#define _trans_cube_LUm static_cube( \ + 69, 70, 68, 71, 32, 35, 33, 34, 20, 23, 22, 21, 27, 24, 25, 26, 1, 0, 3, 2) +#define _trans_cube_LUm_inverse static_cube( \ + 68, 70, 71, 69, 34, 32, 33, 35, 9, 8, 11, 10, 16, 19, 18, 17, 21, 22, 23, 20) +#define _trans_cube_LFm static_cube( \ + 32, 35, 34, 33, 70, 69, 68, 71, 24, 27, 26, 25, 20, 23, 22, 21, 16, 19, 18, 17) +#define _trans_cube_LFm_inverse static_cube( \ + 64, 67, 66, 65, 38, 37, 36, 39, 24, 27, 26, 25, 20, 23, 22, 21, 16, 19, 18, 17) +#define _trans_cube_LDm static_cube( \ + 70, 69, 71, 68, 35, 32, 34, 33, 23, 20, 21, 22, 24, 27, 26, 25, 3, 2, 1, 0) +#define _trans_cube_LDm_inverse static_cube( \ + 69, 71, 70, 68, 35, 33, 32, 34, 11, 10, 9, 8, 17, 18, 19, 16, 20, 23, 22, 21) +#define _trans_cube_LBm static_cube( \ + 35, 32, 33, 34, 69, 70, 71, 68, 27, 24, 25, 26, 23, 20, 21, 22, 18, 17, 16, 19) +#define _trans_cube_LBm_inverse static_cube( \ + 65, 66, 67, 64, 39, 36, 37, 38, 26, 25, 24, 27, 21, 22, 23, 20, 17, 18, 19, 16) +#define _trans_cube_FUm static_cube( \ + 64, 66, 65, 67, 36, 38, 37, 39, 16, 19, 18, 17, 8, 9, 10, 11, 4, 5, 6, 7) +#define _trans_cube_FUm_inverse static_cube( \ + 32, 34, 33, 35, 68, 70, 69, 71, 16, 19, 18, 17, 8, 9, 10, 11, 4, 5, 6, 7) +#define _trans_cube_FRm static_cube( \ + 36, 38, 39, 37, 66, 64, 65, 67, 9, 8, 11, 10, 16, 19, 18, 17, 21, 22, 23, 20) +#define _trans_cube_FRm_inverse static_cube( \ + 37, 38, 36, 39, 64, 67, 65, 66, 20, 23, 22, 21, 27, 24, 25, 26, 1, 0, 3, 2) +#define _trans_cube_FDm static_cube( \ + 66, 64, 67, 65, 38, 36, 39, 37, 19, 16, 17, 18, 9, 8, 11, 10, 6, 7, 4, 5) +#define _trans_cube_FDm_inverse static_cube( \ + 33, 35, 32, 34, 69, 71, 68, 70, 17, 18, 19, 16, 10, 11, 8, 9, 5, 4, 7, 6) +#define _trans_cube_FLm static_cube( \ + 38, 36, 37, 39, 64, 66, 67, 65, 8, 9, 10, 11, 19, 16, 17, 18, 23, 20, 21, 22) +#define _trans_cube_FLm_inverse static_cube( \ + 36, 39, 37, 38, 65, 66, 64, 67, 21, 22, 23, 20, 25, 26, 27, 24, 0, 1, 2, 3) +#define _trans_cube_BUm static_cube( \ + 65, 67, 64, 66, 37, 39, 36, 38, 17, 18, 19, 16, 10, 11, 8, 9, 5, 4, 7, 6) +#define _trans_cube_BUm_inverse static_cube( \ + 34, 32, 35, 33, 70, 68, 71, 69, 19, 16, 17, 18, 9, 8, 11, 10, 6, 7, 4, 5) +#define _trans_cube_BRm static_cube( \ + 39, 37, 36, 38, 65, 67, 66, 64, 10, 11, 8, 9, 18, 17, 16, 19, 22, 21, 20, 23) +#define _trans_cube_BRm_inverse static_cube( \ + 39, 36, 38, 37, 66, 65, 67, 64, 22, 21, 20, 23, 26, 25, 24, 27, 2, 3, 0, 1) +#define _trans_cube_BDm static_cube( \ + 67, 65, 66, 64, 39, 37, 38, 36, 18, 17, 16, 19, 11, 10, 9, 8, 7, 6, 5, 4) +#define _trans_cube_BDm_inverse static_cube( \ + 35, 33, 34, 32, 71, 69, 70, 68, 18, 17, 16, 19, 11, 10, 9, 8, 7, 6, 5, 4) +#define _trans_cube_BLm static_cube( \ + 37, 39, 38, 36, 67, 65, 64, 66, 11, 10, 9, 8, 17, 18, 19, 16, 20, 23, 22, 21) +#define _trans_cube_BLm_inverse static_cube( \ + 38, 37, 39, 36, 67, 64, 66, 65, 23, 20, 21, 22, 24, 27, 26, 25, 3, 2, 1, 0) diff --git a/src/constants.h b/src/constants.h @@ -130,247 +130,6 @@ _static int64_t binomial[12][12] = { #define _eflip UINT8_C(0x10) #define _error UINT8_C(0xFF) -_static cube_t zero = { .corner = {0}, .edge = {0} }; -_static cube_t solved = { - .corner = {0, 1, 2, 3, 4, 5, 6, 7}, - .edge = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} -}; - -#define zero_fast fastcube( \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) -#define solved_fast fastcube( \ - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - -#define _move_cube_U fastcube( \ - 5, 4, 2, 3, 0, 1, 6, 7, 4, 5, 2, 3, 1, 0, 6, 7, 8, 9, 10, 11) -#define _move_cube_U2 fastcube( \ - 1, 0, 2, 3, 5, 4, 6, 7, 1, 0, 2, 3, 5, 4, 6, 7, 8, 9, 10, 11) -#define _move_cube_U3 fastcube( \ - 4, 5, 2, 3, 1, 0, 6, 7, 5, 4, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11) -#define _move_cube_D fastcube( \ - 0, 1, 7, 6, 4, 5, 2, 3, 0, 1, 7, 6, 4, 5, 2, 3, 8, 9, 10, 11) -#define _move_cube_D2 fastcube( \ - 0, 1, 3, 2, 4, 5, 7, 6, 0, 1, 3, 2, 4, 5, 7, 6, 8, 9, 10, 11) -#define _move_cube_D3 fastcube( \ - 0, 1, 6, 7, 4, 5, 3, 2, 0, 1, 6, 7, 4, 5, 3, 2, 8, 9, 10, 11) -#define _move_cube_R fastcube( \ - 70, 1, 2, 69, 4, 32, 35, 7, 0, 1, 2, 3, 8, 5, 6, 11, 7, 9, 10, 4) -#define _move_cube_R2 fastcube( \ - 3, 1, 2, 0, 4, 6, 5, 7, 0, 1, 2, 3, 7, 5, 6, 4, 11, 9, 10, 8) -#define _move_cube_R3 fastcube( \ - 69, 1, 2, 70, 4, 35, 32, 7, 0, 1, 2, 3, 11, 5, 6, 8, 4, 9, 10, 7) -#define _move_cube_L fastcube( \ - 0, 71, 68, 3, 33, 5, 6, 34, 0, 1, 2, 3, 4, 10, 9, 7, 8, 5, 6, 11) -#define _move_cube_L2 fastcube( \ - 0, 2, 1, 3, 7, 5, 6, 4, 0, 1, 2, 3, 4, 6, 5, 7, 8, 10, 9, 11) -#define _move_cube_L3 fastcube( \ - 0, 68, 71, 3, 34, 5, 6, 33, 0, 1, 2, 3, 4, 9, 10, 7, 8, 6, 5, 11) -#define _move_cube_F fastcube( \ - 36, 1, 38, 3, 66, 5, 64, 7, 25, 1, 2, 24, 4, 5, 6, 7, 16, 19, 10, 11) -#define _move_cube_F2 fastcube( \ - 2, 1, 0, 3, 6, 5, 4, 7, 3, 1, 2, 0, 4, 5, 6, 7, 9, 8, 10, 11) -#define _move_cube_F3 fastcube( \ - 38, 1, 36, 3, 64, 5, 66, 7, 24, 1, 2, 25, 4, 5, 6, 7, 19, 16, 10, 11) -#define _move_cube_B fastcube( \ - 0, 37, 2, 39, 4, 67, 6, 65, 0, 27, 26, 3, 4, 5, 6, 7, 8, 9, 17, 18) -#define _move_cube_B2 fastcube( \ - 0, 3, 2, 1, 4, 7, 6, 5, 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 11, 10) -#define _move_cube_B3 fastcube( \ - 0, 39, 2, 37, 4, 65, 6, 67, 0, 26, 27, 3, 4, 5, 6, 7, 8, 9, 18, 17) - -#define _trans_cube_UFr fastcube( \ - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) -#define _trans_cube_UFr_inverse fastcube( \ - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) -#define _trans_cube_ULr fastcube( \ - 4, 5, 7, 6, 1, 0, 2, 3, 5, 4, 7, 6, 0, 1, 2, 3, 25, 26, 27, 24) -#define _trans_cube_ULr_inverse fastcube( \ - 5, 4, 6, 7, 0, 1, 3, 2, 4, 5, 6, 7, 1, 0, 3, 2, 27, 24, 25, 26) -#define _trans_cube_UBr fastcube( \ - 1, 0, 3, 2, 5, 4, 7, 6, 1, 0, 3, 2, 5, 4, 7, 6, 10, 11, 8, 9) -#define _trans_cube_UBr_inverse fastcube( \ - 1, 0, 3, 2, 5, 4, 7, 6, 1, 0, 3, 2, 5, 4, 7, 6, 10, 11, 8, 9) -#define _trans_cube_URr fastcube( \ - 5, 4, 6, 7, 0, 1, 3, 2, 4, 5, 6, 7, 1, 0, 3, 2, 27, 24, 25, 26) -#define _trans_cube_URr_inverse fastcube( \ - 4, 5, 7, 6, 1, 0, 2, 3, 5, 4, 7, 6, 0, 1, 2, 3, 25, 26, 27, 24) -#define _trans_cube_DFr fastcube( \ - 2, 3, 0, 1, 6, 7, 4, 5, 3, 2, 1, 0, 6, 7, 4, 5, 9, 8, 11, 10) -#define _trans_cube_DFr_inverse fastcube( \ - 2, 3, 0, 1, 6, 7, 4, 5, 3, 2, 1, 0, 6, 7, 4, 5, 9, 8, 11, 10) -#define _trans_cube_DLr fastcube( \ - 7, 6, 4, 5, 2, 3, 1, 0, 6, 7, 4, 5, 2, 3, 0, 1, 26, 25, 24, 27) -#define _trans_cube_DLr_inverse fastcube( \ - 7, 6, 4, 5, 2, 3, 1, 0, 6, 7, 4, 5, 2, 3, 0, 1, 26, 25, 24, 27) -#define _trans_cube_DBr fastcube( \ - 3, 2, 1, 0, 7, 6, 5, 4, 2, 3, 0, 1, 7, 6, 5, 4, 11, 10, 9, 8) -#define _trans_cube_DBr_inverse fastcube( \ - 3, 2, 1, 0, 7, 6, 5, 4, 2, 3, 0, 1, 7, 6, 5, 4, 11, 10, 9, 8) -#define _trans_cube_DRr fastcube( \ - 6, 7, 5, 4, 3, 2, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0, 24, 27, 26, 25) -#define _trans_cube_DRr_inverse fastcube( \ - 6, 7, 5, 4, 3, 2, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0, 24, 27, 26, 25) -#define _trans_cube_RUr fastcube( \ - 64, 67, 65, 66, 37, 38, 36, 39, 20, 23, 22, 21, 24, 27, 26, 25, 0, 1, 2, 3) -#define _trans_cube_RUr_inverse fastcube( \ - 32, 34, 35, 33, 70, 68, 69, 71, 8, 9, 10, 11, 16, 19, 18, 17, 20, 23, 22, 21) -#define _trans_cube_RFr fastcube( \ - 38, 37, 36, 39, 64, 67, 66, 65, 24, 27, 26, 25, 23, 20, 21, 22, 19, 16, 17, 18) -#define _trans_cube_RFr_inverse fastcube( \ - 36, 39, 38, 37, 66, 65, 64, 67, 25, 26, 27, 24, 21, 22, 23, 20, 16, 19, 18, 17) -#define _trans_cube_RDr fastcube( \ - 67, 64, 66, 65, 38, 37, 39, 36, 23, 20, 21, 22, 27, 24, 25, 26, 2, 3, 0, 1) -#define _trans_cube_RDr_inverse fastcube( \ - 33, 35, 34, 32, 71, 69, 68, 70, 10, 11, 8, 9, 17, 18, 19, 16, 21, 22, 23, 20) -#define _trans_cube_RBr fastcube( \ - 37, 38, 39, 36, 67, 64, 65, 66, 27, 24, 25, 26, 20, 23, 22, 21, 17, 18, 19, 16) -#define _trans_cube_RBr_inverse fastcube( \ - 37, 38, 39, 36, 67, 64, 65, 66, 27, 24, 25, 26, 20, 23, 22, 21, 17, 18, 19, 16) -#define _trans_cube_LUr fastcube( \ - 65, 66, 64, 67, 36, 39, 37, 38, 21, 22, 23, 20, 26, 25, 24, 27, 1, 0, 3, 2) -#define _trans_cube_LUr_inverse fastcube( \ - 34, 32, 33, 35, 68, 70, 71, 69, 9, 8, 11, 10, 19, 16, 17, 18, 22, 21, 20, 23) -#define _trans_cube_LFr fastcube( \ - 36, 39, 38, 37, 66, 65, 64, 67, 25, 26, 27, 24, 21, 22, 23, 20, 16, 19, 18, 17) -#define _trans_cube_LFr_inverse fastcube( \ - 38, 37, 36, 39, 64, 67, 66, 65, 24, 27, 26, 25, 23, 20, 21, 22, 19, 16, 17, 18) -#define _trans_cube_LDr fastcube( \ - 66, 65, 67, 64, 39, 36, 38, 37, 22, 21, 20, 23, 25, 26, 27, 24, 3, 2, 1, 0) -#define _trans_cube_LDr_inverse fastcube( \ - 35, 33, 32, 34, 69, 71, 70, 68, 11, 10, 9, 8, 18, 17, 16, 19, 23, 20, 21, 22) -#define _trans_cube_LBr fastcube( \ - 39, 36, 37, 38, 65, 66, 67, 64, 26, 25, 24, 27, 22, 21, 20, 23, 18, 17, 16, 19) -#define _trans_cube_LBr_inverse fastcube( \ - 39, 36, 37, 38, 65, 66, 67, 64, 26, 25, 24, 27, 22, 21, 20, 23, 18, 17, 16, 19) -#define _trans_cube_FUr fastcube( \ - 68, 70, 69, 71, 32, 34, 33, 35, 16, 19, 18, 17, 9, 8, 11, 10, 5, 4, 7, 6) -#define _trans_cube_FUr_inverse fastcube( \ - 68, 70, 69, 71, 32, 34, 33, 35, 16, 19, 18, 17, 9, 8, 11, 10, 5, 4, 7, 6) -#define _trans_cube_FRr fastcube( \ - 32, 34, 35, 33, 70, 68, 69, 71, 8, 9, 10, 11, 16, 19, 18, 17, 20, 23, 22, 21) -#define _trans_cube_FRr_inverse fastcube( \ - 64, 67, 65, 66, 37, 38, 36, 39, 20, 23, 22, 21, 24, 27, 26, 25, 0, 1, 2, 3) -#define _trans_cube_FDr fastcube( \ - 70, 68, 71, 69, 34, 32, 35, 33, 19, 16, 17, 18, 8, 9, 10, 11, 7, 6, 5, 4) -#define _trans_cube_FDr_inverse fastcube( \ - 69, 71, 68, 70, 33, 35, 32, 34, 17, 18, 19, 16, 11, 10, 9, 8, 4, 5, 6, 7) -#define _trans_cube_FLr fastcube( \ - 34, 32, 33, 35, 68, 70, 71, 69, 9, 8, 11, 10, 19, 16, 17, 18, 22, 21, 20, 23) -#define _trans_cube_FLr_inverse fastcube( \ - 65, 66, 64, 67, 36, 39, 37, 38, 21, 22, 23, 20, 26, 25, 24, 27, 1, 0, 3, 2) -#define _trans_cube_BUr fastcube( \ - 69, 71, 68, 70, 33, 35, 32, 34, 17, 18, 19, 16, 11, 10, 9, 8, 4, 5, 6, 7) -#define _trans_cube_BUr_inverse fastcube( \ - 70, 68, 71, 69, 34, 32, 35, 33, 19, 16, 17, 18, 8, 9, 10, 11, 7, 6, 5, 4) -#define _trans_cube_BRr fastcube( \ - 35, 33, 32, 34, 69, 71, 70, 68, 11, 10, 9, 8, 18, 17, 16, 19, 23, 20, 21, 22) -#define _trans_cube_BRr_inverse fastcube( \ - 66, 65, 67, 64, 39, 36, 38, 37, 22, 21, 20, 23, 25, 26, 27, 24, 3, 2, 1, 0) -#define _trans_cube_BDr fastcube( \ - 71, 69, 70, 68, 35, 33, 34, 32, 18, 17, 16, 19, 10, 11, 8, 9, 6, 7, 4, 5) -#define _trans_cube_BDr_inverse fastcube( \ - 71, 69, 70, 68, 35, 33, 34, 32, 18, 17, 16, 19, 10, 11, 8, 9, 6, 7, 4, 5) -#define _trans_cube_BLr fastcube( \ - 33, 35, 34, 32, 71, 69, 68, 70, 10, 11, 8, 9, 17, 18, 19, 16, 21, 22, 23, 20) -#define _trans_cube_BLr_inverse fastcube( \ - 67, 64, 66, 65, 38, 37, 39, 36, 23, 20, 21, 22, 27, 24, 25, 26, 2, 3, 0, 1) -#define _trans_cube_UFm fastcube( \ - 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 7, 6, 9, 8, 11, 10) -#define _trans_cube_UFm_inverse fastcube( \ - 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 7, 6, 9, 8, 11, 10) -#define _trans_cube_ULm fastcube( \ - 0, 1, 3, 2, 5, 4, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 24, 27, 26, 25) -#define _trans_cube_ULm_inverse fastcube( \ - 0, 1, 3, 2, 5, 4, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 24, 27, 26, 25) -#define _trans_cube_UBm fastcube( \ - 5, 4, 7, 6, 1, 0, 3, 2, 1, 0, 3, 2, 4, 5, 6, 7, 11, 10, 9, 8) -#define _trans_cube_UBm_inverse fastcube( \ - 5, 4, 7, 6, 1, 0, 3, 2, 1, 0, 3, 2, 4, 5, 6, 7, 11, 10, 9, 8) -#define _trans_cube_URm fastcube( \ - 1, 0, 2, 3, 4, 5, 7, 6, 5, 4, 7, 6, 1, 0, 3, 2, 26, 25, 24, 27) -#define _trans_cube_URm_inverse fastcube( \ - 1, 0, 2, 3, 4, 5, 7, 6, 5, 4, 7, 6, 1, 0, 3, 2, 26, 25, 24, 27) -#define _trans_cube_DFm fastcube( \ - 6, 7, 4, 5, 2, 3, 0, 1, 3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10, 11) -#define _trans_cube_DFm_inverse fastcube( \ - 6, 7, 4, 5, 2, 3, 0, 1, 3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10, 11) -#define _trans_cube_DLm fastcube( \ - 3, 2, 0, 1, 6, 7, 5, 4, 7, 6, 5, 4, 2, 3, 0, 1, 27, 24, 25, 26) -#define _trans_cube_DLm_inverse fastcube( \ - 2, 3, 1, 0, 7, 6, 4, 5, 6, 7, 4, 5, 3, 2, 1, 0, 25, 26, 27, 24) -#define _trans_cube_DBm fastcube( \ - 7, 6, 5, 4, 3, 2, 1, 0, 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9) -#define _trans_cube_DBm_inverse fastcube( \ - 7, 6, 5, 4, 3, 2, 1, 0, 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9) -#define _trans_cube_DRm fastcube( \ - 2, 3, 1, 0, 7, 6, 4, 5, 6, 7, 4, 5, 3, 2, 1, 0, 25, 26, 27, 24) -#define _trans_cube_DRm_inverse fastcube( \ - 3, 2, 0, 1, 6, 7, 5, 4, 7, 6, 5, 4, 2, 3, 0, 1, 27, 24, 25, 26) -#define _trans_cube_RUm fastcube( \ - 68, 71, 69, 70, 33, 34, 32, 35, 21, 22, 23, 20, 25, 26, 27, 24, 0, 1, 2, 3) -#define _trans_cube_RUm_inverse fastcube( \ - 70, 68, 69, 71, 32, 34, 35, 33, 8, 9, 10, 11, 19, 16, 17, 18, 23, 20, 21, 22) -#define _trans_cube_RFm fastcube( \ - 34, 33, 32, 35, 68, 71, 70, 69, 25, 26, 27, 24, 22, 21, 20, 23, 19, 16, 17, 18) -#define _trans_cube_RFm_inverse fastcube( \ - 66, 65, 64, 67, 36, 39, 38, 37, 25, 26, 27, 24, 22, 21, 20, 23, 19, 16, 17, 18) -#define _trans_cube_RDm fastcube( \ - 71, 68, 70, 69, 34, 33, 35, 32, 22, 21, 20, 23, 26, 25, 24, 27, 2, 3, 0, 1) -#define _trans_cube_RDm_inverse fastcube( \ - 71, 69, 68, 70, 33, 35, 34, 32, 10, 11, 8, 9, 18, 17, 16, 19, 22, 21, 20, 23) -#define _trans_cube_RBm fastcube( \ - 33, 34, 35, 32, 71, 68, 69, 70, 26, 25, 24, 27, 21, 22, 23, 20, 17, 18, 19, 16) -#define _trans_cube_RBm_inverse fastcube( \ - 67, 64, 65, 66, 37, 38, 39, 36, 27, 24, 25, 26, 23, 20, 21, 22, 18, 17, 16, 19) -#define _trans_cube_LUm fastcube( \ - 69, 70, 68, 71, 32, 35, 33, 34, 20, 23, 22, 21, 27, 24, 25, 26, 1, 0, 3, 2) -#define _trans_cube_LUm_inverse fastcube( \ - 68, 70, 71, 69, 34, 32, 33, 35, 9, 8, 11, 10, 16, 19, 18, 17, 21, 22, 23, 20) -#define _trans_cube_LFm fastcube( \ - 32, 35, 34, 33, 70, 69, 68, 71, 24, 27, 26, 25, 20, 23, 22, 21, 16, 19, 18, 17) -#define _trans_cube_LFm_inverse fastcube( \ - 64, 67, 66, 65, 38, 37, 36, 39, 24, 27, 26, 25, 20, 23, 22, 21, 16, 19, 18, 17) -#define _trans_cube_LDm fastcube( \ - 70, 69, 71, 68, 35, 32, 34, 33, 23, 20, 21, 22, 24, 27, 26, 25, 3, 2, 1, 0) -#define _trans_cube_LDm_inverse fastcube( \ - 69, 71, 70, 68, 35, 33, 32, 34, 11, 10, 9, 8, 17, 18, 19, 16, 20, 23, 22, 21) -#define _trans_cube_LBm fastcube( \ - 35, 32, 33, 34, 69, 70, 71, 68, 27, 24, 25, 26, 23, 20, 21, 22, 18, 17, 16, 19) -#define _trans_cube_LBm_inverse fastcube( \ - 65, 66, 67, 64, 39, 36, 37, 38, 26, 25, 24, 27, 21, 22, 23, 20, 17, 18, 19, 16) -#define _trans_cube_FUm fastcube( \ - 64, 66, 65, 67, 36, 38, 37, 39, 16, 19, 18, 17, 8, 9, 10, 11, 4, 5, 6, 7) -#define _trans_cube_FUm_inverse fastcube( \ - 32, 34, 33, 35, 68, 70, 69, 71, 16, 19, 18, 17, 8, 9, 10, 11, 4, 5, 6, 7) -#define _trans_cube_FRm fastcube( \ - 36, 38, 39, 37, 66, 64, 65, 67, 9, 8, 11, 10, 16, 19, 18, 17, 21, 22, 23, 20) -#define _trans_cube_FRm_inverse fastcube( \ - 37, 38, 36, 39, 64, 67, 65, 66, 20, 23, 22, 21, 27, 24, 25, 26, 1, 0, 3, 2) -#define _trans_cube_FDm fastcube( \ - 66, 64, 67, 65, 38, 36, 39, 37, 19, 16, 17, 18, 9, 8, 11, 10, 6, 7, 4, 5) -#define _trans_cube_FDm_inverse fastcube( \ - 33, 35, 32, 34, 69, 71, 68, 70, 17, 18, 19, 16, 10, 11, 8, 9, 5, 4, 7, 6) -#define _trans_cube_FLm fastcube( \ - 38, 36, 37, 39, 64, 66, 67, 65, 8, 9, 10, 11, 19, 16, 17, 18, 23, 20, 21, 22) -#define _trans_cube_FLm_inverse fastcube( \ - 36, 39, 37, 38, 65, 66, 64, 67, 21, 22, 23, 20, 25, 26, 27, 24, 0, 1, 2, 3) -#define _trans_cube_BUm fastcube( \ - 65, 67, 64, 66, 37, 39, 36, 38, 17, 18, 19, 16, 10, 11, 8, 9, 5, 4, 7, 6) -#define _trans_cube_BUm_inverse fastcube( \ - 34, 32, 35, 33, 70, 68, 71, 69, 19, 16, 17, 18, 9, 8, 11, 10, 6, 7, 4, 5) -#define _trans_cube_BRm fastcube( \ - 39, 37, 36, 38, 65, 67, 66, 64, 10, 11, 8, 9, 18, 17, 16, 19, 22, 21, 20, 23) -#define _trans_cube_BRm_inverse fastcube( \ - 39, 36, 38, 37, 66, 65, 67, 64, 22, 21, 20, 23, 26, 25, 24, 27, 2, 3, 0, 1) -#define _trans_cube_BDm fastcube( \ - 67, 65, 66, 64, 39, 37, 38, 36, 18, 17, 16, 19, 11, 10, 9, 8, 7, 6, 5, 4) -#define _trans_cube_BDm_inverse fastcube( \ - 35, 33, 34, 32, 71, 69, 70, 68, 18, 17, 16, 19, 11, 10, 9, 8, 7, 6, 5, 4) -#define _trans_cube_BLm fastcube( \ - 37, 39, 38, 36, 67, 65, 64, 66, 11, 10, 9, 8, 17, 18, 19, 16, 20, 23, 22, 21) -#define _trans_cube_BLm_inverse fastcube( \ - 38, 37, 39, 36, 67, 64, 66, 65, 23, 20, 21, 22, 24, 27, 26, 25, 3, 2, 1, 0) - _static const char *cornerstr[] = { [_c_ufr] = "UFR", [_c_ubl] = "UBL", diff --git a/src/cube.c b/src/cube.c @@ -19,7 +19,6 @@ #define DBG_ASSERT(condition, retval, ...) #endif -#include "cube.h" #include "constants.h" #if defined(CUBE_AVX2) @@ -32,8 +31,17 @@ #include "cube_portable.h" #endif -#include "cube_routines.h" -#include "cube_transform.h" /* TODO: merge with cube_routines? */ +#include "constant_cubes.h" +#include "cube_generic.h" + +/* TODO: work in progress */ +#if 0 +#include "constant_cubes_transform.h" +#include "cube_transform.h" +#else +#include "cube_transform_with_switch.h" +#endif + #include "moves.h" #include "solve_h48.h" #include "solve_generic.h" diff --git a/src/cube.h b/src/cube.h @@ -25,23 +25,6 @@ you operate on the cube only via the functions provided below, you don't need to worry about this. ******************************************************************************/ -typedef struct { - uint8_t corner[8]; - uint8_t edge[12]; -} cube_t; - -/* Returns a copy of the solved cube */ -cube_t solvedcube(void); - -/* Basic checks on the cube */ -bool isconsistent(cube_t); -bool issolvable(cube_t); -bool issolved(cube_t); -bool equal(cube_t, cube_t); - -/* All functions can return an error value, use iserror() to check this */ -bool iserror(cube_t); - /* Apply the second cube on the first as a move sequence */ cube_t compose(cube_t, cube_t); diff --git a/src/cube_avx2.h b/src/cube_avx2.h @@ -1,4 +1,4 @@ -typedef __m256i cube_fast_t; +typedef __m256i cube_t; #define _co2_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060)) #define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020)) @@ -8,117 +8,47 @@ typedef __m256i cube_fast_t; #define _eo_avx2 \ _mm256_set_epi64x(INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0) -_static_inline cube_fast_t fastcube( - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t -); -_static uint8_t corner(cube_fast_t, int); -_static uint8_t edge(cube_fast_t, int); -_static cube_fast_t cubetofast(cube_t); -_static cube_t fasttocube(cube_fast_t); -_static_inline bool equal_fast(cube_fast_t, cube_fast_t); -_static_inline bool issolved_fast(cube_fast_t); -_static_inline cube_fast_t invertco_fast(cube_fast_t); -_static_inline cube_fast_t compose_epcpeo(cube_fast_t, cube_fast_t); -_static_inline cube_fast_t compose_fast_edges(cube_fast_t, cube_fast_t); -_static_inline cube_fast_t compose_fast_corners(cube_fast_t, cube_fast_t); -_static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); - -_static_inline int64_t coord_fast_co(cube_fast_t); -_static_inline int64_t coord_fast_csep(cube_fast_t); -_static_inline int64_t coord_fast_cocsep(cube_fast_t); -_static_inline int64_t coord_fast_eo(cube_fast_t); -_static_inline int64_t coord_fast_esep(cube_fast_t); - -_static_inline void copy_corners_fast(cube_fast_t *, cube_fast_t); -_static_inline void copy_edges_fast(cube_fast_t *, cube_fast_t); -_static_inline void set_eo_fast(cube_fast_t *, int64_t); -_static_inline cube_fast_t invcoord_fast_esep(int64_t); - -_static_inline cube_fast_t -fastcube( - uint8_t c_ufr, - uint8_t c_ubl, - uint8_t c_dfl, - uint8_t c_dbr, - uint8_t c_ufl, - uint8_t c_ubr, - uint8_t c_dfr, - uint8_t c_dbl, - - uint8_t e_uf, - uint8_t e_ub, - uint8_t e_db, - uint8_t e_df, - uint8_t e_ur, - uint8_t e_ul, - uint8_t e_dl, - uint8_t e_dr, - uint8_t e_fr, - uint8_t e_fl, - uint8_t e_bl, - uint8_t e_br -) -{ - return _mm256_set_epi8( - 0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, - e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, - 0, 0, 0, 0, 0, 0, 0, 0, - c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr - ); -} - -_static uint8_t -corner(cube_fast_t c, int i) -{ - uint8_t aux[32]; - - DBG_ASSERT(i >= 0 && i < 8, 255, "Corner must be between 0 and 7\n"); - _mm256_storeu_si256((__m256i_u *)aux, c); - - return aux[i]; -} - -_static uint8_t -edge(cube_fast_t c, int i) +#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ + e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ + _mm256_set_epi8(0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, \ + e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr) +#define zero _mm256_set_epi64x(0, 0, 0, 0) +#define solved static_cube( \ + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + +_static void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]); +_static_inline bool equal(cube_t, cube_t); +_static_inline cube_t invertco(cube_t); +_static_inline cube_t compose_epcpeo(cube_t, cube_t); +_static_inline cube_t compose_edges(cube_t, cube_t); +_static_inline cube_t compose_corners(cube_t, cube_t); +_static_inline cube_t compose(cube_t, cube_t); + +_static_inline int64_t coord_co(cube_t); +_static_inline int64_t coord_csep(cube_t); +_static_inline int64_t coord_cocsep(cube_t); +_static_inline int64_t coord_eo(cube_t); +_static_inline int64_t coord_esep(cube_t); + +_static_inline void copy_corners(cube_t *, cube_t); +_static_inline void copy_edges(cube_t *, cube_t); +_static_inline void set_eo(cube_t *, int64_t); +_static_inline cube_t invcoord_esep(int64_t); + +_static void +pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) { uint8_t aux[32]; - DBG_ASSERT(i >= 0 && i < 12, 255, "Edge must be between 0 and 11\n"); - _mm256_storeu_si256((__m256i_u *)aux, c); - - return aux[i+16]; -} - -_static cube_fast_t -cubetofast(cube_t a) -{ - uint8_t aux[32]; - - memset(aux, 0, 32); - memcpy(aux, &a.corner, 8); - memcpy(aux + 16, &a.edge, 12); - - return _mm256_loadu_si256((__m256i_u *)&aux); -} - -_static cube_t -fasttocube(cube_fast_t c) -{ - cube_t a; - uint8_t aux[32]; - - _mm256_storeu_si256((__m256i_u *)aux, c); - memcpy(&a.corner, aux, 8); - memcpy(&a.edge, aux + 16, 12); - - return a; + _mm256_storeu_si256((__m256i_u *)aux, *cube); + memcpy(c, aux, 8); + memcpy(e, aux+16, 12); } _static_inline bool -equal_fast(cube_fast_t c1, cube_fast_t c2) +equal(cube_t c1, cube_t c2) { int32_t mask; __m256i cmp; @@ -129,16 +59,10 @@ equal_fast(cube_fast_t c1, cube_fast_t c2) return mask == ~0; } -_static_inline bool -issolved_fast(cube_fast_t cube) -{ - return equal_fast(cube, solved_fast); -} - -_static_inline cube_fast_t -invertco_fast(cube_fast_t c) +_static_inline cube_t +invertco(cube_t c) { - cube_fast_t co, shleft, shright, summed, newco, cleanco, ret; + cube_t co, shleft, shright, summed, newco, cleanco, ret; co = _mm256_and_si256(c, _co2_avx2); shleft = _mm256_slli_epi32(co, 1); @@ -151,10 +75,10 @@ invertco_fast(cube_fast_t c) return ret; } -_static_inline cube_fast_t -compose_epcpeo(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose_epcpeo(cube_t c1, cube_t c2) { - cube_fast_t b, s, eo2; + cube_t b, s, eo2; /* Permute and clean unused bits */ s = _mm256_shuffle_epi8(c1, c2); @@ -171,27 +95,27 @@ compose_epcpeo(cube_fast_t c1, cube_fast_t c2) return s; } -_static_inline cube_fast_t -compose_fast_edges(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose_edges(cube_t c1, cube_t c2) { return compose_epcpeo(c1, c2); } -_static_inline cube_fast_t -compose_fast_corners(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose_corners(cube_t c1, cube_t c2) { /* * We do a full compose. Minor optimizations are possible, like * saving one instruction by not doing EO, but it should not * be significant. */ - return compose_fast(c1, c2); + return compose(c1, c2); } -_static_inline cube_fast_t -compose_fast(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose(cube_t c1, cube_t c2) { - cube_fast_t s, co1, co2, aux, auy1, auy2, auz1, auz2; + cube_t s, co1, co2, aux, auy1, auy2, auz1, auz2; s = compose_epcpeo(c1, c2); @@ -212,9 +136,9 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) } _static_inline int64_t -coord_fast_co(cube_fast_t c) +coord_co(cube_t c) { - cube_fast_t co; + cube_t co; int64_t mem[4], ret, i, p; co = _mm256_and_si256(c, _co2_avx2); @@ -228,9 +152,9 @@ coord_fast_co(cube_fast_t c) } _static_inline int64_t -coord_fast_csep(cube_fast_t c) +coord_csep(cube_t c) { - cube_fast_t cp, shifted; + cube_t cp, shifted; int64_t mask; cp = _mm256_and_si256(c, _cp_avx2); @@ -241,15 +165,15 @@ coord_fast_csep(cube_fast_t c) } _static_inline int64_t -coord_fast_cocsep(cube_fast_t c) +coord_cocsep(cube_t c) { - return (coord_fast_co(c) << 7) + coord_fast_csep(c); + return (coord_co(c) << 7) + coord_csep(c); } _static_inline int64_t -coord_fast_eo(cube_fast_t c) +coord_eo(cube_t c) { - cube_fast_t eo, shifted; + cube_t eo, shifted; int64_t mask; eo = _mm256_and_si256(c, _eo_avx2); @@ -260,9 +184,9 @@ coord_fast_eo(cube_fast_t c) } _static_inline int64_t -coord_fast_esep(cube_fast_t c) +coord_esep(cube_t c) { - cube_fast_t ep; + cube_t ep; int64_t e, mem[4], i, j, jj, k, l, ret1, ret2, bit1, bit2, is1; ep = _mm256_and_si256(c, _ep_avx2); @@ -291,19 +215,19 @@ coord_fast_esep(cube_fast_t c) } _static_inline void -copy_corners_fast(cube_fast_t *dest, cube_fast_t src) +copy_corners(cube_t *dest, cube_t src) { *dest = _mm256_blend_epi32(*dest, src, 0x0F); } _static_inline void -copy_edges_fast(cube_fast_t *dest, cube_fast_t src) +copy_edges(cube_t *dest, cube_t src) { *dest = _mm256_blend_epi32(*dest, src, 0xF0); } _static_inline void -set_eo_fast(cube_fast_t *cube, int64_t eo) +set_eo(cube_t *cube, int64_t eo) { int64_t eo12, eotop, eobot; __m256i veo; @@ -327,10 +251,10 @@ set_eo_fast(cube_fast_t *cube, int64_t eo) *cube = _mm256_or_si256(*cube, veo); } -_static_inline cube_fast_t -invcoord_fast_esep(int64_t esep) +_static_inline cube_t +invcoord_esep(int64_t esep) { - cube_fast_t eee, ret; + cube_t eee, ret; int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2; uint8_t mem[32]; uint8_t slice[3] = {0}; @@ -356,9 +280,9 @@ invcoord_fast_esep(int64_t esep) mem[i+16] = (slice[s]++) | (uint8_t)(s << 2); } - ret = cubetofast(solved); + ret = solved; eee = _mm256_loadu_si256((__m256i_u *)&mem); - copy_edges_fast(&ret, eee); + copy_edges(&ret, eee); return ret; } diff --git a/src/cube_generic.h b/src/cube_generic.h @@ -0,0 +1,702 @@ +#define _move(M, c) compose(c, _move_cube_ ## M) +#define _premove(M, c) compose(_move_cube_ ## M, c) + +_static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); +_static int permsign(uint8_t *, int); +_static uint8_t readco(const char *); +_static uint8_t readcp(const char *); +_static uint8_t readeo(const char *); +_static uint8_t readep(const char *); +_static cube_t readcube_B32(const char *); +_static cube_t readcube_H48(const char *); +_static uint8_t readpiece_LST(const char **); +_static cube_t readcube_LST(const char *); +_static int writepiece_LST(uint8_t, char *); +_static void writecube_B32(cube_t, char *); +_static void writecube_H48(cube_t, char *); +_static void writecube_LST(cube_t, char *); +_static uint8_t b32toedge(char); +_static uint8_t b32tocorner(char); +_static char edgetob32(uint8_t); +_static char cornertob32(uint8_t); +_static uint8_t readmove(char); +_static uint8_t readmodifier(char); +_static uint8_t readtrans(const char *); +_static int writemoves(uint8_t *, int, char *); +_static void writetrans(uint8_t, char *); +_static cube_t move(cube_t, uint8_t); +_static cube_t transform_edges(cube_t, uint8_t); +_static cube_t transform_corners(cube_t, uint8_t); +_static cube_t transform(cube_t, uint8_t); + +_static struct { + const char *name; + cube_t (*read)(const char *); + void (*write)(cube_t, char *); +} ioformat[] = +{ + { .name = "B32", .read = readcube_B32, .write = writecube_B32 }, + { .name = "LST", .read = readcube_LST, .write = writecube_LST }, + { .name = "H48", .read = readcube_H48, .write = writecube_H48 }, + { .name = "NONE", .read = NULL, .write = NULL }, +}; + +_static_inline cube_t +cubefromarray(uint8_t c[static 8], uint8_t e[static 12]) +{ + return static_cube( + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], + e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], + e[8], e[9], e[10], e[11]); +} + +cube_t +solvedcube(void) +{ + return solved; +} + +bool +isconsistent(cube_t cube) +{ + uint8_t i, p, e, piece, corner[8], edge[12]; + bool found[12]; + + pieces(&cube, corner, edge); + + for (i = 0; i < 12; i++) + found[i] = false; + for (i = 0; i < 12; i++) { + piece = edge[i]; + p = piece & _pbits; + e = piece & _eobit; + if (p >= 12) + goto inconsistent_ep; + if (e != 0 && e != _eobit) + goto inconsistent_eo; + found[p] = true; + } + for (i = 0; i < 12; i++) + if (!found[i]) + goto inconsistent_ep; + + for (i = 0; i < 8; i++) + found[i] = false; + for (i = 0; i < 8; i++) { + piece = corner[i]; + p = piece & _pbits; + e = piece & _cobits; + if (p >= 8) + goto inconsistent_cp; + if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw) + goto inconsistent_co; + found[p] = true; + } + for (i = 0; i < 8; i++) + if (!found[i]) + goto inconsistent_co; + + return true; + +inconsistent_ep: + DBG_LOG("Inconsistent EP\n"); + return false; +inconsistent_cp: + DBG_LOG("Inconsistent CP\n"); + return false; +inconsistent_eo: + DBG_LOG("Inconsistent EO\n"); + return false; +inconsistent_co: + DBG_LOG("Inconsistent CO\n"); + return false; +} + +bool +issolvable(cube_t cube) +{ + uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8]; + + DBG_ASSERT(isconsistent(cube), false, + "issolvable: cube is inconsistent\n"); + + pieces(&cube, corner, edge); + for (i = 0; i < 12; i++) + ep[i] = edge[i] & _pbits; + for (i = 0; i < 8; i++) + cp[i] = corner[i] & _pbits; + + if (permsign(ep, 12) != permsign(cp, 8)) + goto issolvable_parity; + + eo = 0; + for (i = 0; i < 12; i++) { + piece = edge[i]; + eo += (piece & _eobit) >> _eoshift; + } + if (eo % 2 != 0) + goto issolvable_eo; + + co = 0; + for (i = 0; i < 8; i++) { + piece = corner[i]; + co += (piece & _cobits) >> _coshift; + } + if (co % 3 != 0) + goto issolvable_co; + + return true; + +issolvable_parity: + DBG_LOG("EP and CP parities are different\n"); + return false; +issolvable_eo: + DBG_LOG("Odd number of flipped edges\n"); + return false; +issolvable_co: + DBG_LOG("Sum of corner orientation is not multiple of 3\n"); + return false; +} + +bool +issolved(cube_t cube) +{ + return equal(cube, solved); +} + +bool +iserror(cube_t cube) +{ + return equal(cube, zero); +} + +cube_t +inverse(cube_t cube) +{ + uint8_t i, piece, orien, e[12], c[8], edge[12], corner[8]; + + DBG_ASSERT(isconsistent(cube), zero, + "inverse error: inconsistent cube\n"); + + pieces(&cube, corner, edge); + + for (i = 0; i < 12; i++) { + piece = edge[i]; + orien = piece & _eobit; + e[piece & _pbits] = i | orien; + } + + for (i = 0; i < 8; i++) { + piece = corner[i]; + orien = ((piece << 1) | (piece >> 1)) & _cobits2; + c[piece & _pbits] = i | orien; + } + + return cubefromarray(c, e); +} + +cube_t +applymoves(cube_t cube, const char *buf) +{ + uint8_t r, m; + const char *b; + + DBG_ASSERT(isconsistent(cube), zero, + "move error: inconsistent cube\n"); + + for (b = buf; *b != '\0'; b++) { + while (*b == ' ' || *b == '\t' || *b == '\n') + b++; + if (*b == '\0') + goto applymoves_finish; + if ((r = readmove(*b)) == _error) + goto applymoves_error; + if ((m = readmodifier(*(b+1))) != 0) + b++; + cube = move(cube, r + m); + } + +applymoves_finish: + return cube; + +applymoves_error: + DBG_LOG("applymoves error\n"); + return zero; +} + +cube_t +applytrans(cube_t cube, const char *buf) +{ + uint8_t t; + + DBG_ASSERT(isconsistent(cube), zero, + "transformation error: inconsistent cube\n"); + + t = readtrans(buf); + + return transform(cube, t); +} + +cube_t +readcube(const char *format, const char *buf) +{ + int i; + + for (i = 0; ioformat[i].read != NULL; i++) + if (!strcmp(format, ioformat[i].name)) + return ioformat[i].read(buf); + + DBG_LOG("Cannot read cube in the given format\n"); + return zero; +} + +void +writecube(const char *format, cube_t cube, char *buf) +{ + char *errormsg; + size_t len; + + if (!isconsistent(cube)) { + errormsg = "ERROR: cannot write inconsistent cube"; + goto writecube_error; + } + + int i; + + for (i = 0; ioformat[i].write != NULL; i++) { + if (!strcmp(format, ioformat[i].name)) { + ioformat[i].write(cube, buf); + return; + } + } + + errormsg = "ERROR: cannot write cube in the given format"; + +writecube_error: + DBG_LOG("writecube error, see stdout for details\n"); + len = strlen(errormsg); + memcpy(buf, errormsg, len); + buf[len] = '\n'; + buf[len+1] = '\0'; +} + +_static int +permsign(uint8_t *a, int n) +{ + int i, j; + uint8_t ret = 0; + + for (i = 0; i < n; i++) + for (j = i+1; j < n; j++) + ret += a[i] > a[j] ? 1 : 0; + + return ret % 2; +} + +_static uint8_t +readco(const char *str) +{ + if (*str == '0') + return 0; + if (*str == '1') + return _ctwist_cw; + if (*str == '2') + return _ctwist_ccw; + + DBG_LOG("Error reading CO\n"); + return _error; +} + +_static uint8_t +readcp(const char *str) +{ + uint8_t c; + + for (c = 0; c < 8; c++) + if (!strncmp(str, cornerstr[c], 3) || + !strncmp(str, cornerstralt[c], 3)) + return c; + + DBG_LOG("Error reading CP\n"); + return _error; +} + +_static uint8_t +readeo(const char *str) +{ + if (*str == '0') + return 0; + if (*str == '1') + return _eflip; + + DBG_LOG("Error reading EO\n"); + return _error; +} + +_static uint8_t +readep(const char *str) +{ + uint8_t e; + + for (e = 0; e < 12; e++) + if (!strncmp(str, edgestr[e], 2)) + return e; + + DBG_LOG("Error reading EP\n"); + return _error; +} + +_static cube_t +readcube_B32(const char *buf) +{ + int i; + uint8_t c[8], e[12]; + + for (i = 0; i < 8; i++) { + c[i] = b32tocorner(buf[i]); + DBG_ASSERT(c[i] < 255, zero, + "Error reading B32 corner %d (char %d)\n", i, i); + } + + for (i = 0; i < 12; i++) { + e[i] = b32toedge(buf[i+9]); + DBG_ASSERT(e[i] < 255, zero, + "Error reading B32 edge %d (char %d)\n", i, i+9); + } + + return cubefromarray(c, e); +} + +_static cube_t +readcube_H48(const char *buf) +{ + int i; + uint8_t piece, orient, c[8], e[12]; + const char *b; + + b = buf; + + for (i = 0; i < 12; i++) { + while (*b == ' ' || *b == '\t' || *b == '\n') + b++; + if ((piece = readep(b)) == _error) + return zero; + b += 2; + if ((orient = readeo(b)) == _error) + return zero; + b++; + e[i] = piece | orient; + } + for (i = 0; i < 8; i++) { + while (*b == ' ' || *b == '\t' || *b == '\n') + b++; + if ((piece = readcp(b)) == _error) + return zero; + b += 3; + if ((orient = readco(b)) == _error) + return zero; + b++; + c[i] = piece | orient; + } + + return cubefromarray(c, e); +} + +_static uint8_t +readpiece_LST(const char **b) +{ + uint8_t ret; + bool read; + + while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n') + (*b)++; + + for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) { + read = true; + ret = ret * 10 + (**b) - '0'; + } + + return read ? ret : _error; +} + +_static cube_t +readcube_LST(const char *buf) +{ + int i; + uint8_t c[8], e[12]; + + for (i = 0; i < 8; i++) + c[i] = readpiece_LST(&buf); + + for (i = 0; i < 12; i++) + e[i] = readpiece_LST(&buf); + + return cubefromarray(c, e); +} + +_static int +writepiece_LST(uint8_t piece, char *buf) +{ + char digits[3]; + int i, len; + + len = 0; + while (piece != 0) { + digits[len++] = (piece % 10) + '0'; + piece /= 10; + } + + if (len == 0) + digits[len++] = '0'; + + for (i = 0; i < len; i++) + buf[i] = digits[len-i-1]; + + buf[len] = ','; + buf[len+1] = ' '; + + return len+2; +} + +_static void +writecube_B32(cube_t cube, char *buf) +{ + int i; + uint8_t corner[8], edge[12]; + + pieces(&cube, corner, edge); + + for (i = 0; i < 8; i++) + buf[i] = cornertob32(corner[i]); + + buf[8] = '='; + + for (i = 0; i < 12; i++) + buf[i+9] = edgetob32(edge[i]); + + buf[21] = '\0'; +} + +_static void +writecube_H48(cube_t cube, char *buf) +{ + uint8_t piece, perm, orient, corner[8], edge[12]; + int i; + + pieces(&cube, corner, edge); + + for (i = 0; i < 12; i++) { + piece = edge[i]; + perm = piece & _pbits; + orient = (piece & _eobit) >> _eoshift; + buf[4*i ] = edgestr[perm][0]; + buf[4*i + 1] = edgestr[perm][1]; + buf[4*i + 2] = orient + '0'; + buf[4*i + 3] = ' '; + } + for (i = 0; i < 8; i++) { + piece = corner[i]; + perm = piece & _pbits; + orient = (piece & _cobits) >> _coshift; + buf[48 + 5*i ] = cornerstr[perm][0]; + buf[48 + 5*i + 1] = cornerstr[perm][1]; + buf[48 + 5*i + 2] = cornerstr[perm][2]; + buf[48 + 5*i + 3] = orient + '0'; + buf[48 + 5*i + 4] = ' '; + } + + buf[48+39] = '\0'; +} + +_static void +writecube_LST(cube_t cube, char *buf) +{ + int i; + size_t ptr; + uint8_t piece, corner[8], edge[12]; + + ptr = 0; + pieces(&cube, corner, edge); + + for (i = 0; i < 8; i++) { + piece = corner[i]; + ptr += writepiece_LST(piece, buf + ptr); + } + + for (i = 0; i < 12; i++) { + piece = edge[i]; + ptr += writepiece_LST(piece, buf + ptr); + } + + *(buf+ptr-2) = 0; +} + +_static uint8_t +b32toedge(char c) +{ + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g')) + return 255; + + return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a'); +} + +_static uint8_t +b32tocorner(char c) { + uint8_t val; + + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g')) + return 255; + + val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; + + return (val & 7) | ((val & 24) << 2); +} + +_static char +edgetob32(uint8_t edge) +{ + return edge <= 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26); +} + +_static char +cornertob32(uint8_t corner) +{ + uint8_t val; + + val = (corner & 7) | ((corner & 96) >> 2); + + return val <= 26 ? 'A' + (char)val : 'a' + (char)(val - 26); +} + +_static uint8_t +readmove(char c) +{ + switch (c) { + case 'U': + return _move_U; + case 'D': + return _move_D; + case 'R': + return _move_R; + case 'L': + return _move_L; + case 'F': + return _move_F; + case 'B': + return _move_B; + default: + return _error; + } +} + +_static uint8_t +readmodifier(char c) +{ + switch (c) { + case '1': /* Fallthrough */ + case '2': /* Fallthrough */ + case '3': + return c - '0' - 1; + case '\'': + return 2; + default: + return 0; + } +} + +_static uint8_t +readtrans(const char *buf) +{ + uint8_t t; + + for (t = 0; t < 48; t++) + if (!strncmp(buf, transstr[t], 11)) + return t; + + DBG_LOG("readtrans error\n"); + return _error; +} + +_static int +writemoves(uint8_t *m, int n, char *buf) +{ + int i; + size_t len; + const char *s; + char *b; + + for (i = 0, b = buf; i < n; i++, b++) { + s = movestr[m[i]]; + len = strlen(s); + memcpy(b, s, len); + b += len; + *b = ' '; + } + + if (b != buf) + b--; /* Remove last space */ + *b = '\0'; + + return b - buf; +} + +_static void +writetrans(uint8_t t, char *buf) +{ + if (t >= 48) + memcpy(buf, "error trans", 11); + else + memcpy(buf, transstr[t], 11); + buf[11] = '\0'; +} + +_static cube_t +move(cube_t c, uint8_t m) +{ + switch (m) { + case _move_U: + return _move(U, c); + case _move_U2: + return _move(U2, c); + case _move_U3: + return _move(U3, c); + case _move_D: + return _move(D, c); + case _move_D2: + return _move(D2, c); + case _move_D3: + return _move(D3, c); + case _move_R: + return _move(R, c); + case _move_R2: + return _move(R2, c); + case _move_R3: + return _move(R3, c); + case _move_L: + return _move(L, c); + case _move_L2: + return _move(L2, c); + case _move_L3: + return _move(L3, c); + case _move_F: + return _move(F, c); + case _move_F2: + return _move(F2, c); + case _move_F3: + return _move(F3, c); + case _move_B: + return _move(B, c); + case _move_B2: + return _move(B2, c); + case _move_B3: + return _move(B3, c); + default: + DBG_LOG("move error, unknown move\n"); + return zero; + } +} + +/* +TODO transform is now relegated to a separated file because it is too long. +It would be nice to make it shorter without loosing performance. +*/ diff --git a/src/cube_neon.h b/src/cube_neon.h @@ -3,4 +3,4 @@ typedef struct { uint8x16_t corner; uint8x16_t edge; -} cube_fast_t; +} cube_t; diff --git a/src/cube_portable.h b/src/cube_portable.h @@ -1,109 +1,48 @@ typedef struct { uint8_t corner[8]; uint8_t edge[12]; -} cube_fast_t; - -_static_inline cube_fast_t fastcube( - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t -); -_static uint8_t corner(cube_fast_t, int); -_static uint8_t edge(cube_fast_t, int); -_static cube_fast_t cubetofast(cube_t); -_static cube_t fasttocube(cube_fast_t); -_static_inline bool equal_fast(cube_fast_t, cube_fast_t); -_static_inline bool issolved_fast(cube_fast_t); -_static_inline cube_fast_t invertco_fast(cube_fast_t); -_static_inline void compose_edges_inplace(cube_fast_t, cube_fast_t, cube_fast_t *); -_static_inline void compose_corners_inplace(cube_fast_t, cube_fast_t, cube_fast_t *); -_static_inline cube_fast_t compose_fast_edges(cube_fast_t, cube_fast_t); -_static_inline cube_fast_t compose_fast_corners(cube_fast_t, cube_fast_t); -_static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); - -_static_inline int64_t coord_fast_co(cube_fast_t); -_static_inline int64_t coord_fast_csep(cube_fast_t); -_static_inline int64_t coord_fast_cocsep(cube_fast_t); -_static_inline int64_t coord_fast_eo(cube_fast_t); -_static_inline int64_t coord_fast_esep(cube_fast_t); - -_static_inline void copy_corners_fast(cube_fast_t *, cube_fast_t); -_static_inline void copy_edges_fast(cube_fast_t *, cube_fast_t); -_static_inline void set_eo_fast(cube_fast_t *, int64_t); -_static_inline cube_fast_t invcoord_fast_esep(int64_t); - -_static_inline cube_fast_t -fastcube( - uint8_t c_ufr, - uint8_t c_ubl, - uint8_t c_dfl, - uint8_t c_dbr, - uint8_t c_ufl, - uint8_t c_ubr, - uint8_t c_dfr, - uint8_t c_dbl, - - uint8_t e_uf, - uint8_t e_ub, - uint8_t e_db, - uint8_t e_df, - uint8_t e_ur, - uint8_t e_ul, - uint8_t e_dl, - uint8_t e_dr, - uint8_t e_fr, - uint8_t e_fl, - uint8_t e_bl, - uint8_t e_br -) +} cube_t; + +#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ + e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ + ((cube_t) { \ + .corner = { c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl }, \ + .edge = { e_uf, e_ub, e_db, e_df, e_ur, e_ul, \ + e_dl, e_dr, e_fr, e_fl, e_bl, e_br } }) +#define zero static_cube( \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +#define solved static_cube( \ + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + +_static void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]); +_static_inline bool equal(cube_t, cube_t); +_static_inline cube_t invertco(cube_t); +_static_inline void compose_edges_inplace(cube_t, cube_t, cube_t *); +_static_inline void compose_corners_inplace(cube_t, cube_t, cube_t *); +_static_inline cube_t compose_edges(cube_t, cube_t); +_static_inline cube_t compose_corners(cube_t, cube_t); +_static_inline cube_t compose(cube_t, cube_t); + +_static_inline int64_t coord_co(cube_t); +_static_inline int64_t coord_csep(cube_t); +_static_inline int64_t coord_cocsep(cube_t); +_static_inline int64_t coord_eo(cube_t); +_static_inline int64_t coord_esep(cube_t); + +_static_inline void copy_corners(cube_t *, cube_t); +_static_inline void copy_edges(cube_t *, cube_t); +_static_inline void set_eo(cube_t *, int64_t); +_static_inline cube_t invcoord_esep(int64_t); + +_static void +pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) { - cube_fast_t cube = { - .corner = { - c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl - }, - .edge = { - e_uf, e_ub, e_db, e_df, e_ur, e_ul, - e_dl, e_dr, e_fr, e_fl, e_bl, e_br - } - }; - - return cube; -} - -_static uint8_t -corner(cube_fast_t c, int i) -{ - DBG_ASSERT(i >= 0 && i < 8, 255, "Corner must be between 0 and 7\n"); - - return c.corner[i]; -} -_static uint8_t -edge(cube_fast_t c, int i) -{ - DBG_ASSERT(i >= 0 && i < 12, 255, "Edge must be between 0 and 11\n"); - - return c.edge[i]; -} - -_static cube_fast_t -cubetofast(cube_t cube) -{ - cube_fast_t fast; - memcpy(&fast, &cube, sizeof(cube_fast_t)); - return fast; -} - -_static cube_t -fasttocube(cube_fast_t fast) -{ - cube_t cube; - memcpy(&cube, &fast, sizeof(cube_fast_t)); - return cube; + memcpy(c, cube->corner, 8); + memcpy(e, cube->edge, 12); } _static_inline bool -equal_fast(cube_fast_t c1, cube_fast_t c2) +equal(cube_t c1, cube_t c2) { uint8_t i; bool ret; @@ -117,17 +56,11 @@ equal_fast(cube_fast_t c1, cube_fast_t c2) return ret; } -_static_inline bool -issolved_fast(cube_fast_t cube) -{ - return equal_fast(cube, solved_fast); -} - -_static_inline cube_fast_t -invertco_fast(cube_fast_t c) +_static_inline cube_t +invertco(cube_t c) { uint8_t i, piece, orien; - cube_fast_t ret; + cube_t ret; ret = c; for (i = 0; i < 8; i++) { @@ -140,7 +73,7 @@ invertco_fast(cube_fast_t c) } _static_inline void -compose_edges_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) +compose_edges_inplace(cube_t c1, cube_t c2, cube_t *ret) { uint8_t i, piece1, piece2, p, orien; @@ -154,7 +87,7 @@ compose_edges_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) } _static_inline void -compose_corners_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) +compose_corners_inplace(cube_t c1, cube_t c2, cube_t *ret) { uint8_t i, piece1, piece2, p, orien, aux, auy; @@ -169,30 +102,30 @@ compose_corners_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) } } -_static_inline cube_fast_t -compose_fast_edges(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose_edges(cube_t c1, cube_t c2) { - cube_fast_t ret = zero_fast; + cube_t ret = zero; compose_edges_inplace(c1, c2, &ret); return ret; } -_static_inline cube_fast_t -compose_fast_corners(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose_corners(cube_t c1, cube_t c2) { - cube_fast_t ret = zero_fast; + cube_t ret = zero; compose_corners_inplace(c1, c2, &ret); return ret; } -_static_inline cube_fast_t -compose_fast(cube_fast_t c1, cube_fast_t c2) +_static_inline cube_t +compose(cube_t c1, cube_t c2) { - cube_fast_t ret = zero_fast; + cube_t ret = zero; compose_edges_inplace(c1, c2, &ret); compose_corners_inplace(c1, c2, &ret); @@ -201,7 +134,7 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) } _static_inline int64_t -coord_fast_co(cube_fast_t c) +coord_co(cube_t c) { int i, p; int64_t ret; @@ -220,7 +153,7 @@ possible. Encoding this as a number from 0 to C(8,4) would save about 40% of space, but we are not going to use this coordinate in large tables. */ _static_inline int64_t -coord_fast_csep(cube_fast_t c) +coord_csep(cube_t c) { int i, p; int64_t ret; @@ -232,13 +165,13 @@ coord_fast_csep(cube_fast_t c) } _static_inline int64_t -coord_fast_cocsep(cube_fast_t c) +coord_cocsep(cube_t c) { - return (coord_fast_co(c) << 7) + coord_fast_csep(c); + return (coord_co(c) << 7) + coord_csep(c); } _static_inline int64_t -coord_fast_eo(cube_fast_t c) +coord_eo(cube_t c) { int i, p; int64_t ret; @@ -254,7 +187,7 @@ We encode the edge separation as a number from 0 to C(12,4)*C(8,4). It can be seen as the composition of two "subset index" coordinates. */ _static_inline int64_t -coord_fast_esep(cube_fast_t c) +coord_esep(cube_t c) { int64_t i, j, jj, k, l, ret1, ret2, bit1, bit2, is1; @@ -286,19 +219,19 @@ coord_fast_esep(cube_fast_t c) } _static_inline void -copy_corners_fast(cube_fast_t *dest, cube_fast_t src) +copy_corners(cube_t *dest, cube_t src) { memcpy(&dest->corner, src.corner, sizeof(src.corner)); } _static_inline void -copy_edges_fast(cube_fast_t *dest, cube_fast_t src) +copy_edges(cube_t *dest, cube_t src) { memcpy(&dest->edge, src.edge, sizeof(src.edge)); } _static_inline void -set_eo_fast(cube_fast_t *cube, int64_t eo) +set_eo(cube_t *cube, int64_t eo) { uint8_t i, sum, flip; @@ -310,14 +243,14 @@ set_eo_fast(cube_fast_t *cube, int64_t eo) cube->edge[0] = (cube->edge[0] & ~_eobit) | (_eobit * (sum % 2)); } -_static_inline cube_fast_t -invcoord_fast_esep(int64_t esep) +_static_inline cube_t +invcoord_esep(int64_t esep) { - cube_fast_t ret; + cube_t ret; int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2; uint8_t slice[3] = {0}; - ret = cubetofast(solved); + ret = solved; set1 = esep % 70; set2 = esep / 70; diff --git a/src/cube_routines.h b/src/cube_routines.h @@ -1,668 +0,0 @@ -#define _move(M, c) compose_fast(c, _move_cube_ ## M) -#define _premove(M, c) compose_fast(_move_cube_ ## M, c) - -_static int permsign(uint8_t *, int); -_static uint8_t readco(const char *); -_static uint8_t readcp(const char *); -_static uint8_t readeo(const char *); -_static uint8_t readep(const char *); -_static cube_t readcube_H48(const char *); -_static uint8_t readpiece_LST(const char **); -_static cube_t readcube_LST(const char *); -_static int writepiece_LST(uint8_t, char *); -_static void writecube_H48(cube_t, char *); -_static void writecube_LST(cube_t, char *); -_static uint8_t b32toedge(char); -_static uint8_t b32tocorner(char); -_static char edgetob32(uint8_t); -_static char cornertob32(uint8_t); -_static uint8_t readmove(char); -_static uint8_t readmodifier(char); -_static uint8_t readtrans(const char *); -_static int writemoves(uint8_t *, int, char *); -_static void writetrans(uint8_t, char *); -_static cube_fast_t move(cube_fast_t, uint8_t); -_static cube_fast_t transform_edges(cube_fast_t, uint8_t); -_static cube_fast_t transform_corners(cube_fast_t, uint8_t); -_static cube_fast_t transform(cube_fast_t, uint8_t); - -cube_t -solvedcube(void) -{ - return solved; -} - -bool -isconsistent(cube_t cube) -{ - uint8_t i, p, e, piece; - bool found[12]; - - for (i = 0; i < 12; i++) - found[i] = false; - for (i = 0; i < 12; i++) { - piece = cube.edge[i]; - p = piece & _pbits; - e = piece & _eobit; - if (p >= 12) - goto inconsistent_ep; - if (e != 0 && e != _eobit) - goto inconsistent_eo; - found[p] = true; - } - for (i = 0; i < 12; i++) - if (!found[i]) - goto inconsistent_ep; - - for (i = 0; i < 8; i++) - found[i] = false; - for (i = 0; i < 8; i++) { - piece = cube.corner[i]; - p = piece & _pbits; - e = piece & _cobits; - if (p >= 8) - goto inconsistent_cp; - if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw) - goto inconsistent_co; - found[p] = true; - } - for (i = 0; i < 8; i++) - if (!found[i]) - goto inconsistent_co; - - return true; - -inconsistent_ep: - DBG_LOG("Inconsistent EP\n"); - return false; -inconsistent_cp: - DBG_LOG("Inconsistent CP\n"); - return false; -inconsistent_eo: - DBG_LOG("Inconsistent EO\n"); - return false; -inconsistent_co: - DBG_LOG("Inconsistent CO\n"); - return false; -} - -bool -issolvable(cube_t cube) -{ - uint8_t i, eo, co, piece, edges[12], corners[8]; - - DBG_ASSERT(isconsistent(cube), false, - "issolvable: cube is inconsistent\n"); - - for (i = 0; i < 12; i++) - edges[i] = cube.edge[i] & _pbits; - for (i = 0; i < 8; i++) - corners[i] = cube.corner[i] & _pbits; - - if (permsign(edges, 12) != permsign(corners, 8)) - goto issolvable_parity; - - eo = 0; - for (i = 0; i < 12; i++) { - piece = cube.edge[i]; - eo += (piece & _eobit) >> _eoshift; - } - if (eo % 2 != 0) - goto issolvable_eo; - - co = 0; - for (i = 0; i < 8; i++) { - piece = cube.corner[i]; - co += (piece & _cobits) >> _coshift; - } - if (co % 3 != 0) - goto issolvable_co; - - return true; - -issolvable_parity: - DBG_LOG("EP and CP parities are different\n"); - return false; -issolvable_eo: - DBG_LOG("Odd number of flipped edges\n"); - return false; -issolvable_co: - DBG_LOG("Sum of corner orientation is not multiple of 3\n"); - return false; -} - -bool -issolved(cube_t cube) -{ - return equal(cube, solved); -} - -bool -equal(cube_t c1, cube_t c2) -{ - int i; - bool ret; - - ret = true; - for (i = 0; i < 8; i++) - ret = ret && c1.corner[i] == c2.corner[i]; - for (i = 0; i < 12; i++) - ret = ret && c1.edge[i] == c2.edge[i]; - - return ret; -} - -bool -iserror(cube_t cube) -{ - return equal(cube, zero); -} - -cube_t -compose(cube_t c1, cube_t c2) -{ - DBG_ASSERT(isconsistent(c1) && isconsistent(c2), - zero, "compose error: inconsistent cube\n") - - return fasttocube(compose_fast(cubetofast(c1), cubetofast(c2))); -} - -cube_t -inverse(cube_t cube) -{ - cube_t ret; - uint8_t i, piece, orien; - - DBG_ASSERT(isconsistent(cube), zero, - "inverse error: inconsistent cube\n"); - - ret = zero; - - for (i = 0; i < 12; i++) { - piece = cube.edge[i]; - orien = piece & _eobit; - ret.edge[piece & _pbits] = i | orien; - } - - for (i = 0; i < 8; i++) { - piece = cube.corner[i]; - orien = ((piece << 1) | (piece >> 1)) & _cobits2; - ret.corner[piece & _pbits] = i | orien; - } - - return ret; -} - -cube_t -applymoves(cube_t cube, const char *buf) -{ - cube_fast_t fast; - uint8_t r, m; - const char *b; - - DBG_ASSERT(isconsistent(cube), zero, - "move error: inconsistent cube\n"); - - fast = cubetofast(cube); - - for (b = buf; *b != '\0'; b++) { - while (*b == ' ' || *b == '\t' || *b == '\n') - b++; - if (*b == '\0') - goto applymoves_finish; - if ((r = readmove(*b)) == _error) - goto applymoves_error; - if ((m = readmodifier(*(b+1))) != 0) - b++; - fast = move(fast, r + m); - } - -applymoves_finish: - return fasttocube(fast); - -applymoves_error: - DBG_LOG("applymoves error\n"); - return zero; -} - -cube_t -applytrans(cube_t cube, const char *buf) -{ - cube_fast_t fast; - uint8_t t; - - DBG_ASSERT(isconsistent(cube), zero, - "transformation error: inconsistent cube\n"); - - t = readtrans(buf); - fast = cubetofast(cube); - fast = transform(fast, t); - - return fasttocube(fast); -} - -cube_t -readcube(const char *format, const char *buf) -{ - cube_t cube; - - if (!strcmp(format, "H48")) { - cube = readcube_H48(buf); - } else if (!strcmp(format, "LST")) { - cube = readcube_LST(buf); - } else { - DBG_LOG("Cannot read cube in the given format\n"); - cube = zero; - } - - return cube; -} - -void -writecube(const char *format, cube_t cube, char *buf) -{ - char *errormsg; - size_t len; - - if (!isconsistent(cube)) { - errormsg = "ERROR: cannot write inconsistent cube"; - goto writecube_error; - } - - if (!strcmp(format, "H48")) { - writecube_H48(cube, buf); - } else if (!strcmp(format, "LST")) { - writecube_LST(cube, buf); - } else { - errormsg = "ERROR: cannot write cube in the given format"; - goto writecube_error; - } - - return; - -writecube_error: - DBG_LOG("writecube error, see stdout for details\n"); - len = strlen(errormsg); - memcpy(buf, errormsg, len); - buf[len] = '\n'; - buf[len+1] = '\0'; -} - -_static int -permsign(uint8_t *a, int n) -{ - int i, j; - uint8_t ret = 0; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += a[i] > a[j] ? 1 : 0; - - return ret % 2; -} - -_static uint8_t -readco(const char *str) -{ - if (*str == '0') - return 0; - if (*str == '1') - return _ctwist_cw; - if (*str == '2') - return _ctwist_ccw; - - DBG_LOG("Error reading CO\n"); - return _error; -} - -_static uint8_t -readcp(const char *str) -{ - uint8_t c; - - for (c = 0; c < 8; c++) - if (!strncmp(str, cornerstr[c], 3) || - !strncmp(str, cornerstralt[c], 3)) - return c; - - DBG_LOG("Error reading CP\n"); - return _error; -} - -_static uint8_t -readeo(const char *str) -{ - if (*str == '0') - return 0; - if (*str == '1') - return _eflip; - - DBG_LOG("Error reading EO\n"); - return _error; -} - -_static uint8_t -readep(const char *str) -{ - uint8_t e; - - for (e = 0; e < 12; e++) - if (!strncmp(str, edgestr[e], 2)) - return e; - - DBG_LOG("Error reading EP\n"); - return _error; -} - -_static cube_t -readcube_H48(const char *buf) -{ - int i; - uint8_t piece, orient; - cube_t ret = {0}; - const char *b; - - b = buf; - - for (i = 0; i < 12; i++) { - while (*b == ' ' || *b == '\t' || *b == '\n') - b++; - if ((piece = readep(b)) == _error) - return zero; - b += 2; - if ((orient = readeo(b)) == _error) - return zero; - b++; - ret.edge[i] = piece | orient; - } - for (i = 0; i < 8; i++) { - while (*b == ' ' || *b == '\t' || *b == '\n') - b++; - if ((piece = readcp(b)) == _error) - return zero; - b += 3; - if ((orient = readco(b)) == _error) - return zero; - b++; - ret.corner[i] = piece | orient; - } - - return ret; -} - -_static uint8_t -readpiece_LST(const char **b) -{ - uint8_t ret; - bool read; - - while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n') - (*b)++; - - for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) { - read = true; - ret = ret * 10 + (**b) - '0'; - } - - return read ? ret : _error; -} - -_static cube_t -readcube_LST(const char *buf) -{ - int i; - cube_t ret = {0}; - - for (i = 0; i < 8; i++) - ret.corner[i] = readpiece_LST(&buf); - - for (i = 0; i < 12; i++) - ret.edge[i] = readpiece_LST(&buf); - - return ret; -} - -_static int -writepiece_LST(uint8_t piece, char *buf) -{ - char digits[3]; - int i, len; - - len = 0; - while (piece != 0) { - digits[len++] = (piece % 10) + '0'; - piece /= 10; - } - - if (len == 0) - digits[len++] = '0'; - - for (i = 0; i < len; i++) - buf[i] = digits[len-i-1]; - - buf[len] = ','; - buf[len+1] = ' '; - - return len+2; -} - -_static void -writecube_H48(cube_t cube, char *buf) -{ - uint8_t piece, perm, orient; - int i; - - for (i = 0; i < 12; i++) { - piece = cube.edge[i]; - perm = piece & _pbits; - orient = (piece & _eobit) >> _eoshift; - buf[4*i ] = edgestr[perm][0]; - buf[4*i + 1] = edgestr[perm][1]; - buf[4*i + 2] = orient + '0'; - buf[4*i + 3] = ' '; - } - for (i = 0; i < 8; i++) { - piece = cube.corner[i]; - perm = piece & _pbits; - orient = (piece & _cobits) >> _coshift; - buf[48 + 5*i ] = cornerstr[perm][0]; - buf[48 + 5*i + 1] = cornerstr[perm][1]; - buf[48 + 5*i + 2] = cornerstr[perm][2]; - buf[48 + 5*i + 3] = orient + '0'; - buf[48 + 5*i + 4] = ' '; - } - - buf[48+39] = '\0'; -} - -_static void -writecube_LST(cube_t cube, char *buf) -{ - int i; - size_t ptr; - uint8_t piece; - - ptr = 0; - - for (i = 0; i < 8; i++) { - piece = cube.corner[i]; - ptr += writepiece_LST(piece, buf + ptr); - } - - for (i = 0; i < 12; i++) { - piece = cube.edge[i]; - ptr += writepiece_LST(piece, buf + ptr); - } - - *(buf+ptr-2) = 0; -} - -_static uint8_t -b32toedge(char c) -{ - DBG_ASSERT((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'), 255, - "Error reading base32 piece"); - - return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a'); -} - -_static uint8_t -b32tocorner(char c) { - uint8_t val; - - DBG_ASSERT((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'), 255, - "Error reading base32 piece"); - - val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; - - return (val & 7) | ((val & 24) << 2); -} - -_static char -edgetob32(uint8_t edge) -{ - return edge <= 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26); -} - -_static char -cornertob32(uint8_t corner) -{ - uint8_t val; - - val = (corner & 7) | ((corner & 96) >> 2); - - return val <= 26 ? 'A' + (char)val : 'a' + (char)(val - 26); -} - -_static uint8_t -readmove(char c) -{ - switch (c) { - case 'U': - return _move_U; - case 'D': - return _move_D; - case 'R': - return _move_R; - case 'L': - return _move_L; - case 'F': - return _move_F; - case 'B': - return _move_B; - default: - return _error; - } -} - -_static uint8_t -readmodifier(char c) -{ - switch (c) { - case '1': /* Fallthrough */ - case '2': /* Fallthrough */ - case '3': - return c - '0' - 1; - case '\'': - return 2; - default: - return 0; - } -} - -_static uint8_t -readtrans(const char *buf) -{ - uint8_t t; - - for (t = 0; t < 48; t++) - if (!strncmp(buf, transstr[t], 11)) - return t; - - DBG_LOG("readtrans error\n"); - return _error; -} - -_static int -writemoves(uint8_t *m, int n, char *buf) -{ - int i; - size_t len; - const char *s; - char *b; - - for (i = 0, b = buf; i < n; i++, b++) { - s = movestr[m[i]]; - len = strlen(s); - memcpy(b, s, len); - b += len; - *b = ' '; - } - - if (b != buf) - b--; /* Remove last space */ - *b = '\0'; - - return b - buf; -} - -_static void -writetrans(uint8_t t, char *buf) -{ - if (t >= 48) - memcpy(buf, "error trans", 11); - else - memcpy(buf, transstr[t], 11); - buf[11] = '\0'; -} - -_static cube_fast_t -move(cube_fast_t c, uint8_t m) -{ - switch (m) { - case _move_U: - return _move(U, c); - case _move_U2: - return _move(U2, c); - case _move_U3: - return _move(U3, c); - case _move_D: - return _move(D, c); - case _move_D2: - return _move(D2, c); - case _move_D3: - return _move(D3, c); - case _move_R: - return _move(R, c); - case _move_R2: - return _move(R2, c); - case _move_R3: - return _move(R3, c); - case _move_L: - return _move(L, c); - case _move_L2: - return _move(L2, c); - case _move_L3: - return _move(L3, c); - case _move_F: - return _move(F, c); - case _move_F2: - return _move(F2, c); - case _move_F3: - return _move(F3, c); - case _move_B: - return _move(B, c); - case _move_B2: - return _move(B2, c); - case _move_B3: - return _move(B3, c); - default: - DBG_LOG("move error, unknown move\n"); - return zero_fast; - } -} - -/* -TODO transform is now relegated to a separated file because it is too long. -It would be nice to make it shorter without loosing performance. -*/ diff --git a/src/cube_transform.h b/src/cube_transform.h @@ -1,336 +1,176 @@ +/* TODO: remove these macros, if the below works */ + #define _trans_edges_rotation(T, c) \ - compose_fast_edges(compose_fast_edges(_trans_cube_ ## T, c), \ + compose_edges(compose_edges(_trans_cube_ ## T, c), \ _trans_cube_ ## T ## _inverse) #define _trans_edges_mirrored(T, c) _trans_edges_rotation(T, c) #define _trans_corners_rotation(T, c) \ - compose_fast_corners(compose_fast_corners(_trans_cube_ ## T, c), \ + compose_corners(compose_corners(_trans_cube_ ## T, c), \ _trans_cube_ ## T ## _inverse) #define _trans_corners_mirrored(T, c) \ - invertco_fast(compose_fast_corners( \ - compose_fast_corners(_trans_cube_ ## T, c), _trans_cube_ ## T ## _inverse)) + invertco(compose_corners( \ + compose_corners(_trans_cube_ ## T, c), _trans_cube_ ## T ## _inverse)) #define _trans_rotation(T, c) \ - compose_fast(compose_fast(_trans_cube_ ## T, c), \ + compose(compose(_trans_cube_ ## T, c), \ _trans_cube_ ## T ## _inverse) #define _trans_mirrored(T, c) \ - invertco_fast(compose_fast(compose_fast(_trans_cube_ ## T, c), \ + invertco(compose(compose(_trans_cube_ ## T, c), \ _trans_cube_ ## T ## _inverse)) -_static cube_fast_t -transform_edges(cube_fast_t c, uint8_t t) +static cube_t cube_trans_table[48] = { + [_trans_UFr] = _trans_cube_UFr, + [_trans_UFm] = _trans_cube_UFm, + [_trans_ULr] = _trans_cube_URr, + [_trans_ULm] = _trans_cube_ULm, + [_trans_UBr] = _trans_cube_UBr, + [_trans_UBm] = _trans_cube_UBm, + [_trans_URr] = _trans_cube_ULr, + [_trans_URm] = _trans_cube_URm, + [_trans_DFr] = _trans_cube_DFr, + [_trans_DFm] = _trans_cube_DFm, + [_trans_DLr] = _trans_cube_DLr, + [_trans_DLm] = _trans_cube_DRm, + [_trans_DBr] = _trans_cube_DBr, + [_trans_DBm] = _trans_cube_DBm, + [_trans_DRr] = _trans_cube_DRr, + [_trans_DRm] = _trans_cube_DLm, + [_trans_RUr] = _trans_cube_FRr, + [_trans_RUm] = _trans_cube_FLm, + [_trans_RFr] = _trans_cube_LFr, + [_trans_RFm] = _trans_cube_RFm, + [_trans_RDr] = _trans_cube_BLr, + [_trans_RDm] = _trans_cube_BRm, + [_trans_RBr] = _trans_cube_RBr, + [_trans_RBm] = _trans_cube_LBm, + [_trans_LUr] = _trans_cube_FLr, + [_trans_LUm] = _trans_cube_FRm, + [_trans_LFr] = _trans_cube_RFr, + [_trans_LFm] = _trans_cube_LFm, + [_trans_LDr] = _trans_cube_BRr, + [_trans_LDm] = _trans_cube_BLm, + [_trans_LBr] = _trans_cube_LBr, + [_trans_LBm] = _trans_cube_RBm, + [_trans_FUr] = _trans_cube_FUr, + [_trans_FUm] = _trans_cube_FUm, + [_trans_FRr] = _trans_cube_RUr, + [_trans_FRm] = _trans_cube_LUm, + [_trans_FDr] = _trans_cube_BUr, + [_trans_FDm] = _trans_cube_BUm, + [_trans_FLr] = _trans_cube_LUr, + [_trans_FLm] = _trans_cube_RUm, + [_trans_BUr] = _trans_cube_FDr, + [_trans_BUm] = _trans_cube_FDm, + [_trans_BRr] = _trans_cube_LDr, + [_trans_BRm] = _trans_cube_RDm, + [_trans_BDr] = _trans_cube_BDr, + [_trans_BDm] = _trans_cube_BDm, + [_trans_BLr] = _trans_cube_RDr, + [_trans_BLm] = _trans_cube_LDm, +}; + +static cube_t cube_trans_table_inverse[48] = { + [_trans_UFr] = _trans_cube_UFr_inverse, + [_trans_UFm] = _trans_cube_UFm_inverse, + [_trans_ULr] = _trans_cube_URr_inverse, + [_trans_ULm] = _trans_cube_ULm_inverse, + [_trans_UBr] = _trans_cube_UBr_inverse, + [_trans_UBm] = _trans_cube_UBm_inverse, + [_trans_URr] = _trans_cube_ULr_inverse, + [_trans_URm] = _trans_cube_URm_inverse, + [_trans_DFr] = _trans_cube_DFr_inverse, + [_trans_DFm] = _trans_cube_DFm_inverse, + [_trans_DLr] = _trans_cube_DLr_inverse, + [_trans_DLm] = _trans_cube_DRm_inverse, + [_trans_DBr] = _trans_cube_DBr_inverse, + [_trans_DBm] = _trans_cube_DBm_inverse, + [_trans_DRr] = _trans_cube_DRr_inverse, + [_trans_DRm] = _trans_cube_DLm_inverse, + [_trans_RUr] = _trans_cube_FRr_inverse, + [_trans_RUm] = _trans_cube_FLm_inverse, + [_trans_RFr] = _trans_cube_LFr_inverse, + [_trans_RFm] = _trans_cube_RFm_inverse, + [_trans_RDr] = _trans_cube_BLr_inverse, + [_trans_RDm] = _trans_cube_BRm_inverse, + [_trans_RBr] = _trans_cube_RBr_inverse, + [_trans_RBm] = _trans_cube_LBm_inverse, + [_trans_LUr] = _trans_cube_FLr_inverse, + [_trans_LUm] = _trans_cube_FRm_inverse, + [_trans_LFr] = _trans_cube_RFr_inverse, + [_trans_LFm] = _trans_cube_LFm_inverse, + [_trans_LDr] = _trans_cube_BRr_inverse, + [_trans_LDm] = _trans_cube_BLm_inverse, + [_trans_LBr] = _trans_cube_LBr_inverse, + [_trans_LBm] = _trans_cube_RBm_inverse, + [_trans_FUr] = _trans_cube_FUr_inverse, + [_trans_FUm] = _trans_cube_FUm_inverse, + [_trans_FRr] = _trans_cube_RUr_inverse, + [_trans_FRm] = _trans_cube_LUm_inverse, + [_trans_FDr] = _trans_cube_BUr_inverse, + [_trans_FDm] = _trans_cube_BUm_inverse, + [_trans_FLr] = _trans_cube_LUr_inverse, + [_trans_FLm] = _trans_cube_RUm_inverse, + [_trans_BUr] = _trans_cube_FDr_inverse, + [_trans_BUm] = _trans_cube_FDm_inverse, + [_trans_BRr] = _trans_cube_LDr_inverse, + [_trans_BRm] = _trans_cube_RDm_inverse, + [_trans_BDr] = _trans_cube_BDr_inverse, + [_trans_BDm] = _trans_cube_BDm_inverse, + [_trans_BLr] = _trans_cube_RDr_inverse, + [_trans_BLm] = _trans_cube_LDm_inverse, +}; + +_static cube_t +transform_edges(cube_t c, uint8_t t) { - switch (t) { - case _trans_UFr: - return _trans_edges_rotation(UFr, c); - case _trans_ULr: - return _trans_edges_rotation(ULr, c); - case _trans_UBr: - return _trans_edges_rotation(UBr, c); - case _trans_URr: - return _trans_edges_rotation(URr, c); - case _trans_DFr: - return _trans_edges_rotation(DFr, c); - case _trans_DLr: - return _trans_edges_rotation(DLr, c); - case _trans_DBr: - return _trans_edges_rotation(DBr, c); - case _trans_DRr: - return _trans_edges_rotation(DRr, c); - case _trans_RUr: - return _trans_edges_rotation(RUr, c); - case _trans_RFr: - return _trans_edges_rotation(RFr, c); - case _trans_RDr: - return _trans_edges_rotation(RDr, c); - case _trans_RBr: - return _trans_edges_rotation(RBr, c); - case _trans_LUr: - return _trans_edges_rotation(LUr, c); - case _trans_LFr: - return _trans_edges_rotation(LFr, c); - case _trans_LDr: - return _trans_edges_rotation(LDr, c); - case _trans_LBr: - return _trans_edges_rotation(LBr, c); - case _trans_FUr: - return _trans_edges_rotation(FUr, c); - case _trans_FRr: - return _trans_edges_rotation(FRr, c); - case _trans_FDr: - return _trans_edges_rotation(FDr, c); - case _trans_FLr: - return _trans_edges_rotation(FLr, c); - case _trans_BUr: - return _trans_edges_rotation(BUr, c); - case _trans_BRr: - return _trans_edges_rotation(BRr, c); - case _trans_BDr: - return _trans_edges_rotation(BDr, c); - case _trans_BLr: - return _trans_edges_rotation(BLr, c); - case _trans_UFm: - return _trans_edges_mirrored(UFm, c); - case _trans_ULm: - return _trans_edges_mirrored(ULm, c); - case _trans_UBm: - return _trans_edges_mirrored(UBm, c); - case _trans_URm: - return _trans_edges_mirrored(URm, c); - case _trans_DFm: - return _trans_edges_mirrored(DFm, c); - case _trans_DLm: - return _trans_edges_mirrored(DLm, c); - case _trans_DBm: - return _trans_edges_mirrored(DBm, c); - case _trans_DRm: - return _trans_edges_mirrored(DRm, c); - case _trans_RUm: - return _trans_edges_mirrored(RUm, c); - case _trans_RFm: - return _trans_edges_mirrored(RFm, c); - case _trans_RDm: - return _trans_edges_mirrored(RDm, c); - case _trans_RBm: - return _trans_edges_mirrored(RBm, c); - case _trans_LUm: - return _trans_edges_mirrored(LUm, c); - case _trans_LFm: - return _trans_edges_mirrored(LFm, c); - case _trans_LDm: - return _trans_edges_mirrored(LDm, c); - case _trans_LBm: - return _trans_edges_mirrored(LBm, c); - case _trans_FUm: - return _trans_edges_mirrored(FUm, c); - case _trans_FRm: - return _trans_edges_mirrored(FRm, c); - case _trans_FDm: - return _trans_edges_mirrored(FDm, c); - case _trans_FLm: - return _trans_edges_mirrored(FLm, c); - case _trans_BUm: - return _trans_edges_mirrored(BUm, c); - case _trans_BRm: - return _trans_edges_mirrored(BRm, c); - case _trans_BDm: - return _trans_edges_mirrored(BDm, c); - case _trans_BLm: - return _trans_edges_mirrored(BLm, c); - default: - DBG_LOG("transform error, unknown transformation\n"); - return zero_fast; - } + cube_t ret, trans_cube, trans_inv; + + DBG_ASSERT(t < 48, zero, + "transform: invalid transformation %" PRIu8 + ", must be between 0 and 47\n", t); + + trans_cube = cube_trans_table[t]; + trans_inv = cube_trans_table_inverse[t]; + + ret = compose_edges(trans_cube, c); + ret = compose_edges(ret, trans_inv); + + return ret; } -_static cube_fast_t -transform_corners(cube_fast_t c, uint8_t t) +_static cube_t +transform_corners(cube_t c, uint8_t t) { - switch (t) { - case _trans_UFr: - return _trans_corners_rotation(UFr, c); - case _trans_ULr: - return _trans_corners_rotation(ULr, c); - case _trans_UBr: - return _trans_corners_rotation(UBr, c); - case _trans_URr: - return _trans_corners_rotation(URr, c); - case _trans_DFr: - return _trans_corners_rotation(DFr, c); - case _trans_DLr: - return _trans_corners_rotation(DLr, c); - case _trans_DBr: - return _trans_corners_rotation(DBr, c); - case _trans_DRr: - return _trans_corners_rotation(DRr, c); - case _trans_RUr: - return _trans_corners_rotation(RUr, c); - case _trans_RFr: - return _trans_corners_rotation(RFr, c); - case _trans_RDr: - return _trans_corners_rotation(RDr, c); - case _trans_RBr: - return _trans_corners_rotation(RBr, c); - case _trans_LUr: - return _trans_corners_rotation(LUr, c); - case _trans_LFr: - return _trans_corners_rotation(LFr, c); - case _trans_LDr: - return _trans_corners_rotation(LDr, c); - case _trans_LBr: - return _trans_corners_rotation(LBr, c); - case _trans_FUr: - return _trans_corners_rotation(FUr, c); - case _trans_FRr: - return _trans_corners_rotation(FRr, c); - case _trans_FDr: - return _trans_corners_rotation(FDr, c); - case _trans_FLr: - return _trans_corners_rotation(FLr, c); - case _trans_BUr: - return _trans_corners_rotation(BUr, c); - case _trans_BRr: - return _trans_corners_rotation(BRr, c); - case _trans_BDr: - return _trans_corners_rotation(BDr, c); - case _trans_BLr: - return _trans_corners_rotation(BLr, c); - case _trans_UFm: - return _trans_corners_mirrored(UFm, c); - case _trans_ULm: - return _trans_corners_mirrored(ULm, c); - case _trans_UBm: - return _trans_corners_mirrored(UBm, c); - case _trans_URm: - return _trans_corners_mirrored(URm, c); - case _trans_DFm: - return _trans_corners_mirrored(DFm, c); - case _trans_DLm: - return _trans_corners_mirrored(DLm, c); - case _trans_DBm: - return _trans_corners_mirrored(DBm, c); - case _trans_DRm: - return _trans_corners_mirrored(DRm, c); - case _trans_RUm: - return _trans_corners_mirrored(RUm, c); - case _trans_RFm: - return _trans_corners_mirrored(RFm, c); - case _trans_RDm: - return _trans_corners_mirrored(RDm, c); - case _trans_RBm: - return _trans_corners_mirrored(RBm, c); - case _trans_LUm: - return _trans_corners_mirrored(LUm, c); - case _trans_LFm: - return _trans_corners_mirrored(LFm, c); - case _trans_LDm: - return _trans_corners_mirrored(LDm, c); - case _trans_LBm: - return _trans_corners_mirrored(LBm, c); - case _trans_FUm: - return _trans_corners_mirrored(FUm, c); - case _trans_FRm: - return _trans_corners_mirrored(FRm, c); - case _trans_FDm: - return _trans_corners_mirrored(FDm, c); - case _trans_FLm: - return _trans_corners_mirrored(FLm, c); - case _trans_BUm: - return _trans_corners_mirrored(BUm, c); - case _trans_BRm: - return _trans_corners_mirrored(BRm, c); - case _trans_BDm: - return _trans_corners_mirrored(BDm, c); - case _trans_BLm: - return _trans_corners_mirrored(BLm, c); - default: - DBG_LOG("transform error, unknown transformation\n"); - return zero_fast; - } + cube_t ret, trans_cube, trans_inv; + + DBG_ASSERT(t < 48, zero, + "transform: invalid transformation %" PRIu8 + ", must be between 0 and 47\n", t); + + trans_cube = cube_trans_table[t]; + trans_inv = cube_trans_table_inverse[t]; + + ret = compose_corners(trans_cube, c); + ret = compose_corners(ret, trans_inv); + + return t < 24 ? ret : invertco(ret); } -_static cube_fast_t -transform(cube_fast_t c, uint8_t t) +_static cube_t +transform(cube_t c, uint8_t t) { - switch (t) { - case _trans_UFr: - return _trans_rotation(UFr, c); - case _trans_ULr: - return _trans_rotation(ULr, c); - case _trans_UBr: - return _trans_rotation(UBr, c); - case _trans_URr: - return _trans_rotation(URr, c); - case _trans_DFr: - return _trans_rotation(DFr, c); - case _trans_DLr: - return _trans_rotation(DLr, c); - case _trans_DBr: - return _trans_rotation(DBr, c); - case _trans_DRr: - return _trans_rotation(DRr, c); - case _trans_RUr: - return _trans_rotation(RUr, c); - case _trans_RFr: - return _trans_rotation(RFr, c); - case _trans_RDr: - return _trans_rotation(RDr, c); - case _trans_RBr: - return _trans_rotation(RBr, c); - case _trans_LUr: - return _trans_rotation(LUr, c); - case _trans_LFr: - return _trans_rotation(LFr, c); - case _trans_LDr: - return _trans_rotation(LDr, c); - case _trans_LBr: - return _trans_rotation(LBr, c); - case _trans_FUr: - return _trans_rotation(FUr, c); - case _trans_FRr: - return _trans_rotation(FRr, c); - case _trans_FDr: - return _trans_rotation(FDr, c); - case _trans_FLr: - return _trans_rotation(FLr, c); - case _trans_BUr: - return _trans_rotation(BUr, c); - case _trans_BRr: - return _trans_rotation(BRr, c); - case _trans_BDr: - return _trans_rotation(BDr, c); - case _trans_BLr: - return _trans_rotation(BLr, c); - case _trans_UFm: - return _trans_mirrored(UFm, c); - case _trans_ULm: - return _trans_mirrored(ULm, c); - case _trans_UBm: - return _trans_mirrored(UBm, c); - case _trans_URm: - return _trans_mirrored(URm, c); - case _trans_DFm: - return _trans_mirrored(DFm, c); - case _trans_DLm: - return _trans_mirrored(DLm, c); - case _trans_DBm: - return _trans_mirrored(DBm, c); - case _trans_DRm: - return _trans_mirrored(DRm, c); - case _trans_RUm: - return _trans_mirrored(RUm, c); - case _trans_RFm: - return _trans_mirrored(RFm, c); - case _trans_RDm: - return _trans_mirrored(RDm, c); - case _trans_RBm: - return _trans_mirrored(RBm, c); - case _trans_LUm: - return _trans_mirrored(LUm, c); - case _trans_LFm: - return _trans_mirrored(LFm, c); - case _trans_LDm: - return _trans_mirrored(LDm, c); - case _trans_LBm: - return _trans_mirrored(LBm, c); - case _trans_FUm: - return _trans_mirrored(FUm, c); - case _trans_FRm: - return _trans_mirrored(FRm, c); - case _trans_FDm: - return _trans_mirrored(FDm, c); - case _trans_FLm: - return _trans_mirrored(FLm, c); - case _trans_BUm: - return _trans_mirrored(BUm, c); - case _trans_BRm: - return _trans_mirrored(BRm, c); - case _trans_BDm: - return _trans_mirrored(BDm, c); - case _trans_BLm: - return _trans_mirrored(BLm, c); - default: - DBG_LOG("transform error, unknown transformation\n"); - return zero_fast; - } + cube_t ret, trans_cube, trans_inv; + + DBG_ASSERT(t < 48, zero, + "transform: invalid transformation %" PRIu8 + ", must be between 0 and 47\n", t); + + trans_cube = cube_trans_table[t]; + trans_inv = cube_trans_table_inverse[t]; + + ret = compose(trans_cube, c); + ret = compose(ret, trans_inv); + + return t < 24 ? ret : invertco(ret); } diff --git a/src/cube_transform_with_switch.h b/src/cube_transform_with_switch.h @@ -0,0 +1,336 @@ +#define _trans_edges_rotation(T, c) \ + compose_edges(compose_edges(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_edges_mirrored(T, c) _trans_edges_rotation(T, c) + +#define _trans_corners_rotation(T, c) \ + compose_corners(compose_corners(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_corners_mirrored(T, c) \ + invertco(compose_corners( \ + compose_corners(_trans_cube_ ## T, c), _trans_cube_ ## T ## _inverse)) + +#define _trans_rotation(T, c) \ + compose(compose(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_mirrored(T, c) \ + invertco(compose(compose(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse)) + +_static cube_t +transform_edges(cube_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_edges_rotation(UFr, c); + case _trans_ULr: + return _trans_edges_rotation(ULr, c); + case _trans_UBr: + return _trans_edges_rotation(UBr, c); + case _trans_URr: + return _trans_edges_rotation(URr, c); + case _trans_DFr: + return _trans_edges_rotation(DFr, c); + case _trans_DLr: + return _trans_edges_rotation(DLr, c); + case _trans_DBr: + return _trans_edges_rotation(DBr, c); + case _trans_DRr: + return _trans_edges_rotation(DRr, c); + case _trans_RUr: + return _trans_edges_rotation(RUr, c); + case _trans_RFr: + return _trans_edges_rotation(RFr, c); + case _trans_RDr: + return _trans_edges_rotation(RDr, c); + case _trans_RBr: + return _trans_edges_rotation(RBr, c); + case _trans_LUr: + return _trans_edges_rotation(LUr, c); + case _trans_LFr: + return _trans_edges_rotation(LFr, c); + case _trans_LDr: + return _trans_edges_rotation(LDr, c); + case _trans_LBr: + return _trans_edges_rotation(LBr, c); + case _trans_FUr: + return _trans_edges_rotation(FUr, c); + case _trans_FRr: + return _trans_edges_rotation(FRr, c); + case _trans_FDr: + return _trans_edges_rotation(FDr, c); + case _trans_FLr: + return _trans_edges_rotation(FLr, c); + case _trans_BUr: + return _trans_edges_rotation(BUr, c); + case _trans_BRr: + return _trans_edges_rotation(BRr, c); + case _trans_BDr: + return _trans_edges_rotation(BDr, c); + case _trans_BLr: + return _trans_edges_rotation(BLr, c); + case _trans_UFm: + return _trans_edges_mirrored(UFm, c); + case _trans_ULm: + return _trans_edges_mirrored(ULm, c); + case _trans_UBm: + return _trans_edges_mirrored(UBm, c); + case _trans_URm: + return _trans_edges_mirrored(URm, c); + case _trans_DFm: + return _trans_edges_mirrored(DFm, c); + case _trans_DLm: + return _trans_edges_mirrored(DLm, c); + case _trans_DBm: + return _trans_edges_mirrored(DBm, c); + case _trans_DRm: + return _trans_edges_mirrored(DRm, c); + case _trans_RUm: + return _trans_edges_mirrored(RUm, c); + case _trans_RFm: + return _trans_edges_mirrored(RFm, c); + case _trans_RDm: + return _trans_edges_mirrored(RDm, c); + case _trans_RBm: + return _trans_edges_mirrored(RBm, c); + case _trans_LUm: + return _trans_edges_mirrored(LUm, c); + case _trans_LFm: + return _trans_edges_mirrored(LFm, c); + case _trans_LDm: + return _trans_edges_mirrored(LDm, c); + case _trans_LBm: + return _trans_edges_mirrored(LBm, c); + case _trans_FUm: + return _trans_edges_mirrored(FUm, c); + case _trans_FRm: + return _trans_edges_mirrored(FRm, c); + case _trans_FDm: + return _trans_edges_mirrored(FDm, c); + case _trans_FLm: + return _trans_edges_mirrored(FLm, c); + case _trans_BUm: + return _trans_edges_mirrored(BUm, c); + case _trans_BRm: + return _trans_edges_mirrored(BRm, c); + case _trans_BDm: + return _trans_edges_mirrored(BDm, c); + case _trans_BLm: + return _trans_edges_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero; + } +} + +_static cube_t +transform_corners(cube_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_corners_rotation(UFr, c); + case _trans_ULr: + return _trans_corners_rotation(ULr, c); + case _trans_UBr: + return _trans_corners_rotation(UBr, c); + case _trans_URr: + return _trans_corners_rotation(URr, c); + case _trans_DFr: + return _trans_corners_rotation(DFr, c); + case _trans_DLr: + return _trans_corners_rotation(DLr, c); + case _trans_DBr: + return _trans_corners_rotation(DBr, c); + case _trans_DRr: + return _trans_corners_rotation(DRr, c); + case _trans_RUr: + return _trans_corners_rotation(RUr, c); + case _trans_RFr: + return _trans_corners_rotation(RFr, c); + case _trans_RDr: + return _trans_corners_rotation(RDr, c); + case _trans_RBr: + return _trans_corners_rotation(RBr, c); + case _trans_LUr: + return _trans_corners_rotation(LUr, c); + case _trans_LFr: + return _trans_corners_rotation(LFr, c); + case _trans_LDr: + return _trans_corners_rotation(LDr, c); + case _trans_LBr: + return _trans_corners_rotation(LBr, c); + case _trans_FUr: + return _trans_corners_rotation(FUr, c); + case _trans_FRr: + return _trans_corners_rotation(FRr, c); + case _trans_FDr: + return _trans_corners_rotation(FDr, c); + case _trans_FLr: + return _trans_corners_rotation(FLr, c); + case _trans_BUr: + return _trans_corners_rotation(BUr, c); + case _trans_BRr: + return _trans_corners_rotation(BRr, c); + case _trans_BDr: + return _trans_corners_rotation(BDr, c); + case _trans_BLr: + return _trans_corners_rotation(BLr, c); + case _trans_UFm: + return _trans_corners_mirrored(UFm, c); + case _trans_ULm: + return _trans_corners_mirrored(ULm, c); + case _trans_UBm: + return _trans_corners_mirrored(UBm, c); + case _trans_URm: + return _trans_corners_mirrored(URm, c); + case _trans_DFm: + return _trans_corners_mirrored(DFm, c); + case _trans_DLm: + return _trans_corners_mirrored(DLm, c); + case _trans_DBm: + return _trans_corners_mirrored(DBm, c); + case _trans_DRm: + return _trans_corners_mirrored(DRm, c); + case _trans_RUm: + return _trans_corners_mirrored(RUm, c); + case _trans_RFm: + return _trans_corners_mirrored(RFm, c); + case _trans_RDm: + return _trans_corners_mirrored(RDm, c); + case _trans_RBm: + return _trans_corners_mirrored(RBm, c); + case _trans_LUm: + return _trans_corners_mirrored(LUm, c); + case _trans_LFm: + return _trans_corners_mirrored(LFm, c); + case _trans_LDm: + return _trans_corners_mirrored(LDm, c); + case _trans_LBm: + return _trans_corners_mirrored(LBm, c); + case _trans_FUm: + return _trans_corners_mirrored(FUm, c); + case _trans_FRm: + return _trans_corners_mirrored(FRm, c); + case _trans_FDm: + return _trans_corners_mirrored(FDm, c); + case _trans_FLm: + return _trans_corners_mirrored(FLm, c); + case _trans_BUm: + return _trans_corners_mirrored(BUm, c); + case _trans_BRm: + return _trans_corners_mirrored(BRm, c); + case _trans_BDm: + return _trans_corners_mirrored(BDm, c); + case _trans_BLm: + return _trans_corners_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero; + } +} + +_static cube_t +transform(cube_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_rotation(UFr, c); + case _trans_ULr: + return _trans_rotation(ULr, c); + case _trans_UBr: + return _trans_rotation(UBr, c); + case _trans_URr: + return _trans_rotation(URr, c); + case _trans_DFr: + return _trans_rotation(DFr, c); + case _trans_DLr: + return _trans_rotation(DLr, c); + case _trans_DBr: + return _trans_rotation(DBr, c); + case _trans_DRr: + return _trans_rotation(DRr, c); + case _trans_RUr: + return _trans_rotation(RUr, c); + case _trans_RFr: + return _trans_rotation(RFr, c); + case _trans_RDr: + return _trans_rotation(RDr, c); + case _trans_RBr: + return _trans_rotation(RBr, c); + case _trans_LUr: + return _trans_rotation(LUr, c); + case _trans_LFr: + return _trans_rotation(LFr, c); + case _trans_LDr: + return _trans_rotation(LDr, c); + case _trans_LBr: + return _trans_rotation(LBr, c); + case _trans_FUr: + return _trans_rotation(FUr, c); + case _trans_FRr: + return _trans_rotation(FRr, c); + case _trans_FDr: + return _trans_rotation(FDr, c); + case _trans_FLr: + return _trans_rotation(FLr, c); + case _trans_BUr: + return _trans_rotation(BUr, c); + case _trans_BRr: + return _trans_rotation(BRr, c); + case _trans_BDr: + return _trans_rotation(BDr, c); + case _trans_BLr: + return _trans_rotation(BLr, c); + case _trans_UFm: + return _trans_mirrored(UFm, c); + case _trans_ULm: + return _trans_mirrored(ULm, c); + case _trans_UBm: + return _trans_mirrored(UBm, c); + case _trans_URm: + return _trans_mirrored(URm, c); + case _trans_DFm: + return _trans_mirrored(DFm, c); + case _trans_DLm: + return _trans_mirrored(DLm, c); + case _trans_DBm: + return _trans_mirrored(DBm, c); + case _trans_DRm: + return _trans_mirrored(DRm, c); + case _trans_RUm: + return _trans_mirrored(RUm, c); + case _trans_RFm: + return _trans_mirrored(RFm, c); + case _trans_RDm: + return _trans_mirrored(RDm, c); + case _trans_RBm: + return _trans_mirrored(RBm, c); + case _trans_LUm: + return _trans_mirrored(LUm, c); + case _trans_LFm: + return _trans_mirrored(LFm, c); + case _trans_LDm: + return _trans_mirrored(LDm, c); + case _trans_LBm: + return _trans_mirrored(LBm, c); + case _trans_FUm: + return _trans_mirrored(FUm, c); + case _trans_FRm: + return _trans_mirrored(FRm, c); + case _trans_FDm: + return _trans_mirrored(FDm, c); + case _trans_FLm: + return _trans_mirrored(FLm, c); + case _trans_BUm: + return _trans_mirrored(BUm, c); + case _trans_BRm: + return _trans_mirrored(BRm, c); + case _trans_BDm: + return _trans_mirrored(BDm, c); + case _trans_BLm: + return _trans_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero; + } +} diff --git a/src/solve_generic.h b/src/solve_generic.h @@ -1,19 +1,19 @@ typedef struct { - cube_fast_t cube; + cube_t cube; uint8_t depth; int64_t maxsols; char **nextsol; int64_t *nsols; uint8_t nmoves; uint8_t moves[20]; - uint8_t (*estimate)(cube_fast_t); + uint8_t (*estimate)(cube_t); } dfsarg_generic_t; _static void solve_generic_appendsolution(dfsarg_generic_t *); _static int solve_generic_dfs(dfsarg_generic_t *); _static int64_t solve_generic(cube_t, const char *, int8_t, int8_t, int64_t, - int8_t, char *, uint8_t (*)(cube_fast_t)); -_static uint8_t estimate_simple(cube_fast_t); + int8_t, char *, uint8_t (*)(cube_t)); +_static uint8_t estimate_simple(cube_t); _static int64_t solve_simple(cube_t, int8_t, int8_t, int64_t, int8_t, char *); int64_t @@ -135,7 +135,7 @@ solve_generic( int64_t maxsols, int8_t optimal, char *sols, - uint8_t (*estimate)(cube_fast_t) + uint8_t (*estimate)(cube_t) /* TODO: add validator */ /* TODO: maybe add data for estimate */ /* TODO: add moveset (and allowednext?) */ @@ -190,7 +190,7 @@ solve_generic( } arg = (dfsarg_generic_t) { - .cube = cubetofast(cube), + .cube = cube, .maxsols = maxsols, .nextsol = &sols, .nsols = &ret, @@ -223,9 +223,9 @@ solve_generic( } _static uint8_t -estimate_simple(cube_fast_t cube) +estimate_simple(cube_t cube) { - return issolved_fast(cube) ? 0 : 1; + return issolved(cube) ? 0 : 1; } _static int64_t diff --git a/src/solve_h48.h b/src/solve_h48.h @@ -20,14 +20,14 @@ #define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) typedef struct { - cube_fast_t cube; + cube_t cube; uint8_t depth; uint8_t maxdepth; uint16_t *n; uint32_t *buf32; uint8_t *visited; uint64_t *selfsim; - cube_fast_t *rep; + cube_t *rep; } dfsarg_cocsep_t; typedef struct { @@ -36,14 +36,14 @@ typedef struct { uint32_t *cocsepdata; uint32_t *buf32; uint64_t *selfsim; - cube_fast_t *crep; + cube_t *crep; } bfsarg_esep_t; -_static_inline int64_t coord_h48(cube_fast_t, const uint32_t *, uint8_t); -_static_inline int64_t coord_h48_edges(cube_fast_t, int64_t, uint8_t, uint8_t); -_static_inline cube_fast_t invcoord_h48(int64_t, const cube_fast_t *, uint8_t); +_static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); +_static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); +_static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); -_static size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); +_static size_t gendata_cocsep(void *, uint64_t *, cube_t *); _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); _static size_t gendata_h48(void *, uint8_t, uint8_t); _static uint64_t gendata_esep_bfs(bfsarg_esep_t *); @@ -54,7 +54,7 @@ _static_inline uint8_t get_esep_pval(const uint32_t *, int64_t); _static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t); _static_inline int64_t -coord_h48(cube_fast_t c, const uint32_t *cocsepdata, uint8_t h) +coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) { int64_t cocsep, coclass; uint32_t data; @@ -62,7 +62,7 @@ coord_h48(cube_fast_t c, const uint32_t *cocsepdata, uint8_t h) DBG_ASSERT(h <= 11, -1, "coord_h48: h must be between 0 and 11\n"); - cocsep = coord_fast_cocsep(c); + cocsep = coord_cocsep(c); data = cocsepdata[cocsep]; coclass = (int64_t)COCLASS(data); ttrep = (int64_t)TTREP(data); @@ -71,14 +71,14 @@ coord_h48(cube_fast_t c, const uint32_t *cocsepdata, uint8_t h) } _static_inline int64_t -coord_h48_edges(cube_fast_t c, int64_t coclass, uint8_t t, uint8_t h) +coord_h48_edges(cube_t c, int64_t coclass, uint8_t t, uint8_t h) { - cube_fast_t d; + cube_t d; int64_t esep, eo, edges; d = transform_edges(c, t); - esep = coord_fast_esep(d); - eo = coord_fast_eo(d); + esep = coord_esep(d); + eo = coord_eo(d); edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); return coclass * H48_ESIZE(h) + edges; @@ -89,12 +89,12 @@ This function does not necessarily return a cube whose coordinate is the given value, because it works up to symmetry. This means that the returned cube is a transformed cube of one that gives the correct value. */ -_static_inline cube_fast_t -invcoord_h48(int64_t i, const cube_fast_t *crep, uint8_t h) { - cube_fast_t ret; +_static_inline cube_t +invcoord_h48(int64_t i, const cube_t *crep, uint8_t h) { + cube_t ret; int64_t hh, coclass, ee, esep, eo; - DBG_ASSERT(h <= 11, cubetofast(zero), + DBG_ASSERT(h <= 11, zero, "invcoord_h48: h must be between 0 and 11\n"); hh = (int64_t)h; @@ -103,9 +103,9 @@ invcoord_h48(int64_t i, const cube_fast_t *crep, uint8_t h) { esep = ee >> hh; eo = (ee & ((1 << hh) - 1)) << (11 - hh); - ret = invcoord_fast_esep(esep); - copy_corners_fast(&ret, crep[coclass]); - set_eo_fast(&ret, eo); + ret = invcoord_esep(esep); + copy_corners(&ret, crep[coclass]); + set_eo(&ret, eo); return ret; } @@ -122,7 +122,7 @@ After the data as described above, more auxiliary information is appended: of positions having that pruning value. */ _static size_t -gendata_cocsep(void *buf, uint64_t *selfsim, cube_fast_t *rep) +gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) { uint32_t *buf32, *info, cc; uint16_t n; @@ -135,7 +135,7 @@ gendata_cocsep(void *buf, uint64_t *selfsim, cube_fast_t *rep) memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); arg = (dfsarg_cocsep_t) { - .cube = cubetofast(solvedcube()), + .cube = solved, .n = &n, .buf32 = buf32, .visited = visited, @@ -175,10 +175,10 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) uint32_t cc, class, ttrep, depth, olddepth; uint64_t t, is; int64_t i, j; - cube_fast_t d; + cube_t d; dfsarg_cocsep_t nextarg; - i = coord_fast_cocsep(arg->cube); + i = coord_cocsep(arg->cube); olddepth = (uint8_t)(arg->buf32[i] & 0xFF); if (olddepth < arg->depth || get_visited(arg->visited, i)) return 0; @@ -190,7 +190,7 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) for (t = 0, cc = 0; t < 48; t++) { d = transform_corners(arg->cube, t); - j = coord_fast_cocsep(d); + j = coord_cocsep(d); is = (i == j); arg->selfsim[*arg->n] |= is << t; set_visited(arg->visited, j); @@ -231,7 +231,7 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) bfsarg_esep_t arg; int64_t sc, cc, tot, esep_max; uint64_t selfsim[COCSEP_CLASSES]; - cube_fast_t crep[COCSEP_CLASSES]; + cube_t crep[COCSEP_CLASSES]; size_t cocsepsize, infosize; esep_max = (int64_t)ESEP_MAX(h); @@ -241,7 +241,7 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) info = buf32 + (ESEP_TABLESIZE(h, k) / sizeof(uint32_t)); memset(buf32, 0xFF, ESEP_TABLESIZE(h, k)); - sc = coord_h48(cubetofast(solved), cocsepdata, h); + sc = coord_h48(solved, cocsepdata, h); set_esep_pval(buf32, sc, 0); info[1] = 1; arg = (bfsarg_esep_t) { @@ -281,7 +281,7 @@ gendata_esep_bfs(bfsarg_esep_t *arg) uint8_t c, m, x; uint32_t cc; int64_t i, j, k, t, cocsep_coord, sim, esep_max; - cube_fast_t cube, moved, transd; + cube_t cube, moved, transd; esep_max = (uint64_t)ESEP_MAX(arg->h); diff --git a/test/001_pieces/pieces_tests.c b/test/001_pieces/pieces_tests.c @@ -1,13 +1,12 @@ #include "../test.h" -uint8_t corner(cube_fast_t, int); -uint8_t edge(cube_fast_t, int); +void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]); int main(void) { int i; + uint8_t corner[8], edge[12]; char str[STRLENMAX], *aux; cube_t cube; - cube_fast_t fast; aux = str; while (fgets(aux, STRLENMAX, stdin) != NULL) @@ -15,13 +14,13 @@ int main(void) { aux++; cube = readcube("H48", str); - fast = cubetofast(cube); + pieces(&cube, corner, edge); for (i = 0; i < 8; i++) - printf("%" PRIu8 " ", corner(fast, i)); + printf("%" PRIu8 " ", corner[i]); printf("\n"); for (i = 0; i < 12; i++) - printf("%" PRIu8 " ", edge(fast, i)); + printf("%" PRIu8 " ", edge[i]); printf("\n"); return 0; diff --git a/test/002_cube_conversion/00_solved.in b/test/002_cube_conversion/00_solved.in @@ -1 +0,0 @@ -UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 diff --git a/test/002_cube_conversion/00_solved.out b/test/002_cube_conversion/00_solved.out @@ -1 +0,0 @@ -UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 diff --git a/test/002_cube_conversion/01_scrambled.in b/test/002_cube_conversion/01_scrambled.in @@ -1 +0,0 @@ -BL1 DB0 UL1 DF0 BR1 UF1 DL0 FL1 UB0 DR1 FR1 UR1 UBR2 UBL1 DFR2 DBL2 DBR0 DFL0 UFR0 UFL2 diff --git a/test/002_cube_conversion/01_scrambled.out b/test/002_cube_conversion/01_scrambled.out @@ -1 +0,0 @@ -BL1 DB0 UL1 DF0 BR1 UF1 DL0 FL1 UB0 DR1 FR1 UR1 UBR2 UBL1 DFR2 DBL2 DBR0 DFL0 UFR0 UFL2 diff --git a/test/002_cube_conversion/cube_conversion_tests.c b/test/002_cube_conversion/cube_conversion_tests.c @@ -1,25 +0,0 @@ -#include "../test.h" - -bool equal(cube_t, cube_t); - -int main(void) { - char cubestr[STRLENMAX]; - cube_t cube, cube2; - cube_fast_t fast; - - fgets(cubestr, STRLENMAX, stdin); - cube = readcube("H48", cubestr); - fast = cubetofast(cube); - cube2 = fasttocube(fast); - - if (iserror(cube)) { - printf("Error reading cube\n"); - } else if (iserror(cube2)) { - printf("Error converting cube\n"); - } else { - writecube("H48", cube2, cubestr); - printf("%s\n", cubestr); - } - - return 0; -} diff --git a/test/071_coord_eo/coord_eo_tests.c b/test/071_coord_eo/coord_eo_tests.c @@ -1,18 +1,16 @@ #include "../test.h" -int64_t coord_fast_eo(cube_fast_t); +int64_t coord_eo(cube_t); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; int64_t result; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); - result = coord_fast_eo(fast); + result = coord_eo(cube); printf("%" PRId64 "\n", result); diff --git a/test/072_coord_co/coord_co_tests.c b/test/072_coord_co/coord_co_tests.c @@ -1,18 +1,16 @@ #include "../test.h" -int64_t coord_fast_co(cube_fast_t); +int64_t coord_co(cube_t); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; int64_t result; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); - result = coord_fast_co(fast); + result = coord_co(cube); printf("%" PRId64 "\n", result); diff --git a/test/073_coord_csep/coord_csep_tests.c b/test/073_coord_csep/coord_csep_tests.c @@ -1,18 +1,16 @@ #include "../test.h" -int64_t coord_fast_csep(cube_fast_t); +int64_t coord_csep(cube_t); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; int64_t result; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); - result = coord_fast_csep(fast); + result = coord_csep(cube); printf("%" PRId64 "\n", result); diff --git a/test/074_coord_esep/coord_esep_tests.c b/test/074_coord_esep/coord_esep_tests.c @@ -1,18 +1,16 @@ #include "../test.h" -int64_t coord_fast_esep(cube_fast_t); +int64_t coord_esep(cube_t); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; int64_t result; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); - result = coord_fast_esep(fast); + result = coord_esep(cube); printf("%" PRId64 "\n", result); diff --git a/test/075_set_eo/set_eo_tests.c b/test/075_set_eo/set_eo_tests.c @@ -1,32 +1,32 @@ #include "../test.h" -int64_t coord_fast_eo(cube_fast_t); -void set_eo_fast(cube_fast_t *, int64_t); +int64_t coord_eo(cube_t); +void set_eo(cube_t *, int64_t); +void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; + uint8_t edge[12], corner[8]; int64_t eo; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); fgets(str, STRLENMAX, stdin); eo = atoi(str); - set_eo_fast(&fast, eo); + set_eo(&cube, eo); - cube = fasttocube(fast); if (iserror(cube)) { printf("Error setting EO\n"); } else if (!isconsistent(cube)) { + pieces(&cube, corner, edge); fprintf(stderr, "edges: "); for (int i = 0; i < 12; i++) - fprintf(stderr, "%d ", cube.edge[i]); + fprintf(stderr, "%d ", edge[i]); fprintf(stderr, "\n"); for (int i = 0; i < 8; i++) - fprintf(stderr, "%d ", cube.corner[i]); + fprintf(stderr, "%d ", corner[i]); fprintf(stderr, "\n"); printf("Setting EO resulted in inconsistent cube\n"); } else { diff --git a/test/076_copy_corners/copy_corners_tests.c b/test/076_copy_corners/copy_corners_tests.c @@ -1,23 +1,19 @@ #include "../test.h" -void copy_corners_fast(cube_fast_t *, cube_fast_t); +void copy_corners(cube_t *, cube_t); int main(void) { char str[STRLENMAX]; cube_t c1, c2; - cube_fast_t f1, f2; fgets(str, STRLENMAX, stdin); c1 = readcube("H48", str); - f1 = cubetofast(c1); fgets(str, STRLENMAX, stdin); c2 = readcube("H48", str); - f2 = cubetofast(c2); - copy_corners_fast(&f1, f2); + copy_corners(&c1, c2); - c1 = fasttocube(f1); if (iserror(c1)) { printf("Error setting EO\n"); } else if (!isconsistent(c1)) { diff --git a/test/077_copy_edges/copy_edges_tests.c b/test/077_copy_edges/copy_edges_tests.c @@ -1,23 +1,19 @@ #include "../test.h" -void copy_edges_fast(cube_fast_t *, cube_fast_t); +void copy_edges(cube_t *, cube_t); int main(void) { char str[STRLENMAX]; cube_t c1, c2; - cube_fast_t f1, f2; fgets(str, STRLENMAX, stdin); c1 = readcube("H48", str); - f1 = cubetofast(c1); fgets(str, STRLENMAX, stdin); c2 = readcube("H48", str); - f2 = cubetofast(c2); - copy_edges_fast(&f1, f2); + copy_edges(&c1, c2); - c1 = fasttocube(f1); if (iserror(c1)) { printf("Error setting EO\n"); } else if (!isconsistent(c1)) { diff --git a/test/078_invcoord_esep/invcoord_esep_tests.c b/test/078_invcoord_esep/invcoord_esep_tests.c @@ -1,21 +1,19 @@ #include "../test.h" -int64_t coord_fast_esep(cube_fast_t); -cube_fast_t invcoord_fast_esep(int64_t); +int64_t coord_esep(cube_t); +cube_t invcoord_esep(int64_t); int main(void) { char str[STRLENMAX]; cube_t cube; - cube_fast_t fast; int64_t i; fgets(str, STRLENMAX, stdin); cube = readcube("H48", str); - fast = cubetofast(cube); - i = coord_fast_esep(fast); - fast = invcoord_fast_esep(i); - i = coord_fast_esep(fast); + i = coord_esep(cube); + cube = invcoord_esep(i); + i = coord_esep(cube); printf("%" PRId64 "\n", i); diff --git a/test/100_gendata_cocsep/gendata_cocsep_tests.c b/test/100_gendata_cocsep/gendata_cocsep_tests.c @@ -2,12 +2,12 @@ #define COCSEP_CLASSES 3393 -size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); +size_t gendata_cocsep(void *, uint64_t *, cube_t *); int main(void) { uint32_t buf[300000], i; uint64_t selfsim[COCSEP_CLASSES]; - cube_fast_t rep[COCSEP_CLASSES]; + cube_t rep[COCSEP_CLASSES]; size_t result; result = gendata_cocsep(buf, selfsim, rep); diff --git a/test/101_cocsep_selfsim/cocsep_selfsim_tests.c b/test/101_cocsep_selfsim/cocsep_selfsim_tests.c @@ -9,23 +9,23 @@ #define COCSEP_CLASSES 3393 -size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); -int64_t coord_fast_cocsep(cube_fast_t); +size_t gendata_cocsep(void *, uint64_t *, cube_t *); +int64_t coord_cocsep(cube_t); int main(void) { char str[STRLENMAX]; uint32_t buf[300000], data; int64_t coord, coclass; uint64_t selfsim[COCSEP_CLASSES], sim, t; - cube_fast_t fast, rep[COCSEP_CLASSES]; + cube_t cube, rep[COCSEP_CLASSES]; gendata_cocsep(buf, selfsim, rep); /* All cases in the same test so we do not generate data many times */ while (fgets(str, STRLENMAX, stdin) != NULL) { - fast = cubetofast(readcube("H48", str)); - coord = coord_fast_cocsep(fast); + cube = readcube("H48", str); + coord = coord_cocsep(cube); data = buf[coord]; coclass = (data & (0xFFFU << 16)) >> 16; sim = selfsim[coclass]; diff --git a/test/102_coord_invcoord_h48/coord_invcoord_h48_tests.c b/test/102_coord_invcoord_h48/coord_invcoord_h48_tests.c @@ -2,10 +2,10 @@ #define COCSEP_CLASSES 3393 -size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); -int64_t coord_h48(cube_fast_t, const uint32_t *, uint8_t); -cube_fast_t invcoord_h48(int64_t, const cube_fast_t *, uint8_t); -cube_fast_t transform(cube_fast_t, uint8_t); +size_t gendata_cocsep(void *, uint64_t *, cube_t *); +int64_t coord_h48(cube_t, const uint32_t *, uint8_t); +cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); +cube_t transform(cube_t, uint8_t); int main(void) { char str[STRLENMAX]; @@ -15,8 +15,7 @@ int main(void) { uint32_t cocsepdata[300000]; uint64_t selfsim[COCSEP_CLASSES]; int64_t c, cc; - cube_t cube; - cube_fast_t fast, invc, rep[COCSEP_CLASSES]; + cube_t cube, invc, rep[COCSEP_CLASSES]; gendata_cocsep(cocsepdata, selfsim, rep); @@ -24,12 +23,11 @@ int main(void) { h = 11; while (fgets(str, STRLENMAX, stdin) != NULL) { cube = readcube("H48", str); - fast = cubetofast(cube); - c = coord_h48(fast, cocsepdata, h); + c = coord_h48(cube, cocsepdata, h); invc = invcoord_h48(c, rep, h); for (t = 0, found = false; t < 48; t++) { - fast = transform(invc, t); - cc = coord_h48(fast, cocsepdata, h); + cube = transform(invc, t); + cc = coord_h48(cube, cocsepdata, h); found = found || cc == c; } printf("%d %s\n", i, found ? "ok" : "ERROR"); diff --git a/test/test.h b/test/test.h @@ -6,16 +6,14 @@ #define STRLENMAX 10000 +#ifdef CUBE_AVX2 +#include <immintrin.h> +typedef __m256i cube_t; +#else typedef struct { uint8_t corner[8]; uint8_t edge[12]; } cube_t; - -#ifdef CUBE_AVX2 -#include <immintrin.h> -typedef __m256i cube_fast_t; -#else -typedef cube_t cube_fast_t; #endif /* Basic functions used in most tests */ @@ -26,5 +24,3 @@ bool issolvable(cube_t); bool issolved(cube_t); cube_t readcube(char *, char *); void writecube(char *, cube_t, char *); -cube_t fasttocube(cube_fast_t); -cube_fast_t cubetofast(cube_t);