aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-12-07 16:38:40 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2024-12-07 16:38:40 +0100
commit9ac266c76f39620d8343e46ca41cb09d1534384c (patch)
tree823bd419d99fe0f00e6b5b713237a73b4ec7ffca
parentea25a7ccad625c4e664dfd114147971b8a2677f3 (diff)
downloadnissy-core-9ac266c76f39620d8343e46ca41cb09d1534384c.tar.gz
nissy-core-9ac266c76f39620d8343e46ca41cb09d1534384c.zip
Merge the "solver-experiments" branch that I have been working on for
a few weeks. This include mainly three things: 1. Various tweaks for a total performance gain of around 30%. 2. Take into account symmetries and avoid repeated work. This required a re-work of the splitting into tasks before the solve. 3. Add a second fallback table (eoesep). This gives huge performance gains for particular scrambles (e.g. superflip). After merging this commit, remove and re-generate all pruning tables. Squashed commit of the following: commit 60f0705d2d69050e6a30581a2810f686d6f69b80 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Sat Dec 7 16:06:48 2024 +0100 Fix indentation commit cc5d489a251812b6188c0ba264ac6cb2236f1afe Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Sat Dec 7 15:56:19 2024 +0100 Updated documentation commit a3f605dd628546e52564f82b139feb473b0725f3 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Sat Dec 7 14:01:11 2024 +0100 use eoesep table as second fallback commit c75e43c9116c64f97e92b0fe038be8a032925a72 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Fri Dec 6 16:13:23 2024 +0100 First commit for gendata_eoesep commit fea7688ab8bdc5ae0c3480622e2510a3bcd39248 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Dec 3 17:31:00 2024 +0100 Add scramble to tool commit 66866cb71dea4ca8278ecb9e90ff4295771feb42 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Dec 3 17:22:59 2024 +0100 Added tool to check multiple solutions commit ef65611c772c3996bddca8d181da3538e0af1674 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Dec 3 17:16:20 2024 +0100 Write all solutions for symmetric positions commit e3ded26db7d7d4ae7c0e2488151ed14f581f7b8e Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Nov 26 09:14:54 2024 +0100 Added symmetry filter (TODO: print excluded solutions) commit 864c437a9751c58d58562650ca9eba4a9e6ad3eb Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Mon Nov 25 14:51:13 2024 +0100 Improved task split commit b88926d36d7ab0c64c5fe3bb954fd15d41267fba Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Fri Nov 22 19:06:41 2024 +0100 Reworked tasks for multi-threading in view of symmetry filter commit 26fa653f97df8cd601aecb80eaf89f0a00e9ba9f Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Thu Oct 31 15:37:43 2024 +0100 Added transform move commit 19f655ef94d658eaa2fefb5cea3c167a3ec58db6 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Thu Oct 31 09:29:15 2024 +0100 Clarified doc commit 3b0fe1e5ef8b628854e30f0f0067300e2763c954 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Thu Oct 31 08:36:58 2024 +0100 Handle solved cube correctly commit 57705cbc4982e3abe97a36ed64871738d4f721c0 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Thu Oct 31 08:24:30 2024 +0100 Close file commit fc7d462b58bcf3d3a3fbf26c1f3bd04c640a4898 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Oct 29 15:05:48 2024 +0100 Removed stats tool commit 359bf7cb49ef405ee76ed662207d47cb2abcc5a9 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Oct 29 15:01:51 2024 +0100 Updated theory doc commit 39c315af562bc4ce896f41004388a4c34d475d37 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Oct 29 14:51:40 2024 +0100 Remove unused constants commit 57a5d24538aa59a4df9221dad2f99e9f0286bd9d Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Tue Oct 29 10:20:38 2024 +0100 Add tool to solve scrambles from file commit 07e2918c216636891b1fa6adecc9756086a901e9 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Mon Oct 28 17:00:00 2024 +0100 Add make table to tool commit f5e5266c654eb027a5a35c57cc618555246f5e5e Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Mon Oct 28 09:35:49 2024 +0100 Remove old solver, other small things commit a1ec78025b7959dbb845213f7f4e6851ecebc204 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Sun Oct 27 02:00:29 2024 +0200 Improvements commit 8eea23dbe888d923e662e24ae969130e2c67b999 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Sat Oct 26 12:24:19 2024 +0200 Makefile fix commit 3fc3927beacc78971cefeb42da8d71fe6c015fc1 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Fri Oct 25 18:25:09 2024 +0200 More performance gains commit 7b4efa1f9af9722de1ab9ccfc27899825a0d12c4 Author: Sebastiano Tronto <sebastiano@tronto.net> Date: Fri Oct 25 15:53:20 2024 +0200 Alternative solver implementation, small performance gain
-rw-r--r--Makefile6
-rw-r--r--doc/h48.md31
-rw-r--r--doc/transformations.md3
-rw-r--r--src/arch/avx2.h6
-rw-r--r--src/arch/common.h17
-rw-r--r--src/arch/neon.h11
-rw-r--r--src/arch/portable.h12
-rw-r--r--src/core/moves.h54
-rw-r--r--src/core/transform.h40
-rw-r--r--src/nissy.c80
-rw-r--r--src/solvers/h48/coordinate_macros.h1
-rw-r--r--src/solvers/h48/gendata_cocsep.h34
-rw-r--r--src/solvers/h48/gendata_eoesep.h274
-rw-r--r--src/solvers/h48/gendata_h48.h62
-rw-r--r--src/solvers/h48/gendata_types_macros.h11
-rw-r--r--src/solvers/h48/h48.h3
-rw-r--r--src/solvers/h48/solve.h610
-rw-r--r--src/solvers/h48/solve_multithread.h350
-rw-r--r--src/solvers/h48/stats.h100
-rw-r--r--src/utils/constants.h62
-rw-r--r--test/062_transform_move/100_UFr_U.in2
-rw-r--r--test/062_transform_move/100_UFr_U.out1
-rw-r--r--test/062_transform_move/101_UFm_U.in2
-rw-r--r--test/062_transform_move/101_UFm_U.out1
-rw-r--r--test/062_transform_move/102_UFr_R.in2
-rw-r--r--test/062_transform_move/102_UFr_R.out1
-rw-r--r--test/062_transform_move/103_UFm_R.in2
-rw-r--r--test/062_transform_move/103_UFm_R.out1
-rw-r--r--test/062_transform_move/104_UFr_F.in2
-rw-r--r--test/062_transform_move/104_UFr_F.out1
-rw-r--r--test/062_transform_move/105_UFm_F.in2
-rw-r--r--test/062_transform_move/105_UFm_F.out1
-rw-r--r--test/062_transform_move/106_ULr_U.in2
-rw-r--r--test/062_transform_move/106_ULr_U.out1
-rw-r--r--test/062_transform_move/107_ULm_U.in2
-rw-r--r--test/062_transform_move/107_ULm_U.out1
-rw-r--r--test/062_transform_move/108_ULr_R.in2
-rw-r--r--test/062_transform_move/108_ULr_R.out1
-rw-r--r--test/062_transform_move/109_ULm_R.in2
-rw-r--r--test/062_transform_move/109_ULm_R.out1
-rw-r--r--test/062_transform_move/110_ULr_F.in2
-rw-r--r--test/062_transform_move/110_ULr_F.out1
-rw-r--r--test/062_transform_move/111_ULm_F.in2
-rw-r--r--test/062_transform_move/111_ULm_F.out1
-rw-r--r--test/062_transform_move/112_UBr_U.in2
-rw-r--r--test/062_transform_move/112_UBr_U.out1
-rw-r--r--test/062_transform_move/113_UBm_U.in2
-rw-r--r--test/062_transform_move/113_UBm_U.out1
-rw-r--r--test/062_transform_move/114_UBr_R.in2
-rw-r--r--test/062_transform_move/114_UBr_R.out1
-rw-r--r--test/062_transform_move/115_UBm_R.in2
-rw-r--r--test/062_transform_move/115_UBm_R.out1
-rw-r--r--test/062_transform_move/116_UBr_F.in2
-rw-r--r--test/062_transform_move/116_UBr_F.out1
-rw-r--r--test/062_transform_move/117_UBm_F.in2
-rw-r--r--test/062_transform_move/117_UBm_F.out1
-rw-r--r--test/062_transform_move/118_URr_U.in2
-rw-r--r--test/062_transform_move/118_URr_U.out1
-rw-r--r--test/062_transform_move/119_URm_U.in2
-rw-r--r--test/062_transform_move/119_URm_U.out1
-rw-r--r--test/062_transform_move/120_URr_R.in2
-rw-r--r--test/062_transform_move/120_URr_R.out1
-rw-r--r--test/062_transform_move/121_URm_R.in2
-rw-r--r--test/062_transform_move/121_URm_R.out1
-rw-r--r--test/062_transform_move/122_URr_F.in2
-rw-r--r--test/062_transform_move/122_URr_F.out1
-rw-r--r--test/062_transform_move/123_URm_F.in2
-rw-r--r--test/062_transform_move/123_URm_F.out1
-rw-r--r--test/062_transform_move/124_DFr_U.in2
-rw-r--r--test/062_transform_move/124_DFr_U.out1
-rw-r--r--test/062_transform_move/125_DFm_U.in2
-rw-r--r--test/062_transform_move/125_DFm_U.out1
-rw-r--r--test/062_transform_move/126_DFr_R.in2
-rw-r--r--test/062_transform_move/126_DFr_R.out1
-rw-r--r--test/062_transform_move/127_DFm_R.in2
-rw-r--r--test/062_transform_move/127_DFm_R.out1
-rw-r--r--test/062_transform_move/128_DFr_F.in2
-rw-r--r--test/062_transform_move/128_DFr_F.out1
-rw-r--r--test/062_transform_move/129_DFm_F.in2
-rw-r--r--test/062_transform_move/129_DFm_F.out1
-rw-r--r--test/062_transform_move/130_DLr_U.in2
-rw-r--r--test/062_transform_move/130_DLr_U.out1
-rw-r--r--test/062_transform_move/131_DLm_U.in2
-rw-r--r--test/062_transform_move/131_DLm_U.out1
-rw-r--r--test/062_transform_move/132_DLr_R.in2
-rw-r--r--test/062_transform_move/132_DLr_R.out1
-rw-r--r--test/062_transform_move/133_DLm_R.in2
-rw-r--r--test/062_transform_move/133_DLm_R.out1
-rw-r--r--test/062_transform_move/134_DLr_F.in2
-rw-r--r--test/062_transform_move/134_DLr_F.out1
-rw-r--r--test/062_transform_move/135_DLm_F.in2
-rw-r--r--test/062_transform_move/135_DLm_F.out1
-rw-r--r--test/062_transform_move/136_DBr_U.in2
-rw-r--r--test/062_transform_move/136_DBr_U.out1
-rw-r--r--test/062_transform_move/137_DBm_U.in2
-rw-r--r--test/062_transform_move/137_DBm_U.out1
-rw-r--r--test/062_transform_move/138_DBr_R.in2
-rw-r--r--test/062_transform_move/138_DBr_R.out1
-rw-r--r--test/062_transform_move/139_DBm_R.in2
-rw-r--r--test/062_transform_move/139_DBm_R.out1
-rw-r--r--test/062_transform_move/140_DBr_F.in2
-rw-r--r--test/062_transform_move/140_DBr_F.out1
-rw-r--r--test/062_transform_move/141_DBm_F.in2
-rw-r--r--test/062_transform_move/141_DBm_F.out1
-rw-r--r--test/062_transform_move/142_DRr_U.in2
-rw-r--r--test/062_transform_move/142_DRr_U.out1
-rw-r--r--test/062_transform_move/143_DRm_U.in2
-rw-r--r--test/062_transform_move/143_DRm_U.out1
-rw-r--r--test/062_transform_move/144_DRr_R.in2
-rw-r--r--test/062_transform_move/144_DRr_R.out1
-rw-r--r--test/062_transform_move/145_DRm_R.in2
-rw-r--r--test/062_transform_move/145_DRm_R.out1
-rw-r--r--test/062_transform_move/146_DRr_F.in2
-rw-r--r--test/062_transform_move/146_DRr_F.out1
-rw-r--r--test/062_transform_move/147_DRm_F.in2
-rw-r--r--test/062_transform_move/147_DRm_F.out1
-rw-r--r--test/062_transform_move/148_RUr_U.in2
-rw-r--r--test/062_transform_move/148_RUr_U.out1
-rw-r--r--test/062_transform_move/149_RUm_U.in2
-rw-r--r--test/062_transform_move/149_RUm_U.out1
-rw-r--r--test/062_transform_move/150_RUr_R.in2
-rw-r--r--test/062_transform_move/150_RUr_R.out1
-rw-r--r--test/062_transform_move/151_RUm_R.in2
-rw-r--r--test/062_transform_move/151_RUm_R.out1
-rw-r--r--test/062_transform_move/152_RUr_F.in2
-rw-r--r--test/062_transform_move/152_RUr_F.out1
-rw-r--r--test/062_transform_move/153_RUm_F.in2
-rw-r--r--test/062_transform_move/153_RUm_F.out1
-rw-r--r--test/062_transform_move/154_RFr_U.in2
-rw-r--r--test/062_transform_move/154_RFr_U.out1
-rw-r--r--test/062_transform_move/155_RFm_U.in2
-rw-r--r--test/062_transform_move/155_RFm_U.out1
-rw-r--r--test/062_transform_move/156_RFr_R.in2
-rw-r--r--test/062_transform_move/156_RFr_R.out1
-rw-r--r--test/062_transform_move/157_RFm_R.in2
-rw-r--r--test/062_transform_move/157_RFm_R.out1
-rw-r--r--test/062_transform_move/158_RFr_F.in2
-rw-r--r--test/062_transform_move/158_RFr_F.out1
-rw-r--r--test/062_transform_move/159_RFm_F.in2
-rw-r--r--test/062_transform_move/159_RFm_F.out1
-rw-r--r--test/062_transform_move/160_RDr_U.in2
-rw-r--r--test/062_transform_move/160_RDr_U.out1
-rw-r--r--test/062_transform_move/161_RDm_U.in2
-rw-r--r--test/062_transform_move/161_RDm_U.out1
-rw-r--r--test/062_transform_move/162_RDr_R.in2
-rw-r--r--test/062_transform_move/162_RDr_R.out1
-rw-r--r--test/062_transform_move/163_RDm_R.in2
-rw-r--r--test/062_transform_move/163_RDm_R.out1
-rw-r--r--test/062_transform_move/164_RDr_F.in2
-rw-r--r--test/062_transform_move/164_RDr_F.out1
-rw-r--r--test/062_transform_move/165_RDm_F.in2
-rw-r--r--test/062_transform_move/165_RDm_F.out1
-rw-r--r--test/062_transform_move/166_RBr_U.in2
-rw-r--r--test/062_transform_move/166_RBr_U.out1
-rw-r--r--test/062_transform_move/167_RBm_U.in2
-rw-r--r--test/062_transform_move/167_RBm_U.out1
-rw-r--r--test/062_transform_move/168_RBr_R.in2
-rw-r--r--test/062_transform_move/168_RBr_R.out1
-rw-r--r--test/062_transform_move/169_RBm_R.in2
-rw-r--r--test/062_transform_move/169_RBm_R.out1
-rw-r--r--test/062_transform_move/170_RBr_F.in2
-rw-r--r--test/062_transform_move/170_RBr_F.out1
-rw-r--r--test/062_transform_move/171_RBm_F.in2
-rw-r--r--test/062_transform_move/171_RBm_F.out1
-rw-r--r--test/062_transform_move/172_LUr_U.in2
-rw-r--r--test/062_transform_move/172_LUr_U.out1
-rw-r--r--test/062_transform_move/173_LUm_U.in2
-rw-r--r--test/062_transform_move/173_LUm_U.out1
-rw-r--r--test/062_transform_move/174_LUr_R.in2
-rw-r--r--test/062_transform_move/174_LUr_R.out1
-rw-r--r--test/062_transform_move/175_LUm_R.in2
-rw-r--r--test/062_transform_move/175_LUm_R.out1
-rw-r--r--test/062_transform_move/176_LUr_F.in2
-rw-r--r--test/062_transform_move/176_LUr_F.out1
-rw-r--r--test/062_transform_move/177_LUm_F.in2
-rw-r--r--test/062_transform_move/177_LUm_F.out1
-rw-r--r--test/062_transform_move/178_LFr_U.in2
-rw-r--r--test/062_transform_move/178_LFr_U.out1
-rw-r--r--test/062_transform_move/179_LFm_U.in2
-rw-r--r--test/062_transform_move/179_LFm_U.out1
-rw-r--r--test/062_transform_move/180_LFr_R.in2
-rw-r--r--test/062_transform_move/180_LFr_R.out1
-rw-r--r--test/062_transform_move/181_LFm_R.in2
-rw-r--r--test/062_transform_move/181_LFm_R.out1
-rw-r--r--test/062_transform_move/182_LFr_F.in2
-rw-r--r--test/062_transform_move/182_LFr_F.out1
-rw-r--r--test/062_transform_move/183_LFm_F.in2
-rw-r--r--test/062_transform_move/183_LFm_F.out1
-rw-r--r--test/062_transform_move/184_LDr_U.in2
-rw-r--r--test/062_transform_move/184_LDr_U.out1
-rw-r--r--test/062_transform_move/185_LDm_U.in2
-rw-r--r--test/062_transform_move/185_LDm_U.out1
-rw-r--r--test/062_transform_move/186_LDr_R.in2
-rw-r--r--test/062_transform_move/186_LDr_R.out1
-rw-r--r--test/062_transform_move/187_LDm_R.in2
-rw-r--r--test/062_transform_move/187_LDm_R.out1
-rw-r--r--test/062_transform_move/188_LDr_F.in2
-rw-r--r--test/062_transform_move/188_LDr_F.out1
-rw-r--r--test/062_transform_move/189_LDm_F.in2
-rw-r--r--test/062_transform_move/189_LDm_F.out1
-rw-r--r--test/062_transform_move/190_LBr_U.in2
-rw-r--r--test/062_transform_move/190_LBr_U.out1
-rw-r--r--test/062_transform_move/191_LBm_U.in2
-rw-r--r--test/062_transform_move/191_LBm_U.out1
-rw-r--r--test/062_transform_move/192_LBr_R.in2
-rw-r--r--test/062_transform_move/192_LBr_R.out1
-rw-r--r--test/062_transform_move/193_LBm_R.in2
-rw-r--r--test/062_transform_move/193_LBm_R.out1
-rw-r--r--test/062_transform_move/194_LBr_F.in2
-rw-r--r--test/062_transform_move/194_LBr_F.out1
-rw-r--r--test/062_transform_move/195_LBm_F.in2
-rw-r--r--test/062_transform_move/195_LBm_F.out1
-rw-r--r--test/062_transform_move/196_FUr_U.in2
-rw-r--r--test/062_transform_move/196_FUr_U.out1
-rw-r--r--test/062_transform_move/197_FUm_U.in2
-rw-r--r--test/062_transform_move/197_FUm_U.out1
-rw-r--r--test/062_transform_move/198_FUr_R.in2
-rw-r--r--test/062_transform_move/198_FUr_R.out1
-rw-r--r--test/062_transform_move/199_FUm_R.in2
-rw-r--r--test/062_transform_move/199_FUm_R.out1
-rw-r--r--test/062_transform_move/200_FUr_F.in2
-rw-r--r--test/062_transform_move/200_FUr_F.out1
-rw-r--r--test/062_transform_move/201_FUm_F.in2
-rw-r--r--test/062_transform_move/201_FUm_F.out1
-rw-r--r--test/062_transform_move/202_FRr_U.in2
-rw-r--r--test/062_transform_move/202_FRr_U.out1
-rw-r--r--test/062_transform_move/203_FRm_U.in2
-rw-r--r--test/062_transform_move/203_FRm_U.out1
-rw-r--r--test/062_transform_move/204_FRr_R.in2
-rw-r--r--test/062_transform_move/204_FRr_R.out1
-rw-r--r--test/062_transform_move/205_FRm_R.in2
-rw-r--r--test/062_transform_move/205_FRm_R.out1
-rw-r--r--test/062_transform_move/206_FRr_F.in2
-rw-r--r--test/062_transform_move/206_FRr_F.out1
-rw-r--r--test/062_transform_move/207_FRm_F.in2
-rw-r--r--test/062_transform_move/207_FRm_F.out1
-rw-r--r--test/062_transform_move/208_FDr_U.in2
-rw-r--r--test/062_transform_move/208_FDr_U.out1
-rw-r--r--test/062_transform_move/209_FDm_U.in2
-rw-r--r--test/062_transform_move/209_FDm_U.out1
-rw-r--r--test/062_transform_move/210_FDr_R.in2
-rw-r--r--test/062_transform_move/210_FDr_R.out1
-rw-r--r--test/062_transform_move/211_FDm_R.in2
-rw-r--r--test/062_transform_move/211_FDm_R.out1
-rw-r--r--test/062_transform_move/212_FDr_F.in2
-rw-r--r--test/062_transform_move/212_FDr_F.out1
-rw-r--r--test/062_transform_move/213_FDm_F.in2
-rw-r--r--test/062_transform_move/213_FDm_F.out1
-rw-r--r--test/062_transform_move/214_FLr_U.in2
-rw-r--r--test/062_transform_move/214_FLr_U.out1
-rw-r--r--test/062_transform_move/215_FLm_U.in2
-rw-r--r--test/062_transform_move/215_FLm_U.out1
-rw-r--r--test/062_transform_move/216_FLr_R.in2
-rw-r--r--test/062_transform_move/216_FLr_R.out1
-rw-r--r--test/062_transform_move/217_FLm_R.in2
-rw-r--r--test/062_transform_move/217_FLm_R.out1
-rw-r--r--test/062_transform_move/218_FLr_F.in2
-rw-r--r--test/062_transform_move/218_FLr_F.out1
-rw-r--r--test/062_transform_move/219_FLm_F.in2
-rw-r--r--test/062_transform_move/219_FLm_F.out1
-rw-r--r--test/062_transform_move/220_BUr_U.in2
-rw-r--r--test/062_transform_move/220_BUr_U.out1
-rw-r--r--test/062_transform_move/221_BUm_U.in2
-rw-r--r--test/062_transform_move/221_BUm_U.out1
-rw-r--r--test/062_transform_move/222_BUr_R.in2
-rw-r--r--test/062_transform_move/222_BUr_R.out1
-rw-r--r--test/062_transform_move/223_BUm_R.in2
-rw-r--r--test/062_transform_move/223_BUm_R.out1
-rw-r--r--test/062_transform_move/224_BUr_F.in2
-rw-r--r--test/062_transform_move/224_BUr_F.out1
-rw-r--r--test/062_transform_move/225_BUm_F.in2
-rw-r--r--test/062_transform_move/225_BUm_F.out1
-rw-r--r--test/062_transform_move/226_BRr_U.in2
-rw-r--r--test/062_transform_move/226_BRr_U.out1
-rw-r--r--test/062_transform_move/227_BRm_U.in2
-rw-r--r--test/062_transform_move/227_BRm_U.out1
-rw-r--r--test/062_transform_move/228_BRr_R.in2
-rw-r--r--test/062_transform_move/228_BRr_R.out1
-rw-r--r--test/062_transform_move/229_BRm_R.in2
-rw-r--r--test/062_transform_move/229_BRm_R.out1
-rw-r--r--test/062_transform_move/230_BRr_F.in2
-rw-r--r--test/062_transform_move/230_BRr_F.out1
-rw-r--r--test/062_transform_move/231_BRm_F.in2
-rw-r--r--test/062_transform_move/231_BRm_F.out1
-rw-r--r--test/062_transform_move/232_BDr_U.in2
-rw-r--r--test/062_transform_move/232_BDr_U.out1
-rw-r--r--test/062_transform_move/233_BDm_U.in2
-rw-r--r--test/062_transform_move/233_BDm_U.out1
-rw-r--r--test/062_transform_move/234_BDr_R.in2
-rw-r--r--test/062_transform_move/234_BDr_R.out1
-rw-r--r--test/062_transform_move/235_BDm_R.in2
-rw-r--r--test/062_transform_move/235_BDm_R.out1
-rw-r--r--test/062_transform_move/236_BDr_F.in2
-rw-r--r--test/062_transform_move/236_BDr_F.out1
-rw-r--r--test/062_transform_move/237_BDm_F.in2
-rw-r--r--test/062_transform_move/237_BDm_F.out1
-rw-r--r--test/062_transform_move/238_BLr_U.in2
-rw-r--r--test/062_transform_move/238_BLr_U.out1
-rw-r--r--test/062_transform_move/239_BLm_U.in2
-rw-r--r--test/062_transform_move/239_BLm_U.out1
-rw-r--r--test/062_transform_move/240_BLr_R.in2
-rw-r--r--test/062_transform_move/240_BLr_R.out1
-rw-r--r--test/062_transform_move/241_BLm_R.in2
-rw-r--r--test/062_transform_move/241_BLm_R.out1
-rw-r--r--test/062_transform_move/242_BLr_F.in2
-rw-r--r--test/062_transform_move/242_BLr_F.out1
-rw-r--r--test/062_transform_move/243_BLm_F.in2
-rw-r--r--test/062_transform_move/243_BLm_F.out1
-rw-r--r--test/062_transform_move/244_modifier_LBr_R2.in2
-rw-r--r--test/062_transform_move/244_modifier_LBr_R2.out1
-rw-r--r--test/062_transform_move/245_modifier_URr_F3.in2
-rw-r--r--test/062_transform_move/245_modifier_URr_F3.out1
-rw-r--r--test/062_transform_move/246_modifier_RBm_U3.in2
-rw-r--r--test/062_transform_move/246_modifier_RBm_U3.out1
-rw-r--r--test/062_transform_move/247_axis_UBr_L.in2
-rw-r--r--test/062_transform_move/247_axis_UBr_L.out1
-rw-r--r--test/062_transform_move/248_axis_BDm_D3.in2
-rw-r--r--test/062_transform_move/248_axis_BDm_D3.out1
-rw-r--r--test/062_transform_move/249_axis_DLr_B2.in2
-rw-r--r--test/062_transform_move/249_axis_DLr_B2.out1
-rw-r--r--test/062_transform_move/transform_move_tests.c29
-rw-r--r--test/063_symmetry_mask/00_solved.in1
-rw-r--r--test/063_symmetry_mask/00_solved.out1
-rw-r--r--test/063_symmetry_mask/01_U.in1
-rw-r--r--test/063_symmetry_mask/01_U.out1
-rw-r--r--test/063_symmetry_mask/02_B2.in1
-rw-r--r--test/063_symmetry_mask/02_B2.out1
-rw-r--r--test/063_symmetry_mask/03_superflip.in1
-rw-r--r--test/063_symmetry_mask/03_superflip.out1
-rw-r--r--test/063_symmetry_mask/04_scrambled.in1
-rw-r--r--test/063_symmetry_mask/04_scrambled.out1
-rw-r--r--test/063_symmetry_mask/symmetry_mask_tests.c17
-rw-r--r--test/105_gendata_eoesep/00_all.in0
-rw-r--r--test/105_gendata_eoesep/00_all.out9
-rw-r--r--test/105_gendata_eoesep/gendata_eoesep_tests.c46
-rw-r--r--test/130_allowednext_h48/00_empty_U.in3
-rw-r--r--test/130_allowednext_h48/00_empty_U.out1
-rw-r--r--test/130_allowednext_h48/01_F.in4
-rw-r--r--test/130_allowednext_h48/01_F.out1
-rw-r--r--test/130_allowednext_h48/02_U2.in3
-rw-r--r--test/130_allowednext_h48/02_U2.out1
-rw-r--r--test/130_allowednext_h48/03_R_L.in5
-rw-r--r--test/130_allowednext_h48/03_R_L.out1
-rw-r--r--test/130_allowednext_h48/04_D.in3
-rw-r--r--test/130_allowednext_h48/04_D.out1
-rw-r--r--test/130_allowednext_h48/05_U_F_B2.in5
-rw-r--r--test/130_allowednext_h48/05_U_F_B2.out1
-rw-r--r--test/130_allowednext_h48/06_empty_bound.in2
-rw-r--r--test/130_allowednext_h48/06_empty_bound.out1
-rw-r--r--test/130_allowednext_h48/07_F_bound.in3
-rw-r--r--test/130_allowednext_h48/07_F_bound.out1
-rw-r--r--test/130_allowednext_h48/08_U_D_bound_inverse.in4
-rw-r--r--test/130_allowednext_h48/08_U_D_bound_inverse.out1
-rw-r--r--test/130_allowednext_h48/09_R_false_bound.in3
-rw-r--r--test/130_allowednext_h48/09_R_false_bound.out1
-rw-r--r--test/130_allowednext_h48/allowednext_h48_tests.c38
-rw-r--r--tools/200_stats_tables_h48/stats_tables_h48.c117
-rw-r--r--tools/301_solve_file/solve_file.c71
-rw-r--r--tools/302_solve_multisol/solve_multisol.c66
359 files changed, 1732 insertions, 933 deletions
diff --git a/Makefile b/Makefile
index 025fdb5..29b7ef3 100644
--- a/Makefile
+++ b/Makefile
@@ -15,17 +15,17 @@ debugnissy.o:
15 ${CC} ${MACROS} ${DBGFLAGS} -c -o debugnissy.o src/nissy.c 15 ${CC} ${MACROS} ${DBGFLAGS} -c -o debugnissy.o src/nissy.c
16 16
17clean: 17clean:
18 rm -rf *.o *.so run debugrun 18 rm -rf *.o *.s *.so run debugrun
19 19
20test: debugnissy.o 20test: debugnissy.o
21 CC="${CC} ${MACROS} ${DBGFLAGS}" OBJ=debugnissy.o ./test/test.sh 21 CC="${CC} ${MACROS} ${DBGFLAGS}" OBJ=debugnissy.o ./test/test.sh
22 22
23tool: nissy.o 23tool: nissy.o
24 mkdir -p tools/results 24 mkdir -p tables tools/results
25 CC="${CC} ${MACROS} ${CFLAGS}" OBJ=nissy.o ./tools/tool.sh 25 CC="${CC} ${MACROS} ${CFLAGS}" OBJ=nissy.o ./tools/tool.sh
26 26
27debugtool: debugnissy.o 27debugtool: debugnissy.o
28 mkdir -p tools/results 28 mkdir -p tables tools/results
29 CC="${CC} ${MACROS} ${DBGFLAGS}" OBJ=debugnissy.o ./tools/tool.sh 29 CC="${CC} ${MACROS} ${DBGFLAGS}" OBJ=debugnissy.o ./tools/tool.sh
30 30
31shell: nissy.o 31shell: nissy.o
diff --git a/doc/h48.md b/doc/h48.md
index 323453a..678e160 100644
--- a/doc/h48.md
+++ b/doc/h48.md
@@ -230,9 +230,8 @@ can be one of three kinds:
230 If the base value is `b`, a pruning value of 1, 2 or 3 can be used directly 230 If the base value is `b`, a pruning value of 1, 2 or 3 can be used directly
231 as a lower bound of b+1, b+2 and b+3 respectively. However, a value of 0 231 as a lower bound of b+1, b+2 and b+3 respectively. However, a value of 0
232 could mean that the actual lower bound is anything between 0 and b, so we 232 could mean that the actual lower bound is anything between 0 and b, so we
233 cannot take b as a lower bount. Instead we have to use a pruning value from 233 cannot take b as a lower bound. Instead we have to use a pruning value from
234 another table, for example the corner-only table mentioned in the previous 234 another table - see the section "Fallback tables" below.
235 section, or a completely new one.
236* 1 bit per entry, or `k1`: With one bit per entry, the only information we 235* 1 bit per entry, or `k1`: With one bit per entry, the only information we
237 can get from the pruning table is wether or not the current position 236 can get from the pruning table is wether or not the current position
238 requires more or fewer moves than a fixed base value b. This can still be 237 requires more or fewer moves than a fixed base value b. This can still be
@@ -240,6 +239,24 @@ can be one of three kinds:
240 pruning values. 239 pruning values.
241 (Work in progress - `k1` tables not available in the code yet) 240 (Work in progress - `k1` tables not available in the code yet)
242 241
242### Fallback tables
243
244When a pruning table does not store the exact lower bound value, for
245example in the case of `k2` table as described above, we need to refine
246our estimate using another table, which we call *fallback table*.
247In the current implementation, we actually use two different tables:
248
249* **h0** table: for larger `k2` tables we get a fallback value from the full
250 table for the **h0** coordinate.
251* edges-only table: to improve the pruning value for certain specific
252 scrambles, namely whose with solved corners such as the superflip,
253 we employ a second table that takes into account the edges of a full
254 **h11** coordinate. This table is small (around 1MB).
255
256More tables could be used to refine the fallback estimate, but each
257additional table leads to longer lookup times, especially if it is
258too large to fit in cache.
259
243### Estimation refinements 260### Estimation refinements
244 261
245After computing the pruning value, there are a number of different tricks 262After computing the pruning value, there are a number of different tricks
@@ -285,6 +302,12 @@ as described above. For doing this, we need to replace the cube with its
285inverse, and keep track of the moves done from now on so that we can 302inverse, and keep track of the moves done from now on so that we can
286invert them at the end to construct the final solution. 303invert them at the end to construct the final solution.
287 304
305When this technique is used, it is also possible to avoid some table
306lookups: if the last move applied to the cube is a 180° move *on the
307inverse position*, then the coordinate on the normal position has not
308changed. Thus if we keep track of the last computed pruning value,
309we can reuse it and avoid an expensive table lookup.
310
288### Other optimizations 311### Other optimizations
289 312
290Other possible (low-level) optimizations include: 313Other possible (low-level) optimizations include:
@@ -344,7 +367,7 @@ don't have this much memory.
344 367
345### 2 bits tables with for h0 and h11 368### 2 bits tables with for h0 and h11
346 369
347(Work in progress - currently I there is no specialized routine for 370(Work in progress - currently there is no specialized routine for
348computing 2 bits table for "real" coordinates; instead, an optimized 371computing 2 bits table for "real" coordinates; instead, an optimized
349version of the generic method explained below is used) 372version of the generic method explained below is used)
350 373
diff --git a/doc/transformations.md b/doc/transformations.md
index a180ce6..65212ea 100644
--- a/doc/transformations.md
+++ b/doc/transformations.md
@@ -6,4 +6,5 @@ For example, to apply the transformation RBm (mirrored RB) to a cube C:
6 1. Apply a mirror along the M plane to the solved cube 6 1. Apply a mirror along the M plane to the solved cube
7 2. Rotate the mirrored cube with z' y2 7 2. Rotate the mirrored cube with z' y2
8 3. Apply the cube C to the transformed solved cube 8 3. Apply the cube C to the transformed solved cube
9 4. Apply the transformations of step 1a and 1b in reverse 9 4. Apply the transformations of step 2 in reverse
10 5. Apply the transformations of step 1 in reverse
diff --git a/src/arch/avx2.h b/src/arch/avx2.h
index 2c3371e..b6ff510 100644
--- a/src/arch/avx2.h
+++ b/src/arch/avx2.h
@@ -16,6 +16,12 @@
16#define SOLVED_CUBE STATIC_CUBE( \ 16#define SOLVED_CUBE STATIC_CUBE( \
17 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) 17 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
18 18
19STATIC_INLINE int
20popcount_u32(uint32_t x)
21{
22 return _mm_popcnt_u32(x);
23}
24
19STATIC void 25STATIC void
20pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) 26pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
21{ 27{
diff --git a/src/arch/common.h b/src/arch/common.h
index 802790c..52e0fc7 100644
--- a/src/arch/common.h
+++ b/src/arch/common.h
@@ -1,3 +1,5 @@
1STATIC_INLINE int popcount_u32(uint32_t);
2
1STATIC void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]); 3STATIC void pieces(cube_t *, uint8_t [static 8], uint8_t [static 12]);
2STATIC_INLINE bool equal(cube_t, cube_t); 4STATIC_INLINE bool equal(cube_t, cube_t);
3STATIC_INLINE cube_t invertco(cube_t); 5STATIC_INLINE cube_t invertco(cube_t);
@@ -18,6 +20,7 @@ STATIC_INLINE void set_eo(cube_t *, int64_t);
18STATIC_INLINE cube_t invcoord_esep(int64_t); 20STATIC_INLINE cube_t invcoord_esep(int64_t);
19 21
20STATIC_INLINE void invcoord_esep_array(int64_t, int64_t, uint8_t[static 12]); 22STATIC_INLINE void invcoord_esep_array(int64_t, int64_t, uint8_t[static 12]);
23STATIC_INLINE cube_t invcoord_eoesep(int64_t);
21 24
22STATIC_INLINE void 25STATIC_INLINE void
23invcoord_esep_array(int64_t set1, int64_t set2, uint8_t mem[static 12]) 26invcoord_esep_array(int64_t set1, int64_t set2, uint8_t mem[static 12])
@@ -44,3 +47,17 @@ invcoord_esep_array(int64_t set1, int64_t set2, uint8_t mem[static 12])
44 mem[i] = (slice[s]++) | (uint8_t)(s << 2); 47 mem[i] = (slice[s]++) | (uint8_t)(s << 2);
45 } 48 }
46} 49}
50
51STATIC_INLINE cube_t
52invcoord_eoesep(int64_t i)
53{
54 cube_t c;
55 int64_t esep, eo;
56
57 esep = i >> INT64_C(11);
58 eo = i % POW_2_11;
59 c = invcoord_esep(esep);
60 set_eo(&c, eo);
61
62 return c;
63}
diff --git a/src/arch/neon.h b/src/arch/neon.h
index c31c8f9..47dc147 100644
--- a/src/arch/neon.h
+++ b/src/arch/neon.h
@@ -26,6 +26,17 @@ STATIC_INLINE uint8x8_t compose_corners_slim(uint8x8_t, uint8x8_t);
26#define SOLVED_CUBE STATIC_CUBE( \ 26#define SOLVED_CUBE STATIC_CUBE( \
27 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) 27 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
28 28
29/* TODO: optimize this (use intrinsics?) */
30STATIC_INLINE int
31{
32 int ret;
33
34 for (ret = 0; x != 0; x >>= 1)
35 ret += x & 1;
36
37 return ret;
38}
39
29STATIC void 40STATIC void
30pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) 41pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
31{ 42{
diff --git a/src/arch/portable.h b/src/arch/portable.h
index e9a8dd0..b8c5211 100644
--- a/src/arch/portable.h
+++ b/src/arch/portable.h
@@ -9,6 +9,18 @@
9#define SOLVED_CUBE STATIC_CUBE( \ 9#define SOLVED_CUBE STATIC_CUBE( \
10 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) 10 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
11 11
12/* TODO: optimize this (use bit tricks?) */
13STATIC_INLINE int
14popcount_u32(uint32_t x)
15{
16 int ret;
17
18 for (ret = 0; x != 0; x >>= 1)
19 ret += x & 1;
20
21 return ret;
22}
23
12STATIC void 24STATIC void
13pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) 25pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
14{ 26{
diff --git a/src/core/moves.h b/src/core/moves.h
index e3a9bc1..7d4972e 100644
--- a/src/core/moves.h
+++ b/src/core/moves.h
@@ -2,8 +2,8 @@
2#define PREMOVE(M, c) compose(MOVE_CUBE_ ## M, c) 2#define PREMOVE(M, c) compose(MOVE_CUBE_ ## M, c)
3 3
4STATIC_INLINE bool allowednextmove(uint8_t *, uint8_t); 4STATIC_INLINE bool allowednextmove(uint8_t *, uint8_t);
5STATIC_INLINE uint32_t allowednextmove_mask(uint8_t *, uint8_t);
5 6
6STATIC_INLINE uint8_t inverse_trans(uint8_t);
7STATIC_INLINE uint8_t movebase(uint8_t); 7STATIC_INLINE uint8_t movebase(uint8_t);
8STATIC_INLINE uint8_t moveaxis(uint8_t); 8STATIC_INLINE uint8_t moveaxis(uint8_t);
9STATIC_INLINE uint32_t disable_moves(uint32_t, uint8_t); 9STATIC_INLINE uint32_t disable_moves(uint32_t, uint8_t);
@@ -38,26 +38,38 @@ STATIC cube_t applymoves(cube_t, const char *);
38STATIC bool 38STATIC bool
39allowednextmove(uint8_t *moves, uint8_t n) 39allowednextmove(uint8_t *moves, uint8_t n)
40{ 40{
41 uint8_t base[3], axis[3]; 41 return n == 0 ? true :
42 allowednextmove_mask(moves, n-1) & (1 << moves[n-1]);
43}
44
45STATIC uint32_t
46allowednextmove_mask(uint8_t *moves, uint8_t n)
47{
48 uint32_t result;
49 uint8_t base1, base2, axis1, axis2;
50
51 result = MM_ALLMOVES;
42 52
43 if (n < 2) 53 if (n == 0)
44 return true; 54 return result;
45 55
46 base[0] = movebase(moves[n-1]); 56 base1 = movebase(moves[n-1]);
47 axis[0] = moveaxis(moves[n-1]); 57 axis1 = moveaxis(moves[n-1]);
48 base[1] = movebase(moves[n-2]); 58 result = disable_moves(result, base1 * 3);
49 axis[1] = moveaxis(moves[n-2]);
50 59
51 if (base[0] == base[1] || (axis[0] == axis[1] && base[0] < base[1])) 60 if (base1 % 2)
52 return false; 61 result = disable_moves(result, (base1 - 1) * 3);
53 62
54 if (n == 2) 63 if (n == 1)
55 return true; 64 return result;
56 65
57 base[2] = movebase(moves[n-3]); 66 base2 = movebase(moves[n-2]);
58 axis[2] = moveaxis(moves[n-3]); 67 axis2 = moveaxis(moves[n-2]);
59 68
60 return axis[1] != axis[2] || base[0] != base[2]; 69 if(axis1 == axis2)
70 result = disable_moves(result, base2 * 3);
71
72 return result;
61} 73}
62 74
63STATIC_INLINE uint32_t 75STATIC_INLINE uint32_t
@@ -67,12 +79,6 @@ disable_moves(uint32_t current_result, uint8_t base_index)
67} 79}
68 80
69STATIC_INLINE uint8_t 81STATIC_INLINE uint8_t
70inverse_trans(uint8_t t)
71{
72 return inverse_trans_table[t];
73}
74
75STATIC_INLINE uint8_t
76movebase(uint8_t move) 82movebase(uint8_t move)
77{ 83{
78 return move / 3; 84 return move / 3;
@@ -84,6 +90,12 @@ moveaxis(uint8_t move)
84 return move / 6; 90 return move / 6;
85} 91}
86 92
93STATIC_INLINE uint8_t
94moveopposite(uint8_t move)
95{
96 return movebase(move) == 2 * moveaxis(move) ? move + 3 : move - 3;
97}
98
87STATIC cube_t 99STATIC cube_t
88move(cube_t c, uint8_t m) 100move(cube_t c, uint8_t m)
89{ 101{
diff --git a/src/core/transform.h b/src/core/transform.h
index 73636fe..f956718 100644
--- a/src/core/transform.h
+++ b/src/core/transform.h
@@ -21,6 +21,9 @@ STATIC cube_t transform_edges(cube_t, uint8_t);
21STATIC cube_t transform_corners(cube_t, uint8_t); 21STATIC cube_t transform_corners(cube_t, uint8_t);
22STATIC cube_t transform(cube_t, uint8_t); 22STATIC cube_t transform(cube_t, uint8_t);
23STATIC cube_t applytrans(cube_t, const char *); 23STATIC cube_t applytrans(cube_t, const char *);
24STATIC_INLINE uint8_t inverse_trans(uint8_t);
25STATIC uint8_t transform_move(uint8_t, uint8_t);
26STATIC uint64_t symmetry_mask(cube_t);
24 27
25STATIC cube_t 28STATIC cube_t
26transform_edges(cube_t c, uint8_t t) 29transform_edges(cube_t c, uint8_t t)
@@ -354,3 +357,40 @@ applytrans(cube_t cube, const char *buf)
354 357
355 return transform(cube, t); 358 return transform(cube, t);
356} 359}
360
361STATIC_INLINE uint8_t
362inverse_trans(uint8_t t)
363{
364 return inverse_trans_table[t];
365}
366
367STATIC uint8_t
368transform_move(uint8_t m, uint8_t t)
369{
370 uint8_t a, base, modifier;
371
372 a = moveaxis(m);
373 base = trans_move_table[t][a];
374 if (movebase(m) != 2 * a)
375 base = moveopposite(base);
376
377 modifier = m % 3;
378 if (t >= TRANS_UFm)
379 modifier = 2 - modifier;
380
381 return base + modifier;
382}
383
384STATIC uint64_t
385symmetry_mask(cube_t cube)
386{
387 uint64_t t, ret;
388 cube_t transformed;
389
390 for (t = 0, ret = 0; t < 48; t++) {
391 transformed = transform(cube, t);
392 ret |= ((uint64_t)equal(cube, transformed)) << t;
393 }
394
395 return ret;
396}
diff --git a/src/nissy.c b/src/nissy.c
index c09c99e..f933cab 100644
--- a/src/nissy.c
+++ b/src/nissy.c
@@ -12,12 +12,15 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "solvers/solvers.h" 13#include "solvers/solvers.h"
14 14
15int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]); 15long long parse_h48_solver(
16 const char *, uint8_t [static 1], uint8_t [static 1]);
16STATIC bool checkdata(const char *, const tableinfo_t *); 17STATIC bool checkdata(const char *, const tableinfo_t *);
17STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN], 18STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN],
18 const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t); 19 const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t);
19STATIC long long write_result(cube_t, char [static NISSY_SIZE_B32]); 20STATIC long long write_result(cube_t, char [static NISSY_SIZE_B32]);
20STATIC size_t my_strnlen(const char *, size_t); 21STATIC size_t my_strnlen(const char *, size_t);
22STATIC long long nissy_gendata_unsafe(
23 const char *, unsigned long long, char *);
21 24
22#define GETCUBE_OPTIONS(S, F) { .option = S, .fix = F } 25#define GETCUBE_OPTIONS(S, F) { .option = S, .fix = F }
23struct { 26struct {
@@ -28,19 +31,13 @@ struct {
28 GETCUBE_OPTIONS(NULL, NULL) 31 GETCUBE_OPTIONS(NULL, NULL)
29}; 32};
30 33
31int 34long long
32parse_h48_solver(const char *buf, uint8_t h[static 1], uint8_t k[static 1]) 35parse_h48_solver(const char *buf, uint8_t h[static 1], uint8_t k[static 1])
33{ 36{
34 const char *fullbuf = buf; 37 const char *fullbuf = buf;
35 38
36 buf += 3; 39 buf += 3;
37 40
38 if (!strcmp(buf, "stats")) {
39 *h = 0;
40 *k = 4;
41 return 0;
42 }
43
44 if (*buf != 'h') 41 if (*buf != 'h')
45 goto parse_h48_solver_error; 42 goto parse_h48_solver_error;
46 buf++; 43 buf++;
@@ -62,9 +59,9 @@ parse_h48_solver(const char *buf, uint8_t h[static 1], uint8_t k[static 1])
62parse_h48_solver_error: 59parse_h48_solver_error:
63 *h = 0; 60 *h = 0;
64 *k = 0; 61 *k = 0;
65 LOG("Error parsing solver: must be in \"h48h*k*\" format" 62 LOG("Error parsing solver: must be in \"h48h*k*\" format,"
66 " or \"h48stats\", but got %s\n", fullbuf); 63 " but got %s\n", fullbuf);
67 return -1; 64 return NISSY_ERROR_INVALID_SOLVER;
68} 65}
69 66
70STATIC bool 67STATIC bool
@@ -360,20 +357,6 @@ nissy_getcube(
360} 357}
361 358
362long long 359long long
363nissy_datasize(
364 const char *solver
365)
366{
367 if (solver == NULL) {
368 LOG("Error: 'solver' argument is NULL\n");
369 return NISSY_ERROR_NULL_POINTER;
370 }
371
372 /* gendata() handles a NULL *data as a "dryrun" request */
373 return nissy_gendata(solver, 0, NULL);
374}
375
376long long
377nissy_datainfo( 360nissy_datainfo(
378 uint64_t data_size, 361 uint64_t data_size,
379 const char data[data_size], 362 const char data[data_size],
@@ -423,13 +406,32 @@ nissy_datainfo(
423} 406}
424 407
425long long 408long long
409nissy_datasize(
410 const char *solver
411)
412{
413 /* gendata() handles a NULL *data as a "dryrun" request */
414 return nissy_gendata_unsafe(solver, 0, NULL);
415}
416
417long long
426nissy_gendata( 418nissy_gendata(
427 const char *solver, 419 const char *solver,
428 unsigned long long data_size, 420 unsigned long long data_size,
429 char data[data_size] 421 char data[data_size]
430) 422)
431{ 423{
432 int p; 424 return nissy_gendata_unsafe(solver, data_size, data);
425}
426
427STATIC long long
428nissy_gendata_unsafe(
429 const char *solver,
430 unsigned long long data_size,
431 char *data
432)
433{
434 long long parse_ret;
433 gendata_h48_arg_t arg; 435 gendata_h48_arg_t arg;
434 436
435 if (solver == NULL) { 437 if (solver == NULL) {
@@ -440,10 +442,10 @@ nissy_gendata(
440 arg.buf_size = data_size; 442 arg.buf_size = data_size;
441 arg.buf = data; 443 arg.buf = data;
442 if (!strncmp(solver, "h48", 3)) { 444 if (!strncmp(solver, "h48", 3)) {
443 p = parse_h48_solver(solver, &arg.h, &arg.k); 445 parse_ret = parse_h48_solver(solver, &arg.h, &arg.k);
444 arg.maxdepth = 20; 446 arg.maxdepth = 20;
445 if (p != 0) 447 if (parse_ret != NISSY_OK)
446 return NISSY_ERROR_UNKNOWN; 448 return parse_ret;
447 return gendata_h48(&arg); 449 return gendata_h48(&arg);
448 } else { 450 } else {
449 LOG("gendata: unknown solver %s\n", solver); 451 LOG("gendata: unknown solver %s\n", solver);
@@ -495,7 +497,7 @@ nissy_solve(
495) 497)
496{ 498{
497 cube_t c; 499 cube_t c;
498 int p; 500 long long parse_ret;
499 uint8_t h, k; 501 uint8_t h, k;
500 502
501 if (solver == NULL) { 503 if (solver == NULL) {
@@ -521,20 +523,12 @@ nissy_solve(
521 } 523 }
522 524
523 if (!strncmp(solver, "h48", 3)) { 525 if (!strncmp(solver, "h48", 3)) {
524 if (!strcmp(solver, "h48stats")) 526 parse_ret = parse_h48_solver(solver, &h, &k);
525 return solve_h48stats(c, maxmoves, data, sols); 527 if (parse_ret == NISSY_OK)
526 528 return solve_h48(c, minmoves, maxmoves, maxsols,
527 p = parse_h48_solver(solver, &h, &k);
528 if (p != 0) {
529 LOG("solve: unknown solver %s\n", solver);
530 return NISSY_ERROR_INVALID_SOLVER;
531 } else {
532 return THREADS > 1 ?
533 solve_h48_multithread(c, minmoves, maxmoves,
534 maxsols, data_size, data, sols_size, sols, stats) :
535 solve_h48(c, minmoves, maxmoves, maxsols,
536 data_size, data, sols_size, sols, stats); 529 data_size, data, sols_size, sols, stats);
537 } 530 else
531 return parse_ret;
538 } else { 532 } else {
539 LOG("solve: unknown solver '%s'\n", solver); 533 LOG("solve: unknown solver '%s'\n", solver);
540 return NISSY_ERROR_INVALID_SOLVER; 534 return NISSY_ERROR_INVALID_SOLVER;
diff --git a/src/solvers/h48/coordinate_macros.h b/src/solvers/h48/coordinate_macros.h
index 5b67177..04462d6 100644
--- a/src/solvers/h48/coordinate_macros.h
+++ b/src/solvers/h48/coordinate_macros.h
@@ -2,5 +2,6 @@
2 2
3#define COCLASS_MASK (UINT32_C(0xFFFF) << UINT32_C(16)) 3#define COCLASS_MASK (UINT32_C(0xFFFF) << UINT32_C(16))
4#define COCLASS(x) (((x) & COCLASS_MASK) >> UINT32_C(16)) 4#define COCLASS(x) (((x) & COCLASS_MASK) >> UINT32_C(16))
5#define ECLASS(x) COCLASS(x)
5#define TTREP_MASK (UINT32_C(0xFF) << UINT32_C(8)) 6#define TTREP_MASK (UINT32_C(0xFF) << UINT32_C(8))
6#define TTREP(x) (((x) & TTREP_MASK) >> UINT32_C(8)) 7#define TTREP(x) (((x) & TTREP_MASK) >> UINT32_C(8))
diff --git a/src/solvers/h48/gendata_cocsep.h b/src/solvers/h48/gendata_cocsep.h
index b46bcf3..291ae48 100644
--- a/src/solvers/h48/gendata_cocsep.h
+++ b/src/solvers/h48/gendata_cocsep.h
@@ -1,27 +1,16 @@
1STATIC_INLINE bool get_visited(const uint8_t *, int64_t); 1STATIC_INLINE bool gendata_cocsep_get_visited(const uint8_t *, int64_t);
2STATIC_INLINE void set_visited(uint8_t *, int64_t); 2STATIC_INLINE void gendata_cocsep_set_visited(uint8_t *, int64_t);
3 3
4STATIC size_t gendata_cocsep( 4STATIC size_t gendata_cocsep(
5 char [static COCSEP_FULLSIZE+INFOSIZE], uint64_t *, cube_t *); 5 char [static COCSEP_FULLSIZE], uint64_t *, cube_t *);
6STATIC uint32_t gendata_cocsep_dfs(cocsep_dfs_arg_t *); 6STATIC uint32_t gendata_cocsep_dfs(cocsep_dfs_arg_t *);
7STATIC void getdistribution_cocsep(const uint32_t *, uint64_t [static 21]); 7STATIC void getdistribution_cocsep(const uint32_t *, uint64_t [static 21]);
8 8
9STATIC_INLINE int8_t get_h48_cdata(cube_t, const uint32_t *, uint32_t *); 9STATIC_INLINE int8_t get_h48_cdata(cube_t, const uint32_t *, uint32_t *);
10 10
11/*
12Each element of the cocsep table is a uint32_t used as follows:
13 - Lowest 8-bit block: pruning value
14 - Second-lowest 8-bit block: "ttrep" (transformation to representative)
15 - Top 16-bit block: symcoord value
16After the data as described above, more auxiliary information is appended:
17 - A uint32_t representing the number of symmetry classes
18 - A uint32_t representing the highest value of the pruning table
19 - One uint32_t for each "line" of the pruning table, representing the number
20 of positions having that pruning value.
21*/
22STATIC size_t 11STATIC size_t
23gendata_cocsep( 12gendata_cocsep(
24 char buf[static COCSEP_FULLSIZE+INFOSIZE], 13 char buf[static COCSEP_FULLSIZE],
25 uint64_t *selfsim, 14 uint64_t *selfsim,
26 cube_t *rep 15 cube_t *rep
27) 16)
@@ -36,7 +25,7 @@ gendata_cocsep(
36 goto gendata_cocsep_return_size; 25 goto gendata_cocsep_return_size;
37 26
38 memset(buf, 0xFF, COCSEP_FULLSIZE); 27 memset(buf, 0xFF, COCSEP_FULLSIZE);
39 buf32 = (uint32_t *)((char *)buf + INFOSIZE); 28 buf32 = (uint32_t *)(buf + INFOSIZE);
40 if (selfsim != NULL) 29 if (selfsim != NULL)
41 memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); 30 memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES);
42 31
@@ -69,7 +58,7 @@ gendata_cocsep(
69 info.distribution[i] = cc; 58 info.distribution[i] = cc;
70 } 59 }
71 60
72 writetableinfo(&info, COCSEP_FULLSIZE+INFOSIZE, buf); 61 writetableinfo(&info, COCSEP_FULLSIZE, buf);
73 62
74 DBG_ASSERT(n == COCSEP_CLASSES, 0, 63 DBG_ASSERT(n == COCSEP_CLASSES, 0,
75 "cocsep: computed %" PRIu16 " symmetry classes, " 64 "cocsep: computed %" PRIu16 " symmetry classes, "
@@ -101,9 +90,10 @@ gendata_cocsep_dfs(cocsep_dfs_arg_t *arg)
101 90
102 i = coord_cocsep(arg->cube); 91 i = coord_cocsep(arg->cube);
103 olddepth = (uint8_t)(arg->buf32[i] & 0xFF); 92 olddepth = (uint8_t)(arg->buf32[i] & 0xFF);
104 if (olddepth < arg->depth || get_visited(arg->visited, i)) 93 if (olddepth < arg->depth ||
94 gendata_cocsep_get_visited(arg->visited, i))
105 return 0; 95 return 0;
106 set_visited(arg->visited, i); 96 gendata_cocsep_set_visited(arg->visited, i);
107 97
108 if (arg->depth == arg->maxdepth) { 98 if (arg->depth == arg->maxdepth) {
109 if ((arg->buf32[i] & 0xFF) != 0xFF) 99 if ((arg->buf32[i] & 0xFF) != 0xFF)
@@ -118,7 +108,7 @@ gendata_cocsep_dfs(cocsep_dfs_arg_t *arg)
118 arg->selfsim[*arg->n] |= UINT64_C(1) << t; 108 arg->selfsim[*arg->n] |= UINT64_C(1) << t;
119 if (COCLASS(arg->buf32[j]) != UINT32_C(0xFFFF)) 109 if (COCLASS(arg->buf32[j]) != UINT32_C(0xFFFF))
120 continue; 110 continue;
121 set_visited(arg->visited, j); 111 gendata_cocsep_set_visited(arg->visited, j);
122 tinv = inverse_trans(t); 112 tinv = inverse_trans(t);
123 olddepth = arg->buf32[j] & 0xFF; 113 olddepth = arg->buf32[j] & 0xFF;
124 cc += olddepth == 0xFF; 114 cc += olddepth == 0xFF;
@@ -155,13 +145,13 @@ getdistribution_cocsep(const uint32_t *table, uint64_t distr[static 21])
155} 145}
156 146
157STATIC_INLINE bool 147STATIC_INLINE bool
158get_visited(const uint8_t *a, int64_t i) 148gendata_cocsep_get_visited(const uint8_t *a, int64_t i)
159{ 149{
160 return a[VISITED_IND(i)] & VISITED_MASK(i); 150 return a[VISITED_IND(i)] & VISITED_MASK(i);
161} 151}
162 152
163STATIC_INLINE void 153STATIC_INLINE void
164set_visited(uint8_t *a, int64_t i) 154gendata_cocsep_set_visited(uint8_t *a, int64_t i)
165{ 155{
166 a[VISITED_IND(i)] |= VISITED_MASK(i); 156 a[VISITED_IND(i)] |= VISITED_MASK(i);
167} 157}
diff --git a/src/solvers/h48/gendata_eoesep.h b/src/solvers/h48/gendata_eoesep.h
new file mode 100644
index 0000000..d3b73ea
--- /dev/null
+++ b/src/solvers/h48/gendata_eoesep.h
@@ -0,0 +1,274 @@
1STATIC int64_t coord_eoesep_sym(cube_t, const uint32_t [static ESEP_MAX]);
2STATIC size_t gendata_esep_classes(
3 uint32_t [static ESEP_MAX], uint16_t [static ESEP_CLASSES]);
4STATIC size_t gendata_eoesep(char [static EOESEP_FULLSIZE], uint8_t);
5STATIC uint32_t gendata_eoesep_bfs(uint8_t, uint8_t [static EOESEP_BUF],
6 uint32_t [static ESEP_MAX], uint16_t [static ESEP_CLASSES]);
7STATIC uint32_t gendata_eoesep_fromnew(uint8_t, uint8_t [static EOESEP_BUF],
8 uint32_t [static ESEP_MAX], uint16_t [static ESEP_CLASSES]);
9STATIC uint32_t gendata_eoesep_fromdone(uint8_t, uint8_t [static EOESEP_BUF],
10 uint32_t [static ESEP_MAX], uint16_t [static ESEP_CLASSES]);
11STATIC uint32_t gendata_eoesep_marksim(int64_t, uint8_t,
12 uint8_t [static EOESEP_BUF], uint32_t [static ESEP_MAX]);
13STATIC bool gendata_eoesep_next(cube_t, uint8_t,
14 uint8_t [static EOESEP_BUF], uint32_t [static ESEP_MAX]);
15STATIC uint8_t get_eoesep_pval(const uint8_t *, int64_t);
16STATIC uint8_t get_eoesep_pval_cube(const void *, cube_t);
17STATIC void set_eoesep_pval(uint8_t *, int64_t, uint8_t);
18
19STATIC int64_t
20coord_eoesep_sym(cube_t c, const uint32_t esep_classes[static ESEP_MAX])
21{
22 uint8_t ttrep;
23 uint32_t edata, class;
24 int64_t esep, eo;
25
26 esep = coord_esep(c);
27 edata = esep_classes[esep];
28 class = ECLASS(edata);
29 ttrep = TTREP(edata);
30 eo = coord_eo(transform(c, ttrep));
31
32 return (class << UINT32_C(11)) + eo;
33}
34
35STATIC size_t
36gendata_esep_classes(
37 uint32_t esep_classes[static ESEP_MAX],
38 uint16_t rep[static ESEP_CLASSES]
39)
40{
41 bool visited[ESEP_MAX];
42 uint8_t t;
43 uint32_t class, cl, ti;
44 int64_t i, j;
45 cube_t c;
46
47 memset(visited, 0, ESEP_MAX * sizeof(bool));
48 class = 0;
49 for (i = 0; i < ESEP_MAX; i++) {
50 if (visited[i])
51 continue;
52 c = invcoord_esep(i);
53 for (t = 0; t < 48; t++) {
54 j = coord_esep(transform(c, t));
55 cl = class << UINT32_C(16);
56 ti = inverse_trans(t) << UINT32_C(8);
57 esep_classes[j] = cl | ti;
58 visited[j] = true;
59 }
60 rep[class] = i;
61 class++;
62 }
63
64 return class;
65}
66
67STATIC size_t
68gendata_eoesep(char buf[static EOESEP_FULLSIZE], uint8_t maxdepth)
69{
70 uint8_t *buf8, d;
71 uint16_t rep[ESEP_CLASSES];
72 uint32_t *esep_classes, done, level;
73 int64_t coord;
74 tableinfo_t info;
75
76 if (buf == NULL)
77 goto gendata_eoesep_return_size;
78
79 LOG("Computing eoesep data\n");
80 memset(buf, 0xFF, EOESEP_FULLSIZE);
81 esep_classes = (uint32_t *)(buf + INFOSIZE);
82 buf8 = (uint8_t *)(buf + INFOSIZE + 4*ESEP_MAX);
83 gendata_esep_classes(esep_classes, rep);
84
85 info = (tableinfo_t) {
86 .solver = "eoesep data for h48",
87 .type = TABLETYPE_SPECIAL,
88 .infosize = INFOSIZE,
89 .fullsize = EOESEP_FULLSIZE,
90 .hash = 0,
91 .entries = EOESEP_TABLESIZE,
92 .classes = ESEP_CLASSES,
93 .bits = 4,
94 .base = 0,
95 .maxvalue = 11,
96 .next = 0
97 };
98
99 coord = 0; /* Assumed coordinate of solved cube */
100 set_eoesep_pval(buf8, coord, 0);
101 done = 1;
102 info.distribution[0] = 1;
103 for (d = 1; d <= maxdepth && done < EOESEP_TABLESIZE; d++) {
104 level = gendata_eoesep_bfs(d, buf8, esep_classes, rep);
105 done += level;
106 info.distribution[d] = level;
107 }
108
109 writetableinfo(&info, EOESEP_FULLSIZE, buf);
110
111 LOG("eoesep data computed\n");
112
113gendata_eoesep_return_size:
114 return EOESEP_FULLSIZE;
115}
116
117STATIC uint32_t
118gendata_eoesep_bfs(
119 uint8_t d,
120 uint8_t buf8[EOESEP_BUF],
121 uint32_t esep_classes[static ESEP_MAX],
122 uint16_t rep[static ESEP_CLASSES]
123)
124{
125 if (d < 9)
126 return gendata_eoesep_fromdone(d, buf8, esep_classes, rep);
127 else
128 return gendata_eoesep_fromnew(d, buf8, esep_classes, rep);
129}
130
131STATIC uint32_t
132gendata_eoesep_fromdone(
133 uint8_t d,
134 uint8_t buf8[EOESEP_BUF],
135 uint32_t esep_classes[static ESEP_MAX],
136 uint16_t rep[static ESEP_CLASSES]
137)
138{
139 uint8_t pval;
140 int64_t i, esep, eo, coord, done;
141
142 done = 0;
143 for (i = 0; i < (int64_t)ESEP_CLASSES; i++) {
144 esep = rep[i];
145 for (eo = 0; eo < POW_2_11; eo++) {
146 coord = (i << INT64_C(11)) + eo;
147 pval = get_eoesep_pval(buf8, coord);
148 if (pval != d-1)
149 continue;
150
151 coord = (esep << INT64_C(11)) + eo;
152 done += gendata_eoesep_marksim(
153 coord, d, buf8, esep_classes);
154 }
155 }
156
157 return done;
158}
159
160STATIC uint32_t
161gendata_eoesep_fromnew(
162 uint8_t d,
163 uint8_t buf8[EOESEP_BUF],
164 uint32_t esep_classes[static ESEP_MAX],
165 uint16_t rep[static ESEP_CLASSES]
166)
167{
168 uint8_t pval;
169 int64_t i, esep, eo, coord, done;
170 cube_t c;
171
172 done = 0;
173 for (i = 0; i < (int64_t)ESEP_CLASSES; i++) {
174 esep = rep[i];
175 for (eo = 0; eo < POW_2_11; eo++) {
176 coord = (i << INT64_C(11)) + eo;
177 pval = get_eoesep_pval(buf8, coord);
178 if (pval != 15)
179 continue;
180
181 c = invcoord_eoesep((esep << INT64_C(11)) + eo);
182 if (gendata_eoesep_next(c, d, buf8, esep_classes)) {
183 set_eoesep_pval(buf8, coord, d);
184 done++;
185 }
186 }
187 }
188
189 return done;
190}
191
192STATIC uint32_t
193gendata_eoesep_marksim(
194 int64_t i,
195 uint8_t d,
196 uint8_t buf8[static EOESEP_BUF],
197 uint32_t esep_classes[static ESEP_MAX]
198)
199{
200 uint8_t t, m, pval;
201 cube_t c, moved, transformed;
202 uint32_t done;
203 int64_t coord;
204
205 done = 0;
206 c = invcoord_eoesep(i);
207 for (m = 0; m < 18; m++) {
208 moved = move(c, m);
209 for (t = 0; t < 48; t++) {
210 transformed = transform(moved, t);
211 coord = coord_eoesep_sym(transformed, esep_classes);
212 pval = get_eoesep_pval(buf8, coord);
213 if (pval > d) {
214 set_eoesep_pval(buf8, coord, d);
215 done++;
216 }
217 }
218 }
219
220 return done;
221}
222
223STATIC bool
224gendata_eoesep_next(
225 cube_t c,
226 uint8_t d,
227 uint8_t buf8[static EOESEP_BUF],
228 uint32_t esep_classes[static ESEP_MAX]
229)
230{
231 uint8_t m, t, pval;
232 int64_t coord;
233 cube_t moved, transformed;
234
235 for (t = 0; t < 48; t++) {
236 transformed = transform(c, t);
237 for (m = 0; m < 18; m++) {
238 moved = move(transformed, m);
239 coord = coord_eoesep_sym(moved, esep_classes);
240 pval = get_eoesep_pval(buf8, coord);
241 if (pval == d-1)
242 return true;
243 }
244 }
245
246 return false;
247}
248
249STATIC uint8_t
250get_eoesep_pval(const uint8_t *table, int64_t i)
251{
252 return (table[EOESEP_INDEX(i)] & EOESEP_MASK(i)) >> EOESEP_SHIFT(i);
253}
254
255STATIC uint8_t
256get_eoesep_pval_cube(const void *data, cube_t c)
257{
258 int64_t coord;
259 const uint8_t *table;
260 const uint32_t *esep_classes;
261
262 esep_classes = (const uint32_t *)data;
263 table = (const uint8_t *)data + 4*ESEP_MAX;
264 coord = coord_eoesep_sym(c, esep_classes);
265
266 return get_eoesep_pval(table, coord);
267}
268
269STATIC void
270set_eoesep_pval(uint8_t *table, int64_t i, uint8_t val)
271{
272 table[EOESEP_INDEX(i)] = (table[EOESEP_INDEX(i)] & (~EOESEP_MASK(i)))
273 | (val << EOESEP_SHIFT(i));
274}
diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h
index 55c4f34..ae0b732 100644
--- a/src/solvers/h48/gendata_h48.h
+++ b/src/solvers/h48/gendata_h48.h
@@ -61,13 +61,13 @@ gendata_h48short(gendata_h48short_arg_t *arg)
61 return arg->map->n; 61 return arg->map->n;
62} 62}
63 63
64/* Generic function that dispatches to the data generators */
65STATIC int64_t 64STATIC int64_t
66gendata_h48(gendata_h48_arg_t *arg) 65gendata_h48(gendata_h48_arg_t *arg)
67{ 66{
68 uint64_t size, cocsepsize, h48size, fallbacksize; 67 uint64_t size, cocsepsize, h48size, fallbacksize, fallback2size, of;
68 long long r;
69 void *cocsepdata_offset; 69 void *cocsepdata_offset;
70 tableinfo_t cocsepinfo, h48info; 70 tableinfo_t cocsepinfo, h48info, fallbackinfo;
71 gendata_h48_arg_t arg_h0k4; 71 gendata_h48_arg_t arg_h0k4;
72 72
73 if (arg == NULL) { 73 if (arg == NULL) {
@@ -78,7 +78,8 @@ gendata_h48(gendata_h48_arg_t *arg)
78 cocsepsize = COCSEP_FULLSIZE; 78 cocsepsize = COCSEP_FULLSIZE;
79 h48size = INFOSIZE + H48_TABLESIZE(arg->h, arg->k); 79 h48size = INFOSIZE + H48_TABLESIZE(arg->h, arg->k);
80 fallbacksize = arg->k == 2 ? INFOSIZE + H48_TABLESIZE(0, 4) : 0; 80 fallbacksize = arg->k == 2 ? INFOSIZE + H48_TABLESIZE(0, 4) : 0;
81 size = cocsepsize + h48size + fallbacksize; 81 fallback2size = EOESEP_FULLSIZE;
82 size = cocsepsize + h48size + fallbacksize + fallback2size;
82 83
83 if (arg->buf == NULL) 84 if (arg->buf == NULL)
84 return size; /* Dry-run */ 85 return size; /* Dry-run */
@@ -110,18 +111,22 @@ gendata_h48(gendata_h48_arg_t *arg)
110 return NISSY_ERROR_INVALID_SOLVER; 111 return NISSY_ERROR_INVALID_SOLVER;
111 } 112 }
112 113
113 if (readtableinfo(arg->buf_size, arg->buf, &cocsepinfo) != NISSY_OK) { 114 r = readtableinfo(arg->buf_size, arg->buf, &cocsepinfo);
115 if (r != NISSY_OK) {
114 LOG("gendata_h48: could not read info for cocsep table\n"); 116 LOG("gendata_h48: could not read info for cocsep table\n");
115 return NISSY_ERROR_UNKNOWN; 117 return NISSY_ERROR_UNKNOWN;
116 } 118 }
117 119
118 cocsepinfo.next = cocsepsize; 120 cocsepinfo.next = cocsepsize;
119 if (writetableinfo(&cocsepinfo, arg->buf_size, arg->buf) != NISSY_OK) { 121 r = writetableinfo(&cocsepinfo, arg->buf_size, arg->buf);
122 if (r != NISSY_OK) {
120 LOG("gendata_h48: could not write info for cocsep table" 123 LOG("gendata_h48: could not write info for cocsep table"
121 " with updated 'next' value\n"); 124 " with updated 'next' value\n");
122 return NISSY_ERROR_UNKNOWN; 125 return NISSY_ERROR_UNKNOWN;
123 } 126 }
124 127
128 /* Add h0k4 fallback table */
129
125 if (arg->k == 2) { 130 if (arg->k == 2) {
126 arg_h0k4 = *arg; 131 arg_h0k4 = *arg;
127 arg_h0k4.h = 0; 132 arg_h0k4.h = 0;
@@ -134,16 +139,42 @@ gendata_h48(gendata_h48_arg_t *arg)
134 139
135 gendata_h48h0k4(&arg_h0k4); 140 gendata_h48h0k4(&arg_h0k4);
136 141
137 if (readtableinfo_n(arg->buf_size, arg->buf, 2, &h48info) 142 }
138 != NISSY_OK) { 143
139 LOG("gendata_h48: could not read info for h48 table\n"); 144 /* Add eoesep fallback table */
145
146 gendata_eoesep((char *)arg->buf + (size - fallback2size), 20);
147
148 /* Update tableinfo with correct next values */
149
150 r = readtableinfo_n(arg->buf_size, arg->buf, 2, &h48info);
151 if (r != NISSY_OK) {
152 LOG("gendata_h48: could not read info for h48 table\n");
153 return NISSY_ERROR_UNKNOWN;
154 }
155 h48info.next = h48size;
156 r = writetableinfo(&h48info,
157 arg->buf_size - cocsepsize, (char *)arg->buf + cocsepsize);
158 if (r != NISSY_OK) {
159 LOG("gendata_h48: could not write info for h48 table\n");
160 return NISSY_ERROR_UNKNOWN;
161 }
162
163 if (arg->k == 2) {
164 r = readtableinfo_n(arg->buf_size, arg->buf, 3, &fallbackinfo);
165 if (r != NISSY_OK) {
166 LOG("gendata_h48: could not read info for h48 "
167 "fallback table\n");
140 return NISSY_ERROR_UNKNOWN; 168 return NISSY_ERROR_UNKNOWN;
141 } 169 }
142 170
143 h48info.next = h48size; 171 of = cocsepsize + h48size;
144 if (writetableinfo(&h48info, arg->buf_size - cocsepsize, 172 fallbackinfo.next = fallbacksize;
145 (char *)arg->buf + cocsepsize) != NISSY_OK) { 173 r = writetableinfo(&fallbackinfo,
146 LOG("gendata_h48: could not write info for h48 table\n"); 174 arg->buf_size - of, (char *)arg->buf + of);
175 if (r != NISSY_OK) {
176 LOG("gendata_h48: could not write info for h48 "
177 "fallback table\n");
147 return NISSY_ERROR_UNKNOWN; 178 return NISSY_ERROR_UNKNOWN;
148 } 179 }
149 } 180 }
@@ -302,9 +333,8 @@ gendata_h48k2(gendata_h48_arg_t *arg)
302 * 333 *
303 * The following values for the base have been hand-picked. I first 334 * The following values for the base have been hand-picked. I first
304 * performed some statistics on the frequency of these values, but 335 * performed some statistics on the frequency of these values, but
305 * they turned out to be unreliable. I have not figured out why yet. 336 * they turned out to be unreliable. In the end I generated the same
306 * In the end I resorted to generating the same table with multiple 337 * table with multiple base value and see what was best.
307 * base value and see what was best.
308 * 338 *
309 * A curious case is h3, which has this distribution for base 8: 339 * A curious case is h3, which has this distribution for base 8:
310 * [0] = 6686828 340 * [0] = 6686828
diff --git a/src/solvers/h48/gendata_types_macros.h b/src/solvers/h48/gendata_types_macros.h
index 73a46ff..d7c88af 100644
--- a/src/solvers/h48/gendata_types_macros.h
+++ b/src/solvers/h48/gendata_types_macros.h
@@ -3,13 +3,22 @@
3#define COCSEP_VISITEDSIZE DIV_ROUND_UP(COCSEP_TABLESIZE, (size_t)8) 3#define COCSEP_VISITEDSIZE DIV_ROUND_UP(COCSEP_TABLESIZE, (size_t)8)
4#define COCSEP_FULLSIZE (INFOSIZE + (size_t)4 * COCSEP_TABLESIZE) 4#define COCSEP_FULLSIZE (INFOSIZE + (size_t)4 * COCSEP_TABLESIZE)
5 5
6#define ESEP_MAX (COMB_12_4 * COMB_8_4)
7#define ESEP_CLASSES ((size_t)782)
8#define EOESEP_TABLESIZE (ESEP_CLASSES << (size_t)11)
9#define EOESEP_BUF DIV_ROUND_UP(EOESEP_TABLESIZE, 2)
10#define EOESEP_FULLSIZE (INFOSIZE + EOESEP_BUF + (size_t)4 * ESEP_MAX)
11#define EOESEP_INDEX(i) ((i)/2)
12#define EOESEP_SHIFT(i) (UINT8_C(4) * (uint8_t)((i) % 2))
13#define EOESEP_MASK(i) (UINT8_C(0xF) << EOESEP_SHIFT(i))
14
6#define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8)) 15#define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8))
7#define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) 16#define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8)))
8 17
9#define CBOUND_MASK UINT32_C(0xFF) 18#define CBOUND_MASK UINT32_C(0xFF)
10#define CBOUND(x) ((x) & CBOUND_MASK) 19#define CBOUND(x) ((x) & CBOUND_MASK)
11 20
12#define H48_COORDMAX_NOEO ((int64_t)(COCSEP_CLASSES * COMB_12_4 * COMB_8_4)) 21#define H48_COORDMAX_NOEO ((int64_t)(COCSEP_CLASSES * ESEP_MAX))
13#define H48_COORDMAX(h) (H48_COORDMAX_NOEO << (int64_t)(h)) 22#define H48_COORDMAX(h) (H48_COORDMAX_NOEO << (int64_t)(h))
14#define H48_DIV(k) ((size_t)8 / (size_t)(k)) 23#define H48_DIV(k) ((size_t)8 / (size_t)(k))
15#define H48_TABLESIZE(h, k) DIV_ROUND_UP((size_t)H48_COORDMAX((h)), H48_DIV(k)) 24#define H48_TABLESIZE(h, k) DIV_ROUND_UP((size_t)H48_COORDMAX((h)), H48_DIV(k))
diff --git a/src/solvers/h48/h48.h b/src/solvers/h48/h48.h
index 3cf02b7..d5a67ef 100644
--- a/src/solvers/h48/h48.h
+++ b/src/solvers/h48/h48.h
@@ -2,7 +2,6 @@
2#include "map.h" 2#include "map.h"
3#include "gendata_types_macros.h" 3#include "gendata_types_macros.h"
4#include "gendata_cocsep.h" 4#include "gendata_cocsep.h"
5#include "gendata_eoesep.h"
5#include "gendata_h48.h" 6#include "gendata_h48.h"
6#include "stats.h"
7#include "solve.h" 7#include "solve.h"
8#include "solve_multithread.h"
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index d506596..8666007 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -1,9 +1,26 @@
1#define STARTING_MOVES 3
2#define STARTING_CUBES 3240 /* Number of 3-move sequences */
3
4typedef struct {
5 cube_t cube;
6 uint8_t moves[STARTING_MOVES];
7 uint64_t symmask0;
8} solve_h48_task_t;
9
1typedef struct { 10typedef struct {
11 cube_t start_cube;
12 uint64_t symmask0;
2 cube_t cube; 13 cube_t cube;
3 cube_t inverse; 14 cube_t inverse;
4 int8_t nmoves;
5 int8_t depth; 15 int8_t depth;
16 int8_t nmoves;
6 uint8_t moves[MAXLEN]; 17 uint8_t moves[MAXLEN];
18 int8_t npremoves;
19 uint8_t premoves[MAXLEN];
20 int8_t lb_normal;
21 int8_t lb_inverse;
22 bool use_lb_normal;
23 bool use_lb_inverse;
7 _Atomic int64_t *nsols; 24 _Atomic int64_t *nsols;
8 int64_t maxsolutions; 25 int64_t maxsolutions;
9 uint8_t h; 26 uint8_t h;
@@ -11,209 +28,385 @@ typedef struct {
11 uint8_t base; 28 uint8_t base;
12 const uint32_t *cocsepdata; 29 const uint32_t *cocsepdata;
13 const uint8_t *h48data; 30 const uint8_t *h48data;
14 const uint8_t *h48data_fallback; 31 const uint8_t *h48data_fallback_h0k4;
32 const void *h48data_fallback_eoesep;
15 uint64_t solutions_size; 33 uint64_t solutions_size;
16 char **nextsol; 34 uint64_t *solutions_used;
17 uint8_t nissbranch; 35 char **solutions;
18 int8_t npremoves; 36 uint32_t movemask_normal;
19 uint8_t premoves[MAXLEN]; 37 uint32_t movemask_inverse;
20 long long nodes_visited; 38 int64_t nodes_visited;
21 long long table_fallbacks; 39 int64_t table_fallbacks;
22} dfsarg_solveh48_t; 40 int64_t table_lookups;
41 int ntasks;
42 solve_h48_task_t *tasks;
43 int thread_id;
44 pthread_mutex_t *solutions_mutex;
45} dfsarg_solve_h48_t;
23 46
24STATIC uint32_t allowednextmove_h48(uint8_t *, uint8_t, uint8_t); 47typedef struct {
48 cube_t cube;
49 int8_t nmoves;
50 uint8_t moves[STARTING_MOVES];
51 int8_t minmoves;
52 int8_t maxmoves;
53} dfsarg_solve_h48_maketasks_t;
25 54
26STATIC void solve_h48_appendsolution(dfsarg_solveh48_t *); 55STATIC int64_t solve_h48_appendsolution(dfsarg_solve_h48_t *);
27STATIC_INLINE bool solve_h48_stop(dfsarg_solveh48_t *); 56STATIC bool solve_h48_appendmoves(dfsarg_solve_h48_t *, int8_t,
28STATIC int64_t solve_h48_dfs(dfsarg_solveh48_t *); 57 uint8_t *, uint8_t);
29STATIC int64_t solve_h48(cube_t, int8_t, int8_t, int8_t, uint64_t, 58STATIC bool solve_h48_appendchar(dfsarg_solve_h48_t *, char);
59STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t *);
60STATIC int64_t solve_h48_maketasks(
61 dfsarg_solve_h48_t *, dfsarg_solve_h48_maketasks_t *,
62 solve_h48_task_t [static STARTING_CUBES], int *);
63STATIC void *solve_h48_runthread(void *);
64STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t *);
65STATIC int64_t solve_h48(cube_t, int8_t, int8_t, uint64_t, uint64_t,
30 const void *, uint64_t, char *, long long [static NISSY_SIZE_SOLVE_STATS]); 66 const void *, uint64_t, char *, long long [static NISSY_SIZE_SOLVE_STATS]);
31 67
32STATIC uint32_t 68STATIC int64_t
33allowednextmove_h48(uint8_t *moves, uint8_t n, uint8_t h48branch) 69solve_h48_appendsolution(dfsarg_solve_h48_t *arg)
34{ 70{
35 uint32_t result = MM_ALLMOVES; 71 uint8_t t;
36 if (h48branch & MM_NORMALBRANCH) 72 int64_t ret;
37 result &= MM_NOHALFTURNS; 73 uint64_t solstart;
38 if (n < 1)
39 return result;
40 74
41 uint8_t base1 = movebase(moves[n-1]); 75 if (*arg->nsols >= arg->maxsolutions)
42 uint8_t axis1 = moveaxis(moves[n-1]); 76 return 0;
43 77
44 result = disable_moves(result, base1 * 3); 78 solstart = *arg->solutions_used;
45 if (base1 % 2) 79 invertmoves(arg->premoves, arg->npremoves, arg->moves + arg->nmoves);
46 result = disable_moves(result, (base1 - 1) * 3);
47 80
48 if (n == 1) 81 /* Do not append the solution in case premoves cancel with normal */
49 return result; 82 if (arg->npremoves > 0 && !allowednextmove(arg->moves, arg->nmoves+1))
83 return 0;
84 if (arg->npremoves > 1 && !allowednextmove(arg->moves, arg->nmoves+2))
85 return 0;
50 86
51 uint8_t base2 = movebase(moves[n-2]); 87 for (t = 0, ret = 0; t < 48 && *arg->nsols < arg->maxsolutions; t++) {
52 uint8_t axis2 = moveaxis(moves[n-2]); 88 if (!(arg->symmask0 & (UINT64_C(1) << (uint64_t)t)))
89 continue;
53 90
54 if(axis1 == axis2) 91 if (!solve_h48_appendmoves(arg, arg->nmoves + arg->npremoves,
55 result = disable_moves(result, base2 * 3); 92 arg->moves, t))
93 goto solve_h48_appendsolution_error;
94
95 LOG("Solution found: %s\n", *arg->solutions + solstart);
56 96
57 return result; 97 if (!solve_h48_appendchar(arg, '\n'))
98 goto solve_h48_appendsolution_error;
99 (*arg->nsols)++;
100 ret++;
101 }
102
103 return ret;
104
105solve_h48_appendsolution_error:
106 LOG("Could not append solution to buffer: size too small\n");
107 return NISSY_ERROR_BUFFER_SIZE;
58} 108}
59 109
60STATIC void 110STATIC bool
61solve_h48_appendsolution(dfsarg_solveh48_t *arg) 111solve_h48_appendmoves(
112 dfsarg_solve_h48_t *arg,
113 int8_t n,
114 uint8_t *moves,
115 uint8_t t
116)
62{ 117{
118 int i;
63 int64_t strl; 119 int64_t strl;
64 uint8_t invertedpremoves[MAXLEN]; 120 uint8_t mm[MAXLEN];
65 char *solution = *arg->nextsol;
66 121
67 strl = writemoves( 122 for (i = 0; i < n; i++)
68 arg->moves, arg->nmoves, arg->solutions_size, *arg->nextsol); 123 mm[i] = transform_move(moves[i], t);
69 124
70 if (strl < 0) 125 strl = writemoves(mm, n, arg->solutions_size - *arg->solutions_used,
71 goto solve_h48_appendsolution_error; 126 *arg->solutions + *arg->solutions_used);
72 *arg->nextsol += strl-1;
73 arg->solutions_size -= strl-1;
74 127
75 if (arg->npremoves) { 128 if (strl < 0)
76 **arg->nextsol = ' '; 129 return false;
77 (*arg->nextsol)++;
78 arg->solutions_size--;
79 130
80 invertmoves(arg->premoves, arg->npremoves, invertedpremoves); 131 *arg->solutions_used += MAX(0, strl-1);
81 strl = writemoves(invertedpremoves, 132 return true;
82 arg->npremoves, arg->solutions_size, *arg->nextsol); 133}
83 134
84 if (strl < 0) 135STATIC bool
85 goto solve_h48_appendsolution_error; 136solve_h48_appendchar(dfsarg_solve_h48_t *arg, char c)
86 *arg->nextsol += strl-1; 137{
87 arg->solutions_size -= strl-1; 138 if (arg->solutions_size <= *arg->solutions_used)
88 } 139 return false;
89 LOG("Solution found: %s\n", solution);
90 140
91 **arg->nextsol = '\n'; 141 *(*arg->solutions + *arg->solutions_used) = c;
92 (*arg->nextsol)++; 142 (*arg->solutions_used)++;
93 arg->solutions_size--;
94 (*arg->nsols)++;
95 143
96solve_h48_appendsolution_error: 144 return true;
97 /* We could add some logging, but writemoves() already does */
98 return;
99} 145}
100 146
101STATIC_INLINE bool 147STATIC_INLINE bool
102solve_h48_stop(dfsarg_solveh48_t *arg) 148solve_h48_stop(dfsarg_solve_h48_t *arg)
103{ 149{
104 uint32_t data, data_inv; 150 uint32_t data, data_inv;
105 int8_t cbound, cbound_inv, h48bound, h48bound_inv; 151 int64_t coord;
106 int64_t coord, coord_inv; 152 int8_t target, nh;
153 uint8_t pval_cocsep, pval_eoesep;
107 154
155 target = arg->depth - arg->nmoves - arg->npremoves;
156 if (target <= 0 || *arg->nsols == arg->maxsolutions)
157 return true;
158
159 arg->movemask_normal = arg->movemask_inverse = MM_ALLMOVES;
108 arg->nodes_visited++; 160 arg->nodes_visited++;
109 161
110 arg->nissbranch = MM_NORMAL; 162 /* Preliminary probing using last computed bound, if possible */
111 cbound = get_h48_cdata(arg->cube, arg->cocsepdata, &data); 163
112 if (cbound + arg->nmoves + arg->npremoves > arg->depth) 164 if ((arg->use_lb_normal && arg->lb_normal > target) ||
165 (arg->use_lb_inverse && arg->lb_inverse > target))
113 return true; 166 return true;
114 167
115 cbound_inv = get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv); 168 /* Preliminary corner probing */
116 if (cbound_inv + arg->nmoves + arg->npremoves > arg->depth) 169
170 if (get_h48_cdata(arg->cube, arg->cocsepdata, &data) > target ||
171 get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv) > target)
117 return true; 172 return true;
118 173
119 coord = coord_h48_edges(arg->cube, COCLASS(data), TTREP(data), arg->h); 174 /* Inverse probing */
120 h48bound = get_h48_pval(arg->h48data, coord, arg->k);
121 175
122 /* If the h48 bound is > 0, we add the base value. */ 176 if (!arg->use_lb_inverse) {
123 /* Otherwise, we use the fallback h0k4 value instead. */ 177 coord = coord_h48_edges(
178 arg->inverse, COCLASS(data_inv), TTREP(data_inv), arg->h);
179 arg->lb_inverse = get_h48_pval(arg->h48data, coord, arg->k);
180 arg->table_lookups++;
124 181
125 if (arg->k == 2) { 182 if (arg->k == 2 && arg->lb_inverse == 0) {
126 if (h48bound == 0) {
127 arg->table_fallbacks++; 183 arg->table_fallbacks++;
128 h48bound = get_h48_pval( 184
129 arg->h48data_fallback, coord >> arg->h, 4); 185 pval_cocsep = get_h48_pval(
186 arg->h48data_fallback_h0k4, coord >> arg->h, 4);
187 pval_eoesep = get_eoesep_pval_cube(
188 arg->h48data_fallback_eoesep, arg->inverse);
189 arg->lb_inverse = MAX(pval_cocsep, pval_eoesep);
130 } else { 190 } else {
131 h48bound += arg->base; 191 arg->lb_inverse += arg->base;
132 } 192 }
193
194 arg->use_lb_inverse = true;
133 } 195 }
134 if (h48bound + arg->nmoves + arg->npremoves > arg->depth) 196
197 if (arg->lb_inverse > target)
135 return true; 198 return true;
136 if (h48bound + arg->nmoves + arg->npremoves == arg->depth) 199 nh = arg->lb_inverse == target;
137 arg->nissbranch = MM_INVERSEBRANCH; 200 arg->movemask_normal = nh * MM_NOHALFTURNS + (1-nh) * MM_ALLMOVES;
201
202 /* Normal probing */
138 203
139 coord_inv = coord_h48_edges( 204 if (!arg->use_lb_normal) {
140 arg->inverse, COCLASS(data_inv), TTREP(data_inv), arg->h); 205 coord = coord_h48_edges(
141 h48bound_inv = get_h48_pval(arg->h48data, coord_inv, arg->k); 206 arg->cube, COCLASS(data), TTREP(data), arg->h);
142 if (arg->k == 2) { 207 arg->lb_normal = get_h48_pval(arg->h48data, coord, arg->k);
143 if (h48bound_inv == 0) { 208 arg->table_lookups++;
209
210 if (arg->k == 2 && arg->lb_normal == 0) {
144 arg->table_fallbacks++; 211 arg->table_fallbacks++;
145 h48bound_inv = get_h48_pval( 212
146 arg->h48data_fallback, coord_inv >> arg->h, 4); 213 pval_cocsep = get_h48_pval(
214 arg->h48data_fallback_h0k4, coord >> arg->h, 4);
215 pval_eoesep = get_eoesep_pval_cube(
216 arg->h48data_fallback_eoesep, arg->cube);
217 arg->lb_normal = MAX(pval_cocsep, pval_eoesep);
147 } else { 218 } else {
148 h48bound_inv += arg->base; 219 arg->lb_normal += arg->base;
149 } 220 }
221
222 arg->use_lb_normal = true;
150 } 223 }
151 if (h48bound_inv + arg->nmoves + arg->npremoves > arg->depth) 224
225 if (arg->lb_normal > target)
152 return true; 226 return true;
153 if (h48bound_inv + arg->nmoves + arg->npremoves == arg->depth) 227 nh = arg->lb_normal == target;
154 arg->nissbranch = MM_NORMALBRANCH; 228 arg->movemask_inverse = nh * MM_NOHALFTURNS + (1-nh) * MM_ALLMOVES;
155 229
156 return false; 230 return false;
157} 231}
158 232
159STATIC int64_t 233STATIC int64_t
160solve_h48_dfs(dfsarg_solveh48_t *arg) 234solve_h48_dfs(dfsarg_solve_h48_t *arg)
161{ 235{
162 dfsarg_solveh48_t nextarg; 236 int64_t ret, n;
163 int64_t ret; 237 uint8_t m, lbn, lbi;
164 uint8_t m; 238 uint32_t mm_normal, mm_inverse;
165 239 bool ulbi, ulbn;
166 if (*arg->nsols == arg->maxsolutions) 240 cube_t backup_cube, backup_inverse;
167 return 0;
168
169 if (solve_h48_stop(arg))
170 return 0;
171 241
172 if (issolved(arg->cube)) { 242 if (issolved(arg->cube)) {
173 if (arg->nmoves + arg->npremoves != arg->depth) 243 if (arg->nmoves + arg->npremoves != arg->depth)
174 return 0; 244 return 0;
175 solve_h48_appendsolution(arg); 245 pthread_mutex_lock(arg->solutions_mutex);
176 return 1; 246 ret = solve_h48_appendsolution(arg);
247 pthread_mutex_unlock(arg->solutions_mutex);
248 return ret;
177 } 249 }
178 250
179 nextarg = *arg; 251 if (solve_h48_stop(arg))
252 return 0;
253
254 backup_cube = arg->cube;
255 backup_inverse = arg->inverse;
256 lbn = arg->lb_normal;
257 lbi = arg->lb_inverse;
258 ulbn = arg->use_lb_normal;
259 ulbi = arg->use_lb_inverse;
260
180 ret = 0; 261 ret = 0;
181 uint32_t allowed; 262 mm_normal = allowednextmove_mask(arg->moves, arg->nmoves) &
182 if(arg->nissbranch & MM_INVERSE) { 263 arg->movemask_normal;
183 allowed = allowednextmove_h48(arg->premoves, arg->npremoves, arg->nissbranch); 264 mm_inverse = allowednextmove_mask(arg->premoves, arg->npremoves) &
265 arg->movemask_inverse;
266 if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) {
267 arg->nmoves++;
184 for (m = 0; m < 18; m++) { 268 for (m = 0; m < 18; m++) {
185 if(allowed & (1 << m)) { 269 if (!(mm_normal & (1 << m)))
186 nextarg.npremoves = arg->npremoves + 1; 270 continue;
187 nextarg.premoves[arg->npremoves] = m; 271 arg->moves[arg->nmoves-1] = m;
188 nextarg.inverse = move(arg->inverse, m); 272 arg->cube = move(backup_cube, m);
189 nextarg.cube = premove(arg->cube, m); 273 arg->inverse = premove(backup_inverse, m);
190 ret += solve_h48_dfs(&nextarg); 274 arg->lb_inverse = lbi;
191 } 275 arg->use_lb_normal = false;
276 arg->use_lb_inverse = ulbi && m % 3 == 1;
277 n = solve_h48_dfs(arg);
278 if (n < 0)
279 return n;
280 ret += n;
192 } 281 }
282 arg->nmoves--;
193 } else { 283 } else {
194 allowed = allowednextmove_h48(arg->moves, arg->nmoves, arg->nissbranch); 284 arg->npremoves++;
195 for (m = 0; m < 18; m++) { 285 for (m = 0; m < 18; m++) {
196 if (allowed & (1 << m)) { 286 if(!(mm_inverse & (1 << m)))
197 nextarg.nmoves = arg->nmoves + 1; 287 continue;
198 nextarg.moves[arg->nmoves] = m; 288 arg->premoves[arg->npremoves-1] = m;
199 nextarg.cube = move(arg->cube, m); 289 arg->inverse = move(backup_inverse, m);
200 nextarg.inverse = premove(arg->inverse, m); 290 arg->cube = premove(backup_cube, m);
201 ret += solve_h48_dfs(&nextarg); 291 arg->lb_normal = lbn;
202 } 292 arg->use_lb_inverse = false;
293 arg->use_lb_normal = ulbn && m % 3 == 1;
294 n = solve_h48_dfs(arg);
295 if (n < 0)
296 return n;
297 ret += n;
203 } 298 }
299 arg->npremoves--;
204 } 300 }
205 301
206 arg->nodes_visited = nextarg.nodes_visited; 302 arg->cube = backup_cube;
207 arg->table_fallbacks = nextarg.table_fallbacks; 303 arg->inverse = backup_inverse;
304
208 return ret; 305 return ret;
209} 306}
210 307
308STATIC void *
309solve_h48_runthread(void *arg)
310{
311 int i, j;
312 solve_h48_task_t task;
313 dfsarg_solve_h48_t * dfsarg;
314 cube_t cube;
315
316 dfsarg = (dfsarg_solve_h48_t *)arg;
317 cube = dfsarg->start_cube;
318
319 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += THREADS) {
320 task = dfsarg->tasks[i];
321 memcpy(dfsarg->moves, task.moves, STARTING_MOVES);
322 dfsarg->cube = cube;
323 for (j = 0; j < STARTING_MOVES; j++)
324 dfsarg->cube = move(
325 dfsarg->cube, dfsarg->moves[j]);
326 dfsarg->inverse = inverse(dfsarg->cube);
327 dfsarg->nmoves = STARTING_MOVES;
328 dfsarg->npremoves = 0;
329 dfsarg->lb_normal = 0;
330 dfsarg->lb_inverse = 0;
331 dfsarg->use_lb_normal = false;
332 dfsarg->use_lb_inverse = false;
333 dfsarg->movemask_normal = MM_ALLMOVES;
334 dfsarg->movemask_inverse = MM_ALLMOVES;
335
336 solve_h48_dfs(dfsarg);
337 }
338
339 return NULL;
340}
341
342STATIC int64_t
343solve_h48_maketasks(
344 dfsarg_solve_h48_t *solve_arg,
345 dfsarg_solve_h48_maketasks_t *maketasks_arg,
346 solve_h48_task_t tasks[static STARTING_CUBES],
347 int *ntasks
348)
349{
350 int r;
351 int64_t appret;
352 uint8_t m, t;
353 uint32_t mm;
354 cube_t backup_cube;
355
356 if (issolved(maketasks_arg->cube)) {
357 if (maketasks_arg->nmoves > maketasks_arg->maxmoves ||
358 maketasks_arg->nmoves < maketasks_arg->minmoves ||
359 *solve_arg->nsols >= solve_arg->maxsolutions)
360 return NISSY_OK;
361 memcpy(solve_arg->moves,
362 maketasks_arg->moves, maketasks_arg->nmoves);
363 solve_arg->nmoves = maketasks_arg->nmoves;
364 appret = solve_h48_appendsolution(solve_arg);
365 return appret < 0 ? appret : NISSY_OK;
366 }
367
368 if (maketasks_arg->nmoves == STARTING_MOVES) {
369 tasks[*ntasks].cube = maketasks_arg->cube;
370 memcpy(tasks[*ntasks].moves,
371 maketasks_arg->moves, STARTING_MOVES);
372 (*ntasks)++;
373 return NISSY_OK;
374 }
375
376 mm = allowednextmove_mask(maketasks_arg->moves, maketasks_arg->nmoves);
377
378 maketasks_arg->nmoves++;
379 backup_cube = maketasks_arg->cube;
380 for (m = 0; m < 18; m++) {
381 if (!(mm & (1 << m)))
382 continue;
383 maketasks_arg->moves[maketasks_arg->nmoves-1] = m;
384 maketasks_arg->cube = move(backup_cube, m);
385 r = solve_h48_maketasks(
386 solve_arg, maketasks_arg, tasks, ntasks);
387 if (r < 0)
388 return r;
389
390 /* Avoid symmetry-equivalent moves from the starting cube */
391 if (maketasks_arg->nmoves == 1)
392 for (t = 0; t < 48; t++)
393 if (solve_arg->symmask0 &
394 (UINT64_C(1) << (uint64_t)t))
395 mm &= ~(UINT32_C(1) <<
396 (uint32_t)transform_move(m, t));
397 }
398 maketasks_arg->nmoves--;
399 maketasks_arg->cube = backup_cube;
400
401 return NISSY_OK;
402}
403
211STATIC int64_t 404STATIC int64_t
212solve_h48( 405solve_h48(
213 cube_t cube, 406 cube_t cube,
214 int8_t minmoves, 407 int8_t minmoves,
215 int8_t maxmoves, 408 int8_t maxmoves,
216 int8_t maxsolutions, 409 uint64_t maxsolutions,
217 uint64_t data_size, 410 uint64_t data_size,
218 const void *data, 411 const void *data,
219 uint64_t solutions_size, 412 uint64_t solutions_size,
@@ -221,61 +414,150 @@ solve_h48(
221 long long stats[static NISSY_SIZE_SOLVE_STATS] 414 long long stats[static NISSY_SIZE_SOLVE_STATS]
222) 415)
223{ 416{
417 int i, ntasks, eoesep_table_index;
418 int8_t d;
224 _Atomic int64_t nsols; 419 _Atomic int64_t nsols;
225 dfsarg_solveh48_t arg; 420 dfsarg_solve_h48_t arg[THREADS];
226 tableinfo_t info, fbinfo; 421 solve_h48_task_t tasks[STARTING_CUBES];
422 dfsarg_solve_h48_maketasks_t maketasks_arg;
423 long double fallback_rate, lookups_per_node;
424 uint64_t solutions_used, symmask, offset;
425 int64_t nodes_visited, table_lookups, table_fallbacks;
426 tableinfo_t info, fbinfo, fbinfo2;
427 const uint32_t *cocsepdata;
428 const uint8_t *fallback, *h48data;
429 const void *fallback2;
430 pthread_t thread[THREADS];
431 pthread_mutex_t solutions_mutex;
227 432
228 if(readtableinfo_n(data_size, data, 2, &info) != NISSY_OK) 433 if(readtableinfo_n(data_size, data, 2, &info) != NISSY_OK)
229 goto solve_h48_error_data; 434 goto solve_h48_error_data;
230 435
231 arg = (dfsarg_solveh48_t) { 436 cocsepdata = (uint32_t *)((char *)data + INFOSIZE);
232 .cube = cube, 437 h48data = (uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE;
233 .inverse = inverse(cube),
234 .nsols = &nsols,
235 .maxsolutions = maxsolutions,
236 .h = info.h48h,
237 .k = info.bits,
238 .base = info.base,
239 .cocsepdata = (uint32_t *)((char *)data + INFOSIZE),
240 .h48data = (uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE,
241 .solutions_size = solutions_size,
242 .nextsol = &solutions,
243 .nodes_visited = 0,
244 .table_fallbacks = 0
245 };
246 438
439 /* Read fallback table(s) */
440 fallback = NULL;
441 if (readtableinfo_n(data_size, data, 3, &fbinfo) != NISSY_OK)
442 goto solve_h48_error_data;
443 offset = info.next;
444 eoesep_table_index = 3;
247 if (info.bits == 2) { 445 if (info.bits == 2) {
248 if (readtableinfo_n(data_size, data, 3, &fbinfo) != NISSY_OK)
249 goto solve_h48_error_data;
250 /* We only support h0k4 as fallback table */ 446 /* We only support h0k4 as fallback table */
251 if (fbinfo.h48h != 0 || fbinfo.bits != 4) 447 if (fbinfo.h48h != 0 || fbinfo.bits != 4)
252 goto solve_h48_error_data; 448 goto solve_h48_error_data;
253 arg.h48data_fallback = arg.h48data + info.next; 449 fallback = h48data + offset;
254 } else { 450 offset += fbinfo.next;
255 arg.h48data_fallback = NULL; 451 eoesep_table_index++;
452 }
453
454 if (readtableinfo_n(data_size, data, eoesep_table_index, &fbinfo2)
455 != NISSY_OK)
456 goto solve_h48_error_data;
457
458 /* Some heuristic check to see that it is eoesep */
459 if (fbinfo2.bits != 4 || fbinfo2.type != TABLETYPE_SPECIAL)
460 goto solve_h48_error_data;
461 fallback2 = h48data + offset;
462
463 symmask = symmetry_mask(cube);
464 for (i = 0; i < THREADS; i++) {
465 arg[i] = (dfsarg_solve_h48_t) {
466 .start_cube = cube,
467 .cube = cube,
468 .symmask0 = symmask,
469 .nsols = &nsols,
470 .maxsolutions = maxsolutions,
471 .h = info.h48h,
472 .k = info.bits,
473 .base = info.base,
474 .cocsepdata = cocsepdata,
475 .h48data = h48data,
476 .h48data_fallback_h0k4 = fallback,
477 .h48data_fallback_eoesep = fallback2,
478 .solutions_size = solutions_size,
479 .solutions_used = &solutions_used,
480 .solutions = &solutions,
481 .nodes_visited = 0,
482 .table_fallbacks = 0,
483 .table_lookups = 0,
484 .thread_id = i,
485 .solutions_mutex = &solutions_mutex,
486 };
487
256 } 488 }
257 489
258 nsols = 0; 490 nsols = 0;
259 for (arg.depth = minmoves; 491 solutions_used = 0;
260 arg.depth <= maxmoves && nsols < maxsolutions; 492
261 arg.depth++) 493 pthread_mutex_init(&solutions_mutex, NULL);
262 { 494
263 LOG("Found %" PRId64 " solutions, searching at depth %" 495 maketasks_arg = (dfsarg_solve_h48_maketasks_t) {
264 PRId8 "\n", nsols, arg.depth); 496 .cube = cube,
265 arg.nmoves = 0; 497 .nmoves = 0,
266 arg.npremoves = 0; 498 .minmoves = minmoves,
267 solve_h48_dfs(&arg); 499 .maxmoves = maxmoves,
500 };
501 ntasks = 0;
502 solve_h48_maketasks(&arg[0], &maketasks_arg, tasks, &ntasks);
503 if (ntasks < 0)
504 goto solve_h48_error_solutions_buffer;
505 if (*arg[0].nsols >= (int64_t)maxsolutions)
506 goto solve_h48_done;
507
508 for (i = 0; i < THREADS; i++) {
509 arg[i].ntasks = ntasks;
510 arg[i].tasks = tasks;
268 } 511 }
269 **arg.nextsol = '\0';
270 512
271 stats[0] = arg.nodes_visited; 513 LOG("Prepared %d tasks\n", ntasks);
272 stats[1] = arg.table_fallbacks; 514
273 LOG("Nodes visited: %lld\nTable fallbacks: %lld\n", 515 for (
274 arg.nodes_visited, arg.table_fallbacks); 516 d = MAX(minmoves, STARTING_MOVES + 1);
517 d <= maxmoves && nsols < (int64_t)maxsolutions;
518 d++
519 ) {
520 if (d >= 10)
521 LOG("Found %" PRId64 " solutions, searching at depth %"
522 PRId8 "\n", nsols, d);
523 for (i = 0; i < THREADS; i++) {
524 arg[i].depth = d;
525 pthread_create(
526 &thread[i], NULL, solve_h48_runthread, &arg[i]);
527 }
528 for (i = 0; i < THREADS; i++)
529 pthread_join(thread[i], NULL);
530 }
531
532solve_h48_done:
533 if (!solve_h48_appendchar(&arg[0], '\0'))
534 goto solve_h48_error_solutions_buffer;
535
536 nodes_visited = table_lookups = table_fallbacks = 0;
537 for (i = 0; i < THREADS; i++) {
538 nodes_visited += arg[i].nodes_visited;
539 table_fallbacks += arg[i].table_fallbacks;
540 table_lookups += arg[i].table_lookups;
541 }
542
543 stats[0] = nodes_visited;
544 stats[1] = table_lookups;
545 stats[2] = table_fallbacks;
546 lookups_per_node = table_lookups / (long double)nodes_visited;
547 fallback_rate = nodes_visited == 0 ? 0.0 :
548 (table_fallbacks * 100) / (long double)table_lookups;
549 LOG("Nodes visited: %" PRId64 "\n", nodes_visited);
550 LOG("Lookups: %" PRId64 " (%.3Lf per node)\n",
551 table_lookups, lookups_per_node);
552 LOG("Table fallbacks: %" PRId64 " (%.3Lf%%)\n",
553 table_fallbacks, fallback_rate);
275 554
276 return nsols; 555 return nsols;
277 556
278solve_h48_error_data: 557solve_h48_error_data:
279 LOG("solve_h48: error reading table\n"); 558 LOG("solve_h48: error reading table\n");
280 return NISSY_ERROR_DATA; 559 return NISSY_ERROR_DATA;
560
561solve_h48_error_solutions_buffer:
562 return NISSY_ERROR_BUFFER_SIZE;
281} 563}
diff --git a/src/solvers/h48/solve_multithread.h b/src/solvers/h48/solve_multithread.h
deleted file mode 100644
index 72f519e..0000000
--- a/src/solvers/h48/solve_multithread.h
+++ /dev/null
@@ -1,350 +0,0 @@
1#define MAX_QUEUE_SIZE 244
2#define BFS_DEPTH 2
3
4typedef struct {
5 dfsarg_solveh48_t tasks[MAX_QUEUE_SIZE];
6 int front;
7 int rear;
8 int tasks_count;
9 int active;
10 pthread_mutex_t mutex;
11 pthread_cond_t cond;
12 pthread_cond_t active_cond;
13 atomic_bool terminate;
14 _Atomic long long nodes_visited_global;
15 _Atomic long long table_fallbacks_global;
16} task_queue_t;
17
18STATIC void solve_h48_appendsolution_thread(dfsarg_solveh48_t *, task_queue_t *);
19STATIC void init_queue(task_queue_t *);
20STATIC void submit_task(task_queue_t *, dfsarg_solveh48_t);
21STATIC void copy_queue(task_queue_t *, task_queue_t *, int, _Atomic int64_t *);
22STATIC void *start_thread(void *);
23STATIC int64_t solve_h48_bfs(dfsarg_solveh48_t *, task_queue_t *, int8_t);
24STATIC int64_t solve_h48_single(dfsarg_solveh48_t *, task_queue_t *);
25STATIC int64_t solve_h48_multithread(cube_t, int8_t, int8_t, int8_t, uint64_t,
26 const void *, uint64_t, char *, long long [static NISSY_SIZE_SOLVE_STATS]);
27
28STATIC void
29solve_h48_appendsolution_thread(dfsarg_solveh48_t *arg, task_queue_t *tq)
30{
31 pthread_mutex_lock(&tq->mutex);
32 int64_t strl = 0;
33 uint8_t invertedpremoves[MAXLEN];
34 char *solution = *arg->nextsol;
35
36 strl = writemoves(
37 arg->moves, arg->nmoves, arg->solutions_size, *arg->nextsol);
38
39 if (strl < 0)
40 goto solve_h48_appendsolution_thread_error;
41 *arg->nextsol += strl-1;
42 arg->solutions_size -= strl-1;
43
44 if (arg->npremoves)
45 {
46 **arg->nextsol = ' ';
47 (*arg->nextsol)++;
48 arg->solutions_size--;
49
50 invertmoves(arg->premoves, arg->npremoves, invertedpremoves);
51 strl = writemoves(invertedpremoves,
52 arg->npremoves, arg->solutions_size, *arg->nextsol);
53
54 if (strl < 0)
55 goto solve_h48_appendsolution_thread_error;
56 *arg->nextsol += strl-1;
57 arg->solutions_size -= strl-1;
58 }
59 LOG("Solution found: %s\n", solution);
60
61 **arg->nextsol = '\n';
62 (*arg->nextsol)++;
63 arg->solutions_size--;
64 (*arg->nsols)++;
65
66solve_h48_appendsolution_thread_error:
67 /* We could add some logging, but writemoves() already does */
68 pthread_mutex_unlock(&tq->mutex);
69}
70
71STATIC void
72init_queue(task_queue_t *queue)
73{
74 queue->front = 0;
75 queue->rear = 0;
76 queue->tasks_count = 0;
77 queue->active = 0;
78 queue->terminate = ATOMIC_VAR_INIT(false);
79 pthread_mutex_init(&queue->mutex, NULL);
80 pthread_cond_init(&queue->cond, NULL);
81 pthread_cond_init(&queue->active_cond, NULL);
82}
83
84STATIC void
85submit_task(task_queue_t *queue, dfsarg_solveh48_t task)
86{
87 pthread_mutex_lock(&queue->mutex);
88 queue->tasks[queue->rear] = task;
89 queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
90 queue->tasks_count++;
91 pthread_cond_broadcast(&queue->cond);
92 pthread_mutex_unlock(&queue->mutex);
93}
94
95STATIC void
96copy_queue(task_queue_t *src, task_queue_t *dest, int depth, _Atomic int64_t *nsols)
97{
98 pthread_mutex_lock(&dest->mutex);
99 for (int i = src->front; i != src->rear; i = (i + 1) % MAX_QUEUE_SIZE)
100 {
101 dest->tasks[i] = src->tasks[i];
102 dest->tasks[i].depth = depth;
103 }
104 dest->front = src->front;
105 dest->rear = src->rear;
106 dest->tasks_count = src->tasks_count;
107 pthread_cond_broadcast(&dest->cond);
108 pthread_mutex_unlock(&dest->mutex);
109}
110
111STATIC void *
112start_thread(void *arg)
113{
114 task_queue_t *queue = (task_queue_t *)arg;
115 while (1) {
116 pthread_mutex_lock(&queue->mutex);
117 while (queue->tasks_count == 0 && !queue->terminate) {
118 pthread_cond_wait(&queue->cond, &queue->mutex);
119 }
120 if (queue->tasks_count == 0 && queue->terminate) {
121 pthread_mutex_unlock(&queue->mutex);
122 break;
123 }
124
125 if (queue->tasks_count > 0) {
126 dfsarg_solveh48_t task = queue->tasks[queue->front];
127 queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
128 queue->tasks_count--;
129 queue->active++;
130 pthread_mutex_unlock(&queue->mutex);
131
132 solve_h48_single(&task, queue);
133 queue->nodes_visited_global += task.nodes_visited;
134 queue->table_fallbacks_global += task.table_fallbacks;
135
136 pthread_mutex_lock(&queue->mutex);
137 queue->active--;
138
139 if(queue->tasks_count == 0 && queue->active == 0)
140 pthread_cond_signal(&queue->active_cond);
141 }
142 pthread_mutex_unlock(&queue->mutex);
143 }
144 return NULL;
145}
146
147STATIC int64_t
148solve_h48_bfs(dfsarg_solveh48_t *arg_zero, task_queue_t *tq, int8_t maxmoves)
149{
150 dfsarg_solveh48_t queue[MAX_QUEUE_SIZE];
151 int front = 0, rear = 0;
152 dfsarg_solveh48_t nextarg;
153 int depth = 0;
154 int nodes_at_current_depth = 1;
155 int nodes_at_next_depth = 0;
156 queue[rear++] = *arg_zero;
157
158 dfsarg_solveh48_t task_pool[MAX_QUEUE_SIZE];
159
160 while (front < rear){
161 dfsarg_solveh48_t arg = queue[front++];
162 nodes_at_current_depth--;
163
164 if (*arg.nsols == arg.maxsolutions)
165 return 1;
166
167 if (issolved(arg.cube)){
168 if (arg.nmoves + arg.npremoves >= arg.depth && arg.nmoves + arg.npremoves <= maxmoves)
169 solve_h48_appendsolution(&arg);
170 continue;
171 }
172
173 arg.nissbranch = MM_NORMAL;
174 uint32_t allowed = allowednextmove_h48(arg.moves, arg.nmoves, arg.nissbranch);
175
176 for (uint8_t m = 0; m < 18; m++){
177 if (allowed & (1 << m)){
178 nextarg = arg;
179 nextarg.nmoves = arg.nmoves + 1;
180 nextarg.moves[arg.nmoves] = m;
181 nextarg.cube = move(arg.cube, m);
182 nextarg.inverse = premove(arg.inverse, m);
183
184 if (nextarg.nmoves == BFS_DEPTH){
185 dfsarg_solveh48_t *task = &task_pool[rear % MAX_QUEUE_SIZE];
186 *task = nextarg;
187 submit_task(tq, *task);
188 } else {
189 queue[rear++] = nextarg;
190 nodes_at_next_depth++;
191 }
192 }
193 }
194 if (nodes_at_current_depth == 0){
195 nodes_at_current_depth = nodes_at_next_depth;
196 nodes_at_next_depth = 0;
197 LOG("Found %" PRId64 " solutions, searching at depth %" PRId8 "\n", *nextarg.nsols, depth++);
198 }
199 if (depth == BFS_DEPTH) return 0;
200 }
201 return 1;
202}
203
204STATIC int64_t
205solve_h48_single(dfsarg_solveh48_t *arg, task_queue_t *tq)
206{
207 dfsarg_solveh48_t nextarg;
208 int64_t ret;
209 uint8_t m;
210
211 if (*arg->nsols == arg->maxsolutions)
212 return 0;
213
214 if (solve_h48_stop(arg))
215 return 0;
216
217 if (issolved(arg->cube)){
218 if (arg->nmoves + arg->npremoves != arg->depth)
219 return 0;
220 solve_h48_appendsolution_thread(arg, tq);
221 return 1;
222 }
223
224 nextarg = *arg;
225 ret = 0;
226 uint32_t allowed;
227 if (arg->nissbranch & MM_INVERSE){
228 allowed = allowednextmove_h48(arg->premoves, arg->npremoves, arg->nissbranch);
229 for (m = 0; m < 18; m++){
230 if (allowed & (1 << m)){
231 nextarg.npremoves = arg->npremoves + 1;
232 nextarg.premoves[arg->npremoves] = m;
233 nextarg.inverse = move(arg->inverse, m);
234 nextarg.cube = premove(arg->cube, m);
235 ret += solve_h48_single(&nextarg, tq);
236 }
237 }
238 } else {
239 allowed = allowednextmove_h48(arg->moves, arg->nmoves, arg->nissbranch);
240 for (m = 0; m < 18; m++){
241 if (allowed & (1 << m)){
242 nextarg.nmoves = arg->nmoves + 1;
243 nextarg.moves[arg->nmoves] = m;
244 nextarg.cube = move(arg->cube, m);
245 nextarg.inverse = premove(arg->inverse, m);
246 ret += solve_h48_single(&nextarg, tq);
247 }
248 }
249 }
250
251 arg->nodes_visited = nextarg.nodes_visited;
252 arg->table_fallbacks = nextarg.table_fallbacks;
253 return ret;
254}
255
256STATIC int64_t
257solve_h48_multithread(
258 cube_t cube,
259 int8_t minmoves,
260 int8_t maxmoves,
261 int8_t maxsolutions,
262 uint64_t data_size,
263 const void *data,
264 uint64_t solutions_size,
265 char *solutions,
266 long long stats[static NISSY_SIZE_SOLVE_STATS]
267)
268{
269 _Atomic int64_t nsols = 0;
270 int p_depth = 0;
271 dfsarg_solveh48_t arg;
272 tableinfo_t info, fbinfo;
273 pthread_t threads[THREADS];
274
275 if (readtableinfo_n(data_size, data, 2, &info) != NISSY_OK)
276 goto solve_h48_multithread_error_data;
277
278 arg = (dfsarg_solveh48_t){
279 .cube = cube,
280 .inverse = inverse(cube),
281 .nsols = &nsols,
282 .depth = minmoves,
283 .maxsolutions = maxsolutions,
284 .h = info.h48h,
285 .k = info.bits,
286 .base = info.base,
287 .cocsepdata = (uint32_t *)((char *)data + INFOSIZE),
288 .h48data = (uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE,
289 .solutions_size = solutions_size,
290 .nextsol = &solutions,
291 .nodes_visited = 0,
292 .table_fallbacks = 0
293 };
294
295 if (info.bits == 2) {
296 if (readtableinfo_n(data_size, data, 3, &fbinfo) != NISSY_OK)
297 goto solve_h48_multithread_error_data;
298 /* We only support h0k4 as fallback table */
299 if (fbinfo.h48h != 0 || fbinfo.bits != 4)
300 goto solve_h48_multithread_error_data;
301 arg.h48data_fallback = arg.h48data + info.next;
302 } else {
303 arg.h48data_fallback = NULL;
304 }
305
306 task_queue_t q;
307 init_queue(&q);
308 if (solve_h48_bfs(&arg, &q, maxmoves))
309 return nsols;
310
311 task_queue_t nq;
312 init_queue(&nq);
313
314 nq.nodes_visited_global = nq.table_fallbacks_global = 0;
315 for (int i = 0; i < THREADS; i++) {
316 pthread_create(&threads[i], NULL, &start_thread, &nq);
317 }
318
319 nsols = 0;
320 for (p_depth = minmoves > BFS_DEPTH ? minmoves : BFS_DEPTH;
321 p_depth <= maxmoves && nsols < maxsolutions;
322 p_depth++)
323 {
324 LOG("Found %" PRId64 " solutions, "
325 "searching at depth %" PRId8 "\n", nsols, p_depth);
326 copy_queue(&q, &nq, p_depth, &nsols);
327
328 pthread_mutex_lock(&nq.mutex);
329 while (nq.active > 0 || nq.tasks_count > 0)
330 pthread_cond_wait(&nq.active_cond, &nq.mutex);
331 pthread_mutex_unlock(&nq.mutex);
332 }
333
334 atomic_store(&nq.terminate, true);
335 pthread_cond_broadcast(&nq.cond);
336
337 for (int i = 0; i < THREADS; i++) {
338 pthread_join(threads[i], NULL);
339 }
340 **arg.nextsol = '\0';
341
342 stats[0] = nq.nodes_visited_global;
343 stats[1] = nq.table_fallbacks_global;
344 LOG("Nodes visited: %lld\nTable fallbacks: %lld\n",
345 nq.nodes_visited_global, nq.table_fallbacks_global);
346
347 return nsols;
348
349solve_h48_multithread_error_data: LOG("solve_h48: error reading table\n"); return NISSY_ERROR_DATA;
350}
diff --git a/src/solvers/h48/stats.h b/src/solvers/h48/stats.h
deleted file mode 100644
index 2a7e887..0000000
--- a/src/solvers/h48/stats.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2The h48stats solver computes how many moves it takes to solve to
3each of the 12 h48 coordinates, one for each value of h from 0 to 11.
4The solutions array is filled with the length of the solutions. The
5solutions array is therefore not a printable string.
6*/
7
8typedef struct {
9 cube_t cube;
10 int8_t nmoves;
11 int8_t depth;
12 uint8_t moves[MAXLEN];
13 const uint32_t *cocsepdata;
14 const uint8_t *h48data;
15 char *s;
16} dfsarg_solveh48stats_t;
17
18STATIC int64_t solve_h48stats_dfs(dfsarg_solveh48stats_t *);
19STATIC int64_t solve_h48stats(cube_t, int8_t, const void *, char [static 12]);
20
21STATIC int64_t
22solve_h48stats_dfs(dfsarg_solveh48stats_t *arg)
23{
24 const int64_t limit = 11;
25
26 int8_t bound, u;
27 uint8_t m;
28 uint32_t d;
29 int64_t coord, h;
30 dfsarg_solveh48stats_t nextarg;
31
32 /* Check cocsep lower bound (corners only) */
33 bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d);
34 if (bound + arg->nmoves > arg->depth)
35 return 0;
36
37 /* Check h48 lower bound for h=0 (esep, but no eo) */
38 coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 0);
39 bound = get_h48_pval(arg->h48data, coord, 4);
40 if (bound + arg->nmoves > arg->depth)
41 return 0;
42
43 /* Update all other values, if solved */
44 coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11);
45 for (h = 0; h <= limit; h++) {
46 u = coord >> (11-h) == 0 && arg->s[h] == 99;
47 arg->s[h] = u * arg->nmoves + (1-u) * arg->s[h];
48 }
49
50 if (arg->s[limit] != 99)
51 return 0;
52
53 nextarg = *arg;
54 nextarg.nmoves = arg->nmoves + 1;
55 for (m = 0; m < 18; m++) {
56 nextarg.moves[arg->nmoves] = m;
57 if (!allowednextmove(nextarg.moves, nextarg.nmoves)) {
58 /* If a move is not allowed, neither are its 180
59 * and 270 degree variations */
60 m += 2;
61 continue;
62 }
63 nextarg.cube = move(arg->cube, m);
64 solve_h48stats_dfs(&nextarg);
65 }
66
67 return 0;
68}
69
70STATIC int64_t
71solve_h48stats(
72 cube_t cube,
73 int8_t maxmoves,
74 const void *data,
75 char solutions[static 12]
76)
77{
78 int i;
79 dfsarg_solveh48stats_t arg;
80
81 arg = (dfsarg_solveh48stats_t) {
82 .cube = cube,
83 .cocsepdata = (uint32_t *)((char *)data + INFOSIZE),
84 .h48data = (uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE,
85 .s = solutions
86 };
87
88 for (i = 0; i < 12; i++)
89 solutions[i] = (char)99;
90
91 for (arg.depth = 0;
92 arg.depth <= maxmoves && solutions[11] == 99;
93 arg.depth++)
94 {
95 arg.nmoves = 0;
96 solve_h48stats_dfs(&arg);
97 }
98
99 return 0;
100}
diff --git a/src/utils/constants.h b/src/utils/constants.h
index ab1b9d8..dd2b92a 100644
--- a/src/utils/constants.h
+++ b/src/utils/constants.h
@@ -93,12 +93,11 @@ STATIC int64_t binomial[12][12] = {
93#define TRANS_BDm UINT8_C(46) 93#define TRANS_BDm UINT8_C(46)
94#define TRANS_BLm UINT8_C(47) 94#define TRANS_BLm UINT8_C(47)
95 95
96#define MM_NORMAL UINT8_C(0x00) 96#define NMOVES (1+MOVE_B3)
97#define MM_INVERSE UINT8_C(0x01) 97#define NTRANS (1+TRANS_BLr)
98#define MM_INVERSEBRANCH UINT8_C(0x03) 98
99#define MM_NORMALBRANCH UINT8_C(0x02) 99#define MM_ALLMOVES UINT32_C(0x3FFFF)
100#define MM_ALLMOVES UINT32_C(0x3FFFF) 100#define MM_NOHALFTURNS UINT32_C(0x2DB6D)
101#define MM_NOHALFTURNS UINT32_C(0x2DB6D)
102 101
103#define CORNER_UFR UINT8_C(0) 102#define CORNER_UFR UINT8_C(0)
104#define CORNER_UBL UINT8_C(1) 103#define CORNER_UBL UINT8_C(1)
@@ -296,3 +295,54 @@ static uint8_t inverse_trans_table[48] = {
296 [TRANS_BLr] = TRANS_RDr, 295 [TRANS_BLr] = TRANS_RDr,
297 [TRANS_BLm] = TRANS_LDm, 296 [TRANS_BLm] = TRANS_LDm,
298}; 297};
298
299static uint8_t trans_move_table[48][3] = {
300 [TRANS_UFr] = { MOVE_U, MOVE_R, MOVE_F },
301 [TRANS_UFm] = { MOVE_U, MOVE_L, MOVE_F },
302 [TRANS_ULr] = { MOVE_U, MOVE_F, MOVE_L },
303 [TRANS_ULm] = { MOVE_U, MOVE_F, MOVE_R },
304 [TRANS_UBr] = { MOVE_U, MOVE_L, MOVE_B },
305 [TRANS_UBm] = { MOVE_U, MOVE_R, MOVE_B },
306 [TRANS_URr] = { MOVE_U, MOVE_B, MOVE_R },
307 [TRANS_URm] = { MOVE_U, MOVE_B, MOVE_L },
308 [TRANS_DFr] = { MOVE_D, MOVE_L, MOVE_F },
309 [TRANS_DFm] = { MOVE_D, MOVE_R, MOVE_F },
310 [TRANS_DLr] = { MOVE_D, MOVE_B, MOVE_L },
311 [TRANS_DLm] = { MOVE_D, MOVE_B, MOVE_R },
312 [TRANS_DBr] = { MOVE_D, MOVE_R, MOVE_B },
313 [TRANS_DBm] = { MOVE_D, MOVE_L, MOVE_B },
314 [TRANS_DRr] = { MOVE_D, MOVE_F, MOVE_R },
315 [TRANS_DRm] = { MOVE_D, MOVE_F, MOVE_L },
316 [TRANS_RUr] = { MOVE_R, MOVE_F, MOVE_U },
317 [TRANS_RUm] = { MOVE_L, MOVE_F, MOVE_U },
318 [TRANS_RFr] = { MOVE_R, MOVE_D, MOVE_F },
319 [TRANS_RFm] = { MOVE_L, MOVE_D, MOVE_F },
320 [TRANS_RDr] = { MOVE_R, MOVE_B, MOVE_D },
321 [TRANS_RDm] = { MOVE_L, MOVE_B, MOVE_D },
322 [TRANS_RBr] = { MOVE_R, MOVE_U, MOVE_B },
323 [TRANS_RBm] = { MOVE_L, MOVE_U, MOVE_B },
324 [TRANS_LUr] = { MOVE_L, MOVE_B, MOVE_U },
325 [TRANS_LUm] = { MOVE_R, MOVE_B, MOVE_U },
326 [TRANS_LFr] = { MOVE_L, MOVE_U, MOVE_F },
327 [TRANS_LFm] = { MOVE_R, MOVE_U, MOVE_F },
328 [TRANS_LDr] = { MOVE_L, MOVE_F, MOVE_D },
329 [TRANS_LDm] = { MOVE_R, MOVE_F, MOVE_D },
330 [TRANS_LBr] = { MOVE_L, MOVE_D, MOVE_B },
331 [TRANS_LBm] = { MOVE_R, MOVE_D, MOVE_B },
332 [TRANS_FUr] = { MOVE_F, MOVE_L, MOVE_U },
333 [TRANS_FUm] = { MOVE_F, MOVE_R, MOVE_U },
334 [TRANS_FRr] = { MOVE_F, MOVE_U, MOVE_R },
335 [TRANS_FRm] = { MOVE_F, MOVE_U, MOVE_L },
336 [TRANS_FDr] = { MOVE_F, MOVE_R, MOVE_D },
337 [TRANS_FDm] = { MOVE_F, MOVE_L, MOVE_D },
338 [TRANS_FLr] = { MOVE_F, MOVE_D, MOVE_L },
339 [TRANS_FLm] = { MOVE_F, MOVE_D, MOVE_R },
340 [TRANS_BUr] = { MOVE_B, MOVE_R, MOVE_U },
341 [TRANS_BUm] = { MOVE_B, MOVE_L, MOVE_U },
342 [TRANS_BRr] = { MOVE_B, MOVE_D, MOVE_R },
343 [TRANS_BRm] = { MOVE_B, MOVE_D, MOVE_L },
344 [TRANS_BDr] = { MOVE_B, MOVE_L, MOVE_D },
345 [TRANS_BDm] = { MOVE_B, MOVE_R, MOVE_D },
346 [TRANS_BLr] = { MOVE_B, MOVE_U, MOVE_L },
347 [TRANS_BLm] = { MOVE_B, MOVE_U, MOVE_R },
348};
diff --git a/test/062_transform_move/100_UFr_U.in b/test/062_transform_move/100_UFr_U.in
new file mode 100644
index 0000000..ccec6ad
--- /dev/null
+++ b/test/062_transform_move/100_UFr_U.in
@@ -0,0 +1,2 @@
1rotation UF
2U
diff --git a/test/062_transform_move/100_UFr_U.out b/test/062_transform_move/100_UFr_U.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/100_UFr_U.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/101_UFm_U.in b/test/062_transform_move/101_UFm_U.in
new file mode 100644
index 0000000..ffc871f
--- /dev/null
+++ b/test/062_transform_move/101_UFm_U.in
@@ -0,0 +1,2 @@
1mirrored UF
2U
diff --git a/test/062_transform_move/101_UFm_U.out b/test/062_transform_move/101_UFm_U.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/101_UFm_U.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/102_UFr_R.in b/test/062_transform_move/102_UFr_R.in
new file mode 100644
index 0000000..fdce3b8
--- /dev/null
+++ b/test/062_transform_move/102_UFr_R.in
@@ -0,0 +1,2 @@
1rotation UF
2R
diff --git a/test/062_transform_move/102_UFr_R.out b/test/062_transform_move/102_UFr_R.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/102_UFr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/103_UFm_R.in b/test/062_transform_move/103_UFm_R.in
new file mode 100644
index 0000000..acb9790
--- /dev/null
+++ b/test/062_transform_move/103_UFm_R.in
@@ -0,0 +1,2 @@
1mirrored UF
2R
diff --git a/test/062_transform_move/103_UFm_R.out b/test/062_transform_move/103_UFm_R.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/103_UFm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/104_UFr_F.in b/test/062_transform_move/104_UFr_F.in
new file mode 100644
index 0000000..1eb445c
--- /dev/null
+++ b/test/062_transform_move/104_UFr_F.in
@@ -0,0 +1,2 @@
1rotation UF
2F
diff --git a/test/062_transform_move/104_UFr_F.out b/test/062_transform_move/104_UFr_F.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/104_UFr_F.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/105_UFm_F.in b/test/062_transform_move/105_UFm_F.in
new file mode 100644
index 0000000..ce106fe
--- /dev/null
+++ b/test/062_transform_move/105_UFm_F.in
@@ -0,0 +1,2 @@
1mirrored UF
2F
diff --git a/test/062_transform_move/105_UFm_F.out b/test/062_transform_move/105_UFm_F.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/105_UFm_F.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/106_ULr_U.in b/test/062_transform_move/106_ULr_U.in
new file mode 100644
index 0000000..00d5e27
--- /dev/null
+++ b/test/062_transform_move/106_ULr_U.in
@@ -0,0 +1,2 @@
1rotation UL
2U
diff --git a/test/062_transform_move/106_ULr_U.out b/test/062_transform_move/106_ULr_U.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/106_ULr_U.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/107_ULm_U.in b/test/062_transform_move/107_ULm_U.in
new file mode 100644
index 0000000..add90be
--- /dev/null
+++ b/test/062_transform_move/107_ULm_U.in
@@ -0,0 +1,2 @@
1mirrored UL
2U
diff --git a/test/062_transform_move/107_ULm_U.out b/test/062_transform_move/107_ULm_U.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/107_ULm_U.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/108_ULr_R.in b/test/062_transform_move/108_ULr_R.in
new file mode 100644
index 0000000..06414b4
--- /dev/null
+++ b/test/062_transform_move/108_ULr_R.in
@@ -0,0 +1,2 @@
1rotation UL
2R
diff --git a/test/062_transform_move/108_ULr_R.out b/test/062_transform_move/108_ULr_R.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/108_ULr_R.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/109_ULm_R.in b/test/062_transform_move/109_ULm_R.in
new file mode 100644
index 0000000..c1b5d58
--- /dev/null
+++ b/test/062_transform_move/109_ULm_R.in
@@ -0,0 +1,2 @@
1mirrored UL
2R
diff --git a/test/062_transform_move/109_ULm_R.out b/test/062_transform_move/109_ULm_R.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/109_ULm_R.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/110_ULr_F.in b/test/062_transform_move/110_ULr_F.in
new file mode 100644
index 0000000..8446f4c
--- /dev/null
+++ b/test/062_transform_move/110_ULr_F.in
@@ -0,0 +1,2 @@
1rotation UL
2F
diff --git a/test/062_transform_move/110_ULr_F.out b/test/062_transform_move/110_ULr_F.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/110_ULr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/111_ULm_F.in b/test/062_transform_move/111_ULm_F.in
new file mode 100644
index 0000000..16e0363
--- /dev/null
+++ b/test/062_transform_move/111_ULm_F.in
@@ -0,0 +1,2 @@
1mirrored UL
2F
diff --git a/test/062_transform_move/111_ULm_F.out b/test/062_transform_move/111_ULm_F.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/111_ULm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/112_UBr_U.in b/test/062_transform_move/112_UBr_U.in
new file mode 100644
index 0000000..d1994cf
--- /dev/null
+++ b/test/062_transform_move/112_UBr_U.in
@@ -0,0 +1,2 @@
1rotation UB
2U
diff --git a/test/062_transform_move/112_UBr_U.out b/test/062_transform_move/112_UBr_U.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/112_UBr_U.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/113_UBm_U.in b/test/062_transform_move/113_UBm_U.in
new file mode 100644
index 0000000..8ef80ff
--- /dev/null
+++ b/test/062_transform_move/113_UBm_U.in
@@ -0,0 +1,2 @@
1mirrored UB
2U
diff --git a/test/062_transform_move/113_UBm_U.out b/test/062_transform_move/113_UBm_U.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/113_UBm_U.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/114_UBr_R.in b/test/062_transform_move/114_UBr_R.in
new file mode 100644
index 0000000..8529b00
--- /dev/null
+++ b/test/062_transform_move/114_UBr_R.in
@@ -0,0 +1,2 @@
1rotation UB
2R
diff --git a/test/062_transform_move/114_UBr_R.out b/test/062_transform_move/114_UBr_R.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/114_UBr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/115_UBm_R.in b/test/062_transform_move/115_UBm_R.in
new file mode 100644
index 0000000..2934947
--- /dev/null
+++ b/test/062_transform_move/115_UBm_R.in
@@ -0,0 +1,2 @@
1mirrored UB
2R
diff --git a/test/062_transform_move/115_UBm_R.out b/test/062_transform_move/115_UBm_R.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/115_UBm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/116_UBr_F.in b/test/062_transform_move/116_UBr_F.in
new file mode 100644
index 0000000..23d04d1
--- /dev/null
+++ b/test/062_transform_move/116_UBr_F.in
@@ -0,0 +1,2 @@
1rotation UB
2F
diff --git a/test/062_transform_move/116_UBr_F.out b/test/062_transform_move/116_UBr_F.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/116_UBr_F.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/117_UBm_F.in b/test/062_transform_move/117_UBm_F.in
new file mode 100644
index 0000000..bdb4d27
--- /dev/null
+++ b/test/062_transform_move/117_UBm_F.in
@@ -0,0 +1,2 @@
1mirrored UB
2F
diff --git a/test/062_transform_move/117_UBm_F.out b/test/062_transform_move/117_UBm_F.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/117_UBm_F.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/118_URr_U.in b/test/062_transform_move/118_URr_U.in
new file mode 100644
index 0000000..cb3542a
--- /dev/null
+++ b/test/062_transform_move/118_URr_U.in
@@ -0,0 +1,2 @@
1rotation UR
2U
diff --git a/test/062_transform_move/118_URr_U.out b/test/062_transform_move/118_URr_U.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/118_URr_U.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/119_URm_U.in b/test/062_transform_move/119_URm_U.in
new file mode 100644
index 0000000..d4e03e7
--- /dev/null
+++ b/test/062_transform_move/119_URm_U.in
@@ -0,0 +1,2 @@
1mirrored UR
2U
diff --git a/test/062_transform_move/119_URm_U.out b/test/062_transform_move/119_URm_U.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/119_URm_U.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/120_URr_R.in b/test/062_transform_move/120_URr_R.in
new file mode 100644
index 0000000..f316a93
--- /dev/null
+++ b/test/062_transform_move/120_URr_R.in
@@ -0,0 +1,2 @@
1rotation UR
2R
diff --git a/test/062_transform_move/120_URr_R.out b/test/062_transform_move/120_URr_R.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/120_URr_R.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/121_URm_R.in b/test/062_transform_move/121_URm_R.in
new file mode 100644
index 0000000..e9da8c6
--- /dev/null
+++ b/test/062_transform_move/121_URm_R.in
@@ -0,0 +1,2 @@
1mirrored UR
2R
diff --git a/test/062_transform_move/121_URm_R.out b/test/062_transform_move/121_URm_R.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/121_URm_R.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/122_URr_F.in b/test/062_transform_move/122_URr_F.in
new file mode 100644
index 0000000..ab3dbf2
--- /dev/null
+++ b/test/062_transform_move/122_URr_F.in
@@ -0,0 +1,2 @@
1rotation UR
2F
diff --git a/test/062_transform_move/122_URr_F.out b/test/062_transform_move/122_URr_F.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/122_URr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/123_URm_F.in b/test/062_transform_move/123_URm_F.in
new file mode 100644
index 0000000..082051c
--- /dev/null
+++ b/test/062_transform_move/123_URm_F.in
@@ -0,0 +1,2 @@
1mirrored UR
2F
diff --git a/test/062_transform_move/123_URm_F.out b/test/062_transform_move/123_URm_F.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/123_URm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/124_DFr_U.in b/test/062_transform_move/124_DFr_U.in
new file mode 100644
index 0000000..551cbdd
--- /dev/null
+++ b/test/062_transform_move/124_DFr_U.in
@@ -0,0 +1,2 @@
1rotation DF
2U
diff --git a/test/062_transform_move/124_DFr_U.out b/test/062_transform_move/124_DFr_U.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/124_DFr_U.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/125_DFm_U.in b/test/062_transform_move/125_DFm_U.in
new file mode 100644
index 0000000..0ecf796
--- /dev/null
+++ b/test/062_transform_move/125_DFm_U.in
@@ -0,0 +1,2 @@
1mirrored DF
2U
diff --git a/test/062_transform_move/125_DFm_U.out b/test/062_transform_move/125_DFm_U.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/125_DFm_U.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/126_DFr_R.in b/test/062_transform_move/126_DFr_R.in
new file mode 100644
index 0000000..3998467
--- /dev/null
+++ b/test/062_transform_move/126_DFr_R.in
@@ -0,0 +1,2 @@
1rotation DF
2R
diff --git a/test/062_transform_move/126_DFr_R.out b/test/062_transform_move/126_DFr_R.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/126_DFr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/127_DFm_R.in b/test/062_transform_move/127_DFm_R.in
new file mode 100644
index 0000000..26b10e4
--- /dev/null
+++ b/test/062_transform_move/127_DFm_R.in
@@ -0,0 +1,2 @@
1mirrored DF
2R
diff --git a/test/062_transform_move/127_DFm_R.out b/test/062_transform_move/127_DFm_R.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/127_DFm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/128_DFr_F.in b/test/062_transform_move/128_DFr_F.in
new file mode 100644
index 0000000..b212a51
--- /dev/null
+++ b/test/062_transform_move/128_DFr_F.in
@@ -0,0 +1,2 @@
1rotation DF
2F
diff --git a/test/062_transform_move/128_DFr_F.out b/test/062_transform_move/128_DFr_F.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/128_DFr_F.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/129_DFm_F.in b/test/062_transform_move/129_DFm_F.in
new file mode 100644
index 0000000..b4349d6
--- /dev/null
+++ b/test/062_transform_move/129_DFm_F.in
@@ -0,0 +1,2 @@
1mirrored DF
2F
diff --git a/test/062_transform_move/129_DFm_F.out b/test/062_transform_move/129_DFm_F.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/129_DFm_F.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/130_DLr_U.in b/test/062_transform_move/130_DLr_U.in
new file mode 100644
index 0000000..fdf72d3
--- /dev/null
+++ b/test/062_transform_move/130_DLr_U.in
@@ -0,0 +1,2 @@
1rotation DL
2U
diff --git a/test/062_transform_move/130_DLr_U.out b/test/062_transform_move/130_DLr_U.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/130_DLr_U.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/131_DLm_U.in b/test/062_transform_move/131_DLm_U.in
new file mode 100644
index 0000000..ea2a091
--- /dev/null
+++ b/test/062_transform_move/131_DLm_U.in
@@ -0,0 +1,2 @@
1mirrored DL
2U
diff --git a/test/062_transform_move/131_DLm_U.out b/test/062_transform_move/131_DLm_U.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/131_DLm_U.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/132_DLr_R.in b/test/062_transform_move/132_DLr_R.in
new file mode 100644
index 0000000..65bb1b9
--- /dev/null
+++ b/test/062_transform_move/132_DLr_R.in
@@ -0,0 +1,2 @@
1rotation DL
2R
diff --git a/test/062_transform_move/132_DLr_R.out b/test/062_transform_move/132_DLr_R.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/132_DLr_R.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/133_DLm_R.in b/test/062_transform_move/133_DLm_R.in
new file mode 100644
index 0000000..2a1c887
--- /dev/null
+++ b/test/062_transform_move/133_DLm_R.in
@@ -0,0 +1,2 @@
1mirrored DL
2R
diff --git a/test/062_transform_move/133_DLm_R.out b/test/062_transform_move/133_DLm_R.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/133_DLm_R.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/134_DLr_F.in b/test/062_transform_move/134_DLr_F.in
new file mode 100644
index 0000000..5b898ca
--- /dev/null
+++ b/test/062_transform_move/134_DLr_F.in
@@ -0,0 +1,2 @@
1rotation DL
2F
diff --git a/test/062_transform_move/134_DLr_F.out b/test/062_transform_move/134_DLr_F.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/134_DLr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/135_DLm_F.in b/test/062_transform_move/135_DLm_F.in
new file mode 100644
index 0000000..0a02999
--- /dev/null
+++ b/test/062_transform_move/135_DLm_F.in
@@ -0,0 +1,2 @@
1mirrored DL
2F
diff --git a/test/062_transform_move/135_DLm_F.out b/test/062_transform_move/135_DLm_F.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/135_DLm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/136_DBr_U.in b/test/062_transform_move/136_DBr_U.in
new file mode 100644
index 0000000..79e21ce
--- /dev/null
+++ b/test/062_transform_move/136_DBr_U.in
@@ -0,0 +1,2 @@
1rotation DB
2U
diff --git a/test/062_transform_move/136_DBr_U.out b/test/062_transform_move/136_DBr_U.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/136_DBr_U.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/137_DBm_U.in b/test/062_transform_move/137_DBm_U.in
new file mode 100644
index 0000000..871bb28
--- /dev/null
+++ b/test/062_transform_move/137_DBm_U.in
@@ -0,0 +1,2 @@
1mirrored DB
2U
diff --git a/test/062_transform_move/137_DBm_U.out b/test/062_transform_move/137_DBm_U.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/137_DBm_U.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/138_DBr_R.in b/test/062_transform_move/138_DBr_R.in
new file mode 100644
index 0000000..5269265
--- /dev/null
+++ b/test/062_transform_move/138_DBr_R.in
@@ -0,0 +1,2 @@
1rotation DB
2R
diff --git a/test/062_transform_move/138_DBr_R.out b/test/062_transform_move/138_DBr_R.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/138_DBr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/139_DBm_R.in b/test/062_transform_move/139_DBm_R.in
new file mode 100644
index 0000000..4877505
--- /dev/null
+++ b/test/062_transform_move/139_DBm_R.in
@@ -0,0 +1,2 @@
1mirrored DB
2R
diff --git a/test/062_transform_move/139_DBm_R.out b/test/062_transform_move/139_DBm_R.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/139_DBm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/140_DBr_F.in b/test/062_transform_move/140_DBr_F.in
new file mode 100644
index 0000000..242ee5c
--- /dev/null
+++ b/test/062_transform_move/140_DBr_F.in
@@ -0,0 +1,2 @@
1rotation DB
2F
diff --git a/test/062_transform_move/140_DBr_F.out b/test/062_transform_move/140_DBr_F.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/140_DBr_F.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/141_DBm_F.in b/test/062_transform_move/141_DBm_F.in
new file mode 100644
index 0000000..7113caf
--- /dev/null
+++ b/test/062_transform_move/141_DBm_F.in
@@ -0,0 +1,2 @@
1mirrored DB
2F
diff --git a/test/062_transform_move/141_DBm_F.out b/test/062_transform_move/141_DBm_F.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/141_DBm_F.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/142_DRr_U.in b/test/062_transform_move/142_DRr_U.in
new file mode 100644
index 0000000..a2e4cfb
--- /dev/null
+++ b/test/062_transform_move/142_DRr_U.in
@@ -0,0 +1,2 @@
1rotation DR
2U
diff --git a/test/062_transform_move/142_DRr_U.out b/test/062_transform_move/142_DRr_U.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/142_DRr_U.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/143_DRm_U.in b/test/062_transform_move/143_DRm_U.in
new file mode 100644
index 0000000..5e41816
--- /dev/null
+++ b/test/062_transform_move/143_DRm_U.in
@@ -0,0 +1,2 @@
1mirrored DR
2U
diff --git a/test/062_transform_move/143_DRm_U.out b/test/062_transform_move/143_DRm_U.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/143_DRm_U.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/144_DRr_R.in b/test/062_transform_move/144_DRr_R.in
new file mode 100644
index 0000000..5438d75
--- /dev/null
+++ b/test/062_transform_move/144_DRr_R.in
@@ -0,0 +1,2 @@
1rotation DR
2R
diff --git a/test/062_transform_move/144_DRr_R.out b/test/062_transform_move/144_DRr_R.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/144_DRr_R.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/145_DRm_R.in b/test/062_transform_move/145_DRm_R.in
new file mode 100644
index 0000000..36fa171
--- /dev/null
+++ b/test/062_transform_move/145_DRm_R.in
@@ -0,0 +1,2 @@
1mirrored DR
2R
diff --git a/test/062_transform_move/145_DRm_R.out b/test/062_transform_move/145_DRm_R.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/145_DRm_R.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/146_DRr_F.in b/test/062_transform_move/146_DRr_F.in
new file mode 100644
index 0000000..8176399
--- /dev/null
+++ b/test/062_transform_move/146_DRr_F.in
@@ -0,0 +1,2 @@
1rotation DR
2F
diff --git a/test/062_transform_move/146_DRr_F.out b/test/062_transform_move/146_DRr_F.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/146_DRr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/147_DRm_F.in b/test/062_transform_move/147_DRm_F.in
new file mode 100644
index 0000000..cba33b8
--- /dev/null
+++ b/test/062_transform_move/147_DRm_F.in
@@ -0,0 +1,2 @@
1mirrored DR
2F
diff --git a/test/062_transform_move/147_DRm_F.out b/test/062_transform_move/147_DRm_F.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/147_DRm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/148_RUr_U.in b/test/062_transform_move/148_RUr_U.in
new file mode 100644
index 0000000..14a099d
--- /dev/null
+++ b/test/062_transform_move/148_RUr_U.in
@@ -0,0 +1,2 @@
1rotation RU
2U
diff --git a/test/062_transform_move/148_RUr_U.out b/test/062_transform_move/148_RUr_U.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/148_RUr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/149_RUm_U.in b/test/062_transform_move/149_RUm_U.in
new file mode 100644
index 0000000..e44c040
--- /dev/null
+++ b/test/062_transform_move/149_RUm_U.in
@@ -0,0 +1,2 @@
1mirrored RU
2U
diff --git a/test/062_transform_move/149_RUm_U.out b/test/062_transform_move/149_RUm_U.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/149_RUm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/150_RUr_R.in b/test/062_transform_move/150_RUr_R.in
new file mode 100644
index 0000000..7abbaa5
--- /dev/null
+++ b/test/062_transform_move/150_RUr_R.in
@@ -0,0 +1,2 @@
1rotation RU
2R
diff --git a/test/062_transform_move/150_RUr_R.out b/test/062_transform_move/150_RUr_R.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/150_RUr_R.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/151_RUm_R.in b/test/062_transform_move/151_RUm_R.in
new file mode 100644
index 0000000..a4c218b
--- /dev/null
+++ b/test/062_transform_move/151_RUm_R.in
@@ -0,0 +1,2 @@
1mirrored RU
2R
diff --git a/test/062_transform_move/151_RUm_R.out b/test/062_transform_move/151_RUm_R.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/151_RUm_R.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/152_RUr_F.in b/test/062_transform_move/152_RUr_F.in
new file mode 100644
index 0000000..ff318b0
--- /dev/null
+++ b/test/062_transform_move/152_RUr_F.in
@@ -0,0 +1,2 @@
1rotation RU
2F
diff --git a/test/062_transform_move/152_RUr_F.out b/test/062_transform_move/152_RUr_F.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/152_RUr_F.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/153_RUm_F.in b/test/062_transform_move/153_RUm_F.in
new file mode 100644
index 0000000..f9f0934
--- /dev/null
+++ b/test/062_transform_move/153_RUm_F.in
@@ -0,0 +1,2 @@
1mirrored RU
2F
diff --git a/test/062_transform_move/153_RUm_F.out b/test/062_transform_move/153_RUm_F.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/153_RUm_F.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/154_RFr_U.in b/test/062_transform_move/154_RFr_U.in
new file mode 100644
index 0000000..3d2e305
--- /dev/null
+++ b/test/062_transform_move/154_RFr_U.in
@@ -0,0 +1,2 @@
1rotation RF
2U
diff --git a/test/062_transform_move/154_RFr_U.out b/test/062_transform_move/154_RFr_U.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/154_RFr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/155_RFm_U.in b/test/062_transform_move/155_RFm_U.in
new file mode 100644
index 0000000..33e5516
--- /dev/null
+++ b/test/062_transform_move/155_RFm_U.in
@@ -0,0 +1,2 @@
1mirrored RF
2U
diff --git a/test/062_transform_move/155_RFm_U.out b/test/062_transform_move/155_RFm_U.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/155_RFm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/156_RFr_R.in b/test/062_transform_move/156_RFr_R.in
new file mode 100644
index 0000000..482c29c
--- /dev/null
+++ b/test/062_transform_move/156_RFr_R.in
@@ -0,0 +1,2 @@
1rotation RF
2R
diff --git a/test/062_transform_move/156_RFr_R.out b/test/062_transform_move/156_RFr_R.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/156_RFr_R.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/157_RFm_R.in b/test/062_transform_move/157_RFm_R.in
new file mode 100644
index 0000000..b8d7a23
--- /dev/null
+++ b/test/062_transform_move/157_RFm_R.in
@@ -0,0 +1,2 @@
1mirrored RF
2R
diff --git a/test/062_transform_move/157_RFm_R.out b/test/062_transform_move/157_RFm_R.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/157_RFm_R.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/158_RFr_F.in b/test/062_transform_move/158_RFr_F.in
new file mode 100644
index 0000000..7f9c312
--- /dev/null
+++ b/test/062_transform_move/158_RFr_F.in
@@ -0,0 +1,2 @@
1rotation RF
2F
diff --git a/test/062_transform_move/158_RFr_F.out b/test/062_transform_move/158_RFr_F.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/158_RFr_F.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/159_RFm_F.in b/test/062_transform_move/159_RFm_F.in
new file mode 100644
index 0000000..ed3729f
--- /dev/null
+++ b/test/062_transform_move/159_RFm_F.in
@@ -0,0 +1,2 @@
1mirrored RF
2F
diff --git a/test/062_transform_move/159_RFm_F.out b/test/062_transform_move/159_RFm_F.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/159_RFm_F.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/160_RDr_U.in b/test/062_transform_move/160_RDr_U.in
new file mode 100644
index 0000000..11e631d
--- /dev/null
+++ b/test/062_transform_move/160_RDr_U.in
@@ -0,0 +1,2 @@
1rotation RD
2U
diff --git a/test/062_transform_move/160_RDr_U.out b/test/062_transform_move/160_RDr_U.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/160_RDr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/161_RDm_U.in b/test/062_transform_move/161_RDm_U.in
new file mode 100644
index 0000000..ac1e211
--- /dev/null
+++ b/test/062_transform_move/161_RDm_U.in
@@ -0,0 +1,2 @@
1mirrored RD
2U
diff --git a/test/062_transform_move/161_RDm_U.out b/test/062_transform_move/161_RDm_U.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/161_RDm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/162_RDr_R.in b/test/062_transform_move/162_RDr_R.in
new file mode 100644
index 0000000..6b5e82e
--- /dev/null
+++ b/test/062_transform_move/162_RDr_R.in
@@ -0,0 +1,2 @@
1rotation RD
2R
diff --git a/test/062_transform_move/162_RDr_R.out b/test/062_transform_move/162_RDr_R.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/162_RDr_R.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/163_RDm_R.in b/test/062_transform_move/163_RDm_R.in
new file mode 100644
index 0000000..6adf70e
--- /dev/null
+++ b/test/062_transform_move/163_RDm_R.in
@@ -0,0 +1,2 @@
1mirrored RD
2R
diff --git a/test/062_transform_move/163_RDm_R.out b/test/062_transform_move/163_RDm_R.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/163_RDm_R.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/164_RDr_F.in b/test/062_transform_move/164_RDr_F.in
new file mode 100644
index 0000000..99193b0
--- /dev/null
+++ b/test/062_transform_move/164_RDr_F.in
@@ -0,0 +1,2 @@
1rotation RD
2F
diff --git a/test/062_transform_move/164_RDr_F.out b/test/062_transform_move/164_RDr_F.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/164_RDr_F.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/165_RDm_F.in b/test/062_transform_move/165_RDm_F.in
new file mode 100644
index 0000000..25f8d10
--- /dev/null
+++ b/test/062_transform_move/165_RDm_F.in
@@ -0,0 +1,2 @@
1mirrored RD
2F
diff --git a/test/062_transform_move/165_RDm_F.out b/test/062_transform_move/165_RDm_F.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/165_RDm_F.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/166_RBr_U.in b/test/062_transform_move/166_RBr_U.in
new file mode 100644
index 0000000..9fd4fe0
--- /dev/null
+++ b/test/062_transform_move/166_RBr_U.in
@@ -0,0 +1,2 @@
1rotation RB
2U
diff --git a/test/062_transform_move/166_RBr_U.out b/test/062_transform_move/166_RBr_U.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/166_RBr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/167_RBm_U.in b/test/062_transform_move/167_RBm_U.in
new file mode 100644
index 0000000..bb0f464
--- /dev/null
+++ b/test/062_transform_move/167_RBm_U.in
@@ -0,0 +1,2 @@
1mirrored RB
2U
diff --git a/test/062_transform_move/167_RBm_U.out b/test/062_transform_move/167_RBm_U.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/167_RBm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/168_RBr_R.in b/test/062_transform_move/168_RBr_R.in
new file mode 100644
index 0000000..622f92b
--- /dev/null
+++ b/test/062_transform_move/168_RBr_R.in
@@ -0,0 +1,2 @@
1rotation RB
2R
diff --git a/test/062_transform_move/168_RBr_R.out b/test/062_transform_move/168_RBr_R.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/168_RBr_R.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/169_RBm_R.in b/test/062_transform_move/169_RBm_R.in
new file mode 100644
index 0000000..27bbcca
--- /dev/null
+++ b/test/062_transform_move/169_RBm_R.in
@@ -0,0 +1,2 @@
1mirrored RB
2R
diff --git a/test/062_transform_move/169_RBm_R.out b/test/062_transform_move/169_RBm_R.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/169_RBm_R.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/170_RBr_F.in b/test/062_transform_move/170_RBr_F.in
new file mode 100644
index 0000000..ef15b63
--- /dev/null
+++ b/test/062_transform_move/170_RBr_F.in
@@ -0,0 +1,2 @@
1rotation RB
2F
diff --git a/test/062_transform_move/170_RBr_F.out b/test/062_transform_move/170_RBr_F.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/170_RBr_F.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/171_RBm_F.in b/test/062_transform_move/171_RBm_F.in
new file mode 100644
index 0000000..bb41521
--- /dev/null
+++ b/test/062_transform_move/171_RBm_F.in
@@ -0,0 +1,2 @@
1mirrored RB
2F
diff --git a/test/062_transform_move/171_RBm_F.out b/test/062_transform_move/171_RBm_F.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/171_RBm_F.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/172_LUr_U.in b/test/062_transform_move/172_LUr_U.in
new file mode 100644
index 0000000..1c1b153
--- /dev/null
+++ b/test/062_transform_move/172_LUr_U.in
@@ -0,0 +1,2 @@
1rotation LU
2U
diff --git a/test/062_transform_move/172_LUr_U.out b/test/062_transform_move/172_LUr_U.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/172_LUr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/173_LUm_U.in b/test/062_transform_move/173_LUm_U.in
new file mode 100644
index 0000000..97a3788
--- /dev/null
+++ b/test/062_transform_move/173_LUm_U.in
@@ -0,0 +1,2 @@
1mirrored LU
2U
diff --git a/test/062_transform_move/173_LUm_U.out b/test/062_transform_move/173_LUm_U.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/173_LUm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/174_LUr_R.in b/test/062_transform_move/174_LUr_R.in
new file mode 100644
index 0000000..50a6aaa
--- /dev/null
+++ b/test/062_transform_move/174_LUr_R.in
@@ -0,0 +1,2 @@
1rotation LU
2R
diff --git a/test/062_transform_move/174_LUr_R.out b/test/062_transform_move/174_LUr_R.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/174_LUr_R.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/175_LUm_R.in b/test/062_transform_move/175_LUm_R.in
new file mode 100644
index 0000000..13356a5
--- /dev/null
+++ b/test/062_transform_move/175_LUm_R.in
@@ -0,0 +1,2 @@
1mirrored LU
2R
diff --git a/test/062_transform_move/175_LUm_R.out b/test/062_transform_move/175_LUm_R.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/175_LUm_R.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/176_LUr_F.in b/test/062_transform_move/176_LUr_F.in
new file mode 100644
index 0000000..8c7afff
--- /dev/null
+++ b/test/062_transform_move/176_LUr_F.in
@@ -0,0 +1,2 @@
1rotation LU
2F
diff --git a/test/062_transform_move/176_LUr_F.out b/test/062_transform_move/176_LUr_F.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/176_LUr_F.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/177_LUm_F.in b/test/062_transform_move/177_LUm_F.in
new file mode 100644
index 0000000..0dd257b
--- /dev/null
+++ b/test/062_transform_move/177_LUm_F.in
@@ -0,0 +1,2 @@
1mirrored LU
2F
diff --git a/test/062_transform_move/177_LUm_F.out b/test/062_transform_move/177_LUm_F.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/177_LUm_F.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/178_LFr_U.in b/test/062_transform_move/178_LFr_U.in
new file mode 100644
index 0000000..a925cff
--- /dev/null
+++ b/test/062_transform_move/178_LFr_U.in
@@ -0,0 +1,2 @@
1rotation LF
2U
diff --git a/test/062_transform_move/178_LFr_U.out b/test/062_transform_move/178_LFr_U.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/178_LFr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/179_LFm_U.in b/test/062_transform_move/179_LFm_U.in
new file mode 100644
index 0000000..abecf1b
--- /dev/null
+++ b/test/062_transform_move/179_LFm_U.in
@@ -0,0 +1,2 @@
1mirrored LF
2U
diff --git a/test/062_transform_move/179_LFm_U.out b/test/062_transform_move/179_LFm_U.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/179_LFm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/180_LFr_R.in b/test/062_transform_move/180_LFr_R.in
new file mode 100644
index 0000000..83b1ce3
--- /dev/null
+++ b/test/062_transform_move/180_LFr_R.in
@@ -0,0 +1,2 @@
1rotation LF
2R
diff --git a/test/062_transform_move/180_LFr_R.out b/test/062_transform_move/180_LFr_R.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/180_LFr_R.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/181_LFm_R.in b/test/062_transform_move/181_LFm_R.in
new file mode 100644
index 0000000..da71898
--- /dev/null
+++ b/test/062_transform_move/181_LFm_R.in
@@ -0,0 +1,2 @@
1mirrored LF
2R
diff --git a/test/062_transform_move/181_LFm_R.out b/test/062_transform_move/181_LFm_R.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/181_LFm_R.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/182_LFr_F.in b/test/062_transform_move/182_LFr_F.in
new file mode 100644
index 0000000..4614848
--- /dev/null
+++ b/test/062_transform_move/182_LFr_F.in
@@ -0,0 +1,2 @@
1rotation LF
2F
diff --git a/test/062_transform_move/182_LFr_F.out b/test/062_transform_move/182_LFr_F.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/182_LFr_F.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/183_LFm_F.in b/test/062_transform_move/183_LFm_F.in
new file mode 100644
index 0000000..35e1692
--- /dev/null
+++ b/test/062_transform_move/183_LFm_F.in
@@ -0,0 +1,2 @@
1mirrored LF
2F
diff --git a/test/062_transform_move/183_LFm_F.out b/test/062_transform_move/183_LFm_F.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/183_LFm_F.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/184_LDr_U.in b/test/062_transform_move/184_LDr_U.in
new file mode 100644
index 0000000..8bf7eee
--- /dev/null
+++ b/test/062_transform_move/184_LDr_U.in
@@ -0,0 +1,2 @@
1rotation LD
2U
diff --git a/test/062_transform_move/184_LDr_U.out b/test/062_transform_move/184_LDr_U.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/184_LDr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/185_LDm_U.in b/test/062_transform_move/185_LDm_U.in
new file mode 100644
index 0000000..9083212
--- /dev/null
+++ b/test/062_transform_move/185_LDm_U.in
@@ -0,0 +1,2 @@
1mirrored LD
2U
diff --git a/test/062_transform_move/185_LDm_U.out b/test/062_transform_move/185_LDm_U.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/185_LDm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/186_LDr_R.in b/test/062_transform_move/186_LDr_R.in
new file mode 100644
index 0000000..a58b0c1
--- /dev/null
+++ b/test/062_transform_move/186_LDr_R.in
@@ -0,0 +1,2 @@
1rotation LD
2R
diff --git a/test/062_transform_move/186_LDr_R.out b/test/062_transform_move/186_LDr_R.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/186_LDr_R.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/187_LDm_R.in b/test/062_transform_move/187_LDm_R.in
new file mode 100644
index 0000000..f26698c
--- /dev/null
+++ b/test/062_transform_move/187_LDm_R.in
@@ -0,0 +1,2 @@
1mirrored LD
2R
diff --git a/test/062_transform_move/187_LDm_R.out b/test/062_transform_move/187_LDm_R.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/187_LDm_R.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/188_LDr_F.in b/test/062_transform_move/188_LDr_F.in
new file mode 100644
index 0000000..40a6650
--- /dev/null
+++ b/test/062_transform_move/188_LDr_F.in
@@ -0,0 +1,2 @@
1rotation LD
2F
diff --git a/test/062_transform_move/188_LDr_F.out b/test/062_transform_move/188_LDr_F.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/188_LDr_F.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/189_LDm_F.in b/test/062_transform_move/189_LDm_F.in
new file mode 100644
index 0000000..4675cce
--- /dev/null
+++ b/test/062_transform_move/189_LDm_F.in
@@ -0,0 +1,2 @@
1mirrored LD
2F
diff --git a/test/062_transform_move/189_LDm_F.out b/test/062_transform_move/189_LDm_F.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/189_LDm_F.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/190_LBr_U.in b/test/062_transform_move/190_LBr_U.in
new file mode 100644
index 0000000..5d8e6cf
--- /dev/null
+++ b/test/062_transform_move/190_LBr_U.in
@@ -0,0 +1,2 @@
1rotation LB
2U
diff --git a/test/062_transform_move/190_LBr_U.out b/test/062_transform_move/190_LBr_U.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/190_LBr_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/191_LBm_U.in b/test/062_transform_move/191_LBm_U.in
new file mode 100644
index 0000000..da76636
--- /dev/null
+++ b/test/062_transform_move/191_LBm_U.in
@@ -0,0 +1,2 @@
1mirrored LB
2U
diff --git a/test/062_transform_move/191_LBm_U.out b/test/062_transform_move/191_LBm_U.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/191_LBm_U.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/192_LBr_R.in b/test/062_transform_move/192_LBr_R.in
new file mode 100644
index 0000000..df79496
--- /dev/null
+++ b/test/062_transform_move/192_LBr_R.in
@@ -0,0 +1,2 @@
1rotation LB
2R
diff --git a/test/062_transform_move/192_LBr_R.out b/test/062_transform_move/192_LBr_R.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/192_LBr_R.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/193_LBm_R.in b/test/062_transform_move/193_LBm_R.in
new file mode 100644
index 0000000..216f1d9
--- /dev/null
+++ b/test/062_transform_move/193_LBm_R.in
@@ -0,0 +1,2 @@
1mirrored LB
2R
diff --git a/test/062_transform_move/193_LBm_R.out b/test/062_transform_move/193_LBm_R.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/193_LBm_R.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/194_LBr_F.in b/test/062_transform_move/194_LBr_F.in
new file mode 100644
index 0000000..7b1fa9e
--- /dev/null
+++ b/test/062_transform_move/194_LBr_F.in
@@ -0,0 +1,2 @@
1rotation LB
2F
diff --git a/test/062_transform_move/194_LBr_F.out b/test/062_transform_move/194_LBr_F.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/194_LBr_F.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/195_LBm_F.in b/test/062_transform_move/195_LBm_F.in
new file mode 100644
index 0000000..698b0f0
--- /dev/null
+++ b/test/062_transform_move/195_LBm_F.in
@@ -0,0 +1,2 @@
1mirrored LB
2F
diff --git a/test/062_transform_move/195_LBm_F.out b/test/062_transform_move/195_LBm_F.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/195_LBm_F.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/196_FUr_U.in b/test/062_transform_move/196_FUr_U.in
new file mode 100644
index 0000000..6509b98
--- /dev/null
+++ b/test/062_transform_move/196_FUr_U.in
@@ -0,0 +1,2 @@
1rotation FU
2U
diff --git a/test/062_transform_move/196_FUr_U.out b/test/062_transform_move/196_FUr_U.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/196_FUr_U.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/197_FUm_U.in b/test/062_transform_move/197_FUm_U.in
new file mode 100644
index 0000000..68506e1
--- /dev/null
+++ b/test/062_transform_move/197_FUm_U.in
@@ -0,0 +1,2 @@
1mirrored FU
2U
diff --git a/test/062_transform_move/197_FUm_U.out b/test/062_transform_move/197_FUm_U.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/197_FUm_U.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/198_FUr_R.in b/test/062_transform_move/198_FUr_R.in
new file mode 100644
index 0000000..3942662
--- /dev/null
+++ b/test/062_transform_move/198_FUr_R.in
@@ -0,0 +1,2 @@
1rotation FU
2R
diff --git a/test/062_transform_move/198_FUr_R.out b/test/062_transform_move/198_FUr_R.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/198_FUr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/199_FUm_R.in b/test/062_transform_move/199_FUm_R.in
new file mode 100644
index 0000000..6c0e1d8
--- /dev/null
+++ b/test/062_transform_move/199_FUm_R.in
@@ -0,0 +1,2 @@
1mirrored FU
2R
diff --git a/test/062_transform_move/199_FUm_R.out b/test/062_transform_move/199_FUm_R.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/199_FUm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/200_FUr_F.in b/test/062_transform_move/200_FUr_F.in
new file mode 100644
index 0000000..9ca7233
--- /dev/null
+++ b/test/062_transform_move/200_FUr_F.in
@@ -0,0 +1,2 @@
1rotation FU
2F
diff --git a/test/062_transform_move/200_FUr_F.out b/test/062_transform_move/200_FUr_F.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/200_FUr_F.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/201_FUm_F.in b/test/062_transform_move/201_FUm_F.in
new file mode 100644
index 0000000..1336919
--- /dev/null
+++ b/test/062_transform_move/201_FUm_F.in
@@ -0,0 +1,2 @@
1mirrored FU
2F
diff --git a/test/062_transform_move/201_FUm_F.out b/test/062_transform_move/201_FUm_F.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/201_FUm_F.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/202_FRr_U.in b/test/062_transform_move/202_FRr_U.in
new file mode 100644
index 0000000..cf87afa
--- /dev/null
+++ b/test/062_transform_move/202_FRr_U.in
@@ -0,0 +1,2 @@
1rotation FR
2U
diff --git a/test/062_transform_move/202_FRr_U.out b/test/062_transform_move/202_FRr_U.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/202_FRr_U.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/203_FRm_U.in b/test/062_transform_move/203_FRm_U.in
new file mode 100644
index 0000000..bcc8e06
--- /dev/null
+++ b/test/062_transform_move/203_FRm_U.in
@@ -0,0 +1,2 @@
1mirrored FR
2U
diff --git a/test/062_transform_move/203_FRm_U.out b/test/062_transform_move/203_FRm_U.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/203_FRm_U.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/204_FRr_R.in b/test/062_transform_move/204_FRr_R.in
new file mode 100644
index 0000000..651c13e
--- /dev/null
+++ b/test/062_transform_move/204_FRr_R.in
@@ -0,0 +1,2 @@
1rotation FR
2R
diff --git a/test/062_transform_move/204_FRr_R.out b/test/062_transform_move/204_FRr_R.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/204_FRr_R.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/205_FRm_R.in b/test/062_transform_move/205_FRm_R.in
new file mode 100644
index 0000000..ef68c0a
--- /dev/null
+++ b/test/062_transform_move/205_FRm_R.in
@@ -0,0 +1,2 @@
1mirrored FR
2R
diff --git a/test/062_transform_move/205_FRm_R.out b/test/062_transform_move/205_FRm_R.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/205_FRm_R.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/206_FRr_F.in b/test/062_transform_move/206_FRr_F.in
new file mode 100644
index 0000000..c774527
--- /dev/null
+++ b/test/062_transform_move/206_FRr_F.in
@@ -0,0 +1,2 @@
1rotation FR
2F
diff --git a/test/062_transform_move/206_FRr_F.out b/test/062_transform_move/206_FRr_F.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/206_FRr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/207_FRm_F.in b/test/062_transform_move/207_FRm_F.in
new file mode 100644
index 0000000..7a3a380
--- /dev/null
+++ b/test/062_transform_move/207_FRm_F.in
@@ -0,0 +1,2 @@
1mirrored FR
2F
diff --git a/test/062_transform_move/207_FRm_F.out b/test/062_transform_move/207_FRm_F.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/207_FRm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/208_FDr_U.in b/test/062_transform_move/208_FDr_U.in
new file mode 100644
index 0000000..3af2995
--- /dev/null
+++ b/test/062_transform_move/208_FDr_U.in
@@ -0,0 +1,2 @@
1rotation FD
2U
diff --git a/test/062_transform_move/208_FDr_U.out b/test/062_transform_move/208_FDr_U.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/208_FDr_U.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/209_FDm_U.in b/test/062_transform_move/209_FDm_U.in
new file mode 100644
index 0000000..4676c00
--- /dev/null
+++ b/test/062_transform_move/209_FDm_U.in
@@ -0,0 +1,2 @@
1mirrored FD
2U
diff --git a/test/062_transform_move/209_FDm_U.out b/test/062_transform_move/209_FDm_U.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/209_FDm_U.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/210_FDr_R.in b/test/062_transform_move/210_FDr_R.in
new file mode 100644
index 0000000..3dac731
--- /dev/null
+++ b/test/062_transform_move/210_FDr_R.in
@@ -0,0 +1,2 @@
1rotation FD
2R
diff --git a/test/062_transform_move/210_FDr_R.out b/test/062_transform_move/210_FDr_R.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/210_FDr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/211_FDm_R.in b/test/062_transform_move/211_FDm_R.in
new file mode 100644
index 0000000..9cf020a
--- /dev/null
+++ b/test/062_transform_move/211_FDm_R.in
@@ -0,0 +1,2 @@
1mirrored FD
2R
diff --git a/test/062_transform_move/211_FDm_R.out b/test/062_transform_move/211_FDm_R.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/211_FDm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/212_FDr_F.in b/test/062_transform_move/212_FDr_F.in
new file mode 100644
index 0000000..2ac82a2
--- /dev/null
+++ b/test/062_transform_move/212_FDr_F.in
@@ -0,0 +1,2 @@
1rotation FD
2F
diff --git a/test/062_transform_move/212_FDr_F.out b/test/062_transform_move/212_FDr_F.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/212_FDr_F.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/213_FDm_F.in b/test/062_transform_move/213_FDm_F.in
new file mode 100644
index 0000000..908fc92
--- /dev/null
+++ b/test/062_transform_move/213_FDm_F.in
@@ -0,0 +1,2 @@
1mirrored FD
2F
diff --git a/test/062_transform_move/213_FDm_F.out b/test/062_transform_move/213_FDm_F.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/213_FDm_F.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/214_FLr_U.in b/test/062_transform_move/214_FLr_U.in
new file mode 100644
index 0000000..25f4d59
--- /dev/null
+++ b/test/062_transform_move/214_FLr_U.in
@@ -0,0 +1,2 @@
1rotation FL
2U
diff --git a/test/062_transform_move/214_FLr_U.out b/test/062_transform_move/214_FLr_U.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/214_FLr_U.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/215_FLm_U.in b/test/062_transform_move/215_FLm_U.in
new file mode 100644
index 0000000..cc93bb7
--- /dev/null
+++ b/test/062_transform_move/215_FLm_U.in
@@ -0,0 +1,2 @@
1mirrored FL
2U
diff --git a/test/062_transform_move/215_FLm_U.out b/test/062_transform_move/215_FLm_U.out
new file mode 100644
index 0000000..40f1260
--- /dev/null
+++ b/test/062_transform_move/215_FLm_U.out
@@ -0,0 +1 @@
FR1 UB0 DB0 FL1 UR0 UL0 DL0 DR0 DF1 UF1 BL0 BR0 DFR1 UBL0 UFL1 DBR0 UFR2 UBR0 DFL2 DBL0
diff --git a/test/062_transform_move/216_FLr_R.in b/test/062_transform_move/216_FLr_R.in
new file mode 100644
index 0000000..5d23140
--- /dev/null
+++ b/test/062_transform_move/216_FLr_R.in
@@ -0,0 +1,2 @@
1rotation FL
2R
diff --git a/test/062_transform_move/216_FLr_R.out b/test/062_transform_move/216_FLr_R.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/216_FLr_R.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/217_FLm_R.in b/test/062_transform_move/217_FLm_R.in
new file mode 100644
index 0000000..5feaf31
--- /dev/null
+++ b/test/062_transform_move/217_FLm_R.in
@@ -0,0 +1,2 @@
1mirrored FL
2R
diff --git a/test/062_transform_move/217_FLm_R.out b/test/062_transform_move/217_FLm_R.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/217_FLm_R.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/218_FLr_F.in b/test/062_transform_move/218_FLr_F.in
new file mode 100644
index 0000000..bb15d54
--- /dev/null
+++ b/test/062_transform_move/218_FLr_F.in
@@ -0,0 +1,2 @@
1rotation FL
2F
diff --git a/test/062_transform_move/218_FLr_F.out b/test/062_transform_move/218_FLr_F.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/218_FLr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/219_FLm_F.in b/test/062_transform_move/219_FLm_F.in
new file mode 100644
index 0000000..1825937
--- /dev/null
+++ b/test/062_transform_move/219_FLm_F.in
@@ -0,0 +1,2 @@
1mirrored FL
2F
diff --git a/test/062_transform_move/219_FLm_F.out b/test/062_transform_move/219_FLm_F.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/219_FLm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/220_BUr_U.in b/test/062_transform_move/220_BUr_U.in
new file mode 100644
index 0000000..92f1499
--- /dev/null
+++ b/test/062_transform_move/220_BUr_U.in
@@ -0,0 +1,2 @@
1rotation BU
2U
diff --git a/test/062_transform_move/220_BUr_U.out b/test/062_transform_move/220_BUr_U.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/220_BUr_U.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/221_BUm_U.in b/test/062_transform_move/221_BUm_U.in
new file mode 100644
index 0000000..1201881
--- /dev/null
+++ b/test/062_transform_move/221_BUm_U.in
@@ -0,0 +1,2 @@
1mirrored BU
2U
diff --git a/test/062_transform_move/221_BUm_U.out b/test/062_transform_move/221_BUm_U.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/221_BUm_U.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/222_BUr_R.in b/test/062_transform_move/222_BUr_R.in
new file mode 100644
index 0000000..65ce467
--- /dev/null
+++ b/test/062_transform_move/222_BUr_R.in
@@ -0,0 +1,2 @@
1rotation BU
2R
diff --git a/test/062_transform_move/222_BUr_R.out b/test/062_transform_move/222_BUr_R.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/222_BUr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/223_BUm_R.in b/test/062_transform_move/223_BUm_R.in
new file mode 100644
index 0000000..16812de
--- /dev/null
+++ b/test/062_transform_move/223_BUm_R.in
@@ -0,0 +1,2 @@
1mirrored BU
2R
diff --git a/test/062_transform_move/223_BUm_R.out b/test/062_transform_move/223_BUm_R.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/223_BUm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/224_BUr_F.in b/test/062_transform_move/224_BUr_F.in
new file mode 100644
index 0000000..d52786e
--- /dev/null
+++ b/test/062_transform_move/224_BUr_F.in
@@ -0,0 +1,2 @@
1rotation BU
2F
diff --git a/test/062_transform_move/224_BUr_F.out b/test/062_transform_move/224_BUr_F.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/224_BUr_F.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/225_BUm_F.in b/test/062_transform_move/225_BUm_F.in
new file mode 100644
index 0000000..7e02140
--- /dev/null
+++ b/test/062_transform_move/225_BUm_F.in
@@ -0,0 +1,2 @@
1mirrored BU
2F
diff --git a/test/062_transform_move/225_BUm_F.out b/test/062_transform_move/225_BUm_F.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/225_BUm_F.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/226_BRr_U.in b/test/062_transform_move/226_BRr_U.in
new file mode 100644
index 0000000..ab18de3
--- /dev/null
+++ b/test/062_transform_move/226_BRr_U.in
@@ -0,0 +1,2 @@
1rotation BR
2U
diff --git a/test/062_transform_move/226_BRr_U.out b/test/062_transform_move/226_BRr_U.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/226_BRr_U.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/227_BRm_U.in b/test/062_transform_move/227_BRm_U.in
new file mode 100644
index 0000000..71f11a6
--- /dev/null
+++ b/test/062_transform_move/227_BRm_U.in
@@ -0,0 +1,2 @@
1mirrored BR
2U
diff --git a/test/062_transform_move/227_BRm_U.out b/test/062_transform_move/227_BRm_U.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/227_BRm_U.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/228_BRr_R.in b/test/062_transform_move/228_BRr_R.in
new file mode 100644
index 0000000..b9063cc
--- /dev/null
+++ b/test/062_transform_move/228_BRr_R.in
@@ -0,0 +1,2 @@
1rotation BR
2R
diff --git a/test/062_transform_move/228_BRr_R.out b/test/062_transform_move/228_BRr_R.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/228_BRr_R.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/229_BRm_R.in b/test/062_transform_move/229_BRm_R.in
new file mode 100644
index 0000000..2b44bcb
--- /dev/null
+++ b/test/062_transform_move/229_BRm_R.in
@@ -0,0 +1,2 @@
1mirrored BR
2R
diff --git a/test/062_transform_move/229_BRm_R.out b/test/062_transform_move/229_BRm_R.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/229_BRm_R.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/230_BRr_F.in b/test/062_transform_move/230_BRr_F.in
new file mode 100644
index 0000000..4f75490
--- /dev/null
+++ b/test/062_transform_move/230_BRr_F.in
@@ -0,0 +1,2 @@
1rotation BR
2F
diff --git a/test/062_transform_move/230_BRr_F.out b/test/062_transform_move/230_BRr_F.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/230_BRr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/231_BRm_F.in b/test/062_transform_move/231_BRm_F.in
new file mode 100644
index 0000000..b528c7c
--- /dev/null
+++ b/test/062_transform_move/231_BRm_F.in
@@ -0,0 +1,2 @@
1mirrored BR
2F
diff --git a/test/062_transform_move/231_BRm_F.out b/test/062_transform_move/231_BRm_F.out
new file mode 100644
index 0000000..2ac2912
--- /dev/null
+++ b/test/062_transform_move/231_BRm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 FL0 BL0 DR0 FR0 DL0 UL0 BR0 UFR0 UFL2 DBL2 DBR0 DFL1 UBR0 DFR0 UBL1
diff --git a/test/062_transform_move/232_BDr_U.in b/test/062_transform_move/232_BDr_U.in
new file mode 100644
index 0000000..a7581ff
--- /dev/null
+++ b/test/062_transform_move/232_BDr_U.in
@@ -0,0 +1,2 @@
1rotation BD
2U
diff --git a/test/062_transform_move/232_BDr_U.out b/test/062_transform_move/232_BDr_U.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/232_BDr_U.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/233_BDm_U.in b/test/062_transform_move/233_BDm_U.in
new file mode 100644
index 0000000..eea87b2
--- /dev/null
+++ b/test/062_transform_move/233_BDm_U.in
@@ -0,0 +1,2 @@
1mirrored BD
2U
diff --git a/test/062_transform_move/233_BDm_U.out b/test/062_transform_move/233_BDm_U.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/233_BDm_U.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/234_BDr_R.in b/test/062_transform_move/234_BDr_R.in
new file mode 100644
index 0000000..b892468
--- /dev/null
+++ b/test/062_transform_move/234_BDr_R.in
@@ -0,0 +1,2 @@
1rotation BD
2R
diff --git a/test/062_transform_move/234_BDr_R.out b/test/062_transform_move/234_BDr_R.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/234_BDr_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/235_BDm_R.in b/test/062_transform_move/235_BDm_R.in
new file mode 100644
index 0000000..949c5eb
--- /dev/null
+++ b/test/062_transform_move/235_BDm_R.in
@@ -0,0 +1,2 @@
1mirrored BD
2R
diff --git a/test/062_transform_move/235_BDm_R.out b/test/062_transform_move/235_BDm_R.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/235_BDm_R.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/236_BDr_F.in b/test/062_transform_move/236_BDr_F.in
new file mode 100644
index 0000000..44d4b00
--- /dev/null
+++ b/test/062_transform_move/236_BDr_F.in
@@ -0,0 +1,2 @@
1rotation BD
2F
diff --git a/test/062_transform_move/236_BDr_F.out b/test/062_transform_move/236_BDr_F.out
new file mode 100644
index 0000000..cf4f816
--- /dev/null
+++ b/test/062_transform_move/236_BDr_F.out
@@ -0,0 +1 @@
UF0 UB0 DR0 DL0 UR0 UL0 DB0 DF0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBL0 DFR0 UFL0 UBR0 DFL0 DBR0
diff --git a/test/062_transform_move/237_BDm_F.in b/test/062_transform_move/237_BDm_F.in
new file mode 100644
index 0000000..3b78a8a
--- /dev/null
+++ b/test/062_transform_move/237_BDm_F.in
@@ -0,0 +1,2 @@
1mirrored BD
2F
diff --git a/test/062_transform_move/237_BDm_F.out b/test/062_transform_move/237_BDm_F.out
new file mode 100644
index 0000000..2864f5b
--- /dev/null
+++ b/test/062_transform_move/237_BDm_F.out
@@ -0,0 +1 @@
UF0 UB0 DL0 DR0 UR0 UL0 DF0 DB0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFR0 DBL0 UFL0 UBR0 DBR0 DFL0
diff --git a/test/062_transform_move/238_BLr_U.in b/test/062_transform_move/238_BLr_U.in
new file mode 100644
index 0000000..6c1a6f2
--- /dev/null
+++ b/test/062_transform_move/238_BLr_U.in
@@ -0,0 +1,2 @@
1rotation BL
2U
diff --git a/test/062_transform_move/238_BLr_U.out b/test/062_transform_move/238_BLr_U.out
new file mode 100644
index 0000000..f7fb13c
--- /dev/null
+++ b/test/062_transform_move/238_BLr_U.out
@@ -0,0 +1 @@
UF0 BR1 BL1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 UB1 DB1 UFR0 UBR1 DFL0 DBL1 UFL0 DBR2 DFR0 UBL2
diff --git a/test/062_transform_move/239_BLm_U.in b/test/062_transform_move/239_BLm_U.in
new file mode 100644
index 0000000..a85171a
--- /dev/null
+++ b/test/062_transform_move/239_BLm_U.in
@@ -0,0 +1,2 @@
1mirrored BL
2U
diff --git a/test/062_transform_move/239_BLm_U.out b/test/062_transform_move/239_BLm_U.out
new file mode 100644
index 0000000..1367517
--- /dev/null
+++ b/test/062_transform_move/239_BLm_U.out
@@ -0,0 +1 @@
UF0 BL1 BR1 DF0 UR0 UL0 DL0 DR0 FR0 FL0 DB1 UB1 UFR0 DBL1 DFL0 UBR1 UFL0 UBL2 DFR0 DBR2
diff --git a/test/062_transform_move/240_BLr_R.in b/test/062_transform_move/240_BLr_R.in
new file mode 100644
index 0000000..5358ad9
--- /dev/null
+++ b/test/062_transform_move/240_BLr_R.in
@@ -0,0 +1,2 @@
1rotation BL
2R
diff --git a/test/062_transform_move/240_BLr_R.out b/test/062_transform_move/240_BLr_R.out
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/062_transform_move/240_BLr_R.out
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/062_transform_move/241_BLm_R.in b/test/062_transform_move/241_BLm_R.in
new file mode 100644
index 0000000..006edc8
--- /dev/null
+++ b/test/062_transform_move/241_BLm_R.in
@@ -0,0 +1,2 @@
1mirrored BL
2R
diff --git a/test/062_transform_move/241_BLm_R.out b/test/062_transform_move/241_BLm_R.out
new file mode 100644
index 0000000..7721ab5
--- /dev/null
+++ b/test/062_transform_move/241_BLm_R.out
@@ -0,0 +1 @@
UL0 UR0 DB0 DF0 UF0 UB0 DL0 DR0 FR0 FL0 BL0 BR0 UFL0 UBR0 DFL0 DBR0 UBL0 UFR0 DFR0 DBL0
diff --git a/test/062_transform_move/242_BLr_F.in b/test/062_transform_move/242_BLr_F.in
new file mode 100644
index 0000000..25aa91d
--- /dev/null
+++ b/test/062_transform_move/242_BLr_F.in
@@ -0,0 +1,2 @@
1rotation BL
2F
diff --git a/test/062_transform_move/242_BLr_F.out b/test/062_transform_move/242_BLr_F.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/242_BLr_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/243_BLm_F.in b/test/062_transform_move/243_BLm_F.in
new file mode 100644
index 0000000..7fcd3dd
--- /dev/null
+++ b/test/062_transform_move/243_BLm_F.in
@@ -0,0 +1,2 @@
1mirrored BL
2F
diff --git a/test/062_transform_move/243_BLm_F.out b/test/062_transform_move/243_BLm_F.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/243_BLm_F.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/244_modifier_LBr_R2.in b/test/062_transform_move/244_modifier_LBr_R2.in
new file mode 100644
index 0000000..29c983c
--- /dev/null
+++ b/test/062_transform_move/244_modifier_LBr_R2.in
@@ -0,0 +1,2 @@
1rotation LB
2R2
diff --git a/test/062_transform_move/244_modifier_LBr_R2.out b/test/062_transform_move/244_modifier_LBr_R2.out
new file mode 100644
index 0000000..13b229e
--- /dev/null
+++ b/test/062_transform_move/244_modifier_LBr_R2.out
@@ -0,0 +1 @@
UF0 UB0 DF0 DB0 UR0 UL0 DR0 DL0 FR0 FL0 BL0 BR0 UFR0 UBL0 DBR0 DFL0 UFL0 UBR0 DBL0 DFR0
diff --git a/test/062_transform_move/245_modifier_URr_F3.in b/test/062_transform_move/245_modifier_URr_F3.in
new file mode 100644
index 0000000..aab14a7
--- /dev/null
+++ b/test/062_transform_move/245_modifier_URr_F3.in
@@ -0,0 +1,2 @@
1rotation UR
2F'
diff --git a/test/062_transform_move/245_modifier_URr_F3.out b/test/062_transform_move/245_modifier_URr_F3.out
new file mode 100644
index 0000000..d4abffc
--- /dev/null
+++ b/test/062_transform_move/245_modifier_URr_F3.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 BR0 UL0 DL0 FR0 UR0 FL0 BL0 DR0 UBR2 UBL0 DFL0 DFR2 UFL0 DBR1 UFR1 DBL0
diff --git a/test/062_transform_move/246_modifier_RBm_U3.in b/test/062_transform_move/246_modifier_RBm_U3.in
new file mode 100644
index 0000000..7a48502
--- /dev/null
+++ b/test/062_transform_move/246_modifier_RBm_U3.in
@@ -0,0 +1,2 @@
1mirrored RB
2U3
diff --git a/test/062_transform_move/246_modifier_RBm_U3.out b/test/062_transform_move/246_modifier_RBm_U3.out
new file mode 100644
index 0000000..0b0565c
--- /dev/null
+++ b/test/062_transform_move/246_modifier_RBm_U3.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 BL0 FL0 DR0 FR0 UL0 DL0 BR0 UFR0 DBL2 UFL2 DBR0 UBL1 UBR0 DFR0 DFL1
diff --git a/test/062_transform_move/247_axis_UBr_L.in b/test/062_transform_move/247_axis_UBr_L.in
new file mode 100644
index 0000000..54cfc45
--- /dev/null
+++ b/test/062_transform_move/247_axis_UBr_L.in
@@ -0,0 +1,2 @@
1rotation UB
2L
diff --git a/test/062_transform_move/247_axis_UBr_L.out b/test/062_transform_move/247_axis_UBr_L.out
new file mode 100644
index 0000000..8c8fcb3
--- /dev/null
+++ b/test/062_transform_move/247_axis_UBr_L.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 FR0 UL0 DL0 BR0 DR0 FL0 BL0 UR0 DFR2 UBL0 DFL0 UBR2 UFL0 UFR1 DBR1 DBL0
diff --git a/test/062_transform_move/248_axis_BDm_D3.in b/test/062_transform_move/248_axis_BDm_D3.in
new file mode 100644
index 0000000..804ee15
--- /dev/null
+++ b/test/062_transform_move/248_axis_BDm_D3.in
@@ -0,0 +1,2 @@
1mirrored BD
2D3
diff --git a/test/062_transform_move/248_axis_BDm_D3.out b/test/062_transform_move/248_axis_BDm_D3.out
new file mode 100644
index 0000000..e805af8
--- /dev/null
+++ b/test/062_transform_move/248_axis_BDm_D3.out
@@ -0,0 +1 @@
FL1 UB0 DB0 FR1 UR0 UL0 DL0 DR0 UF1 DF1 BL0 BR0 UFL1 UBL0 DFR1 DBR0 DFL2 UBR0 UFR2 DBL0
diff --git a/test/062_transform_move/249_axis_DLr_B2.in b/test/062_transform_move/249_axis_DLr_B2.in
new file mode 100644
index 0000000..fb1ef80
--- /dev/null
+++ b/test/062_transform_move/249_axis_DLr_B2.in
@@ -0,0 +1,2 @@
1rotation DL
2B2
diff --git a/test/062_transform_move/249_axis_DLr_B2.out b/test/062_transform_move/249_axis_DLr_B2.out
new file mode 100644
index 0000000..90765e2
--- /dev/null
+++ b/test/062_transform_move/249_axis_DLr_B2.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 DR0 UL0 DL0 UR0 BR0 FL0 BL0 FR0 DBR0 UBL0 DFL0 UFR0 UFL0 DFR0 UBR0 DBL0
diff --git a/test/062_transform_move/transform_move_tests.c b/test/062_transform_move/transform_move_tests.c
new file mode 100644
index 0000000..4b7f420
--- /dev/null
+++ b/test/062_transform_move/transform_move_tests.c
@@ -0,0 +1,29 @@
1#include "../test.h"
2
3#define MAXMOVES 150
4
5cube_t applytrans(cube_t, const char *);
6uint8_t transform_move(uint8_t, uint8_t);
7int readmoves(const char *, int, uint8_t *);
8cube_t move(cube_t, uint8_t);
9cube_t applymoves(cube_t, const char *);
10uint8_t readtrans(const char[static NISSY_SIZE_TRANSFORMATION]);
11
12void run(void) {
13 char movestr[STRLENMAX], transtr[STRLENMAX], cubestr[STRLENMAX];
14 uint8_t t, moves[MAXMOVES];
15 int i, n;
16 cube_t cube;
17
18 fgets(transtr, STRLENMAX, stdin);
19 fgets(movestr, STRLENMAX, stdin);
20
21 cube = solvedcube();
22 n = readmoves(movestr, MAXMOVES, moves);
23 t = readtrans(transtr);
24 for (i = 0; i < n; i++)
25 cube = move(cube, transform_move(moves[i], t));
26
27 writecube("H48", cube, STRLENMAX, cubestr);
28 printf("%s\n", cubestr);
29}
diff --git a/test/063_symmetry_mask/00_solved.in b/test/063_symmetry_mask/00_solved.in
new file mode 100644
index 0000000..dff224d
--- /dev/null
+++ b/test/063_symmetry_mask/00_solved.in
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0
diff --git a/test/063_symmetry_mask/00_solved.out b/test/063_symmetry_mask/00_solved.out
new file mode 100644
index 0000000..05fdc4c
--- /dev/null
+++ b/test/063_symmetry_mask/00_solved.out
@@ -0,0 +1 @@
111111111111111111111111111111111111111111111111
diff --git a/test/063_symmetry_mask/01_U.in b/test/063_symmetry_mask/01_U.in
new file mode 100644
index 0000000..b5b36ad
--- /dev/null
+++ b/test/063_symmetry_mask/01_U.in
@@ -0,0 +1 @@
UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0
diff --git a/test/063_symmetry_mask/01_U.out b/test/063_symmetry_mask/01_U.out
new file mode 100644
index 0000000..a71f9f4
--- /dev/null
+++ b/test/063_symmetry_mask/01_U.out
@@ -0,0 +1 @@
111100000000000000000000000000000000000000000000
diff --git a/test/063_symmetry_mask/02_B2.in b/test/063_symmetry_mask/02_B2.in
new file mode 100644
index 0000000..9b33e35
--- /dev/null
+++ b/test/063_symmetry_mask/02_B2.in
@@ -0,0 +1 @@
UF0 DB0 UB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BR0 BL0 UFR0 DBR0 DFL0 UBL0 UFL0 DBL0 DFR0 UBR0
diff --git a/test/063_symmetry_mask/02_B2.out b/test/063_symmetry_mask/02_B2.out
new file mode 100644
index 0000000..9a040fc
--- /dev/null
+++ b/test/063_symmetry_mask/02_B2.out
@@ -0,0 +1 @@
100010000100010000000000100010000100010000000000
diff --git a/test/063_symmetry_mask/03_superflip.in b/test/063_symmetry_mask/03_superflip.in
new file mode 100644
index 0000000..ec7594a
--- /dev/null
+++ b/test/063_symmetry_mask/03_superflip.in
@@ -0,0 +1 @@
UF1 UB1 DB1 DF1 UR1 UL1 DL1 DR1 FR1 FL1 BL1 BR1 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0
diff --git a/test/063_symmetry_mask/03_superflip.out b/test/063_symmetry_mask/03_superflip.out
new file mode 100644
index 0000000..05fdc4c
--- /dev/null
+++ b/test/063_symmetry_mask/03_superflip.out
@@ -0,0 +1 @@
111111111111111111111111111111111111111111111111
diff --git a/test/063_symmetry_mask/04_scrambled.in b/test/063_symmetry_mask/04_scrambled.in
new file mode 100644
index 0000000..6c52430
--- /dev/null
+++ b/test/063_symmetry_mask/04_scrambled.in
@@ -0,0 +1 @@
UB1 UL0 UF1 DL0 FL0 DB0 BR0 BL0 DF0 FR0 DR0 UR0 UBR1 DFR1 UBL0 DFL2 DBR1 DBL2 UFR1 UFL1
diff --git a/test/063_symmetry_mask/04_scrambled.out b/test/063_symmetry_mask/04_scrambled.out
new file mode 100644
index 0000000..4b9bb89
--- /dev/null
+++ b/test/063_symmetry_mask/04_scrambled.out
@@ -0,0 +1 @@
100000000000000000000000000000000000000000000000
diff --git a/test/063_symmetry_mask/symmetry_mask_tests.c b/test/063_symmetry_mask/symmetry_mask_tests.c
new file mode 100644
index 0000000..ccc2623
--- /dev/null
+++ b/test/063_symmetry_mask/symmetry_mask_tests.c
@@ -0,0 +1,17 @@
1#include "../test.h"
2
3uint64_t symmetry_mask(cube_t);
4
5void run(void) {
6 char str[STRLENMAX];
7 uint64_t i, result;
8 cube_t cube;
9
10 fgets(str, STRLENMAX, stdin);
11 cube = readcube("H48", str);
12 result = symmetry_mask(cube);
13
14 for (i = 0; i < 48; result >>= 1, i++)
15 printf("%" PRIu64, result % UINT64_C(2));
16 printf("\n");
17}
diff --git a/test/105_gendata_eoesep/00_all.in b/test/105_gendata_eoesep/00_all.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/105_gendata_eoesep/00_all.in
diff --git a/test/105_gendata_eoesep/00_all.out b/test/105_gendata_eoesep/00_all.out
new file mode 100644
index 0000000..df5195d
--- /dev/null
+++ b/test/105_gendata_eoesep/00_all.out
@@ -0,0 +1,9 @@
1939880
2Classes (ESEP only): 782
30: 1
41: 1
52: 3
63: 23
74: 235
85: 2281
96: 22069
diff --git a/test/105_gendata_eoesep/gendata_eoesep_tests.c b/test/105_gendata_eoesep/gendata_eoesep_tests.c
new file mode 100644
index 0000000..62c36bc
--- /dev/null
+++ b/test/105_gendata_eoesep/gendata_eoesep_tests.c
@@ -0,0 +1,46 @@
1/*
2The test does not generate the full table. For reference, these are the values:
3
40: 1
51: 1
62: 3
73: 23
84: 235
95: 2281
106: 22069
117: 182776
128: 767847
139: 617858
1410: 8439
1511: 3
16*/
17
18#include "../test.h"
19
20#define DEPTH 6
21#define EMAX (495*70)
22#define CL 782
23#define ISIZE 512
24#define FULLSIZE (ISIZE + (CL*1024) + (4*EMAX))
25
26char buf[FULLSIZE];
27
28size_t gendata_eoesep(char [static FULLSIZE], uint8_t);
29bool readtableinfo(uint64_t, const char *, tableinfo_t *);
30
31void run(void) {
32 uint32_t i;
33 size_t result;
34 tableinfo_t info;
35
36 result = gendata_eoesep(buf, DEPTH);
37 if (readtableinfo(FULLSIZE, buf, &info) != NISSY_OK) {
38 printf("Error reading info from table\n");
39 return;
40 }
41
42 printf("%zu\n", result);
43 printf("Classes (ESEP only): %zu\n", info.classes);
44 for (i = 0; i <= DEPTH; i++)
45 printf("%" PRIu32 ": %" PRIu64 "\n", i, info.distribution[i]);
46}
diff --git a/test/130_allowednext_h48/00_empty_U.in b/test/130_allowednext_h48/00_empty_U.in
deleted file mode 100644
index 28271a6..0000000
--- a/test/130_allowednext_h48/00_empty_U.in
+++ /dev/null
@@ -1,3 +0,0 @@
10
20
3
diff --git a/test/130_allowednext_h48/00_empty_U.out b/test/130_allowednext_h48/00_empty_U.out
deleted file mode 100644
index 8607955..0000000
--- a/test/130_allowednext_h48/00_empty_U.out
+++ /dev/null
@@ -1 +0,0 @@
10x3FFFF
diff --git a/test/130_allowednext_h48/01_F.in b/test/130_allowednext_h48/01_F.in
deleted file mode 100644
index e7ae375..0000000
--- a/test/130_allowednext_h48/01_F.in
+++ /dev/null
@@ -1,4 +0,0 @@
10
21
3F
4
diff --git a/test/130_allowednext_h48/01_F.out b/test/130_allowednext_h48/01_F.out
deleted file mode 100644
index 5d6f843..0000000
--- a/test/130_allowednext_h48/01_F.out
+++ /dev/null
@@ -1 +0,0 @@
10x38FFF
diff --git a/test/130_allowednext_h48/02_U2.in b/test/130_allowednext_h48/02_U2.in
deleted file mode 100644
index 2c5ee5f..0000000
--- a/test/130_allowednext_h48/02_U2.in
+++ /dev/null
@@ -1,3 +0,0 @@
10
21
3U
diff --git a/test/130_allowednext_h48/02_U2.out b/test/130_allowednext_h48/02_U2.out
deleted file mode 100644
index a9a5adb..0000000
--- a/test/130_allowednext_h48/02_U2.out
+++ /dev/null
@@ -1 +0,0 @@
10x3FFF8
diff --git a/test/130_allowednext_h48/03_R_L.in b/test/130_allowednext_h48/03_R_L.in
deleted file mode 100644
index b6c0625..0000000
--- a/test/130_allowednext_h48/03_R_L.in
+++ /dev/null
@@ -1,5 +0,0 @@
10
22
3R
4L'
5
diff --git a/test/130_allowednext_h48/03_R_L.out b/test/130_allowednext_h48/03_R_L.out
deleted file mode 100644
index a4aa4b2..0000000
--- a/test/130_allowednext_h48/03_R_L.out
+++ /dev/null
@@ -1 +0,0 @@
10x3F03F
diff --git a/test/130_allowednext_h48/04_D.in b/test/130_allowednext_h48/04_D.in
deleted file mode 100644
index 83da556..0000000
--- a/test/130_allowednext_h48/04_D.in
+++ /dev/null
@@ -1,3 +0,0 @@
10
21
3D
diff --git a/test/130_allowednext_h48/04_D.out b/test/130_allowednext_h48/04_D.out
deleted file mode 100644
index fe91843..0000000
--- a/test/130_allowednext_h48/04_D.out
+++ /dev/null
@@ -1 +0,0 @@
10x3FFC0
diff --git a/test/130_allowednext_h48/05_U_F_B2.in b/test/130_allowednext_h48/05_U_F_B2.in
deleted file mode 100644
index 67e090f..0000000
--- a/test/130_allowednext_h48/05_U_F_B2.in
+++ /dev/null
@@ -1,5 +0,0 @@
10
22
3U
4F
5
diff --git a/test/130_allowednext_h48/05_U_F_B2.out b/test/130_allowednext_h48/05_U_F_B2.out
deleted file mode 100644
index 5d6f843..0000000
--- a/test/130_allowednext_h48/05_U_F_B2.out
+++ /dev/null
@@ -1 +0,0 @@
10x38FFF
diff --git a/test/130_allowednext_h48/06_empty_bound.in b/test/130_allowednext_h48/06_empty_bound.in
deleted file mode 100644
index 389e262..0000000
--- a/test/130_allowednext_h48/06_empty_bound.in
+++ /dev/null
@@ -1,2 +0,0 @@
12
20
diff --git a/test/130_allowednext_h48/06_empty_bound.out b/test/130_allowednext_h48/06_empty_bound.out
deleted file mode 100644
index eb601fc..0000000
--- a/test/130_allowednext_h48/06_empty_bound.out
+++ /dev/null
@@ -1 +0,0 @@
10x2DB6D
diff --git a/test/130_allowednext_h48/07_F_bound.in b/test/130_allowednext_h48/07_F_bound.in
deleted file mode 100644
index b3ae33d..0000000
--- a/test/130_allowednext_h48/07_F_bound.in
+++ /dev/null
@@ -1,3 +0,0 @@
12
21
3F
diff --git a/test/130_allowednext_h48/07_F_bound.out b/test/130_allowednext_h48/07_F_bound.out
deleted file mode 100644
index 0dc8997..0000000
--- a/test/130_allowednext_h48/07_F_bound.out
+++ /dev/null
@@ -1 +0,0 @@
10x28B6D
diff --git a/test/130_allowednext_h48/08_U_D_bound_inverse.in b/test/130_allowednext_h48/08_U_D_bound_inverse.in
deleted file mode 100644
index 707f7e0..0000000
--- a/test/130_allowednext_h48/08_U_D_bound_inverse.in
+++ /dev/null
@@ -1,4 +0,0 @@
13
22
3U
4D2 \ No newline at end of file
diff --git a/test/130_allowednext_h48/08_U_D_bound_inverse.out b/test/130_allowednext_h48/08_U_D_bound_inverse.out
deleted file mode 100644
index 6f47cf0..0000000
--- a/test/130_allowednext_h48/08_U_D_bound_inverse.out
+++ /dev/null
@@ -1 +0,0 @@
10x2DB40
diff --git a/test/130_allowednext_h48/09_R_false_bound.in b/test/130_allowednext_h48/09_R_false_bound.in
deleted file mode 100644
index 0b1d441..0000000
--- a/test/130_allowednext_h48/09_R_false_bound.in
+++ /dev/null
@@ -1,3 +0,0 @@
11
21
3R \ No newline at end of file
diff --git a/test/130_allowednext_h48/09_R_false_bound.out b/test/130_allowednext_h48/09_R_false_bound.out
deleted file mode 100644
index 121bfeb..0000000
--- a/test/130_allowednext_h48/09_R_false_bound.out
+++ /dev/null
@@ -1 +0,0 @@
10x3FE3F
diff --git a/test/130_allowednext_h48/allowednext_h48_tests.c b/test/130_allowednext_h48/allowednext_h48_tests.c
deleted file mode 100644
index 64ded35..0000000
--- a/test/130_allowednext_h48/allowednext_h48_tests.c
+++ /dev/null
@@ -1,38 +0,0 @@
1#include "../test.h"
2
3uint32_t allowednextmove_h48(uint8_t *, uint8_t, uint32_t);
4
5static char *moves[] = {
6 "U", "U2", "U'",
7 "D", "D2", "D'",
8 "R", "R2", "R'",
9 "L", "L2", "L'",
10 "F", "F2", "F'",
11 "B", "B2", "B'",
12};
13
14void run(void) {
15 char movestr[STRLENMAX];
16 uint8_t m[100];
17 int n, i, j, bound;
18
19 fgets(movestr, STRLENMAX, stdin);
20 bound = atoi(movestr);
21
22 fgets(movestr, STRLENMAX, stdin);
23 n = atoi(movestr);
24
25 for (i = 0; i < n; i++) {
26 fgets(movestr, STRLENMAX, stdin);
27 movestr[strcspn(movestr, "\n")] = 0;
28 for (j = 0; j < 18; j++)
29 if (!strcmp(movestr, moves[j]))
30 m[i] = j;
31 }
32
33 fprintf(stderr, "Last two: %s, %s\n",
34 n > 1 ? moves[m[n-2]] : "-",
35 n > 0 ? moves[m[n-1]] : "-");
36 uint32_t allowed = allowednextmove_h48(m, n, bound);
37 printf("0x%05X\n", allowed);
38}
diff --git a/tools/200_stats_tables_h48/stats_tables_h48.c b/tools/200_stats_tables_h48/stats_tables_h48.c
deleted file mode 100644
index bdf6329..0000000
--- a/tools/200_stats_tables_h48/stats_tables_h48.c
+++ /dev/null
@@ -1,117 +0,0 @@
1#include <pthread.h>
2
3#include "../tool.h"
4
5#define MAXMOVES 20
6#define LOG_EVERY (NCUBES_PER_THREAD / 10)
7
8int NCUBES_PER_THREAD;
9int64_t size = 0;
10const char *solver = "h48stats";
11const char *filename = "tables/h48h0k4";
12char *buf;
13
14typedef struct {
15 int n;
16 int thread_id;
17 int64_t v[12][100];
18} thread_arg_t;
19
20uint64_t randll(void) {
21 long long int i, ret;
22
23 for (i = 0, ret = 0; i < 64; i++)
24 ret |= (long long int)(rand() % 2) << i;
25
26 return ret;
27}
28
29static void *
30run_thread(void *arg)
31{
32 char s[12], cube[22];
33 long long int ep, eo, cp, co, stats[NISSY_SIZE_SOLVE_STATS];
34 int i, j;
35
36 thread_arg_t *a = (thread_arg_t *)arg;
37
38 for (i = 0; i < a->n; i++) {
39 ep = randll();
40 eo = randll();
41 cp = randll();
42 co = randll();
43 nissy_getcube(ep, eo, cp, co, "fix", cube);
44 nissy_solve(cube, "h48stats", NISSY_NISSFLAG_NORMAL,
45 0, MAXMOVES, 1, -1, size, buf, 12, s, stats);
46 for (j = 0; j < 12; j++)
47 a->v[j][(int)s[j]]++;
48 if ((i+1) % LOG_EVERY == 0)
49 printf("[thread %d] %d cubes solved...\n",
50 a->thread_id, i+1);
51 }
52
53 return NULL;
54}
55
56void run(void) {
57 int64_t i, j, k, tot;
58 double avg;
59 pthread_t thread[THREADS];
60 thread_arg_t arg[THREADS];
61
62 size = nissy_datasize(solver);
63
64 for (i = 0; i < THREADS; i++) {
65 arg[i] = (thread_arg_t) {
66 .thread_id = i,
67 .n = NCUBES_PER_THREAD,
68 .v = {{0}}
69 };
70 pthread_create(&thread[i], NULL, run_thread, &arg[i]);
71 }
72
73 for (i = 0; i < THREADS; i++)
74 pthread_join(thread[i], NULL);
75
76 for (j = 0; j < 12; j++) {
77 printf("Data for h=%" PRId64 "\n", j);
78 for (k = 0, avg = 0.0; k < 16; k++) {
79 for (i = 0, tot = 0; i < THREADS; i++)
80 tot += arg[i].v[j][k];
81 printf("%" PRId64 "\t%" PRId64 "\n", k, tot);
82 avg += tot * k;
83 }
84 avg /= (double)(NCUBES_PER_THREAD * THREADS);
85 printf("Average: %.4lf\n", avg);
86 printf("\n");
87 }
88}
89
90int main(int argc, char **argv) {
91 srand(time(NULL));
92 nissy_setlogger(log_stderr);
93
94 if (argc < 2) {
95 printf("Error: not enough arguments. "
96 "Number of cubes per thread must be provided.\n");
97 return 1;
98 }
99
100 NCUBES_PER_THREAD = atoi(argv[1]);
101
102 if (NCUBES_PER_THREAD < 1 || NCUBES_PER_THREAD > 1000000) {
103 printf("Invalid number of cubes: must be > 0 and "
104 "< 1000000, but %d was given.\n", NCUBES_PER_THREAD);
105 return 1;
106 }
107
108 printf("Using %d cubes per thread (%d total)\n",
109 NCUBES_PER_THREAD, NCUBES_PER_THREAD * THREADS);
110 if (getdata(solver, &buf, filename) != 0)
111 return 1;
112
113 timerun(run);
114
115 free(buf);
116 return 0;
117}
diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c
new file mode 100644
index 0000000..aa45df0
--- /dev/null
+++ b/tools/301_solve_file/solve_file.c
@@ -0,0 +1,71 @@
1#include "../tool.h"
2
3#define SOL_BUFFER_LEN 1000
4#define MAX_SCR 10000
5#define MAX_SCR_LEN 250
6
7char *solver;
8int64_t size = 0, N = 0;
9char *buf;
10char scrambles[MAX_SCR][MAX_SCR_LEN];
11
12void run(void) {
13 int64_t i, nsols;
14 long long stats[NISSY_SIZE_SOLVE_STATS];
15 char sol[SOL_BUFFER_LEN], cube[22];
16
17 printf("Solved the following scrambles:\n\n");
18 for (i = 0; i < N; i++) {
19 printf("%" PRId64 ". %s\n", i+1, scrambles[i]);
20 printf("Solving scramble %s\n", scrambles[i]);
21 if (nissy_applymoves(NISSY_SOLVED_CUBE, scrambles[i], cube)
22 == -1) {
23 printf("Invalid scramble\n");
24 continue;
25 }
26 nsols = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
27 0, 20, 1, -1, size, buf, SOL_BUFFER_LEN, sol, stats);
28 if (nsols == 0)
29 printf("No solution found\n");
30 else
31 printf("Solutions:\n%s\n", sol);
32 }
33}
34
35int main(int argc, char **argv) {
36 char filename[255], *scrfilename;
37 FILE *scrfile;
38
39 if (argc < 3) {
40 printf("Error: not enough arguments. "
41 "A solver and a scramble file must be given.\n");
42 return 1;
43 }
44
45 solver = argv[1];
46 scrfilename = argv[2];
47
48 srand(time(NULL));
49 nissy_setlogger(log_stderr);
50
51 sprintf(filename, "tables/%s", solver);
52 if (getdata(solver, &buf, filename) != 0)
53 return 1;
54
55 size = nissy_datasize(solver);
56
57 if ((scrfile = fopen(scrfilename, "r")) == NULL) {
58 printf("Error: could not read given file '%s'.\n",
59 scrfilename);
60 return 1;
61 }
62
63 printf("Reading scrambles from file '%s'.\n", scrfilename);
64 for (N = 0; fgets(scrambles[N], MAX_SCR_LEN, scrfile) != NULL; N++) ;
65 fclose(scrfile);
66
67 timerun(run);
68
69 free(buf);
70 return 0;
71}
diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c
new file mode 100644
index 0000000..739ccbd
--- /dev/null
+++ b/tools/302_solve_multisol/solve_multisol.c
@@ -0,0 +1,66 @@
1#include "../tool.h"
2
3#define SOL_BUFFER_LEN 10000
4
5int nsol;
6char *solver;
7int64_t size = 0;
8char *buf;
9
10char *scrambles[] = {
11 "U2 D2 F2 B2 L2 R2",
12 "R' D R U R' D' R U'", /* Pure 8-move comm */
13 "R D' R2 D R U2 R' D' R U2 R D R'", /* 12 mover with sym */
14 NULL
15};
16
17void run(void) {
18 int i;
19 int64_t n;
20 long long stats[NISSY_SIZE_SOLVE_STATS];
21 char sol[SOL_BUFFER_LEN], cube[22];
22
23 printf("Solved the following scrambles:\n\n");
24 for (i = 0; scrambles[i] != NULL; i++) {
25 printf("%d. %s\n", i+1, scrambles[i]);
26 printf("Solving scramble %s\n", scrambles[i]);
27 if (nissy_applymoves(NISSY_SOLVED_CUBE, scrambles[i], cube)
28 == -1) {
29 printf("Invalid scramble\n");
30 continue;
31 }
32 n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
33 0, 20, nsol, -1, size, buf, SOL_BUFFER_LEN, sol, stats);
34 if (n == 0)
35 printf("No solution found\n");
36 else
37 printf("Solutions:\n%s\n", sol);
38 }
39}
40
41int main(int argc, char **argv) {
42 char filename[255];
43
44 if (argc < 3) {
45 printf("Error: not enough arguments. "
46 "A solver and a number of solutions must be given.\n");
47 return 1;
48 }
49
50 solver = argv[1];
51 nsol = atoi(argv[2]);
52 srand(time(NULL));
53 nissy_setlogger(log_stderr);
54
55
56 sprintf(filename, "tables/%s", solver);
57 if (getdata(solver, &buf, filename) != 0)
58 return 1;
59
60 size = nissy_datasize(solver);
61
62 timerun(run);
63
64 free(buf);
65 return 0;
66}

Generated with cgit - Back to sebastiano.tronto.net