aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/alg.c105
-rw-r--r--src/alg.h76
-rw-r--r--src/commands.c322
-rw-r--r--src/commands.h194
-rw-r--r--src/coord.c976
-rw-r--r--src/coord.h242
-rw-r--r--src/cube.c920
-rw-r--r--src/cube.h44
-rw-r--r--src/cubetypes.h176
-rw-r--r--src/env.c2
-rw-r--r--src/env.h4
-rw-r--r--src/moves.c409
-rw-r--r--src/moves.h20
-rw-r--r--src/pf.c95
-rw-r--r--src/pf.h20
-rw-r--r--src/pruning.c265
-rw-r--r--src/pruning.h21
-rw-r--r--src/shell.c22
-rw-r--r--src/solve.c469
-rw-r--r--src/solve.h4
-rw-r--r--src/steps.c1514
-rw-r--r--src/steps.h276
-rw-r--r--src/symcoord.c687
-rw-r--r--src/symcoord.h17
-rw-r--r--src/trans.c381
-rw-r--r--src/trans.h36
-rw-r--r--src/utils.c14
27 files changed, 2211 insertions, 5100 deletions
diff --git a/src/alg.c b/src/alg.c
index 52bebc0..47e222b 100644
--- a/src/alg.c
+++ b/src/alg.c
@@ -1,68 +1,18 @@
1#include "alg.h" 1#define ALG_C
2 2
3/* Local functions ***********************************************************/ 3#include "alg.h"
4 4
5static bool allowed_HTM(Move m);
6static bool allowed_URF(Move m);
7static bool allowed_eofb(Move m);
8static bool allowed_drud(Move m);
9static bool allowed_htr(Move m);
10static bool allowed_next_HTM(Move l2, Move l1, Move m);
11static int axis(Move m); 5static int axis(Move m);
12
13static void free_alglistnode(AlgListNode *aln); 6static void free_alglistnode(AlgListNode *aln);
14static void realloc_alg(Alg *alg, int n); 7static void realloc_alg(Alg *alg, int n);
15 8
16/* Movesets ******************************************************************/ 9bool
17
18Moveset
19moveset_HTM = {
20 .allowed = allowed_HTM,
21 .allowed_next = allowed_next_HTM,
22};
23
24Moveset
25moveset_URF = {
26 .allowed = allowed_URF,
27 .allowed_next = allowed_next_HTM,
28};
29
30Moveset
31moveset_eofb = {
32 .allowed = allowed_eofb,
33 .allowed_next = allowed_next_HTM,
34};
35
36Moveset
37moveset_drud = {
38 .allowed = allowed_drud,
39 .allowed_next = allowed_next_HTM,
40};
41
42Moveset
43moveset_htr = {
44 .allowed = allowed_htr,
45 .allowed_next = allowed_next_HTM,
46};
47
48static int nmoveset = 5;
49static Moveset * all_ms[] = {
50 &moveset_HTM,
51 &moveset_URF,
52 &moveset_eofb,
53 &moveset_drud,
54 &moveset_htr,
55};
56
57/* Functions *****************************************************************/
58
59static bool
60allowed_HTM(Move m) 10allowed_HTM(Move m)
61{ 11{
62 return m >= U && m <= B3; 12 return m >= U && m <= B3;
63} 13}
64 14
65static bool 15bool
66allowed_URF(Move m) 16allowed_URF(Move m)
67{ 17{
68 Move b = base_move(m); 18 Move b = base_move(m);
@@ -70,7 +20,7 @@ allowed_URF(Move m)
70 return b == U || b == R || b == F; 20 return b == U || b == R || b == F;
71} 21}
72 22
73static bool 23bool
74allowed_eofb(Move m) 24allowed_eofb(Move m)
75{ 25{
76 Move b = base_move(m); 26 Move b = base_move(m);
@@ -79,7 +29,7 @@ allowed_eofb(Move m)
79 ((b == F || b == B) && m == b+1); 29 ((b == F || b == B) && m == b+1);
80} 30}
81 31
82static bool 32bool
83allowed_drud(Move m) 33allowed_drud(Move m)
84{ 34{
85 Move b = base_move(m); 35 Move b = base_move(m);
@@ -88,7 +38,7 @@ allowed_drud(Move m)
88 ((b == R || b == L || b == F || b == B) && m == b + 1); 38 ((b == R || b == L || b == F || b == B) && m == b + 1);
89} 39}
90 40
91static bool 41bool
92allowed_htr(Move m) 42allowed_htr(Move m)
93{ 43{
94 Move b = base_move(m); 44 Move b = base_move(m);
@@ -96,8 +46,8 @@ allowed_htr(Move m)
96 return moveset_HTM.allowed(m) && m == b + 1; 46 return moveset_HTM.allowed(m) && m == b + 1;
97} 47}
98 48
99static bool 49bool
100allowed_next_HTM(Move l2, Move l1, Move m) 50allowed_next_all(Move l2, Move l1, Move m)
101{ 51{
102 bool p, q; 52 bool p, q;
103 53
@@ -469,6 +419,34 @@ swapmove(Move *m1, Move *m2)
469 *m2 = aux; 419 *m2 = aux;
470} 420}
471 421
422char *
423trans_string(Trans t)
424{
425 static char trans_string_aux[NTRANS][20] = {
426 [uf] = "uf", [ur] = "ur", [ub] = "ub", [ul] = "ul",
427 [df] = "df", [dr] = "dr", [db] = "db", [dl] = "dl",
428 [rf] = "rf", [rd] = "rd", [rb] = "rb", [ru] = "ru",
429 [lf] = "lf", [ld] = "ld", [lb] = "lb", [lu] = "lu",
430 [fu] = "fu", [fr] = "fr", [fd] = "fd", [fl] = "fl",
431 [bu] = "bu", [br] = "br", [bd] = "bd", [bl] = "bl",
432
433 [uf_mirror] = "uf*", [ur_mirror] = "ur*",
434 [ub_mirror] = "ub*", [ul_mirror] = "ul*",
435 [df_mirror] = "df*", [dr_mirror] = "dr*",
436 [db_mirror] = "db*", [dl_mirror] = "dl*",
437 [rf_mirror] = "rf*", [rd_mirror] = "rd*",
438 [rb_mirror] = "rb*", [ru_mirror] = "ru*",
439 [lf_mirror] = "lf*", [ld_mirror] = "ld*",
440 [lb_mirror] = "lb*", [lu_mirror] = "lu*",
441 [fu_mirror] = "fu*", [fr_mirror] = "fr*",
442 [fd_mirror] = "fd*", [fl_mirror] = "fl*",
443 [bu_mirror] = "bu*", [br_mirror] = "br*",
444 [bd_mirror] = "bd*", [bl_mirror] = "bl*",
445 };
446
447 return trans_string_aux[t];
448}
449
472Alg * 450Alg *
473unniss(Alg *alg) 451unniss(Alg *alg)
474{ 452{
@@ -513,12 +491,3 @@ init_moveset(Moveset *ms)
513 } 491 }
514 } 492 }
515} 493}
516
517void
518init_all_movesets()
519{
520 int i;
521
522 for (i = 0; i < nmoveset; i++)
523 init_moveset(all_ms[i]);
524}
diff --git a/src/alg.h b/src/alg.h
index 6bee26b..51e66b0 100644
--- a/src/alg.h
+++ b/src/alg.h
@@ -8,12 +8,13 @@
8#include "cubetypes.h" 8#include "cubetypes.h"
9#include "utils.h" 9#include "utils.h"
10 10
11extern Moveset moveset_HTM; 11bool allowed_all(Move m);
12extern Moveset moveset_URF; 12bool allowed_HTM(Move m);
13extern Moveset moveset_eofb; 13bool allowed_URF(Move m);
14extern Moveset moveset_drud; 14bool allowed_eofb(Move m);
15extern Moveset moveset_htr; 15bool allowed_drud(Move m);
16 16bool allowed_htr(Move m);
17bool allowed_next_all(Move l2, Move l1, Move m);
17void append_alg(AlgList *l, Alg *alg); 18void append_alg(AlgList *l, Alg *alg);
18void append_move(Alg *alg, Move m, bool inverse); 19void append_move(Alg *alg, Move m, bool inverse);
19Move base_move(Move m); 20Move base_move(Move m);
@@ -34,10 +35,71 @@ Alg * on_inverse(Alg *alg);
34void print_alg(Alg *alg, bool l); 35void print_alg(Alg *alg, bool l);
35void print_alglist(AlgList *al, bool l); 36void print_alglist(AlgList *al, bool l);
36void swapmove(Move *m1, Move *m2); 37void swapmove(Move *m1, Move *m2);
38char * trans_string(Trans t); /* Here because similar to move_string, move? */
37Alg * unniss(Alg *alg); 39Alg * unniss(Alg *alg);
38 40
39void init_moveset(Moveset *ms); 41void init_moveset(Moveset *ms);
40void init_all_movesets(); 42
43/* Movesets ******************************************************************/
44
45#ifndef ALG_C
46
47extern Moveset moveset_HTM;
48extern Moveset moveset_URF;
49extern Moveset moveset_eofb;
50extern Moveset moveset_drud;
51extern Moveset moveset_htr;
52
53extern Moveset * all_ms[];
54
55#else
56
57Moveset
58moveset_HTM = {
59 .name = "HTM",
60 .allowed = allowed_HTM,
61 .allowed_next = allowed_next_all,
62};
63
64Moveset
65moveset_URF = {
66 .name = "URF",
67 .allowed = allowed_URF,
68 .allowed_next = allowed_next_all,
69};
70
71Moveset
72moveset_eofb = {
73 .name = "eofb",
74 .allowed = allowed_eofb,
75 .allowed_next = allowed_next_all,
76};
77
78Moveset
79moveset_drud = {
80 .name = "drud",
81 .allowed = allowed_drud,
82 .allowed_next = allowed_next_all,
83};
84
85Moveset
86moveset_htr = {
87 .name = "htr",
88 .allowed = allowed_htr,
89 .allowed_next = allowed_next_all,
90};
91
92Moveset *
93all_ms[] = {
94 &moveset_HTM,
95 &moveset_URF,
96 &moveset_eofb,
97 &moveset_drud,
98 &moveset_htr,
99 NULL
100};
101
102#endif
41 103
42#endif 104#endif
43 105
diff --git a/src/commands.c b/src/commands.c
index a91fb4f..7f58ef5 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -1,187 +1,11 @@
1#include "commands.h" 1#define COMMANDS_C
2
3/* Arg parsing functions *****************************************************/
4
5CommandArgs * gen_parse_args(int c, char **v);
6CommandArgs * help_parse_args(int c, char **v);
7CommandArgs * parse_only_scramble(int c, char **v);
8CommandArgs * parse_no_arg(int c, char **v);
9CommandArgs * solve_parse_args(int c, char **v);
10CommandArgs * scramble_parse_args(int c, char **v);
11
12/* Exec functions ************************************************************/
13 2
14static void gen_exec(CommandArgs *args); 3#include "commands.h"
15static void cleanup_exec(CommandArgs *args);
16static void invert_exec(CommandArgs *args);
17static void solve_exec(CommandArgs *args);
18static void scramble_exec(CommandArgs *args);
19static void steps_exec(CommandArgs *args);
20static void commands_exec(CommandArgs *args);
21static void freemem_exec(CommandArgs *args);
22static void print_exec(CommandArgs *args);
23static void twophase_exec(CommandArgs *args);
24static void help_exec(CommandArgs *args);
25static void quit_exec(CommandArgs *args);
26static void unniss_exec(CommandArgs *args);
27static void version_exec(CommandArgs *args);
28
29/* Local functions ***********************************************************/
30 4
31static bool read_step(CommandArgs *args, char *str); 5static bool read_step(CommandArgs *args, char *str);
32static bool read_scrtype(CommandArgs *args, char *str); 6static bool read_scrtype(CommandArgs *args, char *str);
33static bool read_scramble(int c, char **v, CommandArgs *args); 7static bool read_scramble(int c, char **v, CommandArgs *args);
34 8
35/* Commands ******************************************************************/
36
37Command
38solve_cmd = {
39 .name = "solve",
40 .usage = "solve STEP [OPTIONS] SCRAMBLE",
41 .description = "Solve a step; see command steps for a list of steps",
42 .parse_args = solve_parse_args,
43 .exec = solve_exec
44};
45
46Command
47scramble_cmd = {
48 .name = "scramble",
49 .usage = "scramble [TYPE] [-n N]",
50 .description = "Get a random-position scramble",
51 .parse_args = scramble_parse_args,
52 .exec = scramble_exec,
53};
54
55Command
56gen_cmd = {
57 .name = "gen",
58 .usage = "gen [-t N]",
59 .description = "Generate all tables [using N threads]",
60 .parse_args = gen_parse_args,
61 .exec = gen_exec
62};
63
64Command
65invert_cmd = {
66 .name = "invert",
67 .usage = "invert SCRAMBLE]",
68 .description = "Invert a scramble",
69 .parse_args = parse_only_scramble,
70 .exec = invert_exec,
71};
72
73Command
74steps_cmd = {
75 .name = "steps",
76 .usage = "steps",
77 .description = "List available steps",
78 .parse_args = parse_no_arg,
79 .exec = steps_exec
80};
81
82Command
83commands_cmd = {
84 .name = "commands",
85 .usage = "commands",
86 .description = "List available commands",
87 .parse_args = parse_no_arg,
88 .exec = commands_exec
89};
90
91Command
92freemem_cmd = {
93 .name = "freemem",
94 .usage = "freemem",
95 .description = "free large tables from RAM",
96 .parse_args = parse_no_arg,
97 .exec = freemem_exec,
98};
99
100Command
101print_cmd = {
102 .name = "print",
103 .usage = "print SCRAMBLE",
104 .description = "Print written description of the cube",
105 .parse_args = parse_only_scramble,
106 .exec = print_exec,
107};
108
109Command
110help_cmd = {
111 .name = "help",
112 .usage = "help [COMMAND]",
113 .description = "Display nissy manual page or help on specific command",
114 .parse_args = help_parse_args,
115 .exec = help_exec,
116};
117
118Command
119twophase_cmd = {
120 .name = "twophase",
121 .usage = "twophase",
122 .description = "Find a solution quickly using a 2-phase method",
123 .parse_args = parse_only_scramble,
124 .exec = twophase_exec,
125};
126
127Command
128quit_cmd = {
129 .name = "quit",
130 .usage = "quit",
131 .description = "Quit nissy",
132 .parse_args = parse_no_arg,
133 .exec = quit_exec,
134};
135
136Command
137cleanup_cmd = {
138 .name = "cleanup",
139 .usage = "cleanup SCRAMBLE",
140 .description = "Rewrite a scramble using only standard moves (HTM)",
141 .parse_args = parse_only_scramble,
142 .exec = cleanup_exec,
143};
144
145Command
146unniss_cmd = {
147 .name = "unniss",
148 .usage = "unniss SCRAMBLE",
149 .description = "Rewrite a scramble without NISS",
150 .parse_args = parse_only_scramble,
151 .exec = unniss_exec,
152};
153
154Command
155version_cmd = {
156 .name = "version",
157 .usage = "version",
158 .description = "print nissy version",
159 .parse_args = parse_no_arg,
160 .exec = version_exec,
161};
162
163Command *commands[] = {
164 &commands_cmd,
165 &freemem_cmd,
166 &gen_cmd,
167 &help_cmd,
168 &invert_cmd,
169 &print_cmd,
170 &quit_cmd,
171 &solve_cmd,
172 &scramble_cmd,
173 &steps_cmd,
174 &twophase_cmd,
175 &cleanup_cmd,
176 &unniss_cmd,
177 &version_cmd,
178 NULL
179};
180
181/* Other constants ***********************************************************/
182
183char *scrtypes[20] = { "eo", "corners", "edges", "fmc", "dr", "htr", NULL };
184
185/* Arg parsing functions implementation **************************************/ 9/* Arg parsing functions implementation **************************************/
186 10
187CommandArgs * 11CommandArgs *
@@ -386,17 +210,15 @@ parse_no_arg(int c, char **v)
386 210
387/* Exec functions implementation *********************************************/ 211/* Exec functions implementation *********************************************/
388 212
389static void 213void
390solve_exec(CommandArgs *args) 214solve_exec(CommandArgs *args)
391{ 215{
392 Cube c; 216 Cube c;
393 AlgList *sols; 217 AlgList *sols;
394 218
395 init_all_movesets(); 219 make_solved(&c);
396 init_symcoord(); 220 apply_alg(args->scramble, &c);
397 221 sols = solve(&c, args->step, args->opts);
398 c = apply_alg(args->scramble, (Cube){0});
399 sols = solve(c, args->step, args->opts);
400 222
401 if (args->opts->count_only) 223 if (args->opts->count_only)
402 printf("%d\n", sols->len); 224 printf("%d\n", sols->len);
@@ -406,85 +228,64 @@ solve_exec(CommandArgs *args)
406 free_alglist(sols); 228 free_alglist(sols);
407} 229}
408 230
409static void 231void
410scramble_exec(CommandArgs *args) 232scramble_exec(CommandArgs *args)
411{ 233{
412 Cube cube; 234 Cube cube;
413 CubeArray *arr;
414 Alg *scr, *ruf, *aux; 235 Alg *scr, *ruf, *aux;
415 int i, j, eo, ep, co, cp, a[12]; 236 int i, j, eo, ep, co, cp;
416 int eparr[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 };
417 uint64_t ui, uj, uk; 237 uint64_t ui, uj, uk;
418 238
419 init_all_movesets();
420 init_symcoord();
421
422 srand(time(NULL)); 239 srand(time(NULL));
423 240
424 for (i = 0; i < args->n; i++) { 241 for (i = 0; i < args->n; i++) {
425 242
426 if (!strcmp(args->scrtype, "dr")) { 243 if (!strcmp(args->scrtype, "dr")) {
427 /* Warning: cube is inconsistent because of side CO * 244 ui = rand() % FACTORIAL8;
428 * and EO on U/D. But solve_2phase only solves drfin * 245 uj = rand() % FACTORIAL8;
429 * in this case, so it should be ok. * 246 uk = rand() % FACTORIAL4;
430 * TODO: check this properly *
431 * Moreover we again need to fix parity after *
432 * generating epose manually */
433 do {
434 ui = rand() % FACTORIAL8;
435 uj = rand() % FACTORIAL8;
436 uk = rand() % FACTORIAL4;
437
438 index_to_perm(ui, 12, a);
439 arr = malloc(sizeof(CubeArray));
440 arr->ep = eparr;
441 cube = arrays_to_cube(arr, pf_ep);
442 free(arr);
443 247
444 cube.cp = uj; 248 make_solved(&cube);
445 cube.epose += uk; 249 index_to_perm(ui, 8, cube.cp);
446 } while (!is_admissible(cube)); 250 index_to_perm(uj, 8, cube.ep);
251 index_to_perm(uk, 4, cube.ep + 8);
252 for (j = 8; j < 12; j++)
253 cube.ep[j] += 8;
447 } else if (!strcmp(args->scrtype, "htr")) { 254 } else if (!strcmp(args->scrtype, "htr")) {
448 /* antindex_htrfin() returns a consistent * 255 make_solved(&cube);
449 * cube, except possibly for parity */ 256 /* TODO */
450 do {
451 ui = rand() % (24*24/6);
452 cube = (Cube){0};
453 cube.cp = cornershtrfin_ant[ui];
454 cube.epose = rand() % 24;
455 cube.eposs = rand() % 24;
456 cube.eposm = rand() % 24;
457 } while (!is_admissible(cube));
458 } else { 257 } else {
459 eo = rand() % POW2TO11;
460 ep = rand() % FACTORIAL12; 258 ep = rand() % FACTORIAL12;
461 co = rand() % POW3TO7;
462 cp = rand() % FACTORIAL8; 259 cp = rand() % FACTORIAL8;
260 eo = rand() % POW2TO11;
261 co = rand() % POW3TO7;
463 262
464 if (!strcmp(args->scrtype, "eo")) { 263 if (!strcmp(args->scrtype, "eo")) {
465 eo = 0; 264 eo = 0;
466 } else if (!strcmp(args->scrtype, "corners")) { 265 } else if (!strcmp(args->scrtype, "corners")) {
467 eo = 0; 266 eo = 0;
468 ep = 0; 267 ep = 0;
469 index_to_perm(cp, 8, a);
470 if (perm_sign(a, 8) == 1) {
471 swap(&a[0], &a[1]);
472 cp = perm_to_index(a, 8);
473 }
474 } else if (!strcmp(args->scrtype, "edges")) { 268 } else if (!strcmp(args->scrtype, "edges")) {
475 co = 0; 269 co = 0;
476 cp = 0; 270 cp = 0;
477 index_to_perm(ep, 12, a);
478 if (perm_sign(a, 12) == 1) {
479 swap(&a[0], &a[1]);
480 ep = perm_to_index(a, 12);
481 }
482 } 271 }
483 cube = fourval_to_cube(eo, ep, co, cp); 272
273 make_solved(&cube);
274 index_to_perm(ep, 12, cube.ep);
275 index_to_perm(cp, 8, cube.cp);
276 int_to_sum_zero_array(eo, 2, 12, cube.eo);
277 int_to_sum_zero_array(co, 3, 8, cube.co);
278 }
279
280 if (!is_admissible(&cube)) {
281 if (!strcmp(args->scrtype, "corners"))
282 swap(&cube.cp[UFR], &cube.cp[UFL]);
283 else
284 swap(&cube.ep[UF], &cube.ep[UB]);
484 } 285 }
485 286
486 /* TODO: can be optimized for htr and dr using htrfin, drfin */ 287 /* TODO: can be optimized for htr and dr using htrfin, drfin */
487 scr = solve_2phase(cube, 1); 288 scr = solve_2phase(&cube, 1);
488 289
489 if (!strcmp(args->scrtype, "fmc")) { 290 if (!strcmp(args->scrtype, "fmc")) {
490 aux = new_alg(""); 291 aux = new_alg("");
@@ -513,23 +314,22 @@ scramble_exec(CommandArgs *args)
513 } 314 }
514} 315}
515 316
516static void 317void
517gen_exec(CommandArgs *args) 318gen_exec(CommandArgs *args)
518{ 319{
320/* TODO:
519 int i; 321 int i;
520 322
521 fprintf(stderr, "Generating coordinates...\n"); 323 fprintf(stderr, "Generating coordinates...\n");
522 init_all_movesets();
523 init_symcoord();
524
525 fprintf(stderr, "Generating pruning tables...\n"); 324 fprintf(stderr, "Generating pruning tables...\n");
526 for (i = 0; all_pd[i] != NULL; i++) 325 for (i = 0; all_pd[i] != NULL; i++)
527 genptable(all_pd[i], args->opts->nthreads); 326 genptable(all_pd[i], args->opts->nthreads);
327*/
528 328
529 fprintf(stderr, "Done!\n"); 329 fprintf(stderr, "Done!\n");
530} 330}
531 331
532static void 332void
533invert_exec(CommandArgs *args) 333invert_exec(CommandArgs *args)
534{ 334{
535 Alg *inv; 335 Alg *inv;
@@ -540,7 +340,7 @@ invert_exec(CommandArgs *args)
540 free_alg(inv); 340 free_alg(inv);
541} 341}
542 342
543static void 343void
544steps_exec(CommandArgs *args) 344steps_exec(CommandArgs *args)
545{ 345{
546 int i; 346 int i;
@@ -549,7 +349,7 @@ steps_exec(CommandArgs *args)
549 printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); 349 printf("%-15s %s\n", steps[i]->shortname, steps[i]->name);
550} 350}
551 351
552static void 352void
553commands_exec(CommandArgs *args) 353commands_exec(CommandArgs *args)
554{ 354{
555 int i; 355 int i;
@@ -559,9 +359,10 @@ commands_exec(CommandArgs *args)
559 359
560} 360}
561 361
562static void 362void
563freemem_exec(CommandArgs *args) 363freemem_exec(CommandArgs *args)
564{ 364{
365/* TODO:
565 int i; 366 int i;
566 367
567 for (i = 0; all_pd[i] != NULL; i++) 368 for (i = 0; all_pd[i] != NULL; i++)
@@ -569,35 +370,34 @@ freemem_exec(CommandArgs *args)
569 370
570 for (i = 0; all_sd[i] != NULL; i++) 371 for (i = 0; all_sd[i] != NULL; i++)
571 free_sd(all_sd[i]); 372 free_sd(all_sd[i]);
572 373*/
573 /* TODO: invtables are also large, but for now they are *
574 * statically allocated. Consider releasing those too. */
575} 374}
576 375
577static void 376void
578print_exec(CommandArgs *args) 377print_exec(CommandArgs *args)
579{ 378{
580 init_moves(); 379 Cube c;
581 print_cube(apply_alg(args->scramble, (Cube){0})); 380
381 make_solved(&c);
382 apply_alg(args->scramble, &c);
383 print_cube(&c);
582} 384}
583 385
584static void 386void
585twophase_exec(CommandArgs *args) 387twophase_exec(CommandArgs *args)
586{ 388{
587 Cube c; 389 Cube c;
588 Alg *sol; 390 Alg *sol;
589 391
590 init_all_movesets(); 392 make_solved(&c);
591 init_symcoord(); 393 apply_alg(args->scramble, &c);
592 394 sol = solve_2phase(&c, 1);
593 c = apply_alg(args->scramble, (Cube){0});
594 sol = solve_2phase(c, 1);
595 395
596 print_alg(sol, false); 396 print_alg(sol, false);
597 free_alg(sol); 397 free_alg(sol);
598} 398}
599 399
600static void 400void
601help_exec(CommandArgs *args) 401help_exec(CommandArgs *args)
602{ 402{
603 if (args->command == NULL) { 403 if (args->command == NULL) {
@@ -619,26 +419,24 @@ help_exec(CommandArgs *args)
619 } 419 }
620} 420}
621 421
622static void 422void
623quit_exec(CommandArgs *args) 423quit_exec(CommandArgs *args)
624{ 424{
625 exit(0); 425 exit(0);
626} 426}
627 427
628static void 428void
629cleanup_exec(CommandArgs *args) 429cleanup_exec(CommandArgs *args)
630{ 430{
631 Alg *alg; 431 Alg *alg;
632 432
633 init_moves();
634
635 alg = cleanup(args->scramble); 433 alg = cleanup(args->scramble);
636 print_alg(alg, false); 434 print_alg(alg, false);
637 435
638 free_alg(alg); 436 free_alg(alg);
639} 437}
640 438
641static void 439void
642unniss_exec(CommandArgs *args) 440unniss_exec(CommandArgs *args)
643{ 441{
644 Alg *aux; 442 Alg *aux;
@@ -648,7 +446,7 @@ unniss_exec(CommandArgs *args)
648 free(aux); 446 free(aux);
649} 447}
650 448
651static void 449void
652version_exec(CommandArgs *args) 450version_exec(CommandArgs *args)
653{ 451{
654 printf(VERSION"\n"); 452 printf(VERSION"\n");
@@ -691,6 +489,8 @@ static bool
691read_scrtype(CommandArgs *args, char *str) 489read_scrtype(CommandArgs *args, char *str)
692{ 490{
693 int i; 491 int i;
492 static char *scrtypes[20] =
493 { "eo", "corners", "edges", "fmc", "dr", "htr", NULL };
694 494
695 for (i = 0; scrtypes[i] != NULL; i++) { 495 for (i = 0; scrtypes[i] != NULL; i++) {
696 if (!strcmp(scrtypes[i], str)) { 496 if (!strcmp(scrtypes[i], str)) {
diff --git a/src/commands.h b/src/commands.h
index b7a4c36..5d9f4ee 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -9,6 +9,198 @@
9void free_args(CommandArgs *args); 9void free_args(CommandArgs *args);
10CommandArgs * new_args(); 10CommandArgs * new_args();
11 11
12extern Command * commands[]; 12/* Arg parsing functions *****************************************************/
13
14CommandArgs * gen_parse_args(int c, char **v);
15CommandArgs * help_parse_args(int c, char **v);
16CommandArgs * parse_only_scramble(int c, char **v);
17CommandArgs * parse_no_arg(int c, char **v);
18CommandArgs * solve_parse_args(int c, char **v);
19CommandArgs * scramble_parse_args(int c, char **v);
20
21/* Exec functions ************************************************************/
22
23void gen_exec(CommandArgs *args);
24void cleanup_exec(CommandArgs *args);
25void invert_exec(CommandArgs *args);
26void solve_exec(CommandArgs *args);
27void scramble_exec(CommandArgs *args);
28void steps_exec(CommandArgs *args);
29void commands_exec(CommandArgs *args);
30void freemem_exec(CommandArgs *args);
31void print_exec(CommandArgs *args);
32void twophase_exec(CommandArgs *args);
33void help_exec(CommandArgs *args);
34void quit_exec(CommandArgs *args);
35void unniss_exec(CommandArgs *args);
36void version_exec(CommandArgs *args);
37
38/* Commands ******************************************************************/
39
40#ifndef COMMANDS_C
41
42extern Command cleanup_cmd;
43extern Command commands_cmd;
44extern Command freemem_cmd;
45extern Command gen_cmd;
46extern Command help_cmd;
47extern Command invert_cmd;
48extern Command print_cmd;
49extern Command quit_cmd;
50extern Command scramble_cmd;
51extern Command solve_cmd;
52extern Command steps_cmd;
53extern Command unniss_cmd;
54extern Command version_cmd;
55
56extern Command *commands[];
57
58#else
59
60Command
61solve_cmd = {
62 .name = "solve",
63 .usage = "solve STEP [OPTIONS] SCRAMBLE",
64 .description = "Solve a step; see command steps for a list of steps",
65 .parse_args = solve_parse_args,
66 .exec = solve_exec
67};
68
69Command
70scramble_cmd = {
71 .name = "scramble",
72 .usage = "scramble [TYPE] [-n N]",
73 .description = "Get a random-position scramble",
74 .parse_args = scramble_parse_args,
75 .exec = scramble_exec,
76};
77
78Command
79gen_cmd = {
80 .name = "gen",
81 .usage = "gen [-t N]",
82 .description = "Generate all tables [using N threads]",
83 .parse_args = gen_parse_args,
84 .exec = gen_exec
85};
86
87Command
88invert_cmd = {
89 .name = "invert",
90 .usage = "invert SCRAMBLE]",
91 .description = "Invert a scramble",
92 .parse_args = parse_only_scramble,
93 .exec = invert_exec,
94};
95
96Command
97steps_cmd = {
98 .name = "steps",
99 .usage = "steps",
100 .description = "List available steps",
101 .parse_args = parse_no_arg,
102 .exec = steps_exec
103};
104
105Command
106commands_cmd = {
107 .name = "commands",
108 .usage = "commands",
109 .description = "List available commands",
110 .parse_args = parse_no_arg,
111 .exec = commands_exec
112};
113
114Command
115freemem_cmd = {
116 .name = "freemem",
117 .usage = "freemem",
118 .description = "free large tables from RAM",
119 .parse_args = parse_no_arg,
120 .exec = freemem_exec,
121};
122
123Command
124print_cmd = {
125 .name = "print",
126 .usage = "print SCRAMBLE",
127 .description = "Print written description of the cube",
128 .parse_args = parse_only_scramble,
129 .exec = print_exec,
130};
131
132Command
133help_cmd = {
134 .name = "help",
135 .usage = "help [COMMAND]",
136 .description = "Display nissy manual page or help on specific command",
137 .parse_args = help_parse_args,
138 .exec = help_exec,
139};
140
141Command
142twophase_cmd = {
143 .name = "twophase",
144 .usage = "twophase",
145 .description = "Find a solution quickly using a 2-phase method",
146 .parse_args = parse_only_scramble,
147 .exec = twophase_exec,
148};
149
150Command
151quit_cmd = {
152 .name = "quit",
153 .usage = "quit",
154 .description = "Quit nissy",
155 .parse_args = parse_no_arg,
156 .exec = quit_exec,
157};
158
159Command
160cleanup_cmd = {
161 .name = "cleanup",
162 .usage = "cleanup SCRAMBLE",
163 .description = "Rewrite a scramble using only standard moves (HTM)",
164 .parse_args = parse_only_scramble,
165 .exec = cleanup_exec,
166};
167
168Command
169unniss_cmd = {
170 .name = "unniss",
171 .usage = "unniss SCRAMBLE",
172 .description = "Rewrite a scramble without NISS",
173 .parse_args = parse_only_scramble,
174 .exec = unniss_exec,
175};
176
177Command
178version_cmd = {
179 .name = "version",
180 .usage = "version",
181 .description = "print nissy version",
182 .parse_args = parse_no_arg,
183 .exec = version_exec,
184};
185
186Command *commands[] = {
187 &commands_cmd,
188 &freemem_cmd,
189 &gen_cmd,
190 &help_cmd,
191 &invert_cmd,
192 &print_cmd,
193 &quit_cmd,
194 &solve_cmd,
195 &scramble_cmd,
196 &steps_cmd,
197 &twophase_cmd,
198 &cleanup_cmd,
199 &unniss_cmd,
200 &version_cmd,
201 NULL
202};
203
204#endif
13 205
14#endif 206#endif
diff --git a/src/coord.c b/src/coord.c
index a9df9fd..06f7474 100644
--- a/src/coord.c
+++ b/src/coord.c
@@ -1,611 +1,683 @@
1#include "coord.h" 1#define COORD_C
2
3static uint64_t index_eofb(Cube cube);
4static uint64_t index_eofbepos(Cube cube);
5static uint64_t index_epud(Cube cube);
6static uint64_t index_coud(Cube cube);
7static uint64_t index_corners(Cube cube);
8static uint64_t index_cp(Cube cube);
9static uint64_t index_cphtr(Cube cube);
10static uint64_t index_cornershtr(Cube cube);
11static uint64_t index_cornershtrfin(Cube cube);
12static uint64_t index_drud(Cube cube);
13static uint64_t index_drud_eofb(Cube cube);
14static uint64_t index_htr_drud(Cube cube);
15static uint64_t index_htrfin(Cube cube);
16static uint64_t index_cpud_separate(Cube cube);
17
18static uint64_t move_eofb(Move m, uint64_t ind);
19static uint64_t move_eofbepos(Move m, uint64_t ind);
20static uint64_t move_epud(Move m, uint64_t ind);
21static uint64_t move_coud(Move m, uint64_t ind);
22static uint64_t move_corners(Move m, uint64_t ind);
23static uint64_t move_cp(Move m, uint64_t ind);
24static uint64_t move_cphtr(Move m, uint64_t ind);
25static uint64_t move_cornershtr(Move m, uint64_t ind);
26static uint64_t move_cornershtrfin(Move m, uint64_t ind);
27static uint64_t move_drud(Move m, uint64_t ind);
28static uint64_t move_drud_eofb(Move m, uint64_t ind);
29static uint64_t move_htr_drud(Move m, uint64_t ind);
30static uint64_t move_htrfin(Move m, uint64_t ind);
31static uint64_t move_cpud_separate(Move m, uint64_t ind);
32 2
33static void init_cphtr_cosets(); 3#include "coord.h"
34static void init_cphtr_left_cosets_bfs(int i, int c);
35static void init_cphtr_right_cosets_color(int i, int c);
36static void init_cpud_separate();
37static void init_cornershtrfin();
38static void init_htr_eposs();
39 4
5static uint64_t indexers_getind(Indexer **is, Cube *c);
6static uint64_t indexers_getmax(Indexer **is);
7static void indexers_makecube(Indexer **is, uint64_t ind, Cube *c);
8static void gen_coord_comp(Coordinate *coord);
9static void gen_coord_sym(Coordinate *coord);
10static bool read_coord_mtable(Coordinate *coord);
11static bool read_coord_sd(Coordinate *coord);
12static bool read_coord_ttable(Coordinate *coord);
13static bool write_coord_mtable(Coordinate *coord);
14static bool write_coord_sd(Coordinate *coord);
15static bool write_coord_ttable(Coordinate *coord);
40 16
41/* All sorts of useful costants and tables **********************************/ 17/* Indexers ******************************************************************/
42 18
43static int cphtr_left_cosets[FACTORIAL8]; 19uint64_t
44static int cphtr_right_cosets[FACTORIAL8]; 20index_eofb(Cube *cube)
45static int cphtr_right_rep[BINOM8ON4*6]; 21{
46int cpud_separate_ind[FACTORIAL8]; 22 return (uint64_t)digit_array_to_int(cube->eo, 11, 2);
47int cpud_separate_ant[BINOM8ON4]; 23}
48static int cornershtrfin_ind[FACTORIAL8];
49int cornershtrfin_ant[24*24/6];
50static int htr_eposs_ind[BINOM12ON4];
51static int htr_eposs_ant[BINOM8ON4];
52 24
53/* Coordinates and their implementation **************************************/ 25uint64_t
26index_coud(Cube *cube)
27{
28 return (uint64_t)digit_array_to_int(cube->co, 7, 3);
29}
54 30
55Coordinate 31uint64_t
56coord_eofb = { 32index_cp(Cube *cube)
57 .index = index_eofb, 33{
58 .max = POW2TO11, 34 return (uint64_t)perm_to_index(cube->cp, 8);
59 .move = move_eofb, 35}
60};
61 36
62Coordinate 37uint64_t
63coord_eofbepos = { 38index_cpudsep(Cube *cube)
64 .index = index_eofbepos, 39{
65 .max = POW2TO11 * BINOM12ON4, 40 int i, c[8];
66 .move = move_eofbepos,
67};
68 41
69Coordinate 42 for (i = 0; i < 8; i++)
70coord_coud = { 43 c[i] = cube->cp[i] < 4 ? 0 : 1;
71 .index = index_coud,
72 .max = POW3TO7,
73 .move = move_coud,
74};
75 44
76Coordinate 45 return (uint64_t)subset_to_index(c, 8, 4);
77coord_corners = { 46}
78 .index = index_corners,
79 .max = POW3TO7 * FACTORIAL8,
80 .move = move_corners,
81};
82 47
83Coordinate 48uint64_t
84coord_cp = { 49index_epe(Cube *cube)
85 .index = index_cp, 50{
86 .max = FACTORIAL8, 51 int i, e[4];
87 .move = move_cp,
88};
89 52
90Coordinate 53 for (i = 0; i < 4; i++)
91coord_cphtr = { 54 e[i] = cube->ep[i+8] - 8;
92 .index = index_cphtr,
93 .max = BINOM8ON4 * 6,
94 .move = move_cphtr,
95};
96 55
97Coordinate 56 return (uint64_t)perm_to_index(e, 4);
98coord_cornershtr = { 57}
99 .index = index_cornershtr,
100 .max = POW3TO7 * BINOM8ON4 * 6,
101 .move = move_cornershtr,
102};
103 58
104Coordinate 59uint64_t
105coord_cornershtrfin = { 60index_epud(Cube *cube)
106 .index = index_cornershtrfin, 61{
107 .max = 24*24/6, 62 return (uint64_t)perm_to_index(cube->ep, 8);
108 .move = move_cornershtrfin, 63}
109};
110 64
111Coordinate 65uint64_t
112coord_epud = { 66index_epos(Cube *cube)
113 .index = index_epud, 67{
114 .max = FACTORIAL8, 68 int i, a[12];
115 .move = move_epud,
116};
117 69
118Coordinate 70 for (i = 0; i < 12; i++)
119coord_drud = { 71 a[i] = (cube->ep[i] < 8) ? 0 : 1;
120 .index = index_drud,
121 .max = POW2TO11 * POW3TO7 * BINOM12ON4,
122 .move = move_drud,
123};
124 72
125Coordinate 73 return (uint64_t)subset_to_index(a, 12, 4);
126coord_htr_drud = { 74}
127 .index = index_htr_drud,
128 .max = BINOM8ON4 * 6 * BINOM8ON4,
129 .move = move_htr_drud,
130};
131 75
132Coordinate 76uint64_t
133coord_htrfin = { 77index_eposepe(Cube *cube)
134 .index = index_htrfin, 78{
135 .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */ 79 int i, j, e[4];
136 .move = move_htrfin, 80 uint64_t epos, epe;
137};
138 81
139Coordinate 82 epos = (uint64_t)index_epos(cube);
140coord_drud_eofb = { 83 for (i = 0, j = 0; i < 12; i++)
141 .index = index_drud_eofb, 84 if (cube->ep[i] >= 8)
142 .max = POW3TO7 * BINOM12ON4, 85 e[j++] = cube->ep[i] - 8;
143 .move = move_drud_eofb, 86 epe = (uint64_t)perm_to_index(e, 4);
144};
145 87
146Coordinate 88 return epos * FACTORIAL4 + epe;
147coord_cpud_separate = { 89}
148 .index = index_cpud_separate,
149 .max = BINOM8ON4,
150 .move = move_cpud_separate,
151};
152 90
153/* Indexers ******************************************************************/ 91/* Inverse indexers **********************************************************/
154 92
155static uint64_t 93void
156index_eofb(Cube cube) 94invindex_eofb(uint64_t ind, Cube *cube)
157{ 95{
158 return cube.eofb; 96 int_to_sum_zero_array(ind, 2, 12, cube->eo);
159} 97}
160 98
161static uint64_t 99void
162index_eofbepos(Cube cube) 100invindex_coud(uint64_t ind, Cube *cube)
163{ 101{
164 return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; 102 int_to_sum_zero_array(ind, 3, 8, cube->co);
165} 103}
166 104
167static uint64_t 105void
168index_epud(Cube cube) 106invindex_cp(uint64_t ind, Cube *cube)
169{ 107{
170 uint64_t ret; 108 index_to_perm(ind, 8, cube->cp);
171 CubeArray *arr = new_cubearray(cube, pf_ep);
172
173 ret = perm_to_index(arr->ep, 8);
174 free_cubearray(arr, pf_ep);
175
176 return ret;
177} 109}
178 110
179static uint64_t 111void
180index_coud(Cube cube) 112invindex_cpudsep(uint64_t ind, Cube *cube)
181{ 113{
182 return cube.coud; 114 int i, j, k, c[8];
183}
184 115
185static uint64_t 116 index_to_subset(ind, 8, 4, c);
186index_corners(Cube cube) 117 for (i = 0, j = 0, k = 4; i < 8; i++)
187{ 118 cube->cp[i] = c[i] == 0 ? j++ : k++;
188 return cube.coud * FACTORIAL8 + cube.cp;
189} 119}
190 120
191static uint64_t
192index_cp(Cube cube)
193{
194 return cube.cp;
195}
196 121
197static uint64_t 122void
198index_cphtr(Cube cube) 123invindex_epe(uint64_t ind, Cube *cube)
199{ 124{
200 return cphtr_right_cosets[cube.cp]; 125 int i;
126
127 index_to_perm(ind, 4, &cube->ep[8]);
128 for (i = 0; i < 4; i++)
129 cube->ep[i+8] += 8;
201} 130}
202 131
203static uint64_t 132void
204index_cornershtr(Cube cube) 133invindex_epud(uint64_t ind, Cube *cube)
205{ 134{
206 return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube); 135 index_to_perm(ind, 8, cube->ep);
207} 136}
208 137
209static uint64_t 138void
210index_cornershtrfin(Cube cube) 139invindex_epos(uint64_t ind, Cube *cube)
211{ 140{
212 return cornershtrfin_ind[cube.cp]; 141 int i, j, k;
142
143 index_to_subset(ind, 12, 4, cube->ep);
144 for (i = 0, j = 0, k = 8; i < 12; i++)
145 if (cube->ep[i] == 0)
146 cube->ep[i] = j++;
147 else
148 cube->ep[i] = k++;
213} 149}
214 150
215static uint64_t 151void
216index_drud(Cube cube) 152invindex_eposepe(uint64_t ind, Cube *cube)
217{ 153{
218 uint64_t a, b, c; 154 int i, j, k, e[4];
155 uint64_t epos, epe;
219 156
220 a = cube.eofb; 157 epos = ind / FACTORIAL4;
221 b = cube.coud; 158 epe = ind % FACTORIAL4;
222 c = cube.epose / FACTORIAL4;
223 159
224 b *= POW2TO11; 160 index_to_subset(epos, 12, 4, cube->ep);
225 c *= POW2TO11 * POW3TO7; 161 index_to_perm(epe, 4, e);
226 162
227 return a + b + c; 163 for (i = 0, j = 0, k = 0; i < 12; i++)
164 if (cube->ep[i] == 0)
165 cube->ep[i] = j++;
166 else
167 cube->ep[i] = e[k++] + 8;
228} 168}
229 169
230static uint64_t 170/* Other local functions *****************************************************/
231index_drud_eofb(Cube cube)
232{
233 return index_drud(cube) / POW2TO11;
234}
235 171
236static uint64_t 172static uint64_t
237index_htr_drud(Cube cube) 173indexers_getmax(Indexer **is)
238{ 174{
239 uint64_t a, b; 175 int i;
176 uint64_t max = 1;
240 177
241 a = index_cphtr(cube); 178 for (i = 0; is[i] != NULL; i++)
242 b = htr_eposs_ind[cube.eposs/24]; 179 max *= is[i]->n;
243 180
244 return a * BINOM8ON4 + b; 181 return max;
245} 182}
246 183
247static uint64_t 184static uint64_t
248index_htrfin(Cube cube) 185indexers_getind(Indexer **is, Cube *c)
249{ 186{
250 uint64_t epe, eps, epm, cp, ep; 187 int i;
188 uint64_t max = 0;
251 189
252 epe = cube.epose % 24; 190 for (i = 0; is[i] != NULL; i++) {
253 eps = cube.eposs % 24; 191 max *= is[i]->n;
254 epm = cube.eposm % 24; 192 max += is[i]->index(c);
255 ep = (epe * 24 + eps) *24 + epm; 193 }
256 cp = index_cornershtrfin(cube);
257 194
258 return cp * 24 * 24 * 24 + ep; 195 return max;
259} 196}
260 197
261static uint64_t 198static void
262index_cpud_separate(Cube cube) 199indexers_makecube(Indexer **is, uint64_t ind, Cube *c)
263{ 200{
264 return cpud_separate_ind[cube.cp]; 201 /* Warning: anti-indexers are applied in the same order as indexers. */
265} 202 /* We assume order does not matter, but it would make more sense to */
203 /* Apply them in reverse. */
266 204
267/* Coordinate movers *********************************************************/ 205 int i;
206 uint64_t m;
268 207
269static uint64_t 208 make_solved(c);
270move_eofb(Move m, uint64_t ind) 209 m = indexers_getmax(is);
271{ 210 for (i = 0; is[i] != NULL; i++) {
272 return eofb_mtable[m][ind]; 211 m /= is[i]->n;
212 is[i]->to_cube(ind / m, c);
213 ind %= m;
214 }
273} 215}
274 216
275static uint64_t 217static void
276move_eofbepos(Move m, uint64_t ind) 218gen_coord_comp(Coordinate *coord)
277{ 219{
278 uint64_t a, b; 220 uint64_t ui;
221 Cube c, mvd;
222 Move m;
223 Trans t;
279 224
280 a = epose_mtable[m][(ind / POW2TO11)*24]; 225 coord->max = indexers_getmax(coord->i);
281 b = eofb_mtable[m][ind % POW2TO11];
282 226
283 return (a/24) * POW2TO11 + b; 227 for (m = 0; m < NMOVES; m++)
284} 228 coord->mtable[m] = malloc(coord->max * sizeof(uint64_t));
285 229
286static uint64_t 230 for (t = 0; t < NTRANS; t++)
287move_epud(Move m, uint64_t ind) 231 coord->ttable[t] = malloc(coord->max * sizeof(uint64_t));
288{
289 /* TODO: save to file? */
290 static bool initialized = false;
291 static int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 };
292 static int shortlist[NMOVES] = {
293 [U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5,
294 [R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9
295 };
296 static uint64_t aux[10][FACTORIAL8];
297 uint64_t ui;
298 int j;
299 Move mj;
300 Cube c;
301 CubeArray *arr, *auxarr;
302 232
303 if (!moveset_drud.allowed(m)) { 233 if (!read_coord_mtable(coord)) {
304 fprintf(stderr, "Move not allowed for epud\n" 234 fprintf(stderr, "%s: generating mtable\n", coord->name);
305 "This is a bug, please report\n");
306 return coord_epud.max;
307 }
308 235
309 if (!initialized) { 236 for (ui = 0; ui < coord->max; ui++) {
310 auxarr = malloc(sizeof(CubeArray)); 237 indexers_makecube(coord->i, ui, &c);
311 auxarr->ep = a; 238 for (m = 0; m < NMOVES; m++) {
312 for (ui = 0; ui < coord_epud.max; ui++) { 239 copy_cube(&c, &mvd);
313 index_to_perm(ui, 8, a); 240 apply_move(m, &mvd);
314 c = arrays_to_cube(auxarr, pf_ep); 241 coord->mtable[m][ui] =
315 for (j = 0; moveset_drud.sorted_moves[j] != NULLMOVE; 242 indexers_getind(coord->i, &mvd);
316 j++) {
317 mj = moveset_drud.sorted_moves[j];
318 arr = new_cubearray(apply_move(mj, c), pf_ep);
319 aux[shortlist[mj]][ui] =
320 perm_to_index(arr->ep, 8);
321 free_cubearray(arr, pf_ep);
322 } 243 }
323 } 244 }
324 free(auxarr); 245 if (!write_coord_mtable(coord))
325 246 fprintf(stderr, "%s: error writing mtable\n",
326 initialized = true; 247 coord->name);
248
249 fprintf(stderr, "%s: mtable generated\n", coord->name);
327 } 250 }
328 251
329 return aux[shortlist[m]][ind]; 252 if (!read_coord_ttable(coord)) {
330} 253 fprintf(stderr, "%s: generating ttable\n", coord->name);
331 254
332static uint64_t 255 for (ui = 0; ui < coord->max; ui++) {
333move_coud(Move m, uint64_t ind) 256 indexers_makecube(coord->i, ui, &c);
334{ 257 for (t = 0; t < NTRANS; t++) {
335 return coud_mtable[m][ind]; 258 copy_cube(&c, &mvd);
259 apply_trans(t, &mvd);
260 coord->ttable[t][ui] =
261 indexers_getind(coord->i, &mvd);
262 }
263 }
264 if (!write_coord_ttable(coord))
265 fprintf(stderr, "%s: error writing ttable\n",
266 coord->name);
267 }
336} 268}
337 269
338static uint64_t 270static void
339move_corners(Move m, uint64_t ind) 271gen_coord_sym(Coordinate *coord)
340{ 272{
341 uint64_t a, b; 273 uint64_t i, in, ui, uj, uu, M, nr;
274 int j;
275 Move m;
276 Trans t;
342 277
343 a = coud_mtable[m][ind / FACTORIAL8]; 278 M = coord->base[0]->max;
344 b = cp_mtable[m][ind % FACTORIAL8]; 279 coord->selfsim = malloc(M * sizeof(uint64_t));
280 coord->symclass = malloc(M * sizeof(uint64_t));
281 coord->symrep = malloc(M * sizeof(uint64_t));
282 coord->transtorep = malloc(M * sizeof(Trans));
345 283
346 return a * FACTORIAL8 + b; 284 if (!read_coord_sd(coord)) {
347} 285 fprintf(stderr, "%s: generating syms\n", coord->name);
348 286
349static uint64_t 287 for (i = 0; i < M; i++)
350move_cp(Move m, uint64_t ind) 288 coord->symclass[i] = M+1;
351{
352 return cp_mtable[m][ind];
353}
354 289
355static uint64_t 290 for (i = 0, nr = 0; i < M; i++) {
356move_cphtr(Move m, uint64_t ind) 291 if (coord->symclass[i] != M+1)
357{ 292 continue;
358 static bool initialized = false; 293
359 static uint64_t aux[NMOVES][BINOM8ON4*6]; 294 coord->symrep[nr] = i;
360 uint64_t ui; 295 coord->transtorep[i] = uf;
361 Move j; 296 coord->selfsim[nr] = (uint64_t)0;
297 for (j = 0; j < coord->tgrp->n; j++) {
298 t = coord->tgrp->t[j];
299 in = trans_coord(coord->base[0], t, i);
300 coord->symclass[in] = nr;
301 if (in == i)
302 coord->selfsim[nr] |= ((uint64_t)1<<t);
303 else
304 coord->transtorep[in] =
305 inverse_trans(t);
306 }
307 nr++;
308 }
309
310 coord->max = nr;
311
312 fprintf(stderr, "%s: found %" PRIu64 " classes\n",
313 coord->name, nr);
314 if (!write_coord_sd(coord))
315 fprintf(stderr, "%s: error writing symdata\n",
316 coord->name);
317 }
362 318
363 if (!initialized) { 319 coord->symrep = realloc(coord->symrep, coord->max*sizeof(uint64_t));
364 for (ui = 0; ui < BINOM8ON4*6; ui++) 320 coord->selfsim = realloc(coord->selfsim, coord->max*sizeof(uint64_t));
365 for (j = U; j < NMOVES; j++)
366 aux[j][ui] = cphtr_right_cosets[
367 cp_mtable[j][cphtr_right_rep[ui]]];
368 321
369 initialized = true; 322 for (m = 0; m < NMOVES; m++) {
323 coord->mtable[m] = malloc(coord->max*sizeof(uint64_t));
324 coord->ttrep_move[m] = malloc(coord->max*sizeof(Trans));
370 } 325 }
371 326
372 return aux[m][ind]; 327 if (!read_coord_mtable(coord)) {
328 for (ui = 0; ui < coord->max; ui++) {
329 uu = coord->symrep[ui];
330 for (m = 0; m < NMOVES; m++) {
331 uj = move_coord(coord->base[0], m, uu, NULL);
332 coord->mtable[m][ui] = coord->symclass[uj];
333 coord->ttrep_move[m][ui] =
334 coord->transtorep[uj];
335 }
336 }
337 if (!write_coord_mtable(coord))
338 fprintf(stderr, "%s: error writing mtable\n",
339 coord->name);
340 }
373} 341}
374 342
375static uint64_t 343static bool
376move_cornershtr(Move m, uint64_t ind) 344read_coord_mtable(Coordinate *coord)
377{ 345{
378 uint64_t a, b; 346 FILE *f;
347 char fname[strlen(tabledir)+256];
348 Move m;
349 uint64_t M;
350 bool r;
379 351
380 a = coud_mtable[m][ind/(BINOM8ON4 * 6)]; 352 strcpy(fname, tabledir);
381 b = move_cphtr(m, ind % (BINOM8ON4 * 6)); 353 strcat(fname, "/mt_");
354 strcat(fname, coord->name);
382 355
383 return a * BINOM8ON4 * 6 + b; 356 if ((f = fopen(fname, "rb")) == NULL)
384} 357 return false;
385 358
386static uint64_t 359 M = coord->max;
387move_cornershtrfin(Move m, uint64_t ind) 360 r = true;
388{ 361 for (m = 0; m < NMOVES; m++)
389 int a; 362 r = r && fread(coord->mtable[m], sizeof(uint64_t), M, f) == M;
390 363
391 a = cp_mtable[m][cornershtrfin_ant[ind]]; 364 if (coord->type == SYM_COORD)
365 for (m = 0; m < NMOVES; m++)
366 r = r && fread(coord->ttrep_move[m],
367 sizeof(Trans), M, f) == M;
392 368
393 return cornershtrfin_ind[a]; 369 fclose(f);
370 return r;
394} 371}
395 372
396static uint64_t 373static bool
397move_drud(Move m, uint64_t ind) 374read_coord_sd(Coordinate *coord)
398{ 375{
399 uint64_t a, b, c; 376 FILE *f;
377 char fname[strlen(tabledir)+256];
378 uint64_t M, N;
379 bool r;
380
381 strcpy(fname, tabledir);
382 strcat(fname, "/sd_");
383 strcat(fname, coord->name);
400 384
401 a = eofb_mtable[m][ind % POW2TO11]; 385 if ((f = fopen(fname, "rb")) == NULL)
402 b = coud_mtable[m][(ind / POW2TO11) % POW3TO7]; 386 return false;
403 c = epose_mtable[m][ind / (POW2TO11 * POW3TO7)];
404 387
405 return a + (b + c * POW3TO7) * POW2TO11; 388 r = true;
389 r = r && fread(&coord->max, sizeof(uint64_t), 1, f) == 1;
390 M = coord->max;
391 N = coord->base[0]->max;
392 r = r && fread(coord->symrep, sizeof(uint64_t), M, f) == M;
393 r = r && fread(coord->selfsim, sizeof(uint64_t), M, f) == M;
394 r = r && fread(coord->symclass, sizeof(uint64_t), N, f) == N;
395 r = r && fread(coord->transtorep, sizeof(Trans), N, f) == N;
396
397 fclose(f);
398 return r;
406} 399}
407 400
408static uint64_t 401static bool
409move_drud_eofb(Move m, uint64_t ind) 402read_coord_ttable(Coordinate *coord)
410{ 403{
411 uint64_t a, b; 404 FILE *f;
405 char fname[strlen(tabledir)+256];
406 Trans t;
407 uint64_t M;
408 bool r;
409
410 strcpy(fname, tabledir);
411 strcat(fname, "/tt_");
412 strcat(fname, coord->name);
412 413
413 a = coud_mtable[m][ind % POW3TO7]; 414 if ((f = fopen(fname, "rb")) == NULL)
414 b = epose_mtable[m][(ind / POW3TO7) * 24] / 24; 415 return false;
415 416
416 return a + b * POW3TO7; 417 M = coord->max;
418 r = true;
419 for (t = 0; t < NTRANS; t++)
420 r = r && fread(coord->ttable[t], sizeof(uint64_t), M, f) == M;
421
422 fclose(f);
423 return r;
417} 424}
418 425
419static uint64_t 426static bool
420move_htr_drud(Move m, uint64_t ind) 427write_coord_mtable(Coordinate *coord)
421{ 428{
422 uint64_t a, b; 429 FILE *f;
430 char fname[strlen(tabledir)+256];
431 Move m;
432 uint64_t M;
433 bool r;
434
435 strcpy(fname, tabledir);
436 strcat(fname, "/mt_");
437 strcat(fname, coord->name);
438
439 if ((f = fopen(fname, "wb")) == NULL)
440 return false;
423 441
424 a = move_cphtr(m, ind/BINOM8ON4); 442 M = coord->max;
425 b = eposs_mtable[m][htr_eposs_ant[ind%BINOM8ON4]]; 443 r = true;
444 for (m = 0; m < NMOVES; m++)
445 r = r && fwrite(coord->mtable[m], sizeof(uint64_t), M, f) == M;
426 446
427 return a*BINOM8ON4 + htr_eposs_ind[b/24]; 447 if (coord->type == SYM_COORD)
448 for (m = 0; m < NMOVES; m++)
449 r = r && fwrite(coord->ttrep_move[m],
450 sizeof(Trans), M, f) == M;
451
452 fclose(f);
453 return r;
428} 454}
429 455
430static uint64_t 456static bool
431move_htrfin(Move m, uint64_t ind) 457write_coord_sd(Coordinate *coord)
432{ 458{
433 uint64_t a, b, bm, bs, be; 459 FILE *f;
460 char fname[strlen(tabledir)+256];
461 uint64_t M, N;
462 bool r;
434 463
435 a = move_cornershtrfin(m, ind / (24*24*24)); 464 strcpy(fname, tabledir);
436 bm = eposm_mtable[m][ind%24] % 24; 465 strcat(fname, "/sd_");
437 bs = eposs_mtable[m][(ind/24)%24] % 24; 466 strcat(fname, coord->name);
438 be = epose_mtable[m][(ind/(24*24))%24] % 24;
439 b = (be * 24 + bs) * 24 + bm;
440 467
441 return a * (24*24*24) + b; 468 if ((f = fopen(fname, "wb")) == NULL)
469 return false;
470
471 r = true;
472 M = coord->max;
473 N = coord->base[0]->max;
474 r = r && fwrite(&coord->max, sizeof(uint64_t), 1, f) == 1;
475 r = r && fwrite(coord->symrep, sizeof(uint64_t), M, f) == M;
476 r = r && fwrite(coord->selfsim, sizeof(uint64_t), M, f) == M;
477 r = r && fwrite(coord->symclass, sizeof(uint64_t), N, f) == N;
478 r = r && fwrite(coord->transtorep, sizeof(Trans), N, f) == N;
479
480 fclose(f);
481 return r;
442} 482}
443 483
444static uint64_t 484static bool
445move_cpud_separate(Move m, uint64_t ind) 485write_coord_ttable(Coordinate *coord)
446{ 486{
447 return cpud_separate_ind[cp_mtable[m][cpud_separate_ant[ind]]]; 487 FILE *f;
488 char fname[strlen(tabledir)+256];
489 Trans t;
490 uint64_t M;
491 bool r;
492
493 strcpy(fname, tabledir);
494 strcat(fname, "/tt_");
495 strcat(fname, coord->name);
496
497 if ((f = fopen(fname, "wb")) == NULL)
498 return false;
499
500 M = coord->max;
501 r = true;
502 for (t = 0; t < NTRANS; t++)
503 r = r && fwrite(coord->ttable[t], sizeof(uint64_t), M, f) == M;
504
505 fclose(f);
506 return r;
448} 507}
449 508
450/* Init functions implementation *********************************************/ 509/* Public functions **********************************************************/
451 510
452/* 511void
453 * There is certainly a better way to do this, but for now I just use 512gen_coord(Coordinate *coord)
454 * a "graph coloring" algorithm to compute the left cosets, and I compose
455 * with every possible cp to get the right cosets (it is possible that I am
456 * mixing up left and right).
457 *
458 * For doing it better "Mathematically", we need 3 things:
459 * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other
460 * This is easy and it is done in the commented function cphtr_cp().
461 * - Check that there is no ep/cp parity
462 * - Check that we are not in the "3c" case; this is the part I don't
463 * know how to do.
464 */
465static void
466init_cphtr_cosets()
467{ 513{
468 unsigned int i; 514 int i;
469 int c = 0, d = 0; 515
516 if (coord == NULL || coord->generated)
517 return;
518
519 for (i = 0; i < 2; i++)
520 gen_coord(coord->base[i]);
470 521
471 for (i = 0; i < FACTORIAL8; i++) { 522 switch (coord->type) {
472 cphtr_left_cosets[i] = -1; 523 case COMP_COORD:
473 cphtr_right_cosets[i] = -1; 524 if (coord->i[0] == NULL)
525 goto error_gc;
526 gen_coord_comp(coord);
527 break;
528 case SYM_COORD:
529 if (coord->base[0] == NULL || coord->tgrp == NULL)
530 goto error_gc;
531 gen_coord_sym(coord);
532 break;
533 case SYMCOMP_COORD:
534 if (coord->base[0] == NULL || coord->base[1] == NULL)
535 goto error_gc;
536 coord->max = coord->base[0]->max * coord->base[1]->max;
537 break;
538 default:
539 break;
474 } 540 }
475 541
476 /* First we compute left cosets with a bfs */ 542 coord->generated = true;
477 for (i = 0; i < FACTORIAL8; i++) 543 return;
478 if (cphtr_left_cosets[i] == -1)
479 init_cphtr_left_cosets_bfs(i, c++);
480 544
481 /* Then we compute right cosets using compose() */ 545error_gc:
482 for (i = 0; i < FACTORIAL8; i++) 546 fprintf(stderr, "Error generating coordinates.\n"
483 if (cphtr_right_cosets[i] == -1) 547 "This is a bug, pleae report.\n");
484 init_cphtr_right_cosets_color(i, d++); 548 exit(1);
485} 549}
486 550
487static void 551uint64_t
488init_cphtr_left_cosets_bfs(int i, int c) 552index_coord(Coordinate *coord, Cube *cube, Trans *offtrans)
489{ 553{
490 int j, jj, next[FACTORIAL8], next2[FACTORIAL8], n, n2; 554 uint64_t c[2], cnosym;
555 Trans ttr;
491 556
492 Move k; 557 switch (coord->type) {
558 case COMP_COORD:
559 if (offtrans != NULL)
560 *offtrans = uf;
493 561
494 n = 1; 562 return indexers_getind(coord->i, cube);
495 next[0] = i; 563 case SYM_COORD:
496 cphtr_left_cosets[i] = c; 564 cnosym = index_coord(coord->base[0], cube, NULL);
565 ttr = coord->transtorep[cnosym];
497 566
498 while (n != 0) { 567 if (offtrans != NULL)
499 for (j = 0, n2 = 0; j < n; j++) { 568 *offtrans = ttr;
500 for (k = U2; k < B3; k++) {
501 if (!moveset_htr.allowed(k))
502 continue;
503 jj = apply_move(k, (Cube){ .cp = next[j] }).cp;
504 569
505 if (cphtr_left_cosets[jj] == -1) { 570 return coord->symclass[cnosym];
506 cphtr_left_cosets[jj] = c; 571 case SYMCOMP_COORD:
507 next2[n2++] = jj; 572 c[0] = index_coord(coord->base[0], cube, NULL);
508 } 573 cnosym = index_coord(coord->base[0]->base[0], cube, NULL);
509 } 574 ttr = coord->base[0]->transtorep[cnosym];
510 } 575 c[1] = index_coord(coord->base[1], cube, NULL);
576 c[1] = trans_coord(coord->base[1], ttr, c[1]);
511 577
512 for (j = 0; j < n2; j++) 578 if (offtrans != NULL)
513 next[j] = next2[j]; 579 *offtrans = ttr;
514 n = n2; 580
581 return c[0] * coord->base[1]->max + c[1];
582 default:
583 break;
515 } 584 }
585
586 return coord->max; /* Only reached in case of error */
516} 587}
517 588
518static void 589uint64_t
519init_cphtr_right_cosets_color(int i, int d) 590move_coord(Coordinate *coord, Move m, uint64_t ind, Trans *offtrans)
520{ 591{
521 int cp; 592 uint64_t i[2], M;
522 unsigned int j; 593 Trans ttr;
523 594
524 cphtr_right_rep[d] = i; 595 /* Some safety checks should be done here, but for performance *
525 for (j = 0; j < FACTORIAL8; j++) { 596 * reasons we'd rather do them before calling this function. *
526 if (cphtr_left_cosets[j] == 0) { 597 * We should check if coord is generated. */
527 cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp;
528 cphtr_right_cosets[cp] = d;
529 }
530 }
531}
532 598
533static void 599 switch (coord->type) {
534init_cpud_separate() 600 case COMP_COORD:
535{ 601 if (offtrans != NULL)
536 unsigned int ui; 602 *offtrans = uf;
537 int i, co[8];
538 603
539 for (ui = 0; ui < FACTORIAL8; ui++) { 604 return coord->mtable[m][ind];
540 for (i = 0; i < 8; i++) 605 case SYM_COORD:
541 co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ? 1 : 0; 606 ttr = coord->ttrep_move[m][ind];
542 cpud_separate_ind[ui] = subset_to_index(co, 8, 4);
543 cpud_separate_ant[cpud_separate_ind[ui]] = ui;
544 }
545}
546 607
547static void 608 if (offtrans != NULL)
548init_cornershtrfin() 609 *offtrans = ttr;
549{
550 unsigned int i, j;
551 int n, c;
552 Move m;
553 610
554 for (i = 0; i < FACTORIAL8; i++) 611 return coord->mtable[m][ind];
555 cornershtrfin_ind[i] = -1; 612 case SYMCOMP_COORD:
556 cornershtrfin_ind[0] = 0; 613 M = coord->base[1]->max;
614 i[0] = ind / M;
615 i[1] = ind % M;
616 ttr = coord->base[0]->ttrep_move[m][i[0]];
617 i[0] = coord->base[0]->mtable[m][i[0]];
618 i[1] = coord->base[1]->mtable[m][i[1]];
619 i[1] = coord->base[1]->ttable[ttr][i[1]];
557 620
558 /* 10-pass, I think 5 is enough, but just in case */ 621 if (offtrans != NULL)
559 n = 1; 622 *offtrans = ttr;
560 for (i = 0; i < 10; i++) { 623
561 for (j = 0; j < FACTORIAL8; j++) { 624 return i[0] * M + i[1];
562 if (cornershtrfin_ind[j] == -1) 625 default:
563 continue; 626 break;
564 for (m = U; m < NMOVES; m++) {
565 if (moveset_htr.allowed(m)) {
566 c = cp_mtable[m][j];
567 if (cornershtrfin_ind[c] == -1) {
568 cornershtrfin_ind[c] = n;
569 cornershtrfin_ant[n] = c;
570 n++;
571 }
572 }
573 }
574 }
575 } 627 }
628
629 return coord->max; /* Only reached in case of error */
576} 630}
577 631
578void 632bool
579init_htr_eposs() 633test_coord(Coordinate *coord)
580{ 634{
581 int ep[12], ep2[12]; 635 uint64_t ui, uj;
582 int eps_solved[4] = {UL, UR, DL, DR}; 636 Cube c;
583 unsigned int i, j;
584 637
585 for (i = 0; i < BINOM12ON4; i++) { 638 if (coord->type != COMP_COORD) {
586 for (j = 0; j < 12; j++) 639 fprintf(stderr, "Can only test COMP_COORD\n");
587 ep[j] = ep2[j] = 0; 640 return false;
588 epos_to_partial_ep(i*24, ep, eps_solved);
589 for (j = 0; j < 8; j++)
590 ep2[j/2 + 4*(j%2)] = ep[j] ? 1 : 0;
591 htr_eposs_ind[i] = subset_to_index(ep2, 8, 4);
592 htr_eposs_ant[htr_eposs_ind[i]] = i*24;
593 } 641 }
642
643 gen_coord(coord);
644 for (ui = 0; ui < coord->max; ui++) {
645 indexers_makecube(coord->i, ui, &c);
646 uj = indexers_getind(coord->i, &c);
647 if (ui != uj) {
648 fprintf(stderr, "%s: error: %" PRIu64 " different"
649 " from %" PRIu64 "\n", coord->name, uj, ui);
650 return false;
651 }
652 }
653
654 fprintf(stderr, "%s: test passed\n", coord->name);
655 return true;
594} 656}
595 657
596void 658uint64_t
597init_coord() 659trans_coord(Coordinate *coord, Trans t, uint64_t ind)
598{ 660{
599 static bool initialized = false; 661 uint64_t i[2], M;
600 if (initialized)
601 return;
602 initialized = true;
603 662
604 init_trans(); 663 /* Some safety checks should be done here, but for performance *
664 * reasons we'd rather do them before calling this function. *
665 * We should check if coord is generated. */
605 666
606 init_cphtr_cosets(); 667 switch (coord->type) {
607 init_cornershtrfin(); 668 case COMP_COORD:
608 init_htr_eposs(); 669 return coord->ttable[t][ind];
609 init_cpud_separate(); 670 case SYM_COORD:
610} 671 return ind;
672 case SYMCOMP_COORD:
673 M = coord->base[1]->max;
674 i[0] = ind / M; /* Always fixed */
675 i[1] = ind % M;
676 i[1] = coord->base[1]->ttable[t][i[1]];
677 return i[0] * M + i[1];
678 default:
679 break;
680 }
611 681
682 return coord->max; /* Only reached in case of error */
683}
diff --git a/src/coord.h b/src/coord.h
index 61398a4..47c0579 100644
--- a/src/coord.h
+++ b/src/coord.h
@@ -3,26 +3,232 @@
3 3
4#include "trans.h" 4#include "trans.h"
5 5
6extern Coordinate coord_eofb; 6void gen_coord(Coordinate *coord);
7extern Coordinate coord_eofbepos; 7uint64_t index_coord(Coordinate *coord, Cube *cube,
8extern Coordinate coord_coud; 8 Trans *offtrans);
9extern Coordinate coord_cp; 9uint64_t move_coord(Coordinate *coord, Move m,
10extern Coordinate coord_cphtr; 10 uint64_t ind, Trans *offtrans);
11extern Coordinate coord_corners; 11bool test_coord(Coordinate *coord);
12extern Coordinate coord_cornershtr; 12uint64_t trans_coord(Coordinate *coord, Trans t, uint64_t ind);
13extern Coordinate coord_cornershtrfin;
14extern Coordinate coord_epud;
15extern Coordinate coord_drud;
16extern Coordinate coord_drud_eofb;
17extern Coordinate coord_htr_drud;
18extern Coordinate coord_htrfin;
19extern Coordinate coord_cpud_separate;
20 13
21extern int cpud_separate_ant[BINOM8ON4]; 14/* Base coordinates and their index functions ********************************/
22extern int cpud_separate_ind[FACTORIAL8];
23extern int cornershtrfin_ant[24*24/6];
24 15
25void init_coord(); 16#ifndef COORD_C
17
18extern Coordinate coord_eofb;
19extern Coordinate coord_coud;
20extern Coordinate coord_cp;
21extern Coordinate coord_cpudsep;
22extern Coordinate coord_epos;
23extern Coordinate coord_epe;
24extern Coordinate coord_eposepe;
25extern Coordinate coord_epud;
26extern Coordinate coord_eofbepos;
27extern Coordinate coord_coud_cpudsep;
28extern Coordinate coord_eofbepos_sym16;
29extern Coordinate coord_cp_sym16;
30extern Coordinate coord_corners_sym16;
31extern Coordinate coord_drud_sym16;
32extern Coordinate coord_drudfin_noE_sym16;
33extern Coordinate coord_nxopt31;
34
35#else
36
37/* Indexers ******************************************************************/
38
39uint64_t index_eofb(Cube *cube);
40void invindex_eofb(uint64_t ind, Cube *ret);
41Indexer
42i_eofb = {
43 .n = POW2TO11,
44 .index = index_eofb,
45 .to_cube = invindex_eofb,
46};
47
48uint64_t index_coud(Cube *cube);
49void invindex_coud(uint64_t ind, Cube *ret);
50Indexer
51i_coud = {
52 .n = POW3TO7,
53 .index = index_coud,
54 .to_cube = invindex_coud,
55};
56
57uint64_t index_cp(Cube *cube);
58void invindex_cp(uint64_t ind, Cube *ret);
59Indexer
60i_cp = {
61 .n = FACTORIAL8,
62 .index = index_cp,
63 .to_cube = invindex_cp,
64};
65
66uint64_t index_cpudsep(Cube *cube);
67void invindex_cpudsep(uint64_t ind, Cube *ret);
68Indexer
69i_cpudsep = {
70 .n = BINOM8ON4,
71 .index = index_cpudsep,
72 .to_cube = invindex_cpudsep,
73};
74
75uint64_t index_epos(Cube *cube);
76void invindex_epos(uint64_t ind, Cube *ret);
77Indexer
78i_epos = {
79 .n = BINOM12ON4,
80 .index = index_epos,
81 .to_cube = invindex_epos,
82};
83
84uint64_t index_epe(Cube *cube);
85void invindex_epe(uint64_t ind, Cube *ret);
86Indexer
87i_epe = {
88 .n = FACTORIAL4,
89 .index = index_epe,
90 .to_cube = invindex_epe,
91};
92
93uint64_t index_eposepe(Cube *cube);
94void invindex_eposepe(uint64_t ind, Cube *ret);
95Indexer
96i_eposepe = {
97 .n = BINOM12ON4 * FACTORIAL4,
98 .index = index_eposepe,
99 .to_cube = invindex_eposepe,
100};
101
102uint64_t index_epud(Cube *cube);
103void invindex_epud(uint64_t ind, Cube *ret);
104Indexer
105i_epud = {
106 .n = FACTORIAL8,
107 .index = index_epud,
108 .to_cube = invindex_epud,
109};
110
111/* Composite coordinates *****************************************************/
112
113Coordinate
114coord_eofb = {
115 .name = "eofb",
116 .type = COMP_COORD,
117 .i = {&i_eofb, NULL},
118};
119
120Coordinate
121coord_coud = {
122 .name = "coud",
123 .type = COMP_COORD,
124 .i = {&i_coud, NULL},
125};
126
127Coordinate
128coord_cp = {
129 .name = "cp",
130 .type = COMP_COORD,
131 .i = {&i_cp, NULL},
132};
133
134Coordinate
135coord_cpudsep = {
136 .name = "cpudsep",
137 .type = COMP_COORD,
138 .i = {&i_cpudsep, NULL},
139};
140
141Coordinate
142coord_epos = {
143 .name = "epos",
144 .type = COMP_COORD,
145 .i = {&i_epos, NULL},
146};
147
148Coordinate
149coord_epe = {
150 .name = "epe",
151 .type = COMP_COORD,
152 .i = {&i_epe, NULL},
153};
154
155Coordinate
156coord_eposepe = { /* Has to be done by hand, hard compose epos + epe */
157 .name = "eposepe",
158 .type = COMP_COORD,
159 .i = {&i_eposepe, NULL},
160};
161
162Coordinate
163coord_epud = {
164 .name = "epud",
165 .type = COMP_COORD,
166 .i = {&i_epud, NULL},
167};
168
169Coordinate
170coord_eofbepos = {
171 .name = "eofbepos",
172 .type = COMP_COORD,
173 .i = {&i_epos, &i_eofb, NULL},
174};
175
176Coordinate
177coord_coud_cpudsep = {
178 .name = "coud_cpudsep",
179 .type = COMP_COORD,
180 .i = {&i_coud, &i_cpudsep, NULL},
181};
182
183/* Symcoordinates ************************************************************/
184
185Coordinate
186coord_eofbepos_sym16 = {
187 .name = "eofbepos_sym16",
188 .type = SYM_COORD,
189 .base = {&coord_eofbepos, NULL},
190 .tgrp = &tgrp_udfix,
191};
192
193Coordinate
194coord_cp_sym16 = {
195 .name = "cp_sym16",
196 .type = SYM_COORD,
197 .base = {&coord_cp, NULL},
198 .tgrp = &tgrp_udfix,
199};
200
201/* "Symcomp" coordinates *****************************************************/
202
203Coordinate
204coord_corners_sym16 = {
205 .name = "corners_sym16",
206 .type = SYMCOMP_COORD,
207 .base = {&coord_cp_sym16, &coord_coud},
208};
209
210Coordinate
211coord_drud_sym16 = {
212 .name = "drud_sym16",
213 .type = SYMCOMP_COORD,
214 .base = {&coord_eofbepos_sym16, &coord_coud},
215};
216
217Coordinate
218coord_drudfin_noE_sym16 = {
219 .name = "drudfin_noE_sym16",
220 .type = SYMCOMP_COORD,
221 .base = {&coord_cp_sym16, &coord_epud},
222};
223
224Coordinate
225coord_nxopt31 = {
226 .name = "nxopt31",
227 .type = SYMCOMP_COORD,
228 .base = {&coord_eofbepos_sym16, &coord_coud_cpudsep},
229};
230
231#endif
26 232
27#endif 233#endif
28 234
diff --git a/src/cube.c b/src/cube.c
index aae3a6e..0ccffa4 100644
--- a/src/cube.c
+++ b/src/cube.c
@@ -1,531 +1,121 @@
1#include "cube.h" 1#define CUBE_C
2
3/* Local functions ***********************************************************/
4
5static void init_inverse();
6static bool read_invtables_file();
7static bool write_invtables_file();
8
9/* Tables ********************************************************************/
10
11static uint16_t eo_invtable_e[POW2TO11][BINOM12ON4*FACTORIAL4];
12static uint16_t eo_invtable_s[POW2TO11][BINOM12ON4*FACTORIAL4];
13static uint16_t eo_invtable_m[POW2TO11][BINOM12ON4*FACTORIAL4];
14static uint16_t co_invtable[POW3TO7][FACTORIAL8];
15static uint16_t cp_invtable[FACTORIAL8];
16static uint16_t cpos_invtable[FACTORIAL6];
17
18/* Functions implementation **************************************************/
19
20int
21array_ep_to_epos(int *ep, int *ss)
22{
23 int epos[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
24 int eps[4];
25 int i, j, is;
26
27 for (i = 0, is = 0; i < 12; i++) {
28 for (j = 0; j < 4; j++) {
29 if (ep[i] == ss[j]) {
30 eps[is++] = j;
31 epos[i] = 1;
32 }
33 }
34 }
35
36 for (i = 0; i < 4; i++)
37 swap(&epos[ss[i]], &epos[i+8]);
38
39 return 24 * subset_to_index(epos, 12, 4) + perm_to_index(eps, 4);
40}
41
42Cube
43arrays_to_cube(CubeArray *arr, PieceFilter f)
44{
45 Cube ret = {0};
46
47 static int epe_solved[4] = {FR, FL, BL, BR};
48 static int eps_solved[4] = {UL, UR, DL, DR};
49 static int epm_solved[4] = {UF, UB, DF, DB};
50 2
51 if (f.epose) 3#include "cube.h"
52 ret.epose = array_ep_to_epos(arr->ep, epe_solved);
53 if (f.eposs)
54 ret.eposs = array_ep_to_epos(arr->ep, eps_solved);
55 if (f.eposm)
56 ret.eposm = array_ep_to_epos(arr->ep, epm_solved);
57 if (f.eofb)
58 ret.eofb = digit_array_to_int(arr->eofb, 11, 2);
59 if (f.eorl)
60 ret.eorl = digit_array_to_int(arr->eorl, 11, 2);
61 if (f.eoud)
62 ret.eoud = digit_array_to_int(arr->eoud, 11, 2);
63 if (f.cp)
64 ret.cp = perm_to_index(arr->cp, 8);
65 if (f.coud)
66 ret.coud = digit_array_to_int(arr->coud, 7, 3);
67 if (f.corl)
68 ret.corl = digit_array_to_int(arr->corl, 7, 3);
69 if (f.cofb)
70 ret.cofb = digit_array_to_int(arr->cofb, 7, 3);
71 if (f.cpos)
72 ret.cpos = perm_to_index(arr->cpos, 6);
73
74 return ret;
75}
76 4
77Cube 5void
78compose_filtered(Cube c2, Cube c1, PieceFilter f) 6compose(Cube *c2, Cube *c1)
79{ 7{
80 CubeArray *arr = new_cubearray(c2, f); 8 apply_permutation(c2->ep, c1->ep, 12);
81 Cube ret; 9 apply_permutation(c2->ep, c1->eo, 12);
10 sum_arrays_mod(c2->eo, c1->eo, 12, 2);
82 11
83 ret = move_via_arrays(arr, c1, f); 12 apply_permutation(c2->cp, c1->cp, 8);
84 free_cubearray(arr, f); 13 apply_permutation(c2->cp, c1->co, 8);
14 sum_arrays_mod(c2->co, c1->co, 8, 3);
85 15
86 return ret; 16 apply_permutation(c2->xp, c1->xp, 6);
87} 17}
88 18
89void 19void
90cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) 20copy_cube(Cube *src, Cube *dst)
91{ 21{
92 int i; 22 memcpy(dst->ep, src->ep, 12 * sizeof(int));
93 23 memcpy(dst->eo, src->eo, 12 * sizeof(int));
94 static int epe_solved[4] = {FR, FL, BL, BR}; 24 memcpy(dst->cp, src->cp, 8 * sizeof(int));
95 static int eps_solved[4] = {UL, UR, DL, DR}; 25 memcpy(dst->co, src->co, 8 * sizeof(int));
96 static int epm_solved[4] = {UF, UB, DF, DB}; 26 memcpy(dst->xp, src->xp, 6 * sizeof(int));
97
98 if (f.epose || f.eposs || f.eposm)
99 for (i = 0; i < 12; i++)
100 arr->ep[i] = -1;
101
102 if (f.epose)
103 epos_to_partial_ep(cube.epose, arr->ep, epe_solved);
104 if (f.eposs)
105 epos_to_partial_ep(cube.eposs, arr->ep, eps_solved);
106 if (f.eposm)
107 epos_to_partial_ep(cube.eposm, arr->ep, epm_solved);
108 if (f.eofb)
109 int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb);
110 if (f.eorl)
111 int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl);
112 if (f.eoud)
113 int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud);
114 if (f.cp)
115 index_to_perm(cube.cp, 8, arr->cp);
116 if (f.coud)
117 int_to_sum_zero_array(cube.coud, 3, 8, arr->coud);
118 if (f.corl)
119 int_to_sum_zero_array(cube.corl, 3, 8, arr->corl);
120 if (f.cofb)
121 int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb);
122 if (f.cpos)
123 index_to_perm(cube.cpos, 6, arr->cpos);
124} 27}
125 28
126void 29bool
127epos_to_compatible_ep(int epos, int *ep, int *ss) 30equal(Cube *c1, Cube *c2)
128{ 31{
129 int i, j, k, other[8]; 32 int i;
130 bool flag;
131 33
132 for (i = 0; i < 12; i++) 34 for (i = 0; i < 12; i++)
133 ep[i] = -1; 35 if (c1->ep[i] != c2->ep[i] || c1->eo[i] != c2->eo[i])
134 36 return false;
135 epos_to_partial_ep(epos, ep, ss);
136
137 for (i = 0, j = 0; i < 12; i++) {
138 flag = false;
139 for (k = 0; k < 4; k++)
140 flag = flag || (i == ss[k]);
141 if (!flag)
142 other[j++] = i;
143 }
144
145 for (i = 0, j = 0; i < 12; i++)
146 if (ep[i] == -1)
147 ep[i] = other[j++];
148}
149
150void
151epos_to_partial_ep(int epos, int *ep, int *ss)
152{
153 int i, is, eposs[12], eps[4];
154 37
155 index_to_perm(epos % FACTORIAL4, 4, eps); 38 for (i = 0; i < 8; i++)
156 index_to_subset(epos / FACTORIAL4, 12, 4, eposs); 39 if (c1->cp[i] != c2->cp[i] || c1->co[i] != c2->co[i])
40 return false;
157 41
158 for (i = 0; i < 4; i++) 42 for (i = 0; i < 6; i++)
159 swap(&eposs[ss[i]], &eposs[i+8]); 43 if (c1->xp[i] != c2->xp[i])
44 return false;
160 45
161 for (i = 0, is = 0; i < 12; i++) 46 return true;
162 if (eposs[i])
163 ep[i] = ss[eps[is++]];
164} 47}
165 48
166void 49void
167fix_eorleoud(CubeArray *arr) 50invert_cube(Cube *cube)
168{ 51{
52 Cube aux;
169 int i; 53 int i;
170 54
171 for (i = 0; i < 12; i++) { 55 copy_cube(cube, &aux);
172 if ((edge_slice(i) == 0 && edge_slice(arr->ep[i]) != 0) ||
173 (edge_slice(i) != 0 && edge_slice(arr->ep[i]) == 0)) {
174 arr->eorl[i] = 1 - arr->eofb[i];
175 } else {
176 arr->eorl[i] = arr->eofb[i];
177 }
178 56
179 if ((edge_slice(i) == 2 && edge_slice(arr->ep[i]) != 2) || 57 for (i = 0; i < 12; i++) {
180 (edge_slice(i) != 2 && edge_slice(arr->ep[i]) == 2)) { 58 cube->ep[aux.ep[i]] = i;
181 arr->eoud[i] = 1 - arr->eofb[i]; 59 cube->eo[aux.ep[i]] = aux.eo[i];
182 } else {
183 arr->eoud[i] = arr->eofb[i];
184 }
185 } 60 }
186}
187
188void
189fix_cofbcorl(CubeArray *arr)
190{
191 int i;
192 61
193 for (i = 0; i < 8; i++) { 62 for (i = 0; i < 8; i++) {
194 if (i % 2 == arr->cp[i] % 2) { 63 cube->cp[aux.cp[i]] = i;
195 arr->cofb[i] = arr->coud[i]; 64 cube->co[aux.cp[i]] = (3 - aux.co[i]) % 3;
196 arr->corl[i] = arr->coud[i];
197 } else {
198 if (arr->cp[i] % 2 == 0) {
199 arr->cofb[i] = (arr->coud[i]+1)%3;
200 arr->corl[i] = (arr->coud[i]+2)%3;
201 } else {
202 arr->cofb[i] = (arr->coud[i]+2)%3;
203 arr->corl[i] = (arr->coud[i]+1)%3;
204 }
205 }
206 } 65 }
207}
208
209Cube
210fourval_to_cube(int eofb, int ep, int coud, int cp)
211{
212 CubeArray *arr;
213
214 arr = new_cubearray((Cube){0}, pf_all);
215 66
216 index_to_perm(ep, 12, arr->ep); 67 for (i = 0; i < 6; i++)
217 index_to_perm(cp, 8, arr->cp); 68 cube->xp[aux.xp[i]] = i;
218 int_to_sum_zero_array(eofb, 2, 12, arr->eofb);
219 int_to_sum_zero_array(coud, 3, 8, arr->coud);
220
221 /* fix parity */
222 if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8))
223 swap(&(arr->ep[0]), &(arr->ep[1]));
224
225 fix_eorleoud(arr);
226 fix_cofbcorl(arr);
227
228 return arrays_to_cube(arr, pf_all);
229}
230
231void
232free_cubearray(CubeArray *arr, PieceFilter f)
233{
234 if (f.epose || f.eposs || f.eposm)
235 free(arr->ep);
236 if (f.eofb)
237 free(arr->eofb);
238 if (f.eorl)
239 free(arr->eorl);
240 if (f.eoud)
241 free(arr->eoud);
242 if (f.cp)
243 free(arr->cp);
244 if (f.coud)
245 free(arr->coud);
246 if (f.corl)
247 free(arr->corl);
248 if (f.cofb)
249 free(arr->cofb);
250 if (f.cpos)
251 free(arr->cpos);
252
253 free(arr);
254}
255
256Cube
257move_via_arrays(CubeArray *arr, Cube c, PieceFilter f)
258{
259 CubeArray *arrc = new_cubearray(c, f);
260 Cube ret;
261
262 if (f.epose || f.eposs || f.eposm)
263 apply_permutation(arr->ep, arrc->ep, 12);
264
265 if (f.eofb) {
266 apply_permutation(arr->ep, arrc->eofb, 12);
267 sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2);
268 }
269
270 if (f.eorl) {
271 apply_permutation(arr->ep, arrc->eorl, 12);
272 sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2);
273 }
274
275 if (f.eoud) {
276 apply_permutation(arr->ep, arrc->eoud, 12);
277 sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2);
278 }
279
280 if (f.cp)
281 apply_permutation(arr->cp, arrc->cp, 8);
282
283 if (f.coud) {
284 apply_permutation(arr->cp, arrc->coud, 8);
285 sum_arrays_mod(arr->coud, arrc->coud, 8, 3);
286 }
287
288 if (f.corl) {
289 apply_permutation(arr->cp, arrc->corl, 8);
290 sum_arrays_mod(arr->corl, arrc->corl, 8, 3);
291 }
292
293 if (f.cofb) {
294 apply_permutation(arr->cp, arrc->cofb, 8);
295 sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3);
296 }
297
298 if (f.cpos)
299 apply_permutation(arr->cpos, arrc->cpos, 6);
300
301 ret = arrays_to_cube(arrc, f);
302 free_cubearray(arrc, f);
303
304 return ret;
305}
306
307CubeArray *
308new_cubearray(Cube cube, PieceFilter f)
309{
310 CubeArray *arr = malloc(sizeof(CubeArray));
311
312 if (f.epose || f.eposs || f.eposm)
313 arr->ep = malloc(12 * sizeof(int));
314 if (f.eofb)
315 arr->eofb = malloc(12 * sizeof(int));
316 if (f.eorl)
317 arr->eorl = malloc(12 * sizeof(int));
318 if (f.eoud)
319 arr->eoud = malloc(12 * sizeof(int));
320 if (f.cp)
321 arr->cp = malloc(8 * sizeof(int));
322 if (f.coud)
323 arr->coud = malloc(8 * sizeof(int));
324 if (f.corl)
325 arr->corl = malloc(8 * sizeof(int));
326 if (f.cofb)
327 arr->cofb = malloc(8 * sizeof(int));
328 if (f.cpos)
329 arr->cpos = malloc(6 * sizeof(int));
330
331 cube_to_arrays(cube, arr, f);
332
333 return arr;
334}
335
336Cube
337admissible_ep(Cube cube, PieceFilter f)
338{
339 CubeArray *arr = new_cubearray(cube, f);
340 Cube ret;
341 bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
342 int i, j;
343
344 for (i = 0; i < 12; i++)
345 if (arr->ep[i] != -1)
346 used[arr->ep[i]] = true;
347
348 for (i = 0, j = 0; i < 12; i++) {
349 for ( ; j < 11 && used[j]; j++);
350 if (arr->ep[i] == -1)
351 arr->ep[i] = j++;
352 }
353
354 ret = arrays_to_cube(arr, pf_ep);
355 free_cubearray(arr, f);
356
357 return ret;
358}
359
360Cube
361compose(Cube c2, Cube c1)
362{
363 return compose_filtered(c2, c1, pf_all);
364}
365
366int
367edge_slice(Edge e) {
368 if (e < 0 || e > 11)
369 return -1;
370
371 if (e == FR || e == FL || e == BL || e == BR)
372 return 0;
373 if (e == UR || e == UL || e == DR || e == DL)
374 return 1;
375
376 return 2;
377}
378
379bool
380equal(Cube c1, Cube c2)
381{
382 return c1.eofb == c2.eofb &&
383 c1.epose == c2.epose &&
384 c1.eposs == c2.eposs &&
385 c1.eposm == c2.eposm &&
386 c1.coud == c2.coud &&
387 c1.cp == c2.cp &&
388 c1.cpos == c2.cpos;
389}
390
391Cube
392inverse_cube(Cube cube)
393{
394 CubeArray inv;
395 Cube ret;
396 int i, ep[12];
397
398 for (i = 0; i < 12; i++)
399 ep[i] = where_is_edge(cube, i);
400 inv = (CubeArray){.ep = ep};
401 ret = arrays_to_cube(&inv, pf_ep);
402
403 ret.eofb = ((int)eo_invtable_e[cube.eofb][cube.epose]) |
404 ((int)eo_invtable_m[cube.eofb][cube.eposm]) |
405 ((int)eo_invtable_s[cube.eofb][cube.eposs]);
406 ret.eorl = ((int)eo_invtable_e[cube.eorl][cube.epose]) |
407 ((int)eo_invtable_m[cube.eorl][cube.eposm]) |
408 ((int)eo_invtable_s[cube.eorl][cube.eposs]);
409 ret.eoud = ((int)eo_invtable_e[cube.eoud][cube.epose]) |
410 ((int)eo_invtable_m[cube.eoud][cube.eposm]) |
411 ((int)eo_invtable_s[cube.eoud][cube.eposs]);
412 ret.cp = cp_invtable[cube.cp];
413 ret.cpos = cpos_invtable[cube.cpos];
414 ret.coud = co_invtable[cube.coud][cube.cp];
415 ret.corl = co_invtable[cube.corl][cube.cp];
416 ret.cofb = co_invtable[cube.cofb][cube.cp];
417
418 return ret;
419} 69}
420 70
421bool 71bool
422is_admissible(Cube cube) { 72is_admissible(Cube *c) {
423
424 /* TODO: this should check consistency of different orientations */
425 /* check also that centers are opposite and admissible */
426
427 CubeArray *a = new_cubearray(cube, pf_all);
428 int parity;
429 bool perm; 73 bool perm;
74 int sign, i;
75 int sum_e, sum_c;
430 76
431 perm = is_perm(a->ep, 12) && 77 perm = is_perm(c->ep, 12) && is_perm(c->cp, 8) && is_perm(c->xp, 6);
432 is_perm(a->cp, 8) &&
433 is_perm(a->cpos, 6);
434 parity = perm_sign(a->ep, 12) +
435 perm_sign(a->cp, 8) +
436 perm_sign(a->cpos, 6);
437
438 free_cubearray(a, pf_all);
439 78
440 return perm && parity % 2 == 0; 79 sign = perm_sign(c->ep,12) + perm_sign(c->cp,8) + perm_sign(c->xp,6);
441}
442
443bool
444is_solved(Cube cube)
445{
446 return equal(cube, (Cube){0});
447}
448
449bool
450is_block_solved(Cube cube, Block block)
451{
452 int i;
453 80
454 for (i = 0; i < 12; i++) 81 for (i = 0, sum_e = 0; i < 12; i++)
455 if (block.edge[i] && !is_solved_edge(cube, i)) 82 if (c->eo[i] > 1)
456 return false;
457 for (i = 0; i < 8; i++)
458 if (block.corner[i] && !is_solved_corner(cube, i))
459 return false;
460 for (i = 0; i < 6; i++)
461 if (block.center[i] && !is_solved_center(cube, i))
462 return false; 83 return false;
84 else
85 sum_e += c->eo[i];
463 86
464 return true; 87 for (i = 0, sum_c = 0; i < 8; i++)
465} 88 if (c->co[i] > 2)
89 return false;
90 else
91 sum_c += c->co[i];
466 92
467bool 93 return (perm && sign % 2 == 0 && sum_e % 2 == 0 && sum_c % 2 == 0);
468is_solved_center(Cube cube, Center c)
469{
470 return what_center_at(cube, c) == c;
471} 94}
472 95
473bool 96bool
474is_solved_corner(Cube cube, Corner c) 97is_solved(Cube *cube)
475{ 98{
476 return what_corner_at(cube, c) == c && 99 Cube solved_cube;
477 what_orientation_corner(cube.coud, c); 100 make_solved(&solved_cube);
478}
479 101
480bool 102 return equal(cube, &solved_cube);
481is_solved_edge(Cube cube, Edge e)
482{
483 return what_edge_at(cube, e) == e &&
484 what_orientation_edge(cube.eofb, e);
485} 103}
486 104
487int 105void
488piece_orientation(Cube cube, int piece, char *orientation) 106make_solved(Cube *cube)
489{ 107{
490 int arr[12], n, b, x; 108 static int sorted[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
491 109
492 if (!strcmp(orientation, "eofb")) { 110 memcpy(cube->ep, sorted, 12 * sizeof(int));
493 x = cube.eofb; 111 memset(cube->eo, 0, 12 * sizeof(int));
494 n = 12; 112 memcpy(cube->cp, sorted, 8 * sizeof(int));
495 b = 2; 113 memset(cube->co, 0, 8 * sizeof(int));
496 } else if (!strcmp(orientation, "eorl")) { 114 memcpy(cube->xp, sorted, 6 * sizeof(int));
497 x = cube.eorl;
498 n = 12;
499 b = 2;
500 } else if (!strcmp(orientation, "eoud")) {
501 x = cube.eoud;
502 n = 12;
503 b = 2;
504 } else if (!strcmp(orientation, "coud")) {
505 x = cube.coud;
506 n = 8;
507 b = 3;
508 } else if (!strcmp(orientation, "corl")) {
509 x = cube.corl;
510 n = 8;
511 b = 3;
512 } else if (!strcmp(orientation, "cofb")) {
513 x = cube.cofb;
514 n = 8;
515 b = 3;
516 } else {
517 return -1;
518 }
519
520 int_to_sum_zero_array(x, b, n, arr);
521 if (piece < n)
522 return arr[piece];
523
524 return -1;
525} 115}
526 116
527void 117void
528print_cube(Cube cube) 118print_cube(Cube *cube)
529{ 119{
530 static char edge_string[12][7] = { 120 static char edge_string[12][7] = {
531 [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", 121 [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR",
@@ -545,388 +135,22 @@ print_cube(Cube cube)
545 }; 135 };
546 136
547 for (int i = 0; i < 12; i++) 137 for (int i = 0; i < 12; i++)
548 printf(" %s ", edge_string[what_edge_at(cube, i)]); 138 printf(" %s ", edge_string[cube->ep[i]]);
549 printf("\n"); 139 printf("\n");
550 140
551 for (int i = 0; i < 12; i++) 141 for (int i = 0; i < 12; i++)
552 printf(" %d ", what_orientation_edge(cube.eofb, i)); 142 printf(" %" PRIu8 " ", cube->eo[i]);
553 printf("\n"); 143 printf("\n");
554 144
555 for (int i = 0; i < 8; i++) 145 for (int i = 0; i < 8; i++)
556 printf("%s ", corner_string[what_corner_at(cube, i)]); 146 printf("%s ", corner_string[cube->cp[i]]);
557 printf("\n"); 147 printf("\n");
558 148
559 for (int i = 0; i < 8; i++) 149 for (int i = 0; i < 8; i++)
560 printf(" %d ", what_orientation_corner(cube.coud, i)); 150 printf(" %" PRIu8 " ", cube->co[i]);
561 printf("\n"); 151 printf("\n");
562 152
563 for (int i = 0; i < 6; i++) 153 for (int i = 0; i < 6; i++)
564 printf(" %s ", center_string[what_center_at(cube, i)]); 154 printf(" %s ", center_string[cube->xp[i]]);
565 printf("\n"); 155 printf("\n");
566} 156}
567
568Center
569what_center_at(Cube cube, Center c)
570{
571 static bool initialized = false;
572 static Center aux[FACTORIAL6][6];
573 static int i;
574 static unsigned int ui;
575 static CubeArray *arr;
576
577 if (!initialized) {
578 for (ui = 0; ui < FACTORIAL6; ui++) {
579 arr = new_cubearray((Cube){.cpos = ui}, pf_cpos);
580 for (i = 0; i < 6; i++)
581 aux[ui][i] = arr->cpos[i];
582 free_cubearray(arr, pf_cpos);
583 }
584
585 initialized = true;
586 }
587
588 return aux[cube.cpos][c];
589}
590
591Corner
592what_corner_at(Cube cube, Corner c)
593{
594 int i;
595 unsigned int ui;
596 CubeArray *arr;
597
598 static bool initialized = false;
599 static Corner aux[FACTORIAL8][8];
600
601 if (!initialized) {
602 for (ui = 0; ui < FACTORIAL8; ui++) {
603 arr = new_cubearray((Cube){.cp = ui}, pf_cp);
604 for (i = 0; i < 8; i++)
605 aux[ui][i] = arr->cp[i];
606 free_cubearray(arr, pf_cp);
607 }
608
609 initialized = true;
610 }
611
612 return aux[cube.cp][c];
613}
614
615Edge
616what_edge_at(Cube cube, Edge e)
617{
618 Edge ret;
619 CubeArray *arr = new_cubearray(cube, pf_ep);
620
621 ret = arr->ep[e];
622
623 free_cubearray(arr, pf_ep);
624 return ret;
625}
626
627int
628what_orientation_corner(int co, Corner c)
629{
630 static bool initialized = false;
631 static int auxlast[POW3TO7];
632 static int auxarr[8];
633 static unsigned int ui;
634
635 if (!initialized) {
636 for (ui = 0; ui < POW3TO7; ui++) {
637 int_to_sum_zero_array(ui, 3, 8, auxarr);
638 auxlast[ui] = auxarr[7];
639 }
640
641 initialized = true;
642 }
643
644 if (c < 7)
645 return (co / powint(3, c)) % 3;
646 else
647 return auxlast[co];
648}
649
650int
651what_orientation_edge(int eo, Edge e)
652{
653 static bool initialized = false;
654 static int auxlast[POW2TO11];
655 static int auxarr[12];
656 static unsigned int ui;
657
658 if (!initialized) {
659 for (ui = 0; ui < POW2TO11; ui++) {
660 int_to_sum_zero_array(ui, 2, 12, auxarr);
661 auxlast[ui] = auxarr[11];
662 }
663
664 initialized = true;
665 }
666
667 if (e < 11)
668 return (eo & (1 << e)) ? 1 : 0;
669 else
670 return auxlast[eo];
671}
672
673Center
674where_is_center(Cube cube, Center c)
675{
676 static bool initialized = false;
677 static Center aux[FACTORIAL6][6];
678 static int i;
679 static unsigned int ui;
680 static CubeArray *arr;
681
682 if (!initialized) {
683 for (ui = 0; ui < FACTORIAL6; ui++) {
684 arr = new_cubearray((Cube){.cpos = ui}, pf_cpos);
685 for (i = 0; i < 6; i++)
686 aux[ui][arr->cpos[i]] = i;
687 free_cubearray(arr, pf_cpos);
688 }
689
690 initialized = true;
691 }
692
693 return aux[cube.cpos][c];
694}
695
696Corner
697where_is_corner(Cube cube, Corner c)
698{
699 static bool initialized = false;
700 static Corner aux[FACTORIAL8][8];
701 static int i;
702 static unsigned int ui;
703 static CubeArray *arr;
704
705 if (!initialized) {
706 for (ui = 0; ui < FACTORIAL8; ui++) {
707 arr = new_cubearray((Cube){.cp = ui}, pf_cp);
708 for (i = 0; i < 8; i++)
709 aux[ui][arr->cp[i]] = i;
710 free_cubearray(arr, pf_cp);
711 }
712
713 initialized = true;
714 }
715 return aux[cube.cp][c];
716}
717
718Edge
719where_is_edge(Cube c, Edge e)
720{
721 int r0, r1, r2;
722
723 static bool initialized = false;
724 static int aux[3][BINOM12ON4*FACTORIAL4][12];
725 static int i, j;
726 static unsigned int ui;
727 static CubeArray *arr;
728
729 if (!initialized) {
730 for (ui = 0; ui < BINOM12ON4*FACTORIAL4; ui++) {
731 for (i = 0; i < 3; i++)
732 for (j = 0; j < 12; j++)
733 aux[i][ui][j] = -1;
734
735 arr = new_cubearray((Cube){.epose = ui}, pf_e);
736 for (i = 0; i < 12; i++)
737 if (edge_slice(arr->ep[i]) == 0)
738 aux[0][ui][arr->ep[i]] = i;
739 free_cubearray(arr, pf_e);
740
741 arr = new_cubearray((Cube){.eposs = ui}, pf_s);
742 for (i = 0; i < 12; i++)
743 if (edge_slice(arr->ep[i]) == 1)
744 aux[1][ui][arr->ep[i]] = i;
745 free_cubearray(arr, pf_s);
746
747 arr = new_cubearray((Cube){.eposm = ui}, pf_m);
748 for (i = 0; i < 12; i++)
749 if (edge_slice(arr->ep[i]) == 2)
750 aux[2][ui][arr->ep[i]] = i;
751 free_cubearray(arr, pf_m);
752 }
753
754 initialized = true;
755 }
756
757 r0 = aux[0][c.epose][e];
758 r1 = aux[1][c.eposs][e];
759 r2 = aux[2][c.eposm][e];
760 return MAX(r0, MAX(r1, r2));
761}
762
763static bool
764read_invtables_file()
765{
766 init_env();
767
768 FILE *f;
769 char fname[strlen(tabledir)+20];
770 int b;
771 unsigned int ui, meeo, meco, mecp, mecpos;
772 bool r;
773
774 strcpy(fname, tabledir);
775 strcat(fname, "/invtables");
776
777 if ((f = fopen(fname, "rb")) == NULL)
778 return false;
779
780 b = sizeof(uint16_t);
781 r = true;
782 meeo = BINOM12ON4*FACTORIAL4;
783 meco = FACTORIAL8;
784 mecp = FACTORIAL8;
785 mecpos = FACTORIAL6;
786
787 for (ui = 0; ui < POW2TO11; ui++) {
788 r = r && fread(eo_invtable_e[ui], b, meeo, f) == meeo;
789 r = r && fread(eo_invtable_m[ui], b, meeo, f) == meeo;
790 r = r && fread(eo_invtable_s[ui], b, meeo, f) == meeo;
791 }
792
793 for (ui = 0; ui < POW3TO7; ui++) {
794 r = r && fread(co_invtable[ui], b, meco, f) == meco;
795 }
796
797 r = r && fread(cp_invtable, b, mecp, f) == mecp;
798 r = r && fread(cpos_invtable, b, mecpos, f) == mecpos;
799
800 fclose(f);
801 return r;
802}
803
804static bool
805write_invtables_file()
806{
807 init_env();
808
809 FILE *f;
810 char fname[strlen(tabledir)+20];
811 unsigned int ui, meeo, meco, mecp, mecpos;
812 int b;
813 bool r;
814
815 strcpy(fname, tabledir);
816 strcat(fname, "/invtables");
817
818 if ((f = fopen(fname, "wb")) == NULL)
819 return false;
820
821 b = sizeof(uint16_t);
822 r = true;
823 meeo = BINOM12ON4*FACTORIAL4;
824 meco = FACTORIAL8;
825 mecp = FACTORIAL8;
826 mecpos = FACTORIAL6;
827
828 for (ui = 0; ui < POW2TO11; ui++) {
829 r = r && fwrite(eo_invtable_e[ui], b, meeo, f) == meeo;
830 r = r && fwrite(eo_invtable_m[ui], b, meeo, f) == meeo;
831 r = r && fwrite(eo_invtable_s[ui], b, meeo, f) == meeo;
832 }
833
834 for (ui = 0; ui < POW3TO7; ui++) {
835 r = r && fwrite(co_invtable[ui], b, meco, f) == meco;
836 }
837
838 r = r && fwrite(cp_invtable, b, mecp, f) == mecp;
839 r = r && fwrite(cpos_invtable, b, mecpos, f) == mecpos;
840
841 fclose(f);
842 return r;
843}
844
845void
846init_inverse()
847{
848 static bool initialized = false;
849 if (initialized)
850 return;
851 initialized = true;
852
853 if (read_invtables_file())
854 return;
855
856 fprintf(stderr, "Cannot load invtables, generating it\n");
857
858 CubeArray *aux, *inv;
859 Cube c;
860 int i, j, eoaux[12], eoinv[12];
861 unsigned int ui, uj;
862
863 aux = new_cubearray((Cube){0}, pf_all);
864 inv = new_cubearray((Cube){0}, pf_all);
865
866 for (ui = 0; ui < POW2TO11; ui++) {
867 int_to_sum_zero_array(ui, 2, 12, eoaux);
868 for (uj = 0; uj < BINOM12ON4*FACTORIAL4; uj++) {
869 for (j = 0; j < 12; j++)
870 eoinv[j] = 0;
871 c = (Cube){.epose = uj, .eposm = 0, .eposs = 0};
872 eoinv[FR] = eoaux[where_is_edge(c, FR)];
873 eoinv[FL] = eoaux[where_is_edge(c, FL)];
874 eoinv[BL] = eoaux[where_is_edge(c, BL)];
875 eoinv[BR] = eoaux[where_is_edge(c, BR)];
876 eo_invtable_e[ui][uj] = digit_array_to_int(eoinv,11,2);
877
878 for (j = 0; j < 12; j++)
879 eoinv[j] = 0;
880 c = (Cube){.epose = 0, .eposm = uj, .eposs = 0};
881 eoinv[UF] = eoaux[where_is_edge(c, UF)];
882 eoinv[UB] = eoaux[where_is_edge(c, UB)];
883 eoinv[DF] = eoaux[where_is_edge(c, DF)];
884 eoinv[DB] = eoaux[where_is_edge(c, DB)];
885 eo_invtable_m[ui][uj] = digit_array_to_int(eoinv,11,2);
886
887 for (j = 0; j < 12; j++)
888 eoinv[j] = 0;
889 c = (Cube){.epose = 0, .eposm = 0, .eposs = uj};
890 eoinv[UL] = eoaux[where_is_edge(c, UL)];
891 eoinv[UR] = eoaux[where_is_edge(c, UR)];
892 eoinv[DL] = eoaux[where_is_edge(c, DL)];
893 eoinv[DR] = eoaux[where_is_edge(c, DR)];
894 eo_invtable_s[ui][uj] = digit_array_to_int(eoinv,11,2);
895 }
896 }
897
898 for (ui = 0; ui < FACTORIAL8; ui++) {
899 cube_to_arrays((Cube){.cp = ui}, aux, pf_cp);
900 for (i = 0; i < 8; i++)
901 inv->cp[aux->cp[i]] = i;
902 cp_invtable[ui] = (uint16_t)arrays_to_cube(inv, pf_cp).cp;
903
904 for (uj = 0; uj < POW3TO7; uj++) {
905 cube_to_arrays((Cube){.coud = uj}, aux, pf_coud);
906 for (i = 0; i < 8; i++)
907 inv->coud[aux->cp[i]] = (3-aux->coud[i])%3;
908 co_invtable[uj][ui] =
909 (uint16_t)arrays_to_cube(inv, pf_coud).coud;
910 }
911 }
912
913 for (ui = 0; ui < FACTORIAL6; ui++) {
914 cube_to_arrays((Cube){.cpos = ui}, aux, pf_cpos);
915 for (i = 0; i < 6; i++)
916 inv->cpos[aux->cpos[i]] = i;
917 cpos_invtable[ui] =
918 (uint16_t)arrays_to_cube(inv, pf_cpos).cpos;
919 }
920
921 free_cubearray(aux, pf_all);
922 free_cubearray(inv, pf_all);
923
924 if (!write_invtables_file())
925 fprintf(stderr, "Error writing invtables\n");
926}
927
928void
929init_cube()
930{
931 init_inverse();
932}
diff --git a/src/cube.h b/src/cube.h
index 483a89a..9f8b23d 100644
--- a/src/cube.h
+++ b/src/cube.h
@@ -3,44 +3,18 @@
3 3
4#include <stdio.h> 4#include <stdio.h>
5 5
6#include "cubetypes.h"
6#include "env.h" 7#include "env.h"
7#include "pf.h"
8#include "utils.h" 8#include "utils.h"
9 9
10Cube admissible_ep(Cube cube, PieceFilter f); 10void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */
11int array_ep_to_epos(int *ep, int *eps_solved); 11void copy_cube(Cube *src, Cube *dst);
12Cube arrays_to_cube(CubeArray *arr, PieceFilter f); 12bool equal(Cube *c1, Cube *c2);
13Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ 13void invert_cube(Cube *cube);
14Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); 14bool is_admissible(Cube *cube);
15void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); 15bool is_solved(Cube *cube);
16int edge_slice(Edge e); /* E=0, S=1, M=2 */ 16void make_solved(Cube *cube);
17bool equal(Cube c1, Cube c2); 17void print_cube(Cube *cube);
18Cube inverse_cube(Cube cube);
19bool is_admissible(Cube cube);
20bool is_solved(Cube cube);
21bool is_block_solved(Cube cube, Block);
22bool is_solved_center(Cube cube, Center c);
23bool is_solved_corner(Cube cube, Corner c);
24bool is_solved_edge(Cube cube, Edge e);
25void epos_to_partial_ep(int epos, int *ep, int *ss);
26void epos_to_compatible_ep(int epos, int *ep, int *ss);
27void fix_eorleoud(CubeArray *arr);
28void fix_cofbcorl(CubeArray *arr);
29Cube fourval_to_cube(int eofb, int ep, int coud, int cp);
30void free_cubearray(CubeArray *arr, PieceFilter f);
31Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf);
32CubeArray * new_cubearray(Cube cube, PieceFilter f);
33void print_cube(Cube cube);
34Center what_center_at(Cube cube, Center c);
35Corner what_corner_at(Cube cube, Corner c);
36Edge what_edge_at(Cube cube, Edge e);
37int what_orientation_corner(int co, Corner c);
38int what_orientation_edge(int eo, Edge e);
39Center where_is_center(Cube cube, Center c);
40Corner where_is_corner(Cube cube, Corner c);
41Edge where_is_edge(Cube cube, Edge e);
42
43void init_cube();
44 18
45#endif 19#endif
46 20
diff --git a/src/cubetypes.h b/src/cubetypes.h
index ad9c627..cf6b7d5 100644
--- a/src/cubetypes.h
+++ b/src/cubetypes.h
@@ -10,6 +10,8 @@
10#define NROTATIONS 24 10#define NROTATIONS 24
11#define entry_group_t uint8_t /* For pruning tables */ 11#define entry_group_t uint8_t /* For pruning tables */
12 12
13#define MAX_N_COORD 6
14
13/* Enums *********************************************************************/ 15/* Enums *********************************************************************/
14 16
15typedef enum 17typedef enum
@@ -28,6 +30,12 @@ corner
28} Corner; 30} Corner;
29 31
30typedef enum 32typedef enum
33coordtype
34{
35 COMP_COORD, SYM_COORD, SYMCOMP_COORD
36} CoordType;
37
38typedef enum
31edge 39edge
32{ 40{
33 UF, UL, UB, UR, 41 UF, UL, UB, UR,
@@ -81,28 +89,24 @@ typedef struct command Command;
81typedef struct commandargs CommandArgs; 89typedef struct commandargs CommandArgs;
82typedef struct coordinate Coordinate; 90typedef struct coordinate Coordinate;
83typedef struct cube Cube; 91typedef struct cube Cube;
84typedef struct cubearray CubeArray;
85typedef struct dfsarg DfsArg; 92typedef struct dfsarg DfsArg;
86typedef struct estimatedata EstimateData; 93typedef struct indexer Indexer;
94typedef struct movable Movable;
87typedef struct moveset Moveset; 95typedef struct moveset Moveset;
88typedef struct piecefilter PieceFilter; 96typedef struct pdgendata PDGenData;
89typedef struct prunedata PruneData; 97typedef struct prunedata PruneData;
90typedef struct solveoptions SolveOptions; 98typedef struct solveoptions SolveOptions;
91typedef struct step Step; 99typedef struct step Step;
100typedef struct stepalt StepAlt;
92typedef struct symdata SymData; 101typedef struct symdata SymData;
93typedef struct threaddatasolve ThreadDataSolve; 102typedef struct threaddatasolve ThreadDataSolve;
94typedef struct threaddatagenpt ThreadDataGenpt; 103typedef struct threaddatagenpt ThreadDataGenpt;
104typedef struct transgroup TransGroup;
95 105
96typedef Cube (*AntiIndexer) (uint64_t); 106typedef bool (*Checker) (Cube *);
97typedef bool (*Checker) (Cube);
98typedef uint64_t (*CoordMover) (Move, uint64_t);
99typedef uint64_t (*CoordTransformer) (Trans, uint64_t);
100typedef int (*Estimator) (DfsArg *);
101typedef bool (*Validator) (Alg *); 107typedef bool (*Validator) (Alg *);
102typedef void (*Exec) (CommandArgs *); 108typedef void (*Exec) (CommandArgs *);
103typedef uint64_t (*Indexer) (Cube);
104typedef CommandArgs * (*ArgParser) (int, char **); 109typedef CommandArgs * (*ArgParser) (int, char **);
105typedef int (*TransDetector) (Cube, Trans *);
106typedef int (*TransFinder) (uint64_t, Trans *); 110typedef int (*TransFinder) (uint64_t, Trans *);
107 111
108 112
@@ -167,83 +171,69 @@ commandargs
167struct 171struct
168coordinate 172coordinate
169{ 173{
170 Indexer index; 174 char * name;
175 CoordType type;
176 bool generated;
177 Indexer * i[99];
171 uint64_t max; 178 uint64_t max;
172 CoordMover move; 179 uint64_t * mtable[NMOVES];
173 CoordTransformer transform; 180 uint64_t * ttable[NTRANS];
174 SymData * sd; 181 TransGroup * tgrp;
175 TransFinder tfind; /* TODO: should be easy to remove */ 182 Coordinate * base[2];
176 Coordinate * base; /* TODO: part of refactor */ 183 uint64_t * symclass;
184 uint64_t * symrep;
185 Trans * transtorep;
186 Trans * ttrep_move[NMOVES];
187 uint64_t * selfsim;
177}; 188};
178 189
179struct 190struct
180cube 191cube
181{ 192{
182 int epose; 193 int ep[12];
183 int eposs; 194 int eo[12];
184 int eposm; 195 int cp[8];
185 int eofb; 196 int co[8];
186 int eorl; 197 int xp[6];
187 int eoud;
188 int cp;
189 int coud;
190 int cofb;
191 int corl;
192 int cpos;
193}; 198};
194 199
195struct 200struct
196cubearray 201movable
197{ 202{
198 int * ep; 203 uint64_t val;
199 int * eofb; 204 Trans t;
200 int * eorl;
201 int * eoud;
202 int * cp;
203 int * coud;
204 int * corl;
205 int * cofb;
206 int * cpos;
207}; 205};
208 206
209struct 207struct
210dfsarg 208dfsarg
211{ 209{
212 Step * step; 210 Cube * cube;
213 SolveOptions * opts; 211 Movable ind[MAX_N_COORD];
214 Trans t; 212 Trans t;
215 Cube cube; 213 StepAlt * sa;
216 Cube inverse; 214 SolveOptions * opts;
217 int d; 215 int d;
218 uint64_t badmoves; 216 int bound;
219 uint64_t badmovesinv;
220 bool niss; 217 bool niss;
221 Move last1; 218 Move last[2];
222 Move last2; 219 Move lastinv[2];
223 Move last1inv;
224 Move last2inv;
225 EstimateData * ed;
226 AlgList * sols; 220 AlgList * sols;
227 pthread_mutex_t * sols_mutex; 221 pthread_mutex_t * sols_mutex;
228 Alg * current_alg; 222 Alg * current_alg;
229}; 223};
230 224
231struct 225struct
232estimatedata 226indexer
233{ 227{
234 int corners; 228 int n;
235 int normal_ud; 229 uint64_t (*index)(Cube *);
236 int normal_fb; 230 void (*to_cube)(uint64_t, Cube *);
237 int normal_rl;
238 int inverse_ud;
239 int inverse_fb;
240 int inverse_rl;
241 int oldret;
242}; 231};
243 232
244struct 233struct
245moveset 234moveset
246{ 235{
236 char * name;
247 bool (*allowed)(Move); 237 bool (*allowed)(Move);
248 bool (*allowed_next)(Move, Move, Move); 238 bool (*allowed_next)(Move, Move, Move);
249 Move sorted_moves[NMOVES+1]; 239 Move sorted_moves[NMOVES+1];
@@ -251,34 +241,24 @@ moveset
251}; 241};
252 242
253struct 243struct
254piecefilter 244pdgendata
255{ 245{
256 bool epose; 246 Coordinate * coord;
257 bool eposs; 247 Moveset * moveset;
258 bool eposm; 248 bool compact;
259 bool eofb; 249 PruneData * pd;
260 bool eorl;
261 bool eoud;
262 bool cp;
263 bool coud;
264 bool cofb;
265 bool corl;
266 bool cpos;
267}; 250};
268 251
269struct 252struct
270prunedata 253prunedata
271{ 254{
272 char * filename;
273 entry_group_t * ptable; 255 entry_group_t * ptable;
274 bool generated;
275 uint64_t n; 256 uint64_t n;
276 Coordinate * coord; 257 Coordinate * coord;
277 Moveset * moveset; 258 Moveset * moveset;
278 bool compact; 259 bool compact;
279 int base; 260 int base;
280 uint64_t count[16]; 261 uint64_t count[16];
281 PruneData * fallback;
282 uint64_t fbmod; 262 uint64_t fbmod;
283}; 263};
284 264
@@ -302,19 +282,35 @@ step
302{ 282{
303 char * shortname; 283 char * shortname;
304 char * name; 284 char * name;
305 bool final; 285 StepAlt * alt[99];
306 Checker is_done; 286 Trans t[99];
307 Estimator estimate;
308 Checker ready;
309 char * ready_msg; 287 char * ready_msg;
310 Validator is_valid; 288};
289
290struct
291stepalt
292{
293 Checker ready;
294 bool final;
311 Moveset * moveset; 295 Moveset * moveset;
312 Trans pre_trans; 296 /* Just a comment, (TODO: remove this): moveset is really a stepalt
313 TransDetector detect; 297 * property, because for example we may want to define a "fingertrick
314 int ntables; 298 * friendly ZBLL" step, where we allow either <R U D> or <R U F> as
315 PruneData * tables[10]; 299 * movesets (or similar) */
300 int n_coord;
301 Coordinate * coord[MAX_N_COORD];
302 Trans coord_trans[MAX_N_COORD];
303 PruneData * pd[MAX_N_COORD];
304 bool compact_pd[MAX_N_COORD];
305 Coordinate * fallback_coord[MAX_N_COORD];
306 PruneData * fallback_pd[MAX_N_COORD];
307 uint64_t fbmod[MAX_N_COORD];
308 int n_dbtrick;
309 int dbtrick[MAX_N_COORD][3];
310 Validator is_valid;
316}; 311};
317 312
313/*
318struct 314struct
319symdata 315symdata
320{ 316{
@@ -328,23 +324,18 @@ symdata
328 uint64_t * unsym; 324 uint64_t * unsym;
329 Trans * transtorep; 325 Trans * transtorep;
330 uint64_t * selfsim; 326 uint64_t * selfsim;
331 CoordTransformer transform; /* TODO: remove, use that of base coord */
332}; 327};
328*/
329
333 330
334struct 331struct
335threaddatasolve 332threaddatasolve
336{ 333{
334 DfsArg arg;
337 int thid; 335 int thid;
338 Trans t;
339 Cube cube;
340 Step * step;
341 int depth;
342 SolveOptions * opts;
343 AlgList * start; 336 AlgList * start;
344 AlgListNode ** node; 337 AlgListNode ** node;
345 AlgList * sols;
346 pthread_mutex_t * start_mutex; 338 pthread_mutex_t * start_mutex;
347 pthread_mutex_t * sols_mutex;
348}; 339};
349 340
350struct 341struct
@@ -359,4 +350,11 @@ threaddatagenpt
359 pthread_mutex_t * upmutex; 350 pthread_mutex_t * upmutex;
360}; 351};
361 352
353struct
354transgroup
355{
356 int n;
357 Trans t[NTRANS];
358};
359
362#endif 360#endif
diff --git a/src/env.c b/src/env.c
index 282bc8f..375bfa8 100644
--- a/src/env.c
+++ b/src/env.c
@@ -1,3 +1,5 @@
1#define ENV_C
2
1#include "env.h" 3#include "env.h"
2 4
3bool initialized_env = false; 5bool initialized_env = false;
diff --git a/src/env.h b/src/env.h
index 871a9c1..a49d643 100644
--- a/src/env.h
+++ b/src/env.h
@@ -8,8 +8,8 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10 10
11extern char *tabledir;
12
13void init_env(); 11void init_env();
14 12
13extern char *tabledir;
14
15#endif 15#endif
diff --git a/src/moves.c b/src/moves.c
index 02880ca..51012db 100644
--- a/src/moves.c
+++ b/src/moves.c
@@ -1,79 +1,18 @@
1#define MOVES_C
2
1#include "moves.h" 3#include "moves.h"
2 4
3/* Local functions ***********************************************************/ 5/* Local functions ***********************************************************/
4 6
5static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f);
6static void cleanup_aux(Alg *alg, Alg *ret, bool inv); 7static void cleanup_aux(Alg *alg, Alg *ret, bool inv);
7static bool read_mtables_file();
8static bool write_mtables_file();
9 8
10/* Tables and other data *****************************************************/ 9/* Tables and other data *****************************************************/
11 10
12/* Every move is translated to a an <U, x, y> alg before filling the 11/* Moves are represented as cubes and applied using compose(). Every move is *
13 transition tables, see init_moves() */ 12 * translated to a an <U, x, y> alg before filling the transition tables. *
14 13 * See init_moves(). */
15static int edge_cycle[NMOVES][12] =
16{
17 [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR },
18 [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR },
19 [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL }
20};
21
22static int corner_cycle[NMOVES][8] =
23{
24 [U] = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR },
25 [x] = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR },
26 [y] = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL }
27};
28
29static int center_cycle[NMOVES][6] =
30{
31 [x] = { F_center, B_center, R_center, L_center, D_center, U_center },
32 [y] = { U_center, D_center, B_center, F_center, R_center, L_center }
33};
34
35static int eofb_flipped[NMOVES][12] = {
36 [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 },
37 [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }
38};
39 14
40static int eorl_flipped[NMOVES][12] = { 15static Cube move_array[NMOVES];
41 [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
42 [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }
43};
44
45static int eoud_flipped[NMOVES][12] = {
46 [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 },
47 [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 },
48 [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
49};
50
51static int coud_flipped[NMOVES][8] = {
52 [x] = {
53 [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2,
54 [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2
55 }
56};
57
58static int corl_flipped[NMOVES][8] = {
59 [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 },
60 [y] = {
61 [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2,
62 [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1
63 }
64};
65
66static int cofb_flipped[NMOVES][8] = {
67 [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 },
68 [x] = {
69 [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2,
70 [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1
71 },
72 [y] = {
73 [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1,
74 [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2
75 }
76};
77 16
78static char equiv_alg_string[100][NMOVES] = { 17static char equiv_alg_string[100][NMOVES] = {
79 [NULLMOVE] = "", 18 [NULLMOVE] = "",
@@ -137,89 +76,34 @@ static char equiv_alg_string[100][NMOVES] = {
137 [z3] = " y x yyy " 76 [z3] = " y x yyy "
138}; 77};
139 78
140/* Transition tables, to be loaded up at the beginning */
141int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
142int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
143int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
144int eofb_mtable[NMOVES][POW2TO11];
145int eorl_mtable[NMOVES][POW2TO11];
146int eoud_mtable[NMOVES][POW2TO11];
147int cp_mtable[NMOVES][FACTORIAL8];
148int coud_mtable[NMOVES][POW3TO7];
149int cofb_mtable[NMOVES][POW3TO7];
150int corl_mtable[NMOVES][POW3TO7];
151int cpos_mtable[NMOVES][FACTORIAL6];
152
153
154/* Local functions implementation ********************************************/
155
156static Cube
157apply_move_cubearray(Move m, Cube cube, PieceFilter f)
158{
159 /*init_moves();*/
160
161 CubeArray m_arr = {
162 edge_cycle[m],
163 eofb_flipped[m],
164 eorl_flipped[m],
165 eoud_flipped[m],
166 corner_cycle[m],
167 coud_flipped[m],
168 corl_flipped[m],
169 cofb_flipped[m],
170 center_cycle[m]
171 };
172
173 return move_via_arrays(&m_arr, cube, f);
174}
175 79
176/* Public functions **********************************************************/ 80/* Public functions **********************************************************/
177 81
178Cube 82void
179apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) 83apply_alg(Alg *alg, Cube *cube)
180{ 84{
181 Cube ret = {0}; 85 Cube aux;
182 int i; 86 int i;
183 87
88 copy_cube(cube, &aux);
89 make_solved(cube);
90
184 for (i = 0; i < alg->len; i++) 91 for (i = 0; i < alg->len; i++)
185 if (alg->inv[i]) 92 if (alg->inv[i])
186 ret = a ? apply_move(alg->move[i], ret) : 93 apply_move(alg->move[i], cube);
187 apply_move_cubearray(alg->move[i], ret, f);
188 94
189 ret = compose_filtered(c, inverse_cube(ret), f); 95 invert_cube(cube);
96 compose(&aux, cube);
190 97
191 for (i = 0; i < alg->len; i++) 98 for (i = 0; i < alg->len; i++)
192 if (!alg->inv[i]) 99 if (!alg->inv[i])
193 ret = a ? apply_move(alg->move[i], ret) : 100 apply_move(alg->move[i], cube);
194 apply_move_cubearray(alg->move[i], ret, f);
195
196 return ret;
197} 101}
198 102
199Cube 103void
200apply_alg(Alg *alg, Cube cube) 104apply_move(Move m, Cube *cube)
201{ 105{
202 return apply_alg_generic(alg, cube, pf_all, true); 106 compose(&move_array[m], cube);
203}
204
205Cube
206apply_move(Move m, Cube cube)
207{
208 /*init_moves();*/
209
210 return (Cube) {
211 .epose = epose_mtable[m][cube.epose],
212 .eposs = eposs_mtable[m][cube.eposs],
213 .eposm = eposm_mtable[m][cube.eposm],
214 .eofb = eofb_mtable[m][cube.eofb],
215 .eorl = eorl_mtable[m][cube.eorl],
216 .eoud = eoud_mtable[m][cube.eoud],
217 .coud = coud_mtable[m][cube.coud],
218 .cofb = cofb_mtable[m][cube.cofb],
219 .corl = corl_mtable[m][cube.corl],
220 .cp = cp_mtable[m][cube.cp],
221 .cpos = cpos_mtable[m][cube.cpos]
222 };
223} 107}
224 108
225Alg * 109Alg *
@@ -279,31 +163,27 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv)
279{ 163{
280 int i, j; 164 int i, j;
281 Cube c, d; 165 Cube c, d;
282 Move m, mm; 166 Move m;
283 Alg *equiv_alg; 167 Alg *equiv_alg;
284 168
285 c = (Cube){0}; 169 make_solved(&c);
286 for (i = 0; i < alg->len; i++) { 170 for (i = 0; i < alg->len; i++) {
287 if (alg->inv[i] != inv) 171 if (alg->inv[i] != inv)
288 continue; 172 continue;
289 173
290 equiv_alg = new_alg(equiv_alg_string[alg->move[i]]); 174 equiv_alg = new_alg(equiv_alg_string[alg->move[i]]);
291 175
292 for (j = 0; j < equiv_alg->len; j++) { 176 for (j = 0; j < equiv_alg->len; j++)
293 m = equiv_alg->move[j]; 177 if (equiv_alg->move[j] == U)
294 if (m == U) { 178 append_move(ret, 3 * c.xp[U_center] + 1, inv);
295 mm = 3*what_center_at(c, U_center) + 1; 179 else
296 append_move(ret, mm, inv); 180 apply_move(equiv_alg->move[j], &c);
297 } else {
298 c = apply_move(m, c);
299 }
300 }
301 181
302 free_alg(equiv_alg); 182 free_alg(equiv_alg);
303 } 183 }
304 184
305 m = NULLMOVE; 185 m = NULLMOVE;
306 switch (what_center_at(c, F_center)) { 186 switch (c.xp[F_center]) {
307 case U_center: 187 case U_center:
308 m = x3; 188 m = x3;
309 break; 189 break;
@@ -317,7 +197,7 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv)
317 m = y3; 197 m = y3;
318 break; 198 break;
319 case B_center: 199 case B_center:
320 if (what_center_at(c, U_center) == U_center) 200 if (c.xp[U_center] == U_center)
321 m = y2; 201 m = y2;
322 else 202 else
323 m = x2; 203 m = x2;
@@ -325,120 +205,24 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv)
325 default: 205 default:
326 break; 206 break;
327 } 207 }
328 d = apply_move(m, (Cube){0}); 208
209 make_solved(&d);
210 apply_move(m, &d);
329 if (m != NULLMOVE) 211 if (m != NULLMOVE)
330 append_move(ret, m, inv); 212 append_move(ret, m, inv);
331 213
332 m = NULLMOVE; 214 m = NULLMOVE;
333 if (what_center_at(c, U_center) == what_center_at(d, D_center)) { 215 if (c.xp[U_center] == d.xp[D_center]) {
334 m = z2; 216 m = z2;
335 } else if (what_center_at(c, U_center) == what_center_at(d, R_center)) { 217 } else if (c.xp[U_center] == d.xp[R_center]) {
336 m = z3; 218 m = z3;
337 } else if (what_center_at(c, U_center) == what_center_at(d, L_center)) { 219 } else if (c.xp[U_center] == d.xp[L_center]) {
338 m = z; 220 m = z;
339 } 221 }
340 if (m != NULLMOVE) 222 if (m != NULLMOVE)
341 append_move(ret, m, inv); 223 append_move(ret, m, inv);
342} 224}
343 225
344static bool
345read_mtables_file()
346{
347 init_env();
348
349 FILE *f;
350 char fname[strlen(tabledir)+20];
351 int m, b = sizeof(int);
352 bool r = true;
353
354 /* Table sizes, used for reading and writing files */
355 uint64_t me[11] = {
356 [0] = FACTORIAL12/FACTORIAL8,
357 [1] = FACTORIAL12/FACTORIAL8,
358 [2] = FACTORIAL12/FACTORIAL8,
359 [3] = POW2TO11,
360 [4] = POW2TO11,
361 [5] = POW2TO11,
362 [6] = FACTORIAL8,
363 [7] = POW3TO7,
364 [8] = POW3TO7,
365 [9] = POW3TO7,
366 [10] = FACTORIAL6
367 };
368
369 strcpy(fname, tabledir);
370 strcat(fname, "/mtables");
371
372 if ((f = fopen(fname, "rb")) == NULL)
373 return false;
374
375 for (m = 0; m < NMOVES; m++) {
376 r = r && fread(epose_mtable[m], b, me[0], f) == me[0];
377 r = r && fread(eposs_mtable[m], b, me[1], f) == me[1];
378 r = r && fread(eposm_mtable[m], b, me[2], f) == me[2];
379 r = r && fread(eofb_mtable[m], b, me[3], f) == me[3];
380 r = r && fread(eorl_mtable[m], b, me[4], f) == me[4];
381 r = r && fread(eoud_mtable[m], b, me[5], f) == me[5];
382 r = r && fread(cp_mtable[m], b, me[6], f) == me[6];
383 r = r && fread(coud_mtable[m], b, me[7], f) == me[7];
384 r = r && fread(corl_mtable[m], b, me[8], f) == me[8];
385 r = r && fread(cofb_mtable[m], b, me[9], f) == me[9];
386 r = r && fread(cpos_mtable[m], b, me[10], f) == me[10];
387 }
388
389 fclose(f);
390 return r;
391}
392
393static bool
394write_mtables_file()
395{
396 init_env();
397
398 FILE *f;
399 char fname[strlen(tabledir)+20];
400 int m, b = sizeof(int);
401 bool r = true;
402
403 /* Table sizes, used for reading and writing files */
404 uint64_t me[11] = {
405 [0] = FACTORIAL12/FACTORIAL8,
406 [1] = FACTORIAL12/FACTORIAL8,
407 [2] = FACTORIAL12/FACTORIAL8,
408 [3] = POW2TO11,
409 [4] = POW2TO11,
410 [5] = POW2TO11,
411 [6] = FACTORIAL8,
412 [7] = POW3TO7,
413 [8] = POW3TO7,
414 [9] = POW3TO7,
415 [10] = FACTORIAL6
416 };
417
418 strcpy(fname, tabledir);
419 strcat(fname, "/mtables");
420
421 if ((f = fopen(fname, "wb")) == NULL)
422 return false;
423
424 for (m = 0; m < NMOVES; m++) {
425 r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0];
426 r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1];
427 r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2];
428 r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3];
429 r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4];
430 r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5];
431 r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6];
432 r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7];
433 r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8];
434 r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9];
435 r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10];
436 }
437
438 fclose(f);
439 return r;
440}
441
442void 226void
443init_moves() { 227init_moves() {
444 static bool initialized = false; 228 static bool initialized = false;
@@ -446,101 +230,54 @@ init_moves() {
446 return; 230 return;
447 initialized = true; 231 initialized = true;
448 232
449 Cube c;
450 CubeArray arrs;
451 int i;
452 unsigned int ui;
453 Move m; 233 Move m;
454 Alg *equiv_alg[NMOVES]; 234 Alg *equiv_alg[NMOVES];
455 235
456 init_cube(); 236 static const Cube mcu = {
457 237 .ep = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR },
458 for (i = 0; i < NMOVES; i++) 238 .cp = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR },
459 equiv_alg[i] = new_alg(equiv_alg_string[i]); 239 };
460 240 static const Cube mcx = {
461 /* Generate all move cycles and flips; I do this regardless */ 241 .ep = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR },
462 for (i = 0; i < NMOVES; i++) { 242 .eo = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 },
463 if (i == U || i == x || i == y) 243 .cp = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR },
464 continue; 244 .co = { [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2,
465 245 [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 },
466 c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); 246 .xp = { F_center, B_center, R_center,
467 247 L_center, D_center, U_center },
468 arrs = (CubeArray) { 248 };
469 edge_cycle[i], 249 static const Cube mcy = {
470 eofb_flipped[i], 250 .ep = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL },
471 eorl_flipped[i], 251 .eo = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 },
472 eoud_flipped[i], 252 .cp = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL },
473 corner_cycle[i], 253 .xp = { U_center, D_center, B_center,
474 coud_flipped[i], 254 F_center, R_center, L_center },
475 corl_flipped[i], 255 };
476 cofb_flipped[i],
477 center_cycle[i]
478 };
479 cube_to_arrays(c, &arrs, pf_all);
480 }
481 256
482 if (read_mtables_file()) 257 move_array[U] = mcu;
483 return; 258 move_array[x] = mcx;
259 move_array[y] = mcy;
484 260
485 fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); 261 for (m = 0; m < NMOVES; m++)
262 equiv_alg[m] = new_alg(equiv_alg_string[m]);
486 263
487 /* Initialize transition tables */
488 for (m = 0; m < NMOVES; m++) { 264 for (m = 0; m < NMOVES; m++) {
489 for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { 265 switch (m) {
490 c = (Cube){ .epose = ui }; 266 case NULLMOVE:
491 c = apply_move_cubearray(m, c, pf_e); 267 make_solved(&move_array[m]);
492 epose_mtable[m][ui] = c.epose; 268 break;
493 269 case U:
494 c = (Cube){ .eposs = ui }; 270 case x:
495 c = apply_move_cubearray(m, c, pf_s); 271 case y:
496 eposs_mtable[m][ui] = c.eposs; 272 break;
497 273 default:
498 c = (Cube){ .eposm = ui }; 274 make_solved(&move_array[m]);
499 c = apply_move_cubearray(m, c, pf_m); 275 apply_alg(equiv_alg[m], &move_array[m]);
500 eposm_mtable[m][ui] = c.eposm; 276 break;
501 }
502 for (ui = 0; ui < POW2TO11; ui++ ) {
503 c = (Cube){ .eofb = ui };
504 c = apply_move_cubearray(m, c, pf_eo);
505 eofb_mtable[m][ui] = c.eofb;
506
507 c = (Cube){ .eorl = ui };
508 c = apply_move_cubearray(m, c, pf_eo);
509 eorl_mtable[m][ui] = c.eorl;
510
511 c = (Cube){ .eoud = ui };
512 c = apply_move_cubearray(m, c, pf_eo);
513 eoud_mtable[m][ui] = c.eoud;
514 }
515 for (ui = 0; ui < POW3TO7; ui++) {
516 c = (Cube){ .coud = ui };
517 c = apply_move_cubearray(m, c, pf_co);
518 coud_mtable[m][ui] = c.coud;
519
520 c = (Cube){ .corl = ui };
521 c = apply_move_cubearray(m, c, pf_co);
522 corl_mtable[m][ui] = c.corl;
523
524 c = (Cube){ .cofb = ui };
525 c = apply_move_cubearray(m, c, pf_co);
526 cofb_mtable[m][ui] = c.cofb;
527 }
528 for (ui = 0; ui < FACTORIAL8; ui++) {
529 c = (Cube){ .cp = ui };
530 c = apply_move_cubearray(m, c, pf_cp);
531 cp_mtable[m][ui] = c.cp;
532 }
533 for (ui = 0; ui < FACTORIAL6; ui++) {
534 c = (Cube){ .cpos = ui };
535 c = apply_move_cubearray(m, c, pf_cpos);
536 cpos_mtable[m][ui] = c.cpos;
537 } 277 }
538 } 278 }
539 279
540 if (!write_mtables_file()) 280 for (m = 0; m < NMOVES; m++)
541 fprintf(stderr, "Error writing mtables\n"); 281 free_alg(equiv_alg[m]);
542
543 for (i = 0; i < NMOVES; i++)
544 free_alg(equiv_alg[i]);
545} 282}
546 283
diff --git a/src/moves.h b/src/moves.h
index 14ae087..4afe8fb 100644
--- a/src/moves.h
+++ b/src/moves.h
@@ -5,24 +5,8 @@
5#include "cube.h" 5#include "cube.h"
6#include "env.h" 6#include "env.h"
7 7
8/* 8void apply_alg(Alg *alg, Cube *cube);
9 * Tables are exposed to allow for faster moves in some cases. 9void apply_move(Move m, Cube *cube);
10 */
11extern int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
12extern int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
13extern int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8];
14extern int eofb_mtable[NMOVES][POW2TO11];
15extern int eorl_mtable[NMOVES][POW2TO11];
16extern int eoud_mtable[NMOVES][POW2TO11];
17extern int cp_mtable[NMOVES][FACTORIAL8];
18extern int coud_mtable[NMOVES][POW3TO7];
19extern int cofb_mtable[NMOVES][POW3TO7];
20extern int corl_mtable[NMOVES][POW3TO7];
21extern int cpos_mtable[NMOVES][FACTORIAL6];
22
23Cube apply_alg(Alg *alg, Cube cube);
24Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a);
25Cube apply_move(Move m, Cube cube);
26Alg * cleanup(Alg *alg); 10Alg * cleanup(Alg *alg);
27 11
28void init_moves(); 12void init_moves();
diff --git a/src/pf.c b/src/pf.c
deleted file mode 100644
index 7d86e4e..0000000
--- a/src/pf.c
+++ /dev/null
@@ -1,95 +0,0 @@
1#include "pf.h"
2
3PieceFilter
4pf_all = {
5 .epose = true,
6 .eposs = true,
7 .eposm = true,
8 .eofb = true,
9 .eorl = true,
10 .eoud = true,
11 .cp = true,
12 .cofb = true,
13 .corl = true,
14 .coud = true,
15 .cpos = true
16};
17
18PieceFilter
19pf_4val = {
20 .epose = true,
21 .eposs = true,
22 .eposm = true,
23 .eofb = true,
24 .coud = true,
25 .cp = true
26};
27
28PieceFilter
29pf_epcp = {
30 .epose = true,
31 .eposs = true,
32 .eposm = true,
33 .cp = true
34};
35
36PieceFilter
37pf_cpos = {
38 .cpos = true
39};
40
41PieceFilter
42pf_cp = {
43 .cp = true
44};
45
46PieceFilter
47pf_ep = {
48 .epose = true,
49 .eposs = true,
50 .eposm = true
51};
52
53PieceFilter
54pf_e = {
55 .epose = true
56};
57
58PieceFilter
59pf_s = {
60 .eposs = true
61};
62
63PieceFilter
64pf_m = {
65 .eposm = true
66};
67
68PieceFilter
69pf_eo = {
70 .eofb = true,
71 .eorl = true,
72 .eoud = true
73};
74
75PieceFilter
76pf_co = {
77 .cofb = true,
78 .corl = true,
79 .coud = true
80};
81
82PieceFilter
83pf_coud = {
84 .coud = true
85};
86
87PieceFilter
88pf_edges = {
89 .epose = true,
90 .eposs = true,
91 .eposm = true,
92 .eofb = true,
93 .eorl = true,
94 .eoud = true
95};
diff --git a/src/pf.h b/src/pf.h
deleted file mode 100644
index 0b552dc..0000000
--- a/src/pf.h
+++ /dev/null
@@ -1,20 +0,0 @@
1#ifndef PF_H
2#define PF_H
3
4#include "cubetypes.h"
5
6extern PieceFilter pf_all;
7extern PieceFilter pf_4val;
8extern PieceFilter pf_epcp;
9extern PieceFilter pf_cpos;
10extern PieceFilter pf_cp;
11extern PieceFilter pf_ep;
12extern PieceFilter pf_e;
13extern PieceFilter pf_s;
14extern PieceFilter pf_m;
15extern PieceFilter pf_eo;
16extern PieceFilter pf_co;
17extern PieceFilter pf_coud;
18extern PieceFilter pf_edges;
19
20#endif
diff --git a/src/pruning.c b/src/pruning.c
index 1dba949..5be977c 100644
--- a/src/pruning.c
+++ b/src/pruning.c
@@ -1,3 +1,5 @@
1#define PRUNING_C
2
1#include "pruning.h" 3#include "pruning.h"
2 4
3#define ENTRIES_PER_GROUP (2*sizeof(entry_group_t)) 5#define ENTRIES_PER_GROUP (2*sizeof(entry_group_t))
@@ -10,101 +12,11 @@ static void genptable_fixnasty(PruneData *pd, int d, int nthreads);
10static void genptable_setbase(PruneData *pd); 12static void genptable_setbase(PruneData *pd);
11static void * instance_bfs(void *arg); 13static void * instance_bfs(void *arg);
12static void * instance_fixnasty(void *arg); 14static void * instance_fixnasty(void *arg);
13static void ptable_update(PruneData *pd, Cube cube, int m); 15static void ptable_update(PruneData *pd, uint64_t ind, int m);
14static void ptable_update_index(PruneData *pd, uint64_t ind, int m);
15static int ptableval_index(PruneData *pd, uint64_t ind);
16static bool read_ptable_file(PruneData *pd); 16static bool read_ptable_file(PruneData *pd);
17static bool write_ptable_file(PruneData *pd); 17static bool write_ptable_file(PruneData *pd);
18 18
19PruneData 19PDGenData *active_pdg[256];
20pd_eofb_HTM = {
21 .filename = "pt_eofb_HTM",
22 .coord = &coord_eofb,
23 .moveset = &moveset_HTM,
24};
25
26PruneData
27pd_coud_HTM = {
28 .filename = "pt_coud_HTM",
29 .coord = &coord_coud,
30 .moveset = &moveset_HTM,
31};
32
33PruneData
34pd_cornershtr_HTM = {
35 .filename = "pt_cornershtr_HTM",
36 .coord = &coord_cornershtr,
37 .moveset = &moveset_HTM,
38};
39
40PruneData
41pd_corners_HTM = {
42 .filename = "pt_corners_HTM",
43 .coord = &coord_corners,
44 .moveset = &moveset_HTM,
45};
46
47PruneData
48pd_drud_sym16_HTM = {
49 .filename = "pt_drud_sym16_HTM",
50 .coord = &coord_drud_sym16,
51 .moveset = &moveset_HTM,
52};
53
54PruneData
55pd_drud_eofb = {
56 .filename = "pt_drud_eofb",
57 .coord = &coord_drud_eofb,
58 .moveset = &moveset_eofb,
59};
60
61PruneData
62pd_drudfin_noE_sym16_drud = {
63 .filename = "pt_drudfin_noE_sym16_drud",
64 .coord = &coord_drudfin_noE_sym16,
65 .moveset = &moveset_drud,
66};
67
68PruneData
69pd_htr_drud = {
70 .filename = "pt_htr_drud",
71 .coord = &coord_htr_drud,
72 .moveset = &moveset_drud,
73};
74
75PruneData
76pd_htrfin_htr = {
77 .filename = "pt_htrfin_htr",
78 .coord = &coord_htrfin,
79 .moveset = &moveset_htr,
80};
81
82PruneData
83pd_nxopt31_HTM = {
84 .filename = "pt_nxopt31_HTM",
85 .coord = &coord_nxopt31,
86 .moveset = &moveset_HTM,
87
88 .compact = true,
89 .fallback = &pd_drud_sym16_HTM,
90 .fbmod = BINOM8ON4,
91};
92
93PruneData * all_pd[] = {
94 &pd_eofb_HTM,
95 &pd_coud_HTM,
96 &pd_cornershtr_HTM,
97 &pd_corners_HTM,
98 &pd_drud_sym16_HTM,
99 &pd_drud_eofb,
100 &pd_drudfin_noE_sym16_drud,
101 &pd_htr_drud,
102 &pd_htrfin_htr,
103 &pd_nxopt31_HTM,
104 NULL
105};
106
107/* Functions *****************************************************************/
108 20
109int 21int
110findchunk(PruneData *pd, int nchunks, uint64_t i) 22findchunk(PruneData *pd, int nchunks, uint64_t i)
@@ -117,39 +29,41 @@ findchunk(PruneData *pd, int nchunks, uint64_t i)
117 return MIN(nchunks-1, (int)(i / chunksize)); 29 return MIN(nchunks-1, (int)(i / chunksize));
118} 30}
119 31
120void 32PruneData *
121free_pd(PruneData *pd) 33genptable(PDGenData *pdg, int nthreads)
122{
123 if (pd->generated)
124 free(pd->ptable);
125
126 pd->generated = false;
127}
128
129void
130genptable(PruneData *pd, int nthreads)
131{ 34{
132 bool compact; 35 bool compact;
133 int d, nchunks; 36 int d, nchunks, i;
134 uint64_t oldn, sz; 37 uint64_t oldn, sz;
38 PruneData *pd;
135 39
136 if (pd->generated) 40 for (i = 0; active_pdg[i] != NULL; i++) {
137 return; 41 pd = active_pdg[i]->pd;
42 if (pd->coord == pdg->coord &&
43 pd->moveset == pdg->moveset &&
44 pd->compact == pdg->compact)
45 return pd;
46 }
47
48 pd = malloc(sizeof(PruneData));
49 pdg->pd = pd;
50 pd->coord = pdg->coord;
51 pd->moveset = pdg->moveset;
52 pd->compact = pdg->compact;
138 53
139 /* TODO: check if memory is enough, otherwise maybe exit gracefully? */
140 sz = ptablesize(pd) * (pd->compact ? 2 : 1); 54 sz = ptablesize(pd) * (pd->compact ? 2 : 1);
141 pd->ptable = malloc(sz * sizeof(entry_group_t)); 55 pd->ptable = malloc(sz * sizeof(entry_group_t));
142 56
143 if (read_ptable_file(pd)) { 57 gen_coord(pd->coord);
144 pd->generated = true; 58
145 return; 59 if (read_ptable_file(pd))
146 } 60 goto genptable_done;
147 61
148 if (nthreads < 4) { 62 if (nthreads < 4) {
149 fprintf(stderr, 63 fprintf(stderr,
150 "--- Warning ---\n" 64 "--- Warning ---\n"
151 "You are using only %d threads to generate the pruning" 65 "You are using only %d threads to generate the pruning"
152 "tables. This can take a while." 66 "tables. This can take a while.\n"
153 "Unless you did this intentionally, you should re-run" 67 "Unless you did this intentionally, you should re-run"
154 "this command with `-t 4' or more.\n" 68 "this command with `-t 4' or more.\n"
155 "---------------\n\n", nthreads 69 "---------------\n\n", nthreads
@@ -160,16 +74,16 @@ genptable(PruneData *pd, int nthreads)
160 /* For the first steps we proceed the same way for compact and not */ 74 /* For the first steps we proceed the same way for compact and not */
161 compact = pd->compact; 75 compact = pd->compact;
162 pd->compact = false; 76 pd->compact = false;
163 pd->generated = true;
164 77
165 nchunks = MIN(ptablesize(pd), 100000); 78 nchunks = MIN(ptablesize(pd), 100000);
166 fprintf(stderr, "Cannot load %s, generating it with %d threads\n", 79 fprintf(stderr, "Generating pt_%s_%s with %d threads\n",
167 pd->filename, nthreads); 80 pd->coord->name, pd->moveset->name, nthreads);
168
169 81
170 memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t)); 82 memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t));
83 for (i = 0; i < 16; i++)
84 pd->count[i] = 0;
171 85
172 ptable_update(pd, (Cube){0}, 0); 86 ptable_update(pd, 0, 0);
173 pd->n = 1; 87 pd->n = 1;
174 oldn = 0; 88 oldn = 0;
175 genptable_fixnasty(pd, 0, nthreads); 89 genptable_fixnasty(pd, 0, nthreads);
@@ -192,9 +106,19 @@ genptable(PruneData *pd, int nthreads)
192 genptable_setbase(pd); 106 genptable_setbase(pd);
193 if (compact) 107 if (compact)
194 genptable_compress(pd); 108 genptable_compress(pd);
195 109
196 if (!write_ptable_file(pd)) 110 if (!write_ptable_file(pd))
197 fprintf(stderr, "Error writing ptable file\n"); 111 fprintf(stderr, "Error writing ptable file\n");
112
113genptable_done:
114 for (i = 0; active_pdg[i] != NULL; i++);
115 active_pdg[i] = malloc(sizeof(PDGenData));
116 active_pdg[i]->coord = pdg->coord;
117 active_pdg[i]->moveset = pdg->moveset;
118 active_pdg[i]->compact = pdg->compact;
119 active_pdg[i]->pd = pd;
120
121 return pd;
198} 122}
199 123
200static void 124static void
@@ -245,7 +169,7 @@ genptable_compress(PruneData *pd)
245 for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) { 169 for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) {
246 if (i+j >= pd->coord->max) 170 if (i+j >= pd->coord->max)
247 break; 171 break;
248 val = ptableval_index(pd, i+j) - pd->base; 172 val = ptableval(pd, i+j) - pd->base;
249 v = (entry_group_t)MIN(3, MAX(0, val)); 173 v = (entry_group_t)MIN(3, MAX(0, val));
250 mask |= v << (2*j); 174 mask |= v << (2*j);
251 } 175 }
@@ -264,7 +188,7 @@ genptable_fixnasty(PruneData *pd, int d, int nthreads)
264 ThreadDataGenpt td[nthreads]; 188 ThreadDataGenpt td[nthreads];
265 pthread_mutex_t *upmtx; 189 pthread_mutex_t *upmtx;
266 190
267 if (pd->coord->tfind == NULL) 191 if (pd->coord->type != SYMCOMP_COORD)
268 return; 192 return;
269 193
270 upmtx = malloc(sizeof(pthread_mutex_t)); 194 upmtx = malloc(sizeof(pthread_mutex_t));
@@ -320,17 +244,17 @@ instance_bfs(void *arg)
320 for (i = rmin; i < rmax; i++) { 244 for (i = rmin; i < rmax; i++) {
321 ichunk = findchunk(td->pd, td->nchunks, i); 245 ichunk = findchunk(td->pd, td->nchunks, i);
322 pthread_mutex_lock(td->mutex[ichunk]); 246 pthread_mutex_lock(td->mutex[ichunk]);
323 pval = ptableval_index(td->pd, i); 247 pval = ptableval(td->pd, i);
324 pthread_mutex_unlock(td->mutex[ichunk]); 248 pthread_mutex_unlock(td->mutex[ichunk]);
325 if (pval == td->d) { 249 if (pval == td->d) {
326 for (j = 0; ms[j] != NULLMOVE; j++) { 250 for (j = 0; ms[j] != NULLMOVE; j++) {
327 ii = td->pd->coord->move(ms[j], i); 251 /* ii = td->pd->coord->move(ms[j], i); */
252 ii = move_coord(td->pd->coord, ms[j], i, NULL);
328 ichunk = findchunk(td->pd, td->nchunks, ii); 253 ichunk = findchunk(td->pd, td->nchunks, ii);
329 pthread_mutex_lock(td->mutex[ichunk]); 254 pthread_mutex_lock(td->mutex[ichunk]);
330 pval = ptableval_index(td->pd, ii); 255 pval = ptableval(td->pd, ii);
331 if (pval > td->d+1) { 256 if (pval > td->d+1) {
332 ptable_update_index(td->pd, 257 ptable_update(td->pd, ii, td->d+1);
333 ii, td->d+1);
334 updated++; 258 updated++;
335 } 259 }
336 pthread_mutex_unlock(td->mutex[ichunk]); 260 pthread_mutex_unlock(td->mutex[ichunk]);
@@ -349,13 +273,15 @@ static void *
349instance_fixnasty(void *arg) 273instance_fixnasty(void *arg)
350{ 274{
351 ThreadDataGenpt *td; 275 ThreadDataGenpt *td;
352 uint64_t i, ii, nb, blocksize, rmin, rmax, updated; 276 uint64_t i, ii, blocksize, rmin, rmax, updated, ss, M;
353 int j, n; 277 int j;
354 Trans t, aux[NTRANS]; 278 Trans t;
355 279
356 td = (ThreadDataGenpt *)arg; 280 td = (ThreadDataGenpt *)arg;
357 nb = td->pd->coord->max / td->pd->coord->base->max; 281
358 blocksize = (td->pd->coord->base->max / td->nthreads) * nb; 282 /* We know type = SYMCOMP_COORD */
283 M = td->pd->coord->base[1]->max;
284 blocksize = (td->pd->coord->base[0]->max / td->nthreads) * M;
359 rmin = ((uint64_t)td->thid) * blocksize; 285 rmin = ((uint64_t)td->thid) * blocksize;
360 rmax = td->thid == td->nthreads - 1 ? 286 rmax = td->thid == td->nthreads - 1 ?
361 td->pd->coord->max : 287 td->pd->coord->max :
@@ -363,16 +289,15 @@ instance_fixnasty(void *arg)
363 289
364 updated = 0; 290 updated = 0;
365 for (i = rmin; i < rmax; i++) { 291 for (i = rmin; i < rmax; i++) {
366 if (ptableval_index(td->pd, i) == td->d) { 292 if (ptableval(td->pd, i) == td->d) {
367 if ((n = td->pd->coord->tfind(i, aux)) == 1) 293 ss = td->pd->coord->base[0]->selfsim[i/M];
368 continue; 294 for (j = 0; j < td->pd->coord->base[0]->tgrp->n; j++) {
369 295 t = td->pd->coord->base[0]->tgrp->t[j];
370 for (j = 0; j < n; j++) { 296 if (t == uf || !(ss & ((uint64_t)1<<t)))
371 if ((t = aux[j]) == uf)
372 continue; 297 continue;
373 ii = td->pd->coord->transform(t, i); 298 ii = trans_coord(td->pd->coord, t, i);
374 if (ptableval_index(td->pd, ii) > td->d) { 299 if (ptableval(td->pd, ii) > td->d) {
375 ptable_update_index(td->pd, ii, td->d); 300 ptable_update(td->pd, ii, td->d);
376 updated++; 301 updated++;
377 } 302 }
378 } 303 }
@@ -391,10 +316,7 @@ print_ptable(PruneData *pd)
391{ 316{
392 uint64_t i; 317 uint64_t i;
393 318
394 if (!pd->generated) 319 printf("Table %s_%s\n", pd->coord->name, pd->moveset->name);
395 genptable(pd, 1); /* TODO: set default nthreads somewhere */
396
397 printf("Table %s\n", pd->filename);
398 printf("Base value: %d\n", pd->base); 320 printf("Base value: %d\n", pd->base);
399 for (i = 0; i < 16; i++) 321 for (i = 0; i < 16; i++)
400 printf("%2" PRIu64 "\t%10" PRIu64 "\n", i, pd->count[i]); 322 printf("%2" PRIu64 "\t%10" PRIu64 "\n", i, pd->count[i]);
@@ -411,13 +333,7 @@ ptablesize(PruneData *pd)
411} 333}
412 334
413static void 335static void
414ptable_update(PruneData *pd, Cube cube, int n) 336ptable_update(PruneData *pd, uint64_t ind, int n)
415{
416 ptable_update_index(pd, pd->coord->index(cube), n);
417}
418
419static void
420ptable_update_index(PruneData *pd, uint64_t ind, int n)
421{ 337{
422 int sh; 338 int sh;
423 entry_group_t mask; 339 entry_group_t mask;
@@ -432,27 +348,12 @@ ptable_update_index(PruneData *pd, uint64_t ind, int n)
432} 348}
433 349
434int 350int
435ptableval(PruneData *pd, Cube cube) 351ptableval(PruneData *pd, uint64_t ind)
436{
437 return ptableval_index(pd, pd->coord->index(cube));
438}
439
440static int
441ptableval_index(PruneData *pd, uint64_t ind)
442{ 352{
443 int sh, ret; 353 int sh, ret;
444 entry_group_t mask; 354 uint64_t e;
445 uint64_t i, e;
446 entry_group_t m; 355 entry_group_t m;
447 356
448 if (!pd->generated) {
449 fprintf(stderr, "Warning: request pruning table value"
450 " for uninitialized table %s.\n It's fine, but it"
451 " should not happen. Please report bug.\n",
452 pd->filename);
453 genptable(pd, 1); /* TODO: set default or remove this case */
454 }
455
456 if (pd->compact) { 357 if (pd->compact) {
457 e = ENTRIES_PER_GROUP_COMPACT; 358 e = ENTRIES_PER_GROUP_COMPACT;
458 m = 3; 359 m = 3;
@@ -463,19 +364,9 @@ ptableval_index(PruneData *pd, uint64_t ind)
463 sh = (ind % e) * 4; 364 sh = (ind % e) * 4;
464 } 365 }
465 366
466 mask = m << sh; 367 ret = (pd->ptable[ind/e] & (m << sh)) >> sh;
467 i = ind/e;
468
469 ret = (pd->ptable[i] & mask) >> sh;
470
471 if (pd->compact) {
472 if (ret)
473 ret += pd->base;
474 else
475 ret = ptableval_index(pd->fallback, ind / pd->fbmod);
476 }
477 368
478 return ret; 369 return pd->compact ? ret + pd->base : ret;
479} 370}
480 371
481static bool 372static bool
@@ -484,13 +375,15 @@ read_ptable_file(PruneData *pd)
484 init_env(); 375 init_env();
485 376
486 FILE *f; 377 FILE *f;
487 char fname[strlen(tabledir)+100]; 378 char fname[strlen(tabledir)+256];
488 int i; 379 int i;
489 uint64_t r; 380 uint64_t r;
490 381
491 strcpy(fname, tabledir); 382 strcpy(fname, tabledir);
492 strcat(fname, "/"); 383 strcat(fname, "/pt_");
493 strcat(fname, pd->filename); 384 strcat(fname, pd->coord->name);
385 strcat(fname, "_");
386 strcat(fname, pd->moveset->name);
494 387
495 if ((f = fopen(fname, "rb")) == NULL) 388 if ((f = fopen(fname, "rb")) == NULL)
496 return false; 389 return false;
@@ -511,13 +404,15 @@ write_ptable_file(PruneData *pd)
511 init_env(); 404 init_env();
512 405
513 FILE *f; 406 FILE *f;
514 char fname[strlen(tabledir)+100]; 407 char fname[strlen(tabledir)+256];
515 int i; 408 int i;
516 uint64_t w; 409 uint64_t w;
517 410
518 strcpy(fname, tabledir); 411 strcpy(fname, tabledir);
519 strcat(fname, "/"); 412 strcat(fname, "/pt_");
520 strcat(fname, pd->filename); 413 strcat(fname, pd->coord->name);
414 strcat(fname, "_");
415 strcat(fname, pd->moveset->name);
521 416
522 if ((f = fopen(fname, "wb")) == NULL) 417 if ((f = fopen(fname, "wb")) == NULL)
523 return false; 418 return false;
diff --git a/src/pruning.h b/src/pruning.h
index 6bdbee1..6965910 100644
--- a/src/pruning.h
+++ b/src/pruning.h
@@ -1,26 +1,15 @@
1#ifndef PRUNING_H 1#ifndef PRUNING_H
2#define PRUNING_H 2#define PRUNING_H
3 3
4#include "symcoord.h" 4#include "coord.h"
5
6extern PruneData pd_eofb_HTM;
7extern PruneData pd_coud_HTM;
8extern PruneData pd_corners_HTM;
9extern PruneData pd_cornershtr_HTM;
10extern PruneData pd_drud_sym16_HTM;
11extern PruneData pd_drud_eofb;
12extern PruneData pd_drudfin_noE_sym16_drud;
13extern PruneData pd_htr_drud;
14extern PruneData pd_htrfin_htr;
15extern PruneData pd_nxopt31_HTM;
16
17extern PruneData * all_pd[];
18 5
19void free_pd(PruneData *pd); 6void free_pd(PruneData *pd);
20void genptable(PruneData *pd, int nthreads); 7PruneData * genptable(PDGenData *data, int nthreads);
21void print_ptable(PruneData *pd); 8void print_ptable(PruneData *pd);
22uint64_t ptablesize(PruneData *pd); 9uint64_t ptablesize(PruneData *pd);
23int ptableval(PruneData *pd, Cube cube); 10int ptableval(PruneData *pd, uint64_t ind);
11
12extern PDGenData *active_pdg[256];
24 13
25#endif 14#endif
26 15
diff --git a/src/shell.c b/src/shell.c
index 0001e0d..44665a8 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1,3 +1,5 @@
1#define SHELL_C
2
1#include "shell.h" 3#include "shell.h"
2 4
3static void cleanwhitespaces(char *line); 5static void cleanwhitespaces(char *line);
@@ -7,7 +9,9 @@ bool
7checkfiles() 9checkfiles()
8{ 10{
9 /* TODO: add more checks (other files, use checksum...) */ 11 /* TODO: add more checks (other files, use checksum...) */
10 FILE *f; 12 /* How to check for pruning tables with new method? */
13 /* Solution: use list of steps */
14 /*
11 char fname[strlen(tabledir)+100]; 15 char fname[strlen(tabledir)+100];
12 int i; 16 int i;
13 17
@@ -20,6 +24,7 @@ checkfiles()
20 else 24 else
21 fclose(f); 25 fclose(f);
22 } 26 }
27 */
23 28
24 return true; 29 return true;
25} 30}
@@ -143,6 +148,21 @@ main(int argc, char *argv[])
143 char *closing_cmd[1] = { "freemem" }; 148 char *closing_cmd[1] = { "freemem" };
144 149
145 init_env(); 150 init_env();
151 init_trans();
152
153/*
154 Cube c;
155 make_solved(&c);
156 c.co[0] = 1;
157 c.co[6] = 2;
158 print_cube(&c);
159 apply_trans(uf_mirror, &c);
160 print_cube(&c);
161*/
162
163/*
164 test_coord(&coord_coud_cpudsep);
165*/
146 166
147 if (!checkfiles()) { 167 if (!checkfiles()) {
148 fprintf(stderr, 168 fprintf(stderr,
diff --git a/src/solve.c b/src/solve.c
index d4c0f18..911d208 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -1,37 +1,34 @@
1#define SOLVE_C
2
1#include "solve.h" 3#include "solve.h"
2 4
3/* Local functions ***********************************************************/ 5/* Local functions ***********************************************************/
4 6
5static bool allowed_next(Move move, DfsArg *arg); 7static bool allowed_next(Move move, StepAlt *sa, Move l0, Move l1);
6static bool cancel_niss(DfsArg *arg); 8static bool cancel_niss(DfsArg *arg);
7static void copy_dfsarg(DfsArg *src, DfsArg *dst); 9static void copy_dfsarg(DfsArg *src, DfsArg *dst);
8static void dfs(DfsArg *arg); 10static void dfs(DfsArg *arg);
9static void dfs_branch(DfsArg *arg); 11static void dfs_add_sol(DfsArg *arg);
10static bool dfs_check_solved(DfsArg *arg);
11static bool dfs_switch(DfsArg *arg);
12static void dfs_niss(DfsArg *arg); 12static void dfs_niss(DfsArg *arg);
13static bool dfs_stop(DfsArg *arg); 13static bool dfs_move_checkstop(DfsArg *arg);
14static void * instance_thread(void *arg); 14static void * instance_thread(void *arg);
15static void invert_branch(DfsArg *arg); 15static void multidfs(DfsArg *arg);
16static void multidfs(Cube c, Trans t, Step *s, SolveOptions *opts,
17 AlgList *sols, int d);
18static bool niss_makes_sense(DfsArg *arg); 16static bool niss_makes_sense(DfsArg *arg);
19static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols); 17static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols);
20 18
21/* Local functions ***********************************************************/ 19/* Local functions ***********************************************************/
22 20
23static bool 21static bool
24allowed_next(Move m, DfsArg *arg) 22allowed_next(Move m, StepAlt *sa, Move l0, Move l1)
25{ 23{
26 bool bad, allowed, order; 24 bool allowed, order;
27 uint64_t mbit; 25 uint64_t mbit;
28 26
29 mbit = ((uint64_t)1) << m; 27 mbit = ((uint64_t)1) << m;
30 bad = mbit & arg->badmoves; 28 allowed = mbit & sa->moveset->mask[l1][l0];
31 allowed = mbit & arg->step->moveset->mask[arg->last2][arg->last1]; 29 order = !commute(l0, m) || l0 < m;
32 order = !commute(arg->last1, m) || arg->last1 < m;
33 30
34 return allowed && !bad && order; 31 return allowed && order;
35} 32}
36 33
37static bool 34static bool
@@ -41,20 +38,20 @@ cancel_niss(DfsArg *arg)
41 Move i1, i2; 38 Move i1, i2;
42 bool p, p1, p2, q, q1, q2; 39 bool p, p1, p2, q, q1, q2;
43 40
44 if (arg->last1inv == NULLMOVE) 41 if (arg->lastinv[0] == NULLMOVE)
45 return false; 42 return false;
46 43
47 ms = arg->step->moveset; 44 ms = arg->sa->moveset;
48 i1 = inverse_move(arg->last1inv); 45 i1 = inverse_move(arg->lastinv[0]);
49 i2 = inverse_move(arg->last2inv); 46 i2 = inverse_move(arg->lastinv[1]);
50 47
51 p1 = !ms->allowed_next(arg->last2, arg->last1, i1); 48 p1 = !ms->allowed_next(arg->last[1], arg->last[0], i1);
52 p2 = !ms->allowed_next(arg->last2, i1, arg->last1); 49 p2 = !ms->allowed_next(arg->last[1], i1, arg->last[0]);
53 p = p1 || (commute(i1, arg->last1) && p2); 50 p = p1 || (commute(i1, arg->last[0]) && p2);
54 51
55 q1 = !ms->allowed_next(arg->last2, arg->last1, i2); 52 q1 = !ms->allowed_next(arg->last[1], arg->last[0], i2);
56 q2 = !ms->allowed_next(arg->last2, i2, arg->last1); 53 q2 = !ms->allowed_next(arg->last[1], i2, arg->last[0]);
57 q = q1 || (commute(i2, arg->last1) && q2); 54 q = q1 || (commute(i2, arg->last[0]) && q2);
58 55
59 return p || (commute(i1, i2) && q); 56 return p || (commute(i1, i2) && q);
60} 57}
@@ -62,142 +59,145 @@ cancel_niss(DfsArg *arg)
62static void 59static void
63copy_dfsarg(DfsArg *src, DfsArg *dst) 60copy_dfsarg(DfsArg *src, DfsArg *dst)
64{ 61{
65 dst->step = src->step; 62 int i;
66 dst->opts = src->opts;
67 dst->t = src->t;
68 dst->cube = src->cube;
69 dst->inverse = src->inverse;
70 dst->d = src->d;
71 dst->badmoves = src->badmoves;
72 dst->badmovesinv = src->badmovesinv;
73 dst->niss = src->niss;
74 dst->last1 = src->last1;
75 dst->last2 = src->last2;
76 dst->last1inv = src->last1inv;
77 dst->last2inv = src->last2inv;
78 dst->sols = src->sols;
79 dst->sols_mutex = src->sols_mutex;
80 dst->current_alg = src->current_alg;
81
82 copy_estimatedata(src->ed, dst->ed);
83}
84
85static void
86dfs(DfsArg *arg)
87{
88 bool sw = false;
89
90 if (dfs_stop(arg))
91 return;
92
93 if (dfs_check_solved(arg))
94 return;
95 63
96 if (arg->step->final && (sw = dfs_switch(arg))) 64 dst->cube = src->cube;
97 invert_branch(arg); 65 dst->t = src->t;
98 dfs_branch(arg); 66 dst->sa = src->sa;
67 dst->opts = src->opts;
68 dst->d = src->d;
69 dst->bound = src->bound; /* In theory not needed */
70 dst->niss = src->niss;
71 dst->sols = src->sols;
72 dst->sols_mutex = src->sols_mutex;
73 dst->current_alg = src->current_alg;
99 74
100 if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg)) 75 for (i = 0; i < 2; i++) {
101 dfs_niss(arg); 76 dst->last[i] = src->last[i];
77 dst->lastinv[i] = src->lastinv[i];
78 }
102 79
103 if (sw) 80 for (i = 0; i < src->sa->n_coord; i++) {
104 invert_branch(arg); 81 dst->ind[i].val = src->ind[i].val;
82 dst->ind[i].t = src->ind[i].t;
83 }
105} 84}
106 85
107static void 86static void
108dfs_branch(DfsArg *arg) 87dfs(DfsArg *arg)
109{ 88{
110 int i; 89 int i;
111 Move m; 90 Move m;
112 DfsArg *newarg; 91 DfsArg newarg;
113 92
114 newarg = malloc(sizeof(DfsArg)); 93 if (dfs_move_checkstop(arg))
115 newarg->ed = malloc(sizeof(EstimateData)); 94 return;
116
117 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) {
118 m = arg->step->moveset->sorted_moves[i];
119 if (allowed_next(m, arg)) {
120 copy_dfsarg(arg, newarg);
121 newarg->last2 = arg->last1;
122 newarg->last1 = m;
123 newarg->cube = apply_move(m, arg->cube);
124 append_move(arg->current_alg, m, newarg->niss);
125 95
126 dfs(newarg); 96 if (arg->bound == 0) {
97 if (arg->current_alg->len == arg->d)
98 dfs_add_sol(arg);
99 return;
100 }
127 101
102 for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) {
103 m = arg->sa->moveset->sorted_moves[i];
104 if (allowed_next(m, arg->sa, arg->last[0], arg->last[1])) {
105 copy_dfsarg(arg, &newarg);
106 newarg.last[1] = arg->last[0];
107 newarg.last[0] = m;
108 append_move(arg->current_alg, m, newarg.niss);
109 dfs(&newarg);
128 arg->current_alg->len--; 110 arg->current_alg->len--;
129 } 111 }
130 } 112 }
131 113
132 free(newarg->ed); 114 if (niss_makes_sense(arg))
133 free(newarg); 115 dfs_niss(arg);
134} 116}
135 117
136static bool 118static void
137dfs_check_solved(DfsArg *arg) 119dfs_add_sol(DfsArg *arg)
138{ 120{
139 if (!arg->step->is_done(arg->cube)) 121 bool valid, accepted, nisscanc;
140 return false;
141
142 if (arg->current_alg->len == arg->d) {
143 if ((arg->step->is_valid(arg->current_alg) || arg->opts->all)
144 && (!arg->step->final || !cancel_niss(arg))) {
145
146 pthread_mutex_lock(arg->sols_mutex);
147
148 if (arg->sols->len < arg->opts->max_solutions) {
149 append_alg(arg->sols, arg->current_alg);
150 122
151 transform_alg( 123 valid = arg->sa->is_valid==NULL || arg->sa->is_valid(arg->current_alg);
152 inverse_trans(arg->t), 124 accepted = valid || arg->opts->all;
153 arg->sols->last->alg 125 nisscanc = arg->sa->final && cancel_niss(arg);
154 );
155 if (arg->step->final)
156 inplace(unniss, arg->sols->last->alg);
157 126
158 if (arg->opts->verbose) 127 if (accepted && !nisscanc) {
159 print_alg(arg->sols->last->alg, false); 128 pthread_mutex_lock(arg->sols_mutex);
160 }
161 129
162 pthread_mutex_unlock(arg->sols_mutex); 130 if (arg->sols->len < arg->opts->max_solutions) {
131 append_alg(arg->sols, arg->current_alg);
132 transform_alg(
133 inverse_trans(arg->t), arg->sols->last->alg);
134 if (arg->opts->verbose)
135 print_alg(arg->sols->last->alg, false);
163 } 136 }
164 }
165 137
166 return true; 138 pthread_mutex_unlock(arg->sols_mutex);
139 }
167} 140}
168 141
169static void 142static void
170dfs_niss(DfsArg *arg) 143dfs_niss(DfsArg *arg)
171{ 144{
172 DfsArg *newarg; 145 DfsArg newarg;
146 Alg *inv;
147 Cube *c;
148
149 copy_dfsarg(arg, &newarg);
173 150
174 newarg = malloc(sizeof(DfsArg)); 151 /* Invert current alg and scramble */
175 newarg->ed = malloc(sizeof(EstimateData)); 152 newarg.cube = malloc(sizeof(Cube));
153 inv = inverse_alg(arg->current_alg);
154 c = malloc(sizeof(Cube));
155 make_solved(newarg.cube);
156 apply_alg(inv, newarg.cube);
157 copy_cube(arg->cube, c);
158 invert_cube(c);
159 compose(c, newarg.cube);
176 160
177 copy_dfsarg(arg, newarg); 161 /* New indexes */
178 swapmove(&(newarg->last1), &(newarg->last1inv)); 162 compute_ind(newarg.sa, newarg.cube, newarg.ind);
179 swapmove(&(newarg->last2), &(newarg->last2inv));
180 newarg->niss = !(arg->niss);
181 newarg->cube = inverse_cube(arg->cube);
182 163
183 dfs(newarg); 164 swapmove(&(newarg.last[0]), &(newarg.lastinv[0]));
165 swapmove(&(newarg.last[1]), &(newarg.lastinv[1]));
166 newarg.niss = !(arg->niss);
184 167
185 free(newarg->ed); 168 dfs(&newarg);
186 free(newarg); 169
170 free_alg(inv);
171 free(c);
172 free(newarg.cube);
187} 173}
188 174
189static bool 175static bool
190dfs_stop(DfsArg *arg) 176dfs_move_checkstop(DfsArg *arg)
191{ 177{
192 int lowerbound;
193 bool b; 178 bool b;
179 int i, goal;
180 Move mm;
181 Trans tt = uf; /* Avoid uninitialized warning */
182
183 /* Moving */
184 if (arg->last[0] != NULLMOVE) {
185 for (i = 0; i < arg->sa->n_coord; i++) {
186 mm = transform_move(arg->ind[i].t, arg->last[0]);
187 arg->ind[i].val = move_coord(arg->sa->coord[i],
188 mm, arg->ind[i].val, &tt);
189 arg->ind[i].t = transform_trans(tt, arg->ind[i].t);
190 }
191 }
194 192
195 lowerbound = arg->step->estimate(arg); 193 /* Computing bound for coordinates */
194 goal = arg->d - arg->current_alg->len;
195 arg->bound = estimate_stepalt(arg->sa, arg->ind, goal);
196 if (arg->opts->can_niss && !arg->niss) 196 if (arg->opts->can_niss && !arg->niss)
197 lowerbound = MIN(1, lowerbound); 197 arg->bound = MIN(1, arg->bound);
198 198
199 if (arg->current_alg->len + lowerbound > arg->d) { 199 if (arg->bound > goal) {
200 b = true; 200 b = true;
201 } else { 201 } else {
202 pthread_mutex_lock(arg->sols_mutex); 202 pthread_mutex_lock(arg->sols_mutex);
203 b = arg->sols->len >= arg->opts->max_solutions; 203 b = arg->sols->len >= arg->opts->max_solutions;
@@ -207,37 +207,12 @@ dfs_stop(DfsArg *arg)
207 return b; 207 return b;
208} 208}
209 209
210static bool
211dfs_switch(DfsArg *arg)
212{
213 int i, bn, bi;
214
215 bn = 0;
216 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++)
217 if (allowed_next(arg->step->moveset->sorted_moves[i], arg))
218 bn++;
219
220 swapmove(&(arg->last1), &(arg->last1inv));
221 swapmove(&(arg->last2), &(arg->last2inv));
222 swapu64(&(arg->badmoves), &(arg->badmovesinv));
223
224 bi = 0;
225 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++)
226 if (allowed_next(arg->step->moveset->sorted_moves[i], arg))
227 bi++;
228
229 swapmove(&(arg->last1), &(arg->last1inv));
230 swapmove(&(arg->last2), &(arg->last2inv));
231 swapu64(&(arg->badmoves), &(arg->badmovesinv));
232
233 return bi < bn;
234}
235
236static void * 210static void *
237instance_thread(void *arg) 211instance_thread(void *arg)
238{ 212{
239 bool b; 213 bool b, inv;
240 Cube c; 214 Cube c;
215 Move m;
241 ThreadDataSolve *td; 216 ThreadDataSolve *td;
242 AlgListNode *node; 217 AlgListNode *node;
243 DfsArg darg; 218 DfsArg darg;
@@ -257,68 +232,46 @@ instance_thread(void *arg)
257 if (b) 232 if (b)
258 break; 233 break;
259 234
260 c = node->alg->inv[0] ? 235 inv = node->alg->inv[0];
261 apply_move(node->alg->move[0], inverse_cube(td->cube)) : 236 m = node->alg->move[0];
262 apply_move(node->alg->move[0], td->cube); 237
238 copy_cube(td->arg.cube, &c);
239 if (inv)
240 invert_cube(&c);
263 241
264 darg.step = td->step; 242 copy_dfsarg(&td->arg, &darg);
265 darg.opts = td->opts; 243 compute_ind(td->arg.sa, &c, darg.ind);
266 darg.t = td->t; 244 darg.cube = &c;
267 darg.cube = c; 245
268 darg.d = td->depth; 246 darg.niss = inv;
269 darg.niss = node->alg->inv[0]; 247 darg.last[0] = m;
270 darg.last1 = node->alg->move[0]; 248 darg.last[1] = NULLMOVE;
271 darg.last2 = NULLMOVE; 249 darg.lastinv[0] = NULLMOVE;
272 darg.last1inv = NULLMOVE; 250 darg.lastinv[1] = NULLMOVE;
273 darg.last2inv = NULLMOVE;
274 darg.sols = td->sols;
275 darg.sols_mutex = td->sols_mutex;
276 darg.current_alg = new_alg(""); 251 darg.current_alg = new_alg("");
277 append_move(darg.current_alg, node->alg->move[0], 252 append_move(darg.current_alg, m, inv);
278 node->alg->inv[0]);
279 darg.ed = malloc(sizeof(EstimateData));
280 reset_estimatedata(darg.ed);
281 darg.badmoves = 0;
282 darg.badmovesinv = 0;
283 253
284 dfs(&darg); 254 dfs(&darg);
285 255
286 free_alg(darg.current_alg); 256 free_alg(darg.current_alg);
287 free(darg.ed);
288 } 257 }
289 258
290 return NULL; 259 return NULL;
291} 260}
292 261
293static void 262static void
294invert_branch(DfsArg *arg) 263multidfs(DfsArg *arg)
295{
296 Cube aux;
297
298 aux = arg->cube;
299 arg->cube = is_solved(arg->inverse) ?
300 inverse_cube(arg->cube) : arg->inverse;
301 arg->inverse = aux;
302
303 swapu64(&(arg->badmoves), &(arg->badmovesinv));
304 arg->niss = !(arg->niss);
305 swapmove(&(arg->last1), &(arg->last1inv));
306 swapmove(&(arg->last2), &(arg->last2inv));
307 invert_estimatedata(arg->ed);
308}
309
310static void
311multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d)
312{ 264{
313 int i; 265 int i;
266 Cube local_cube;
314 Alg *alg; 267 Alg *alg;
315 AlgList *start; 268 AlgList *start;
316 AlgListNode **node; 269 AlgListNode **node;
317 pthread_t t[opts->nthreads]; 270 pthread_t t[arg->opts->nthreads];
318 ThreadDataSolve td[opts->nthreads]; 271 ThreadDataSolve td[arg->opts->nthreads];
319 pthread_mutex_t *start_mutex, *sols_mutex; 272 pthread_mutex_t *start_mutex, *sols_mutex;
320 273
321 node = malloc(sizeof(AlgListNode *)); 274 node = malloc(sizeof(AlgListNode *));
322 start_mutex = malloc(sizeof(pthread_mutex_t)); 275 start_mutex = malloc(sizeof(pthread_mutex_t));
323 sols_mutex = malloc(sizeof(pthread_mutex_t)); 276 sols_mutex = malloc(sizeof(pthread_mutex_t));
324 277
@@ -326,11 +279,11 @@ multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d)
326 pthread_mutex_init(start_mutex, NULL); 279 pthread_mutex_init(start_mutex, NULL);
327 pthread_mutex_init(sols_mutex, NULL); 280 pthread_mutex_init(sols_mutex, NULL);
328 281
329 for (i = 0; s->moveset->sorted_moves[i] != NULLMOVE; i++) { 282 for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) {
330 alg = new_alg(""); 283 alg = new_alg("");
331 append_move(alg, s->moveset->sorted_moves[i], false); 284 append_move(alg, arg->sa->moveset->sorted_moves[i], false);
332 append_alg(start, alg); 285 append_alg(start, alg);
333 if (opts->can_niss) { 286 if (arg->opts->can_niss && !arg->sa->final) {
334 alg->inv[0] = true; 287 alg->inv[0] = true;
335 append_alg(start, alg); 288 append_alg(start, alg);
336 } 289 }
@@ -338,22 +291,22 @@ multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d)
338 } 291 }
339 *node = start->first; 292 *node = start->first;
340 293
341 for (i = 0; i < opts->nthreads; i++) { 294 copy_cube(arg->cube, &local_cube);
342 td[i].thid = i; 295
343 td[i].t = tr; 296 for (i = 0; i < arg->opts->nthreads; i++) {
344 td[i].cube = c; 297 copy_dfsarg(arg, &(td[i].arg));
345 td[i].step = s; 298 td[i].arg.cube = &local_cube;
346 td[i].depth = d; 299 td[i].arg.sols_mutex = sols_mutex;
347 td[i].opts = opts; 300
348 td[i].start = start; 301 td[i].thid = i;
349 td[i].node = node; 302 td[i].start = start;
350 td[i].sols = sols; 303 td[i].node = node;
351 td[i].start_mutex = start_mutex; 304 td[i].start_mutex = start_mutex;
352 td[i].sols_mutex = sols_mutex; 305
353 pthread_create(&t[i], NULL, instance_thread, &td[i]); 306 pthread_create(&t[i], NULL, instance_thread, &td[i]);
354 } 307 }
355 308
356 for (i = 0; i < opts->nthreads; i++) 309 for (i = 0; i < arg->opts->nthreads; i++)
357 pthread_join(t[i], NULL); 310 pthread_join(t[i], NULL);
358 311
359 free_alglist(start); 312 free_alglist(start);
@@ -367,8 +320,13 @@ niss_makes_sense(DfsArg *arg)
367{ 320{
368 Cube testcube; 321 Cube testcube;
369 322
370 testcube = apply_move(inverse_move(arg->last1), (Cube){0}); 323 if (arg->sa->final || arg->niss || !arg->opts->can_niss)
371 return arg->current_alg->len == 0 || !arg->step->is_done(testcube); 324 return false;
325
326 make_solved(&testcube);
327 apply_move(inverse_move(arg->last[0]), &testcube);
328 return arg->current_alg->len == 0 ||
329 estimate_stepalt(arg->sa, arg->ind, 0) > 0;
372} 330}
373 331
374static bool 332static bool
@@ -386,62 +344,84 @@ solvestop(int d, int op, SolveOptions *opts, AlgList *sols)
386/* Public functions **********************************************************/ 344/* Public functions **********************************************************/
387 345
388AlgList * 346AlgList *
389solve(Cube cube, Step *step, SolveOptions *opts) 347solve(Cube *cube, Step *step, SolveOptions *opts)
390{ 348{
391 bool ready; 349 int i, d, op;
392 int i, d, op, nt; 350 bool ready[99], one_ready, zerosol;
393 AlgList *sols; 351 Movable ind[99][10];
394 Cube c; 352 AlgList *s;
395 Trans tt[NTRANS]; 353 Cube *c[99];
354 DfsArg arg[99];
396 355
397 prepare_step(step, opts); 356 prepare_step(step, opts);
357 s = new_alglist();
398 358
399 if (step->detect != NULL) { 359 for (i = 0, one_ready = false; step->alt[i] != NULL; i++) {
400 nt = step->detect(cube, tt); 360 c[i] = malloc(sizeof(Cube));
401 } else { 361 copy_cube(cube, c[i]);
402 tt[0] = step->pre_trans; 362 apply_trans(step->t[i], c[i]);
403 ready = step->ready == NULL ||
404 step->ready(apply_trans(tt[0], cube));
405 nt = ready ? 1 : 0;
406 }
407 363
408 sols = new_alglist(); 364 arg[i].cube = c[i];
365 arg[i].t = step->t[i];
366 arg[i].sa = step->alt[i];
367 arg[i].opts = opts;
368 arg[i].sols = s;
409 369
410 if (nt == 0) { 370 if ((ready[i] = step->alt[i]->ready(c[i]))) {
371 one_ready = true;
372 /* Only for local use for 0 moves solutions */
373 compute_ind(step->alt[i], c[i], ind[i]);
374 }
375 }
376 if (!one_ready) {
411 fprintf(stderr, "Cube not ready for solving step: "); 377 fprintf(stderr, "Cube not ready for solving step: ");
412 fprintf(stderr, "%s\n", step->ready_msg); 378 fprintf(stderr, "%s\n", step->ready_msg);
413 return sols; 379 return s;
414 } 380 }
415 381
416 if (opts->min_moves == 0) { 382 /* If the empty moves sequence is a solution for one of the
417 for (i = 0; i < nt; i++) { 383 * alternatives, all longer solutions will be discarded, so we may
418 c = apply_trans(tt[i], cube); 384 * just set its ready[] value to false. If the solution is accepted
419 if (step->is_done(c)) { 385 * we append it and start searching from d = 1. */
420 append_alg(sols, new_alg("")); 386 for (i = 0, zerosol = false; step->alt[i] != NULL; i++) {
421 return sols; 387 if (ready[i] && estimate_stepalt(step->alt[i],ind[i],0) == 0) {
422 } 388 ready[i] = false;
389 zerosol = true;
423 } 390 }
424 } 391 }
392 if (zerosol && opts->min_moves == 0) {
393 append_alg(s, new_alg(""));
394 opts->min_moves = 1;
395 if (opts->verbose)
396 printf("Step is already solved"
397 "(empty alg is a solution)\n");
398 }
425 399
426 op = -1; 400 for (d = opts->min_moves, op = -1; !solvestop(d, op, opts, s); d++) {
427 for (d = opts->min_moves; !solvestop(d, op, opts, sols); d++) {
428 if (opts->verbose) 401 if (opts->verbose)
429 fprintf(stderr, "Searching depth %d\n", d); 402 fprintf(stderr, "Searching depth %d\n", d);
430 403
431 for (i = 0; i < nt && !solvestop(d, op, opts, sols); i++) { 404 for (i=0; step->alt[i]!=NULL && !solvestop(d,op,opts,s); i++) {
432 c = apply_trans(tt[i], cube); 405 if (!ready[i])
433 multidfs(c, tt[i], step, opts, sols, d); 406 continue;
434 if (sols->len > 0 && op == -1) 407
408 arg[i].d = d;
409 multidfs(&arg[i]);
410
411 if (s->len > 0 && op == -1)
435 op = d; 412 op = d;
436 } 413 }
437 } 414 }
438 415
439 return sols; 416 for (i = 0; step->alt[i] != NULL; i++)
417 free(c[i]);
418
419 return s;
440} 420}
441 421
442/* TODO: make more general! */ 422/* TODO: make more general! */
443Alg * 423Alg *
444solve_2phase(Cube cube, int nthreads) 424solve_2phase(Cube *cube, int nthreads)
445{ 425{
446 int bestlen, newb; 426 int bestlen, newb;
447 Alg *bestalg, *ret; 427 Alg *bestalg, *ret;
@@ -466,18 +446,19 @@ solve_2phase(Cube cube, int nthreads)
466 opts2.can_niss = false; 446 opts2.can_niss = false;
467 opts2.verbose = false; 447 opts2.verbose = false;
468 448
469 /* We skip step1 if it is solved on any axis */ 449 /* We skip step1 if it is solved on U/D */
470 if (drany_HTM.is_done(cube)) { 450 if (check_drud(cube)) {
471 sols1 = new_alglist(); 451 sols1 = new_alglist();
472 append_alg(sols1, new_alg("")); 452 append_alg(sols1, new_alg(""));
473 } else { 453 } else {
474 sols1 = solve(cube, &drany_HTM, &opts1); 454 sols1 = solve(cube, &drud_HTM, &opts1);
475 } 455 }
476 bestalg = new_alg(""); 456 bestalg = new_alg("");
477 bestlen = 999; 457 bestlen = 999;
478 for (i = sols1->first; i != NULL; i = i->next) { 458 for (i = sols1->first; i != NULL; i = i->next) {
479 c = apply_alg(i->alg, cube); 459 copy_cube(cube, &c);
480 sols2 = solve(c, &dranyfin_DR, &opts2); 460 apply_alg(i->alg, &c);
461 sols2 = solve(&c, &dranyfin_DR, &opts2);
481 462
482 if (sols2->len > 0) { 463 if (sols2->len > 0) {
483 newb = i->alg->len + sols2->first->alg->len; 464 newb = i->alg->len + sols2->first->alg->len;
diff --git a/src/solve.h b/src/solve.h
index 6ce6609..9039e4a 100644
--- a/src/solve.h
+++ b/src/solve.h
@@ -5,7 +5,7 @@
5#include "steps.h" 5#include "steps.h"
6#include "trans.h" 6#include "trans.h"
7 7
8AlgList * solve(Cube cube, Step *step, SolveOptions *opts); 8AlgList * solve(Cube *cube, Step *step, SolveOptions *opts);
9Alg * solve_2phase(Cube cube, int nthreads); 9Alg * solve_2phase(Cube *cube, int nthreads);
10 10
11#endif 11#endif
diff --git a/src/steps.c b/src/steps.c
index 3189811..81af269 100644
--- a/src/steps.c
+++ b/src/steps.c
@@ -1,1372 +1,112 @@
1#include "steps.h" 1#define STEPS_C
2
3#define UPDATECHECKSTOP(a, b, c) if ((a=(MAX((a),(b))))>(c)) return (a);
4
5/* Checkers, estimators and validators ***************************************/
6
7static bool check_centers(Cube cube);
8static bool check_coud_HTM(Cube cube);
9static bool check_coud_URF(Cube cube);
10static bool check_corners_HTM(Cube cube);
11static bool check_corners_URF(Cube cube);
12static bool check_cornershtr(Cube cube);
13static bool check_eofb(Cube cube);
14static bool check_drud(Cube cube);
15static bool check_htr(Cube cube);
16
17static int estimate_eofb_HTM(DfsArg *arg);
18static int estimate_coud_HTM(DfsArg *arg);
19static int estimate_coud_URF(DfsArg *arg);
20static int estimate_corners_HTM(DfsArg *arg);
21static int estimate_cornershtr_HTM(DfsArg *arg);
22static int estimate_corners_URF(DfsArg *arg);
23static int estimate_cornershtr_URF(DfsArg *arg);
24static int estimate_drud_HTM(DfsArg *arg);
25static int estimate_drud_eofb(DfsArg *arg);
26static int estimate_dr_eofb(DfsArg *arg);
27static int estimate_drudfin_drud(DfsArg *arg);
28static int estimate_htr_drud(DfsArg *arg);
29static int estimate_htrfin_htr(DfsArg *arg);
30static int estimate_nxopt31_HTM(DfsArg *arg);
31static int estimate_light_HTM(DfsArg *arg);
32
33static int estimate_nxoptlike(DfsArg *arg, PruneData *pd);
34
35static bool always_valid(Alg *alg);
36static bool validate_singlecw_ending(Alg *alg);
37
38/* Pre-transformation detectors **********************************************/
39
40static int detect_pretrans_eofb(Cube cube, Trans *ret);
41static int detect_pretrans_drud(Cube cube, Trans *ret);
42static int detect_pretrans_void_3axis(Cube cube, Trans *ret);
43
44/* Messages for when cube is not ready ***************************************/
45
46static char check_centers_msg[100] = "cube must be oriented (centers solved)";
47static char check_eo_msg[100] = "EO must be solved on given axis";
48static char check_dr_msg[100] = "DR must be solved on given axis";
49static char check_htr_msg[100] = "HTR must be solved";
50static char check_drany_msg[100] = "DR must be solved on at least one axis";
51
52/* Steps *********************************************************************/
53
54/* Optimal solvers *******************/
55
56Step
57optimal_HTM = {
58 .shortname = "optimal",
59 .name = "Optimal solve (in HTM)",
60
61 .final = true,
62 .is_done = is_solved,
63 .estimate = estimate_nxopt31_HTM,
64 .ready = check_centers,
65 .ready_msg = check_centers_msg,
66 .is_valid = always_valid,
67 .moveset = &moveset_HTM,
68
69 .pre_trans = uf,
70
71 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
72 .ntables = 2,
73};
74
75Step
76optimal_light_HTM = {
77 .shortname = "light",
78 .name = "Optimal solve (in HTM), small table (500Mb RAM total)",
79
80 .final = true,
81 .is_done = is_solved,
82 .estimate = estimate_light_HTM,
83 .ready = check_centers,
84 .ready_msg = check_centers_msg,
85 .is_valid = always_valid,
86 .moveset = &moveset_HTM,
87
88 .pre_trans = uf,
89
90 .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM},
91 .ntables = 2,
92};
93
94/* Optimal after EO ******************/
95
96Step
97eofin_eo = {
98 .shortname = "eofin",
99 .name = "Optimal solve after EO without breaking EO (detected)",
100
101 .final = true,
102 .is_done = is_solved,
103 .estimate = estimate_nxopt31_HTM,
104 .ready = check_eofb,
105 .ready_msg = check_eo_msg,
106 .is_valid = always_valid,
107 .moveset = &moveset_eofb,
108
109 .detect = detect_pretrans_eofb,
110
111 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
112 .ntables = 2,
113};
114
115Step
116eofbfin_eofb = {
117 .shortname = "eofbfin",
118 .name = "Optimal after EO on F/B without breaking EO",
119
120 .final = true,
121 .is_done = is_solved,
122 .estimate = estimate_nxopt31_HTM,
123 .ready = check_eofb,
124 .ready_msg = check_eo_msg,
125 .is_valid = always_valid,
126 .moveset = &moveset_eofb,
127
128 .pre_trans = uf,
129
130 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
131 .ntables = 2,
132};
133
134Step
135eorlfin_eorl = {
136 .shortname = "eorlfin",
137 .name = "Optimal after EO on R/L without breaking EO",
138
139 .final = true,
140 .is_done = is_solved,
141 .estimate = estimate_nxopt31_HTM,
142 .ready = check_eofb,
143 .ready_msg = check_eo_msg,
144 .is_valid = always_valid,
145 .moveset = &moveset_eofb,
146
147 .pre_trans = ur,
148
149 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
150 .ntables = 2,
151};
152
153Step
154eoudfin_eoud = {
155 .shortname = "eoudfin",
156 .name = "Optimal after EO on U/D without breaking EO",
157
158 .final = true,
159 .is_done = is_solved,
160 .estimate = estimate_nxopt31_HTM,
161 .ready = check_eofb,
162 .ready_msg = check_eo_msg,
163 .is_valid = always_valid,
164 .moveset = &moveset_eofb,
165
166 .pre_trans = fd,
167
168 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
169 .ntables = 2,
170};
171
172/* EO steps **************************/
173Step
174eoany_HTM = {
175 .shortname = "eo",
176 .name = "EO on any axis",
177
178 .final = false,
179 .is_done = check_eofb,
180 .estimate = estimate_eofb_HTM,
181 .ready = check_centers,
182 .ready_msg = check_centers_msg,
183 .is_valid = validate_singlecw_ending,
184 .moveset = &moveset_HTM,
185
186 .detect = detect_pretrans_void_3axis,
187
188 .tables = {&pd_eofb_HTM},
189 .ntables = 1,
190};
191
192Step
193eofb_HTM = {
194 .shortname = "eofb",
195 .name = "EO on F/B",
196
197 .final = false,
198 .is_done = check_eofb,
199 .estimate = estimate_eofb_HTM,
200 .ready = check_centers,
201 .ready_msg = check_centers_msg,
202 .is_valid = validate_singlecw_ending,
203 .moveset = &moveset_HTM,
204
205 .pre_trans = uf,
206
207 .tables = {&pd_eofb_HTM},
208 .ntables = 1,
209};
210
211Step
212eorl_HTM = {
213 .shortname = "eorl",
214 .name = "EO on R/L",
215
216 .final = false,
217 .is_done = check_eofb,
218 .estimate = estimate_eofb_HTM,
219 .ready = check_centers,
220 .ready_msg = check_centers_msg,
221 .is_valid = validate_singlecw_ending,
222 .moveset = &moveset_HTM,
223
224 .pre_trans = ur,
225
226 .tables = {&pd_eofb_HTM},
227 .ntables = 1,
228};
229
230Step
231eoud_HTM = {
232 .shortname = "eoud",
233 .name = "EO on U/D",
234
235 .final = false,
236 .is_done = check_eofb,
237 .estimate = estimate_eofb_HTM,
238 .ready = check_centers,
239 .ready_msg = check_centers_msg,
240 .is_valid = validate_singlecw_ending,
241 .moveset = &moveset_HTM,
242
243 .pre_trans = fd,
244
245 .tables = {&pd_eofb_HTM},
246 .ntables = 1,
247};
248
249/* CO steps **************************/
250Step
251coany_HTM = {
252 .shortname = "co",
253 .name = "CO on any axis",
254
255 .final = false,
256 .is_done = check_coud_HTM,
257 .estimate = estimate_coud_HTM,
258 .ready = NULL,
259 .is_valid = validate_singlecw_ending,
260 .moveset = &moveset_HTM,
261
262 .detect = detect_pretrans_void_3axis,
263
264 .tables = {&pd_coud_HTM},
265 .ntables = 1,
266};
267
268Step
269coud_HTM = {
270 .shortname = "coud",
271 .name = "CO on U/D",
272
273 .final = false,
274 .is_done = check_coud_HTM,
275 .estimate = estimate_coud_HTM,
276 .ready = NULL,
277 .is_valid = validate_singlecw_ending,
278 .moveset = &moveset_HTM,
279
280 .pre_trans = uf,
281
282 .tables = {&pd_coud_HTM},
283 .ntables = 1,
284};
285
286Step
287corl_HTM = {
288 .shortname = "corl",
289 .name = "CO on R/L",
290
291 .final = false,
292 .is_done = check_coud_HTM,
293 .estimate = estimate_coud_HTM,
294 .ready = NULL,
295 .is_valid = validate_singlecw_ending,
296 .moveset = &moveset_HTM,
297
298 .pre_trans = rf,
299
300 .tables = {&pd_coud_HTM},
301 .ntables = 1,
302};
303
304Step
305cofb_HTM = {
306 .shortname = "cofb",
307 .name = "CO on F/B",
308
309 .final = false,
310 .is_done = check_coud_HTM,
311 .estimate = estimate_coud_HTM,
312 .ready = NULL,
313 .is_valid = validate_singlecw_ending,
314 .moveset = &moveset_HTM,
315
316 .pre_trans = fd,
317
318 .tables = {&pd_coud_HTM},
319 .ntables = 1,
320};
321
322Step
323coany_URF = {
324 .shortname = "co-URF",
325 .name = "CO any axis (URF moveset)",
326
327 .final = false,
328 .is_done = check_coud_URF,
329 .estimate = estimate_coud_URF,
330 .ready = NULL,
331 .is_valid = validate_singlecw_ending,
332 .moveset = &moveset_URF,
333
334 .detect = detect_pretrans_void_3axis,
335
336 .tables = {&pd_coud_HTM},
337 .ntables = 1,
338};
339
340Step
341coud_URF = {
342 .shortname = "coud-URF",
343 .name = "CO on U/D (URF moveset)",
344
345 .final = false,
346 .is_done = check_coud_URF,
347 .estimate = estimate_coud_URF,
348 .ready = NULL,
349 .is_valid = validate_singlecw_ending,
350 .moveset = &moveset_URF,
351
352 .pre_trans = uf,
353
354 .tables = {&pd_coud_HTM},
355 .ntables = 1,
356};
357
358Step
359corl_URF = {
360 .shortname = "corl-URF",
361 .name = "CO on R/L (URF moveset)",
362
363 .final = false,
364 .is_done = check_coud_URF,
365 .estimate = estimate_coud_URF,
366 .ready = NULL,
367 .is_valid = validate_singlecw_ending,
368 .moveset = &moveset_URF,
369
370 .pre_trans = rf,
371
372 .tables = {&pd_coud_HTM},
373 .ntables = 1,
374};
375
376Step
377cofb_URF = {
378 .shortname = "cofb-URF",
379 .name = "CO on F/B (URF moveset)",
380
381 .final = false,
382 .is_done = check_coud_URF,
383 .estimate = estimate_coud_URF,
384 .ready = NULL,
385 .is_valid = validate_singlecw_ending,
386 .moveset = &moveset_URF,
387
388 .pre_trans = fd,
389
390 .tables = {&pd_coud_HTM},
391 .ntables = 1,
392};
393
394/* Misc corner steps *****************/
395Step
396cornershtr_HTM = {
397 .shortname = "chtr",
398 .name = "Solve corners to HTR state",
399
400 .final = false,
401 .is_done = check_cornershtr,
402 .estimate = estimate_cornershtr_HTM,
403 .ready = NULL,
404 .is_valid = validate_singlecw_ending,
405 .moveset = &moveset_HTM,
406
407 .pre_trans = uf,
408
409 .tables = {&pd_cornershtr_HTM},
410 .ntables = 1,
411};
412
413Step
414cornershtr_URF = {
415 .shortname = "chtr-URF",
416 .name = "Solve corners to HTR state (URF moveset)",
417
418 .final = false,
419 .is_done = check_cornershtr,
420 .estimate = estimate_cornershtr_URF,
421 .ready = NULL,
422 .is_valid = validate_singlecw_ending,
423 .moveset = &moveset_URF,
424
425 .pre_trans = uf,
426
427 .tables = {&pd_cornershtr_HTM},
428 .ntables = 1,
429};
430
431Step
432corners_HTM = {
433 .shortname = "corners",
434 .name = "Solve corners",
435
436 .final = true,
437 .is_done = check_corners_HTM,
438 .estimate = estimate_corners_HTM,
439 .ready = NULL,
440 .is_valid = always_valid,
441 .moveset = &moveset_HTM,
442
443 .pre_trans = uf,
444
445 .tables = {&pd_corners_HTM},
446 .ntables = 1,
447};
448
449Step
450corners_URF = {
451 .shortname = "corners-URF",
452 .name = "Solve corners (URF moveset)",
453
454 .final = true, /* TODO: check if this works with reorient */
455 .is_done = check_corners_URF,
456 .estimate = estimate_corners_URF,
457 .ready = NULL,
458 .is_valid = always_valid,
459 .moveset = &moveset_URF,
460
461 .pre_trans = uf,
462
463 .tables = {&pd_corners_HTM},
464 .ntables = 1,
465};
466
467/* DR steps **************************/
468Step
469drany_HTM = {
470 .shortname = "dr",
471 .name = "DR on any axis",
472
473 .final = false,
474 .is_done = check_drud,
475 .estimate = estimate_drud_HTM,
476 .ready = check_centers,
477 .ready_msg = check_centers_msg,
478 .is_valid = validate_singlecw_ending,
479 .moveset = &moveset_HTM,
480
481 .detect = detect_pretrans_void_3axis,
482
483 .tables = {&pd_drud_sym16_HTM},
484 .ntables = 1,
485};
486
487Step
488drud_HTM = {
489 .shortname = "drud",
490 .name = "DR on U/D",
491
492 .final = false,
493 .is_done = check_drud,
494 .estimate = estimate_drud_HTM,
495 .ready = check_centers,
496 .ready_msg = check_centers_msg,
497 .is_valid = validate_singlecw_ending,
498 .moveset = &moveset_HTM,
499
500 .pre_trans = uf,
501
502 .tables = {&pd_drud_sym16_HTM},
503 .ntables = 1,
504};
505
506Step
507drrl_HTM = {
508 .shortname = "drrl",
509 .name = "DR on R/L",
510
511 .final = false,
512 .is_done = check_drud,
513 .estimate = estimate_drud_HTM,
514 .ready = check_centers,
515 .ready_msg = check_centers_msg,
516 .is_valid = validate_singlecw_ending,
517 .moveset = &moveset_HTM,
518
519 .pre_trans = rf,
520
521 .tables = {&pd_drud_sym16_HTM},
522 .ntables = 1,
523};
524
525Step
526drfb_HTM = {
527 .shortname = "drfb",
528 .name = "DR on F/B",
529
530 .final = false,
531 .is_done = check_drud,
532 .estimate = estimate_drud_HTM,
533 .ready = check_centers,
534 .ready_msg = check_centers_msg,
535 .is_valid = validate_singlecw_ending,
536 .moveset = &moveset_HTM,
537
538 .pre_trans = fd,
539
540 .tables = {&pd_drud_sym16_HTM},
541 .ntables = 1,
542};
543
544/* DR from EO */
545Step
546dr_eo = {
547 .shortname = "dr-eo",
548 .name = "DR without breaking EO (automatically detected)",
549
550 .final = false,
551 .is_done = check_drud,
552 .estimate = estimate_dr_eofb,
553 .ready = check_eofb,
554 .ready_msg = check_eo_msg,
555 .is_valid = validate_singlecw_ending,
556 .moveset = &moveset_eofb,
557
558 .detect = detect_pretrans_eofb,
559
560 .tables = {&pd_drud_eofb},
561 .ntables = 1,
562};
563
564Step
565dr_eofb = {
566 .shortname = "dr-eofb",
567 .name = "DR on U/D or R/L without breaking EO on F/B",
568
569 .final = false,
570 .is_done = check_drud,
571 .estimate = estimate_dr_eofb,
572 .ready = check_eofb,
573 .ready_msg = check_eo_msg,
574 .is_valid = validate_singlecw_ending,
575 .moveset = &moveset_eofb,
576
577 .pre_trans = uf,
578
579 .tables = {&pd_drud_eofb},
580 .ntables = 1,
581};
582
583Step
584dr_eorl = {
585 .shortname = "dr-eorl",
586 .name = "DR on U/D or F/B without breaking EO on R/L",
587
588 .final = false,
589 .is_done = check_drud,
590 .estimate = estimate_dr_eofb,
591 .ready = check_eofb,
592 .ready_msg = check_eo_msg,
593 .is_valid = validate_singlecw_ending,
594 .moveset = &moveset_eofb,
595
596 .pre_trans = ur,
597
598 .tables = {&pd_drud_eofb},
599 .ntables = 1,
600};
601
602Step
603dr_eoud = {
604 .shortname = "dr-eoud",
605 .name = "DR on R/L or F/B without breaking EO on U/D",
606
607 .final = false,
608 .is_done = check_drud,
609 .estimate = estimate_dr_eofb,
610 .ready = check_eofb,
611 .ready_msg = check_eo_msg,
612 .is_valid = validate_singlecw_ending,
613 .moveset = &moveset_eofb,
614
615 .pre_trans = fd,
616
617 .tables = {&pd_drud_eofb},
618 .ntables = 1,
619};
620
621Step
622drud_eofb = {
623 .shortname = "drud-eofb",
624 .name = "DR on U/D without breaking EO on F/B",
625
626 .final = false,
627 .is_done = check_drud,
628 .estimate = estimate_drud_eofb,
629 .ready = check_eofb,
630 .ready_msg = check_eo_msg,
631 .is_valid = validate_singlecw_ending,
632 .moveset = &moveset_eofb,
633
634 .pre_trans = uf,
635
636 .tables = {&pd_drud_eofb},
637 .ntables = 1,
638};
639
640Step
641drrl_eofb = {
642 .shortname = "drrl-eofb",
643 .name = "DR on R/L without breaking EO on F/B",
644
645 .final = false,
646 .is_done = check_drud,
647 .estimate = estimate_drud_eofb,
648 .ready = check_eofb,
649 .ready_msg = check_eo_msg,
650 .is_valid = validate_singlecw_ending,
651 .moveset = &moveset_eofb,
652
653 .pre_trans = rf,
654
655 .tables = {&pd_drud_eofb},
656 .ntables = 1,
657};
658
659Step
660drud_eorl = {
661 .shortname = "drud-eorl",
662 .name = "DR on U/D without breaking EO on R/L",
663
664 .final = false,
665 .is_done = check_drud,
666 .estimate = estimate_drud_eofb,
667 .ready = check_eofb,
668 .ready_msg = check_eo_msg,
669 .is_valid = validate_singlecw_ending,
670 .moveset = &moveset_eofb,
671
672 .pre_trans = ur,
673
674 .tables = {&pd_drud_eofb},
675 .ntables = 1,
676};
677
678Step
679drfb_eorl = {
680 .shortname = "drfb-eorl",
681 .name = "DR on F/B without breaking EO on R/L",
682
683 .final = false,
684 .is_done = check_drud,
685 .estimate = estimate_drud_eofb,
686 .ready = check_eofb,
687 .ready_msg = check_eo_msg,
688 .is_valid = validate_singlecw_ending,
689 .moveset = &moveset_eofb,
690
691 .pre_trans = fr,
692
693 .tables = {&pd_drud_eofb},
694 .ntables = 1,
695};
696
697Step
698drfb_eoud = {
699 .shortname = "drfb-eoud",
700 .name = "DR on F/B without breaking EO on U/D",
701
702 .final = false,
703 .is_done = check_drud,
704 .estimate = estimate_drud_eofb,
705 .ready = check_eofb,
706 .ready_msg = check_eo_msg,
707 .is_valid = validate_singlecw_ending,
708 .moveset = &moveset_eofb,
709
710 .pre_trans = fd,
711
712 .tables = {&pd_drud_eofb},
713 .ntables = 1,
714};
715
716Step
717drrl_eoud = {
718 .shortname = "drrl-eoud",
719 .name = "DR on R/L without breaking EO on U/D",
720
721 .final = false,
722 .is_done = check_drud,
723 .estimate = estimate_drud_eofb,
724 .ready = check_eofb,
725 .ready_msg = check_eo_msg,
726 .is_valid = validate_singlecw_ending,
727 .moveset = &moveset_eofb,
728
729 .pre_trans = rd,
730
731 .tables = {&pd_drud_eofb},
732 .ntables = 1,
733};
734
735/* DR finish steps */
736Step
737dranyfin_DR = {
738 .shortname = "drfin",
739 .name = "DR finish on any axis without breaking DR",
740
741 .final = true,
742 .is_done = is_solved,
743 .estimate = estimate_drudfin_drud,
744 .ready = check_drud,
745 .ready_msg = check_drany_msg,
746 .is_valid = always_valid,
747 .moveset = &moveset_drud,
748
749 .detect = detect_pretrans_drud,
750
751 .tables = {&pd_drudfin_noE_sym16_drud},
752 .ntables = 1,
753};
754
755Step
756drudfin_drud = {
757 .shortname = "drudfin",
758 .name = "DR finish on U/D without breaking DR",
759
760 .final = true,
761 .is_done = is_solved,
762 .estimate = estimate_drudfin_drud,
763 .ready = check_drud,
764 .ready_msg = check_dr_msg,
765 .is_valid = always_valid,
766 .moveset = &moveset_drud,
767
768 .pre_trans = uf,
769
770 .tables = {&pd_drudfin_noE_sym16_drud},
771 .ntables = 1,
772};
773
774Step
775drrlfin_drrl = {
776 .shortname = "drrlfin",
777 .name = "DR finish on R/L without breaking DR",
778
779 .final = true,
780 .is_done = is_solved,
781 .estimate = estimate_drudfin_drud,
782 .ready = check_drud,
783 .ready_msg = check_dr_msg,
784 .is_valid = always_valid,
785 .moveset = &moveset_drud,
786
787 .pre_trans = rf,
788
789 .tables = {&pd_drudfin_noE_sym16_drud},
790 .ntables = 1,
791};
792
793Step
794drfbfin_drfb = {
795 .shortname = "drfbfin",
796 .name = "DR finish on F/B without breaking DR",
797
798 .final = true,
799 .is_done = is_solved,
800 .estimate = estimate_drudfin_drud,
801 .ready = check_drud,
802 .ready_msg = check_dr_msg,
803 .is_valid = always_valid,
804 .moveset = &moveset_drud,
805
806 .pre_trans = fd,
807
808 .tables = {&pd_drudfin_noE_sym16_drud},
809 .ntables = 1,
810};
811
812/* HTR from DR */
813Step
814htr_any = {
815 .shortname = "htr",
816 .name = "HTR from DR",
817
818 .final = false,
819 .is_done = check_htr,
820 .estimate = estimate_htr_drud,
821 .ready = check_drud,
822 .ready_msg = check_drany_msg,
823 .is_valid = validate_singlecw_ending,
824 .moveset = &moveset_drud,
825 2
826 .detect = detect_pretrans_drud, 3#include "steps.h"
827
828 .tables = {&pd_htr_drud},
829 .ntables = 1,
830};
831
832Step
833htr_drud = {
834 .shortname = "htr-drud",
835 .name = "HTR from DR on U/D",
836
837 .final = false,
838 .is_done = check_htr,
839 .estimate = estimate_htr_drud,
840 .ready = check_drud,
841 .ready_msg = check_dr_msg,
842 .is_valid = validate_singlecw_ending,
843 .moveset = &moveset_drud,
844
845 .pre_trans = uf,
846
847 .tables = {&pd_htr_drud},
848 .ntables = 1,
849};
850
851Step
852htr_drrl = {
853 .shortname = "htr-drrl",
854 .name = "HTR from DR on R/L",
855
856 .final = false,
857 .is_done = check_htr,
858 .estimate = estimate_htr_drud,
859 .ready = check_drud,
860 .ready_msg = check_dr_msg,
861 .is_valid = validate_singlecw_ending,
862 .moveset = &moveset_drud,
863
864 .pre_trans = rf,
865
866 .tables = {&pd_htr_drud},
867 .ntables = 1,
868};
869
870Step
871htr_drfb = {
872 .shortname = "htr-drfb",
873 .name = "HTR from DR on F/B",
874
875 .final = false,
876 .is_done = check_htr,
877 .estimate = estimate_htr_drud,
878 .ready = check_drud,
879 .ready_msg = check_dr_msg,
880 .is_valid = validate_singlecw_ending,
881 .moveset = &moveset_drud,
882
883 .pre_trans = fd,
884
885 .tables = {&pd_htr_drud},
886 .ntables = 1,
887};
888
889/* HTR finish */
890Step
891htrfin_htr = {
892 .shortname = "htrfin",
893 .name = "HTR finish without breaking HTR",
894
895 .final = true,
896 .is_done = is_solved,
897 .estimate = estimate_htrfin_htr,
898 .ready = check_htr,
899 .ready_msg = check_htr_msg,
900 .is_valid = always_valid,
901 .moveset = &moveset_htr,
902
903 .pre_trans = uf,
904
905 .tables = {&pd_htrfin_htr},
906 .ntables = 1,
907};
908
909Step *steps[] = {
910 &optimal_HTM, /* first is default */
911 &optimal_light_HTM,
912
913 &eofin_eo,
914 &eofbfin_eofb,
915 &eorlfin_eorl,
916 &eoudfin_eoud,
917
918 &eoany_HTM,
919 &eofb_HTM,
920 &eorl_HTM,
921 &eoud_HTM,
922
923 &coany_HTM,
924 &coud_HTM,
925 &corl_HTM,
926 &cofb_HTM,
927
928 &coany_URF,
929 &coud_URF,
930 &corl_URF,
931 &cofb_URF,
932
933 &drany_HTM,
934 &drud_HTM,
935 &drrl_HTM,
936 &drfb_HTM,
937
938 &dr_eo,
939 &dr_eofb,
940 &dr_eorl,
941 &dr_eoud,
942 &drud_eofb,
943 &drrl_eofb,
944 &drud_eorl,
945 &drfb_eorl,
946 &drfb_eoud,
947 &drrl_eoud,
948
949 &dranyfin_DR,
950 &drudfin_drud,
951 &drrlfin_drrl,
952 &drfbfin_drfb,
953
954 &htr_any,
955 &htr_drud,
956 &htr_drrl,
957 &htr_drfb,
958
959 &htrfin_htr,
960
961 &cornershtr_HTM,
962 &cornershtr_URF,
963 &corners_HTM,
964 &corners_URF,
965
966 NULL
967};
968
969/* Checkers, estimators and validators ***************************************/
970
971static bool
972check_centers(Cube cube)
973{
974 return cube.cpos == 0;
975}
976
977static bool
978check_coud_HTM(Cube cube)
979{
980 return cube.coud == 0;
981}
982
983static bool
984check_coud_URF(Cube cube)
985{
986 Cube c2, c3;
987
988 c2 = apply_move(z, cube);
989 c3 = apply_move(x, cube);
990 4
991 return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; 5/* TODO: change all checkers to use coordinates! */
992}
993 6
994static bool 7bool
995check_corners_URF(Cube cube) 8check_centers(Cube *cube)
996{ 9{
997 Cube c; 10 int i;
998 Trans i;
999 11
1000 for (i = 0; i < NROTATIONS; i++) { 12 for (i = 0; i < 6; i++)
1001 c = apply_alg(rotation_alg(i), cube); 13 if (cube->xp[i] != i)
1002 if (c.cp && c.coud) 14 return false;
1003 return true;
1004 }
1005 15
1006 return false; 16 return true;
1007} 17}
1008 18
1009static bool 19bool
1010check_corners_HTM(Cube cube) 20check_coud_HTM(Cube *cube)
1011{ 21{
1012 return cube.cp == 0 && cube.coud == 0; 22 int i;
1013}
1014 23
1015static bool 24 for (i = 0; i < 8; i++)
1016check_cornershtr(Cube cube) 25 if (cube->co[i] != 0)
1017{ 26 return false;
1018 return coord_cornershtr.index(cube) == 0;
1019}
1020 27
1021static bool 28 return true;
1022check_eofb(Cube cube)
1023{
1024 return cube.eofb == 0;
1025} 29}
1026 30
1027static bool 31bool
1028check_drud(Cube cube) 32check_coud_URF(Cube *cube)
1029{ 33{
1030 return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; 34 Cube c2, c3;
1031}
1032 35
1033static bool 36 copy_cube(cube, &c2);
1034check_htr(Cube cube) 37 copy_cube(cube, &c3);
1035{
1036 return check_drud(cube) && coord_htr_drud.index(cube) == 0;
1037}
1038 38
1039static int 39 apply_move(z, &c2);
1040estimate_eofb_HTM(DfsArg *arg) 40 apply_move(x, &c3);
1041{
1042 return ptableval(&pd_eofb_HTM, arg->cube);
1043}
1044 41
1045static int 42 return check_coud_HTM(cube) ||
1046estimate_coud_HTM(DfsArg *arg) 43 check_coud_HTM(&c2) ||
1047{ 44 check_coud_HTM(&c3);
1048 return ptableval(&pd_coud_HTM, arg->cube);
1049} 45}
1050 46
1051static int 47bool
1052estimate_coud_URF(DfsArg *arg) 48check_cp_HTM(Cube *cube)
1053{ 49{
1054 /* TODO: I can improve this by checking first the orientation of 50 int i;
1055 * the corner in DBL and use that as a reference */
1056
1057 Cube c;
1058
1059 c = arg->cube;
1060
1061 int ud = estimate_coud_HTM(arg);
1062 arg->cube = apply_move(z, c);
1063 int rl = estimate_coud_HTM(arg);
1064 arg->cube = apply_move(x, c);
1065 int fb = estimate_coud_HTM(arg);
1066
1067 arg->cube = c;
1068 51
1069 return MIN(ud, MIN(rl, fb)); 52 for (i = 0; i < 8; i++)
1070} 53 if (cube->cp[i] != i)
54 return false;
1071 55
1072static int 56 return true;
1073estimate_corners_HTM(DfsArg *arg)
1074{
1075 return ptableval(&pd_corners_HTM, arg->cube);
1076}
1077
1078static int
1079estimate_cornershtr_HTM(DfsArg *arg)
1080{
1081 return ptableval(&pd_cornershtr_HTM, arg->cube);
1082} 57}
1083 58
1084static int 59bool
1085estimate_cornershtr_URF(DfsArg *arg) 60check_corners_HTM(Cube *cube)
1086{ 61{
1087 /* TODO: I can improve this by checking first the corner in DBL 62 return check_coud_HTM(cube) && check_cp_HTM(cube);
1088 * and use that as a reference */
1089
1090 int ret;
1091 Cube c;
1092 Trans i;
1093
1094 c = arg->cube;
1095 ret = 15;
1096
1097 for (i = 0; i < NROTATIONS; i++) {
1098 arg->cube = apply_alg(rotation_alg(i), c);
1099 ret = MIN(ret, estimate_cornershtr_HTM(arg));
1100 }
1101
1102 arg->cube = c;
1103
1104 return ret;
1105} 63}
1106 64
1107static int 65bool
1108estimate_corners_URF(DfsArg *arg) 66check_corners_URF(Cube *cube)
1109{ 67{
1110 /* TODO: I can improve this by checking first the corner in DBL
1111 * and use that as a reference */
1112
1113 int ret;
1114 Cube c; 68 Cube c;
1115 Trans i; 69 Trans i;
1116 70
1117 c = arg->cube;
1118 ret = 15;
1119
1120 for (i = 0; i < NROTATIONS; i++) { 71 for (i = 0; i < NROTATIONS; i++) {
1121 arg->cube = apply_alg(rotation_alg(i), c); 72 copy_cube(cube, &c);
1122 ret = MIN(ret, estimate_corners_HTM(arg)); 73 apply_alg(rotation_alg(i), &c);
74 if (check_corners_HTM(&c))
75 return true;
1123 } 76 }
1124 77
1125 arg->cube = c; 78 return false;
1126
1127 return ret;
1128}
1129
1130static int
1131estimate_drud_HTM(DfsArg *arg)
1132{
1133 return ptableval(&pd_drud_sym16_HTM, arg->cube);
1134}
1135
1136static int
1137estimate_drud_eofb(DfsArg *arg)
1138{
1139 return ptableval(&pd_drud_eofb, arg->cube);
1140}
1141
1142static int
1143estimate_dr_eofb(DfsArg *arg)
1144{
1145 int r1, r2;
1146
1147 r1 = ptableval(&pd_drud_eofb, arg->cube);
1148 r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube));
1149
1150 return MIN(r1, r2);
1151}
1152
1153static int
1154estimate_drudfin_drud(DfsArg *arg)
1155{
1156 int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube);
1157
1158 if (val != 0)
1159 return val;
1160
1161 return arg->cube.epose % 24 == 0 ? 0 : 1;
1162}
1163
1164static int
1165estimate_htr_drud(DfsArg *arg)
1166{
1167 return ptableval(&pd_htr_drud, arg->cube);
1168}
1169
1170static int
1171estimate_htrfin_htr(DfsArg *arg)
1172{
1173 return ptableval(&pd_htrfin_htr, arg->cube);
1174} 79}
1175 80
1176static int 81bool
1177estimate_nxopt31_HTM(DfsArg *arg) 82check_cornershtr(Cube *cube)
1178{ 83{
1179 return estimate_nxoptlike(arg, &pd_nxopt31_HTM); 84 /* TODO (use coord) */
85 return true;
1180} 86}
1181 87
1182/* TODO: also use generic procedure for this */ 88bool
1183static int 89check_eofb(Cube *cube)
1184estimate_light_HTM(DfsArg *arg)
1185{ 90{
1186 int target, ret; 91 /* TODO (use coord) */
1187 Cube aux; 92 return true;
1188
1189 static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) |
1190 (1<<D) | (1<<D2) | (1<<D3);
1191 static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) |
1192 (1<<L) | (1<<L2) | (1<<L3);
1193 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) |
1194 (1<<B) | (1<<B2) | (1<<B3);
1195 static const uint64_t htmask = (1<<U2) | (1<<D2) |
1196 (1<<R2) | (1<<L2) |
1197 (1<<F2) | (1<<B2);
1198
1199 ret = -1;
1200 target = arg->d - arg->current_alg->len;
1201 arg->inverse = (Cube){0};
1202 arg->badmovesinv = 0;
1203 arg->badmoves = 0;
1204
1205 /* Corners */
1206 arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube);
1207 UPDATECHECKSTOP(ret, arg->ed->corners, target);
1208
1209 /* Normal probing */
1210 arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube);
1211 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target);
1212 aux = apply_trans(fd, arg->cube);
1213 arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux);
1214 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target);
1215 aux = apply_trans(rf, arg->cube);
1216 arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux);
1217 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target);
1218
1219 /* If ret == 0, it's solved (corners + triple slice solved) */
1220 if (ret == 0)
1221 return is_solved(arg->cube) ? 0 : 1;
1222
1223 /* Michel de Bondt's trick*/
1224 if (arg->ed->normal_ud == arg->ed->normal_fb &&
1225 arg->ed->normal_fb == arg->ed->normal_rl) {
1226 UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target);
1227 }
1228
1229 /* Inverse probing */
1230 if (!((1<<arg->last1) & htmask)) {
1231 aux = arg->inverse = inverse_cube(arg->cube);
1232 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) {
1233 arg->ed->inverse_ud =
1234 ptableval(&pd_drud_sym16_HTM, aux);
1235 }
1236 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1237 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) {
1238 aux = apply_trans(fd, arg->inverse);
1239 arg->ed->inverse_fb =
1240 ptableval(&pd_drud_sym16_HTM, aux);
1241 }
1242 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1243 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) {
1244 aux = apply_trans(rf, arg->inverse);
1245 arg->ed->inverse_rl =
1246 ptableval(&pd_drud_sym16_HTM, aux);
1247 }
1248 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1249 } else {
1250 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1251 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1252 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1253 }
1254
1255 /* Michel de Bondt's trick*/
1256 if (arg->ed->inverse_ud == arg->ed->inverse_fb &&
1257 arg->ed->inverse_fb == arg->ed->inverse_rl) {
1258 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target);
1259 }
1260
1261 /* nxopt trick + half turn trick */
1262 if (arg->ed->normal_ud == target)
1263 arg->badmovesinv |= udmask | htmask;
1264 if (arg->ed->normal_fb == target)
1265 arg->badmovesinv |= fbmask | htmask;
1266 if (arg->ed->normal_rl == target)
1267 arg->badmovesinv |= rlmask | htmask;
1268
1269 if (arg->ed->inverse_ud == target)
1270 arg->badmoves |= udmask | htmask;
1271 if (arg->ed->inverse_fb == target)
1272 arg->badmoves |= fbmask | htmask;
1273 if (arg->ed->inverse_rl == target)
1274 arg->badmoves |= rlmask | htmask;
1275
1276 return arg->ed->oldret = ret;
1277} 93}
1278 94
1279static int 95bool
1280estimate_nxoptlike(DfsArg *arg, PruneData *pd) 96check_drud(Cube *cube)
1281{ 97{
1282 int target, ret; 98 /* TODO (use coord) */
1283 Cube aux; 99 return true;
1284
1285 static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) |
1286 (1<<D) | (1<<D2) | (1<<D3);
1287 static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) |
1288 (1<<L) | (1<<L2) | (1<<L3);
1289 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) |
1290 (1<<B) | (1<<B2) | (1<<B3);
1291
1292 ret = -1;
1293 target = arg->d - arg->current_alg->len;
1294 arg->inverse = (Cube){0};
1295 arg->badmovesinv = 0;
1296 arg->badmoves = 0;
1297
1298 /* Corners */
1299 arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube);
1300 UPDATECHECKSTOP(ret, arg->ed->corners, target);
1301
1302 /* Normal probing */
1303 arg->ed->normal_ud = ptableval(pd, arg->cube);
1304 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target);
1305 aux = apply_trans(fd, arg->cube);
1306 arg->ed->normal_fb = ptableval(pd, aux);
1307 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target);
1308 aux = apply_trans(rf, arg->cube);
1309 arg->ed->normal_rl = ptableval(pd, aux);
1310 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target);
1311
1312 if (ret == 0)
1313 return arg->step->is_done(arg->cube) ? 0 : 1;
1314
1315 /* Michel de Bondt's trick*/
1316 if (arg->ed->normal_ud == arg->ed->normal_fb &&
1317 arg->ed->normal_fb == arg->ed->normal_rl) {
1318 UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target);
1319 }
1320
1321 /* Inverse probing */
1322 aux = arg->inverse = inverse_cube(arg->cube);
1323 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) {
1324 arg->ed->inverse_ud = ptableval(pd, aux);
1325 }
1326 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1327 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) {
1328 aux = apply_trans(fd, arg->inverse);
1329 arg->ed->inverse_fb = ptableval(pd, aux);
1330 }
1331 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1332 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) {
1333 aux = apply_trans(rf, arg->inverse);
1334 arg->ed->inverse_rl = ptableval(pd, aux);
1335 }
1336 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1337
1338 /* Michel de Bondt's trick*/
1339 if (arg->ed->inverse_ud == arg->ed->inverse_fb &&
1340 arg->ed->inverse_fb == arg->ed->inverse_rl) {
1341 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target);
1342 }
1343
1344 /* nxopt trick */
1345 if (arg->ed->normal_ud == target)
1346 arg->badmovesinv |= udmask;
1347 if (arg->ed->normal_fb == target)
1348 arg->badmovesinv |= fbmask;
1349 if (arg->ed->normal_rl == target)
1350 arg->badmovesinv |= rlmask;
1351
1352 if (arg->ed->inverse_ud == target)
1353 arg->badmoves |= udmask;
1354 if (arg->ed->inverse_fb == target)
1355 arg->badmoves |= fbmask;
1356 if (arg->ed->inverse_rl == target)
1357 arg->badmoves |= rlmask;
1358
1359 return arg->ed->oldret = ret;
1360} 100}
1361 101
1362 102bool
1363static bool 103check_htr(Cube *cube)
1364always_valid(Alg *alg)
1365{ 104{
105 /* TODO (check_drud(cube) and coord_htr_drud == 0) */
1366 return true; 106 return true;
1367} 107}
1368 108
1369static bool 109bool
1370validate_singlecw_ending(Alg *alg) 110validate_singlecw_ending(Alg *alg)
1371{ 111{
1372 int i; 112 int i;
@@ -1389,93 +129,93 @@ validate_singlecw_ending(Alg *alg)
1389 return nor && inv; 129 return nor && inv;
1390} 130}
1391 131
1392/* Pre-transformation detectors **********************************************/ 132/* Public functions **********************************************************/
1393 133
1394static int 134void
1395detect_pretrans_eofb(Cube cube, Trans *ret) 135compute_ind(StepAlt *a, Cube *cube, Movable *ind)
1396{ 136{
1397 int i, n; 137 int i;
1398 static Trans tt[3] = {uf, ur, fd}; 138 Cube mvd;
139 Trans t, tt;
1399 140
1400 for (i = 0, n = 0; i < 3; i++) 141 for (i = 0; i < a->n_coord; i++) {
1401 if (check_eofb(apply_trans(tt[i], cube))) 142 t = a->coord_trans[i];
1402 ret[n++] = tt[i]; 143 copy_cube(cube, &mvd);
144 apply_trans(t, &mvd);
1403 145
1404 return n; 146 ind[i].val = index_coord(a->coord[i], &mvd, &tt);
147 ind[i].t = transform_trans(tt, t);
148 }
1405} 149}
1406 150
1407static int 151int
1408detect_pretrans_drud(Cube cube, Trans *ret) 152estimate_stepalt(StepAlt *a, Movable *ind, int goal)
1409{ 153{
1410 int i, n; 154 int i, ret, est[a->n_coord];
1411 static Trans tt[3] = {uf, fr, rd};
1412 155
1413 for (i = 0, n = 0; i < 3; i++) 156 for (i = 0; i < a->n_coord; i++) {
1414 if (check_drud(apply_trans(tt[i], cube))) 157 est[i] = ptableval(a->pd[i], ind[i].val);
1415 ret[n++] = tt[i]; 158 if (est[i] == a->pd[i]->base && a->compact_pd[i])
159 est[i] = ptableval(a->fallback_pd[i],
160 ind[i].val/a->fbmod[i]);
161 if (ind[i].val != 0 && est[i] == 0) /* est == 0 iff solved */
162 est[i] = 1;
163/*
164TODO: remove this debug code
165printf("%d: est=%d | ", i, est[i]);
166*/
1416 167
1417 return n; 168 if (est[i] > goal)
1418} 169 return est[i];
170 }
1419 171
1420static int 172 for (i = 0; i < a->n_dbtrick; i++)
1421detect_pretrans_void_3axis(Cube cube, Trans *ret) 173 if (est[a->dbtrick[i][0]] > 0 &&
1422{ 174 est[a->dbtrick[i][0]] == est[a->dbtrick[i][1]] &&
1423 ret[0] = uf; 175 est[a->dbtrick[i][0]] == est[a->dbtrick[i][2]])
1424 ret[1] = fr; 176 est[a->dbtrick[i][0]] += 1;
1425 ret[2] = rd;
1426 177
1427 return 3; 178 for (i = 0, ret = -1; i < a->n_coord; i++)
1428} 179 ret = MAX(ret, est[i]);
1429 180
1430/* Public functions **********************************************************/ 181/*
182TODO: remove this debug code
183printf("Final estimate: %d\n", ret);
184*/
1431 185
1432void 186 return ret;
1433copy_estimatedata(EstimateData *src, EstimateData *dst)
1434{
1435 dst->corners = src->corners;
1436 dst->normal_ud = src->normal_ud;
1437 dst->normal_fb = src->normal_fb;
1438 dst->normal_rl = src->normal_rl;
1439 dst->inverse_ud = src->inverse_ud;
1440 dst->inverse_fb = src->inverse_fb;
1441 dst->inverse_rl = src->inverse_rl;
1442 dst->oldret = src->oldret;
1443} 187}
1444 188
1445void 189void
1446invert_estimatedata(EstimateData *ed) 190prepare_step(Step *step, SolveOptions *opts)
1447{ 191{
1448 swap(&(ed->normal_ud), &(ed->inverse_ud)); 192 int i, j;
1449 swap(&(ed->normal_fb), &(ed->inverse_fb)); 193 PDGenData pdg;
1450 swap(&(ed->normal_rl), &(ed->inverse_rl)); 194 StepAlt *a;
1451}
1452 195
1453void 196 for (i = 0; step->alt[i] != NULL; i++) {
1454reset_estimatedata(EstimateData *ed) 197 a = step->alt[i];
1455{ 198 init_moveset(a->moveset);
1456 ed->corners = -1; 199 pdg.moveset = a->moveset;
1457 ed->normal_ud = -1; 200 for (j = 0; j < a->n_coord; j++) {
1458 ed->normal_fb = -1; 201 gen_coord(a->coord[j]);
1459 ed->normal_rl = -1;
1460 ed->inverse_ud = -1;
1461 ed->inverse_fb = -1;
1462 ed->inverse_rl = -1;
1463 ed->oldret = -1;
1464}
1465 202
1466void 203 pdg.coord = a->coord[j];
1467prepare_step(Step *step, SolveOptions *opts) 204 pdg.compact = a->compact_pd[j];
1468{ 205 pdg.pd = NULL;
1469 int i;
1470 206
1471 if (step->final && opts->can_niss) { 207 a->pd[j] = genptable(&pdg, opts->nthreads);
1472 opts->can_niss = false; 208
1473 fprintf(stderr, "Step is final, NISS not used (-n ignored)\n"); 209 if (a->compact_pd[j]) {
1474 } 210 gen_coord(a->fallback_coord[j]);
1475 211
1476 for (i = 0; i < step->ntables; i++) { 212 pdg.coord = a->fallback_coord[j];
1477 genptable(step->tables[i], opts->nthreads); 213 pdg.compact = false;
1478 if (step->tables[i]->compact) 214 pdg.pd = NULL;
1479 genptable(step->tables[i]->fallback, opts->nthreads); 215
216 a->fallback_pd[j] =
217 genptable(&pdg, opts->nthreads);
218 }
219 }
1480 } 220 }
1481} 221}
diff --git a/src/steps.h b/src/steps.h
index da5c041..341be98 100644
--- a/src/steps.h
+++ b/src/steps.h
@@ -3,15 +3,275 @@
3 3
4#include "pruning.h" 4#include "pruning.h"
5 5
6extern Step * steps[]; 6bool check_centers(Cube *cube);
7bool check_coud_HTM(Cube *cube);
8bool check_coud_URF(Cube *cube);
9bool check_cp_HTM(Cube *cube);
10bool check_corners_HTM(Cube *cube);
11bool check_corners_URF(Cube *cube);
12bool check_cornershtr(Cube *cube);
13bool check_eofb(Cube *cube);
14bool check_drud(Cube *cube);
15bool check_htr(Cube *cube);
16void compute_ind(StepAlt *a, Cube *cube, Movable *ind);
17int estimate_stepalt(StepAlt *a, Movable *ind, int goal);
18void prepare_step(Step *step, SolveOptions *opts);
19bool always_valid(Alg *alg);
20bool validate_singlecw_ending(Alg *alg);
7 21
8/* Two steps used directly by two-phase solver */ 22#ifndef STEPS_C
9extern Step drany_HTM;
10extern Step dranyfin_DR;
11 23
12void copy_estimatedata(EstimateData *s, EstimateData *d); 24extern char check_centers_msg[100];
13void invert_estimatedata(EstimateData *ed); 25extern char check_eo_msg[100];
14void reset_estimatedata(EstimateData *ed); 26extern char check_dr_msg[100];
15void prepare_step(Step *step, SolveOptions *opts); 27extern char check_htr_msg[100];
28extern char check_drany_msg[100];
29
30extern StepAlt sa_nxopt31_HTM;
31extern StepAlt sa_eofb_HTM;
32extern StepAlt sa_drud_HTM;
33extern StepAlt sa_drfin_drud;
34
35extern Step optimal_HTM;
36extern Step eoany_HTM;
37extern Step eofb_HTM;
38extern Step eorl_HTM;
39extern Step eoud_HTM;
40extern Step drany_HTM;
41extern Step drud_HTM;
42extern Step drrl_HTM;
43extern Step drfb_HTM;
44extern Step dranyfin_DR;
45extern Step drudfin_drud;
46extern Step drrlfin_drrl;
47extern Step drfbfin_drfb;
48
49extern Step *steps[];
50
51#else
52
53char check_centers_msg[100] = "cube must be oriented (centers solved)";
54char check_eo_msg[100] = "EO must be solved on given axis";
55char check_dr_msg[100] = "DR must be solved on given axis";
56char check_htr_msg[100] = "HTR must be solved";
57char check_drany_msg[100] = "DR must be solved on at least one axis";
58
59/* Optimal solvers *******************/
60/* TODO: build options for smaller optimal solvers */
61
62StepAlt
63sa_nxopt31_HTM = {
64 .ready = check_centers,
65 .final = true,
66 .moveset = &moveset_HTM,
67 .n_coord = 6,
68 .coord = {&coord_nxopt31, &coord_nxopt31, &coord_nxopt31,
69 &coord_eposepe, &coord_eposepe, &coord_eposepe},
70 /* TODO: use khuge as fallback? */
71 .coord_trans = {uf, rd, bl, uf, rd, bl},
72 .compact_pd = {true, true, true, false, false, false},
73 .fallback_coord = {&coord_drud_sym16, &coord_drud_sym16,
74 &coord_drud_sym16},
75 .fbmod = {BINOM8ON4, BINOM8ON4, BINOM8ON4},
76 .n_dbtrick = 1, /* TODO: change to 2 when khuge */
77 .dbtrick = {{0, 1, 2}},
78 .is_valid = NULL,
79};
80Step
81optimal_HTM = {
82 .shortname = "optimal",
83 .name = "Optimal solve (in HTM)",
84 .alt = {&sa_nxopt31_HTM, NULL},
85 .t = {uf},
86 .ready_msg = check_centers_msg,
87};
88
89/* Optimal after EO ******************/
90/* TODO: eofin_eo (generic), eofbfin_eofb, eorlfin_eorl, eoudfin_eoud */
91
92/* EO steps **************************/
93/* TODO: eoany_HTM (generic), eofb_HTM, eorl_HTM, eoud_HTM */
94
95StepAlt
96sa_eofb_HTM = {
97 .ready = check_centers,
98 .final = false,
99 .moveset = &moveset_HTM,
100 .n_coord = 1,
101 .coord = {&coord_eofb},
102 .coord_trans = {uf},
103 .compact_pd = {false},
104 .n_dbtrick = 0,
105 .is_valid = validate_singlecw_ending,
106};
107Step
108eoany_HTM = {
109 .shortname = "eo",
110 .name = "EO on any axis",
111 .alt = {&sa_eofb_HTM, &sa_eofb_HTM, &sa_eofb_HTM, NULL},
112 .t = {uf, ur, fd},
113 .ready_msg = check_centers_msg,
114};
115Step
116eofb_HTM = {
117 .shortname = "eofb",
118 .name = "EO on F/B",
119 .alt = {&sa_eofb_HTM, NULL},
120 .t = {uf},
121 .ready_msg = check_centers_msg,
122};
123Step
124eorl_HTM = {
125 .shortname = "eorl",
126 .name = "EO on R/L",
127 .alt = {&sa_eofb_HTM, NULL},
128 .t = {ur},
129 .ready_msg = check_centers_msg,
130};
131Step
132eoud_HTM = {
133 .shortname = "eoud",
134 .name = "EO on U/D",
135 .alt = {&sa_eofb_HTM, NULL},
136 .t = {fd},
137 .ready_msg = check_centers_msg,
138};
139
140/* CO steps **************************/
141/* TODO: coany_HTM (generic), cofb_HTM, corl_HTM, coud_HTM */
142/* TODO: coany_URF (generic), cofb_URF, corl_URF, coud_URF */
143
144/* Misc corner steps *****************/
145/* TODO: cornershtr_HTM, cornershtr_URF, corners_HTM, corners_URF */
146/* TODO (new): corners_drud */
147
148/* DR steps **************************/
149/* TODO: dr_eo (generic) */
150/* TODO: dr_eofb (generic), dr_eorl (generic), dr_eoud (generic) */
151/* TODO: drud_eofb, drrl_eofb, drud_eorl, drfb_eorl, drrl_eoud, drfb_eoud */
152
153StepAlt
154sa_drud_HTM = {
155 .ready = check_centers,
156 .final = false,
157 .moveset = &moveset_HTM,
158 .n_coord = 1,
159 .coord = {&coord_drud_sym16},
160 .coord_trans = {uf},
161 .compact_pd = {false}, /* TODO: maybe compactify */
162 .n_dbtrick = 0,
163 .is_valid = validate_singlecw_ending,
164};
165Step
166drany_HTM = {
167 .shortname = "dr",
168 .name = "DR on any axis",
169 .alt = {&sa_drud_HTM, &sa_drud_HTM, &sa_drud_HTM, NULL},
170 .t = {uf, rf, fd},
171 .ready_msg = check_centers_msg,
172};
173Step
174drud_HTM = {
175 .shortname = "drud",
176 .name = "DR on U/D",
177 .alt = {&sa_drud_HTM, NULL},
178 .t = {uf},
179 .ready_msg = check_centers_msg,
180};
181Step
182drrl_HTM = {
183 .shortname = "drrl",
184 .name = "DR on R/L",
185 .alt = {&sa_drud_HTM, NULL},
186 .t = {rf},
187 .ready_msg = check_centers_msg,
188};
189Step
190drfb_HTM = {
191 .shortname = "drfb",
192 .name = "DR on F/B",
193 .alt = {&sa_drud_HTM, NULL},
194 .t = {fd},
195 .ready_msg = check_centers_msg,
196};
197
198/* DR finish steps */
199StepAlt
200sa_drfin_drud = {
201 .ready = check_drud,
202 .final = true,
203 .moveset = &moveset_drud,
204 .n_coord = 1,
205 .coord = {&coord_drudfin_noE_sym16}, /* TODO: maybe no noE */
206 .coord_trans = {uf},
207 .compact_pd = {false}, /* TODO: maybe compactify */
208 .n_dbtrick = 0,
209 .is_valid = NULL,
210};
211Step
212dranyfin_DR = {
213 .shortname = "drfin",
214 .name = "DR finish on any axis without breaking DR",
215 .alt = {&sa_drfin_drud, &sa_drfin_drud, &sa_drfin_drud, NULL},
216 .t = {uf, rf, fd},
217 .ready_msg = check_dr_msg,
218};
219Step
220drudfin_drud = {
221 .shortname = "drudfin",
222 .name = "DR finis on U/D without breaking DR",
223 .alt = {&sa_drfin_drud, NULL},
224 .t = {uf},
225 .ready_msg = check_dr_msg,
226};
227Step
228drrlfin_drrl = {
229 .shortname = "drrlfin",
230 .name = "DR finish on R/L without breaking DR",
231 .alt = {&sa_drfin_drud, NULL},
232 .t = {rf},
233 .ready_msg = check_dr_msg,
234};
235Step
236drfbfin_drfb = {
237 .shortname = "drfbfin",
238 .name = "DR finish on F/B without breaking DR",
239 .alt = {&sa_drfin_drud, NULL},
240 .t = {fd},
241 .ready_msg = check_dr_msg,
242};
243
244/* HTR from DR */
245/* TODO: htr_any (generic), htr_drud, htr_drrl, htr_drfb */
246
247/* HTR finish */
248/* TODO: htrfin_htr */
249
250Step *steps[] = {
251 &optimal_HTM, /* first is default */
252
253 &eoany_HTM, &eofb_HTM, &eorl_HTM, &eoud_HTM,
254 &drany_HTM, &drud_HTM, &drrl_HTM, &drfb_HTM,
255 &dranyfin_DR, &drudfin_drud, &drrlfin_drrl, &drfbfin_drfb,
256
257/* TODO:
258 &optimal_light_HTM,
259
260 &eofin_eo, &eofbfin_eofb, &eorlfin_eorl, &eoudfin_eoud,
261 &coany_HTM, &coud_HTM, &corl_HTM, &cofb_HTM,
262 &coany_URF, &coud_URF, &corl_URF, &cofb_URF,
263 &dr_eo, &dr_eofb, &dr_eorl, &dr_eoud,
264 &drud_eofb, &drrl_eofb,
265 &drud_eorl, &drfb_eorl,
266 &drfb_eoud, &drrl_eoud,
267 &htr_any, &htr_drud, &htr_drrl, &htr_drfb,
268 &htrfin_htr,
269 &cornershtr_HTM, &cornershtr_URF, &corners_HTM, &corners_URF,
270 NULL
271*/
272
273};
274
275#endif
16 276
17#endif 277#endif
diff --git a/src/symcoord.c b/src/symcoord.c
deleted file mode 100644
index 20d7c28..0000000
--- a/src/symcoord.c
+++ /dev/null
@@ -1,687 +0,0 @@
1#include "symcoord.h"
2
3/* These constants have been computed generating the respective SymData */
4#define CLASSES_CP_16 2768
5#define CLASSES_EOFBEPOS_16 64430
6
7static uint64_t index_cp_sym16(Cube cube);
8static uint64_t index_eofbepos_sym16(Cube cube);
9static uint64_t index_drud_sym16(Cube cube);
10static uint64_t index_drudfin_noE_sym16(Cube cube);
11static uint64_t index_nxopt31(Cube cube);
12
13static uint64_t move_cp_sym16(Move m, uint64_t ind);
14static uint64_t move_eofbepos_sym16(Move m, uint64_t ind);
15static uint64_t move_drud_sym16(Move m, uint64_t ind);
16static uint64_t move_drudfin_noE_sym16(Move m, uint64_t ind);
17static uint64_t move_nxopt31(Move m, uint64_t ind);
18
19static int tfind_from_mask(uint64_t mask, Trans *ret);
20static int tfind_drud_sym16(uint64_t ind, Trans *ret);
21static int tfind_drudfin_noE_sym16(uint64_t ind, Trans *ret);
22static int tfind_nxopt31(uint64_t ind, Trans *ret);
23
24static uint64_t transform_cp(Trans t, uint64_t ind);
25static uint64_t transform_eofbepos(Trans t, uint64_t ind);
26static uint64_t transform_drud_sym16(Trans t, uint64_t ind);
27static uint64_t transform_drudfin_noE_sym16(Trans t, uint64_t ind);
28static uint64_t transform_nxopt31(Trans t, uint64_t ind);
29
30static void gensym(SymData *sd);
31static void init_symc_moves();
32static void init_symc_trans();
33static bool read_symdata_file(SymData *sd);
34static bool read_symc_moves_file();
35static bool read_symc_trans_file();
36static bool write_symdata_file(SymData *sd);
37static bool write_symc_moves_file();
38static bool write_symc_trans_file();
39
40/* Some tables ***************************************************************/
41
42static uint64_t move_cp_16[NMOVES][CLASSES_CP_16];
43static uint64_t move_eofbepos_16[NMOVES][CLASSES_EOFBEPOS_16];
44
45static int trans_eofbepos[NTRANS][POW2TO11*BINOM12ON4];
46static int trans_epud[NTRANS][FACTORIAL8];
47static int trans_cpud_separate[NTRANS][BINOM8ON4];
48
49static Trans ttrep_move_cp_16[NMOVES][CLASSES_CP_16];
50static Trans ttrep_move_eofbepos_16[NMOVES][CLASSES_EOFBEPOS_16];
51
52
53/* Transformation groups and symmetry data ***********************************/
54
55static Trans
56trans_group_udfix[16] = {
57 uf, ur, ub, ul,
58 df, dr, db, dl,
59 uf_mirror, ur_mirror, ub_mirror, ul_mirror,
60 df_mirror, dr_mirror, db_mirror, dl_mirror,
61};
62
63static SymData
64sd_cp_16 = {
65 .filename = "sd_cp_16_new",
66 .coord = &coord_cp,
67 .sym_coord = &coord_cp_sym16,
68 .ntrans = 16,
69 .trans = trans_group_udfix,
70 .transform = transform_cp,
71};
72
73static SymData
74sd_eofbepos_16 = {
75 .filename = "sd_eofbepos_16_new",
76 .coord = &coord_eofbepos,
77 .sym_coord = &coord_eofbepos_sym16,
78 .ntrans = 16,
79 .trans = trans_group_udfix,
80 .transform = transform_eofbepos,
81};
82
83SymData * all_sd[] = {
84 &sd_cp_16,
85 &sd_eofbepos_16,
86 NULL
87};
88
89
90/* Coordinates and their implementation **************************************/
91
92Coordinate
93coord_eofbepos_sym16 = {
94 .index = index_eofbepos_sym16,
95 .move = move_eofbepos_sym16,
96};
97
98Coordinate
99coord_cp_sym16 = {
100 .index = index_cp_sym16,
101 .move = move_cp_sym16,
102};
103
104Coordinate
105coord_drud_sym16 = {
106 .index = index_drud_sym16,
107 .move = move_drud_sym16,
108 .max = POW3TO7 * CLASSES_EOFBEPOS_16,
109 .base = &coord_eofbepos_sym16,
110 .transform = transform_drud_sym16,
111 .tfind = tfind_drud_sym16,
112};
113
114Coordinate
115coord_drudfin_noE_sym16 = {
116 .index = index_drudfin_noE_sym16,
117 .move = move_drudfin_noE_sym16,
118 .max = FACTORIAL8 * CLASSES_CP_16,
119 .base = &coord_cp_sym16,
120 .transform = transform_drudfin_noE_sym16,
121 .tfind = tfind_drudfin_noE_sym16,
122};
123
124Coordinate
125coord_nxopt31 = {
126 .index = index_nxopt31,
127 .move = move_nxopt31,
128 .max = POW3TO7 * BINOM8ON4 * CLASSES_EOFBEPOS_16,
129 .base = &coord_eofbepos_sym16,
130 .transform = transform_nxopt31,
131 .tfind = tfind_nxopt31,
132};
133
134/* Functions *****************************************************************/
135
136static uint64_t
137index_cp_sym16(Cube cube)
138{
139 return sd_cp_16.class[coord_cp.index(cube)];
140}
141
142static uint64_t
143index_drud_sym16(Cube cube)
144{
145 Trans t;
146
147 t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)];
148
149 return index_eofbepos_sym16(cube) * POW3TO7 + co_ttable[t][cube.coud];
150}
151
152static uint64_t
153index_drudfin_noE_sym16(Cube cube)
154{
155 Trans t;
156 Cube c;
157
158 t = sd_cp_16.transtorep[coord_cp.index(cube)];
159 c = apply_trans(t, cube);
160
161 /* TODO: add transform to coord_epud to make this faster */
162 return index_cp_sym16(c) * FACTORIAL8 + coord_epud.index(c);
163}
164
165static uint64_t
166index_eofbepos_sym16(Cube cube)
167{
168 return sd_eofbepos_16.class[coord_eofbepos.index(cube)];
169}
170
171static uint64_t
172index_nxopt31(Cube cube)
173{
174 Trans t;
175 uint64_t a;
176 int coud, cp;
177
178 t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)];
179 coud = co_ttable[t][cube.coud];
180 cp = cp_ttable[t][cube.cp];
181 a = (index_eofbepos_sym16(cube)*POW3TO7) + coud;
182
183 return a * BINOM8ON4 + coord_cpud_separate.index((Cube){.cp = cp});
184}
185
186static uint64_t
187move_cp_sym16(Move m, uint64_t ind)
188{
189 return move_cp_16[m][ind];
190}
191
192static uint64_t
193move_eofbepos_sym16(Move m, uint64_t ind)
194{
195 return move_eofbepos_16[m][ind];
196}
197
198static uint64_t
199move_drud_sym16(Move m, uint64_t ind)
200{
201 uint64_t coud, eofbepos;
202 Trans ttr;
203
204 eofbepos = move_eofbepos_16[m][ind / POW3TO7];
205 ttr = ttrep_move_eofbepos_16[m][ind / POW3TO7];
206 coud = coud_mtable[m][ind % POW3TO7];
207 coud = co_ttable[ttr][coud]; /* Source is always coud */
208
209 return eofbepos * POW3TO7 + coud;
210}
211
212static uint64_t
213move_drudfin_noE_sym16(Move m, uint64_t ind)
214{
215 uint64_t cp, epud;
216 Trans ttr;
217
218 cp = move_cp_16[m][ind / FACTORIAL8];
219 ttr = ttrep_move_cp_16[m][ind / FACTORIAL8];
220 epud = coord_epud.move(m, ind % FACTORIAL8);
221 epud = trans_epud[ttr][epud];
222
223 return cp * FACTORIAL8 + epud;
224}
225
226static uint64_t
227move_nxopt31(Move m, uint64_t ind)
228{
229 uint64_t eofbepos, cpsep, coud;
230 Trans ttr;
231
232 eofbepos = ind / (POW3TO7 * BINOM8ON4);
233 coud = (ind / BINOM8ON4) % POW3TO7;
234 cpsep = ind % BINOM8ON4;
235
236 ttr = ttrep_move_eofbepos_16[m][eofbepos];
237 eofbepos = move_eofbepos_16[m][eofbepos];
238 coud = coud_mtable[m][coud];
239 coud = co_ttable[ttr][coud]; /* Source is always coud */
240 cpsep = coord_cpud_separate.move(m, cpsep);
241 cpsep = trans_cpud_separate[ttr][cpsep];
242
243 return (eofbepos * POW3TO7 + coud) * BINOM8ON4 + cpsep;
244}
245
246static uint64_t
247transform_cp(Trans t, uint64_t ind)
248{
249 return cp_ttable[t][ind];
250}
251
252static uint64_t
253transform_eofbepos(Trans t, uint64_t ind)
254{
255 return trans_eofbepos[t][ind];
256}
257
258static uint64_t
259transform_drud_sym16(Trans t, uint64_t ind)
260{
261 uint64_t coud, eofbepos;
262
263 eofbepos = ind / POW3TO7; /* Assum trans fixes eofbepos */
264 coud = co_ttable[t][ind % POW3TO7]; /* Source is always coud */
265
266 return eofbepos * POW3TO7 + coud;
267}
268
269static uint64_t
270transform_drudfin_noE_sym16(Trans t, uint64_t ind)
271{
272 uint64_t cp, epud;
273
274 cp = ind / FACTORIAL8; /* Assume trans fixes cp */
275 epud = trans_epud[t][ind % FACTORIAL8];
276
277 return cp * FACTORIAL8 + epud;
278}
279
280static uint64_t
281transform_nxopt31(Trans t, uint64_t ind)
282{
283 uint64_t eofbepos, cpsep, coud;
284
285 eofbepos = ind / (POW3TO7 * BINOM8ON4);
286 coud = (ind / BINOM8ON4) % POW3TO7;
287 cpsep = ind % BINOM8ON4;
288
289 coud = co_ttable[t][coud]; /* Source is always coud */
290 cpsep = trans_cpud_separate[t][cpsep];
291
292 return (eofbepos * POW3TO7 + coud) * BINOM8ON4 + cpsep;
293}
294
295static int
296tfind_from_mask(uint64_t mask, Trans *ret)
297{
298 Trans t;
299 int i = 0;
300
301 for (t = uf; t < NTRANS; t++)
302 if (((uint64_t)1 << t) & mask)
303 ret[i++] = t;
304
305 return i;
306}
307
308static int
309tfind_drud_sym16(uint64_t ind, Trans *ret)
310{
311 uint64_t mask = sd_eofbepos_16.selfsim[ind / POW3TO7];
312
313 return tfind_from_mask(mask, ret);
314}
315
316static int
317tfind_drudfin_noE_sym16(uint64_t ind, Trans *ret)
318{
319 uint64_t mask = sd_cp_16.selfsim[ind / FACTORIAL8];
320
321 return tfind_from_mask(mask, ret);
322}
323
324static int
325tfind_nxopt31(uint64_t ind, Trans *ret)
326{
327 uint64_t mask = sd_eofbepos_16.selfsim[ind / (POW3TO7 * BINOM8ON4)];
328
329 return tfind_from_mask(mask, ret);
330}
331
332/* Other functions ***********************************************************/
333
334void
335free_sd(SymData *sd)
336{
337 if (sd->generated) {
338 free(sd->class);
339 free(sd->unsym);
340 free(sd->transtorep);
341 }
342
343 sd->generated = false;
344}
345
346static void
347gensym(SymData *sd)
348{
349 uint64_t i, in, nreps = 0;
350 Trans t;
351 int j;
352
353 if (sd->generated)
354 return;
355
356 sd->class = malloc(sd->coord->max * sizeof(uint64_t));
357 sd->unsym = malloc(sd->coord->max * sizeof(uint64_t));
358 sd->transtorep = malloc(sd->coord->max * sizeof(Trans));
359 sd->selfsim = malloc(sd->coord->max * sizeof(uint64_t));
360
361 if (read_symdata_file(sd)) {
362 sd->generated = true;
363 return;
364 }
365
366 fprintf(stderr, "Cannot load %s, generating it\n", sd->filename);
367
368 for (i = 0; i < sd->coord->max; i++)
369 sd->class[i] = sd->coord->max + 1;
370
371 for (i = 0; i < sd->coord->max; i++) {
372 if (sd->class[i] == sd->coord->max + 1) {
373 sd->unsym[nreps] = i;
374 sd->transtorep[i] = uf;
375 sd->selfsim[nreps] = (uint64_t)0;
376 for (j = 0; j < sd->ntrans; j++) {
377 t = sd->trans[j];
378 in = sd->transform(t, i);
379 sd->class[in] = nreps;
380 if (in == i)
381 sd->selfsim[nreps] |=
382 ((uint64_t)1 << t);
383 else
384 sd->transtorep[in] = inverse_trans(t);
385 }
386 nreps++;
387 }
388 }
389
390 sd->sym_coord->max = nreps;
391 sd->unsym = realloc(sd->unsym, nreps * sizeof(uint64_t));
392 sd->selfsim = realloc(sd->selfsim, nreps * sizeof(uint64_t));
393 sd->generated = true;
394
395 fprintf(stderr, "Found %" PRIu64 " classes\n", nreps);
396
397 if (!write_symdata_file(sd))
398 fprintf(stderr, "Error writing SymData file\n");
399
400 return;
401}
402
403static bool
404read_symdata_file(SymData *sd)
405{
406 init_env();
407
408 FILE *f;
409 char fname[strlen(tabledir)+100];
410 uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max;
411 bool r = true;
412
413 strcpy(fname, tabledir);
414 strcat(fname, "/");
415 strcat(fname, sd->filename);
416
417 if ((f = fopen(fname, "rb")) == NULL)
418 return false;
419
420 r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1;
421 r = r && fread(sd->unsym, sizeof(uint64_t), *sn, f) == *sn;
422 r = r && fread(sd->selfsim, sizeof(uint64_t), *sn, f) == *sn;
423 r = r && fread(sd->class, sizeof(uint64_t), n, f) == n;
424 r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n;
425
426 fclose(f);
427 return r;
428}
429
430static bool
431read_symc_moves_file()
432{
433 init_env();
434
435 Move m;
436 bool r = true;
437 FILE *f;
438 char fname[strlen(tabledir)+100];
439
440 strcpy(fname, tabledir);
441 strcat(fname, "/symc_moves");
442
443 if ((f = fopen(fname, "rb")) == NULL)
444 return false;
445
446 for (m = 0; m < NMOVES; m++) {
447 r = r && fread(move_cp_16[m], sizeof(uint64_t),
448 CLASSES_CP_16, f) == CLASSES_CP_16;
449 r = r && fread(move_eofbepos_16[m], sizeof(uint64_t),
450 CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16;
451
452 r = r && fread(ttrep_move_cp_16[m], sizeof(Trans),
453 CLASSES_CP_16, f) == CLASSES_CP_16;
454 r = r && fread(ttrep_move_eofbepos_16[m], sizeof(Trans),
455 CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16;
456 }
457
458 fclose(f);
459 return r;
460}
461
462static bool
463read_symc_trans_file()
464{
465 init_env();
466
467 Trans t;
468 bool r = true;
469 FILE *f;
470 char fname[strlen(tabledir)+100];
471
472 strcpy(fname, tabledir);
473 strcat(fname, "/symc_trans");
474
475 if ((f = fopen(fname, "rb")) == NULL)
476 return false;
477
478 for (t = 0; t < NTRANS; t++) {
479 r = r && fread(trans_eofbepos[t], sizeof(int),
480 POW2TO11*BINOM12ON4, f) == POW2TO11*BINOM12ON4;
481 r = r && fread(trans_epud[t], sizeof(int),
482 FACTORIAL8, f) == FACTORIAL8;
483 r = r && fread(trans_cpud_separate[t], sizeof(int),
484 BINOM8ON4, f) == BINOM8ON4;
485 }
486
487 fclose(f);
488 return r;
489}
490
491static bool
492write_symdata_file(SymData *sd)
493{
494 init_env();
495
496 FILE *f;
497 char fname[strlen(tabledir)+100];
498 uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max;
499 bool r = true;
500
501 strcpy(fname, tabledir);
502 strcat(fname, "/");
503 strcat(fname, sd->filename);
504
505 if ((f = fopen(fname, "wb")) == NULL)
506 return false;
507
508 r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1;
509 r = r && fwrite(sd->unsym, sizeof(uint64_t), *sn, f) == *sn;
510 r = r && fwrite(sd->selfsim, sizeof(uint64_t), *sn, f) == *sn;
511 r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n;
512 r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n;
513
514 fclose(f);
515 return r;
516}
517
518static bool
519write_symc_moves_file()
520{
521 init_env();
522
523 Move m;
524 bool r = true;
525 FILE *f;
526 char fname[strlen(tabledir)+100];
527
528 strcpy(fname, tabledir);
529 strcat(fname, "/symc_moves");
530
531 if ((f = fopen(fname, "wb")) == NULL)
532 return false;
533
534 for (m = 0; m < NMOVES; m++) {
535 r = r && fwrite(move_cp_16[m], sizeof(uint64_t),
536 CLASSES_CP_16, f) == CLASSES_CP_16;
537 r = r && fwrite(move_eofbepos_16[m], sizeof(uint64_t),
538 CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16;
539
540 r = r && fwrite(ttrep_move_cp_16[m], sizeof(Trans),
541 CLASSES_CP_16, f) == CLASSES_CP_16;
542 r = r && fwrite(ttrep_move_eofbepos_16[m], sizeof(Trans),
543 CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16;
544 }
545
546 fclose(f);
547 return r;
548}
549
550static bool
551write_symc_trans_file()
552{
553 init_env();
554
555 Trans t;
556 bool r = true;
557 FILE *f;
558 char fname[strlen(tabledir)+100];
559
560 strcpy(fname, tabledir);
561 strcat(fname, "/symc_trans");
562
563 if ((f = fopen(fname, "wb")) == NULL)
564 return false;
565
566 for (t = 0; t < NTRANS; t++) {
567 r = r && fwrite(trans_eofbepos[t], sizeof(int),
568 POW2TO11*BINOM12ON4, f) == POW2TO11*BINOM12ON4;
569 r = r && fwrite(trans_epud[t], sizeof(int),
570 FACTORIAL8, f) == FACTORIAL8;
571 r = r && fwrite(trans_cpud_separate[t], sizeof(int),
572 BINOM8ON4, f) == BINOM8ON4;
573 }
574
575 fclose(f);
576 return r;
577}
578
579static void
580init_symc_moves()
581{
582 uint64_t i, ii, coo;
583 Move j;
584
585 if (read_symc_moves_file())
586 return;
587
588 for (i = 0; i < CLASSES_CP_16; i++) {
589 ii = sd_cp_16.unsym[i];
590 for (j = 0; j < NMOVES; j++) {
591 coo = sd_cp_16.coord->move(j, ii);
592 move_cp_16[j][i] = sd_cp_16.class[coo];
593 ttrep_move_cp_16[j][i] = sd_cp_16.transtorep[coo];
594 }
595 }
596
597 for (i = 0; i < CLASSES_EOFBEPOS_16; i++) {
598 ii = sd_eofbepos_16.unsym[i];
599 for (j = 0; j < NMOVES; j++) {
600 coo = sd_eofbepos_16.coord->move(j, ii);
601 move_eofbepos_16[j][i] = sd_eofbepos_16.class[coo];
602 ttrep_move_eofbepos_16[j][i] =
603 sd_eofbepos_16.transtorep[coo];
604 }
605 }
606
607 if (!write_symc_moves_file())
608 fprintf(stderr, "Error writing SymMoves file\n");
609}
610
611void
612init_symc_trans()
613{
614 uint64_t i;
615 int j, cp;
616 int epe[4] = {FR, FL, BL, BR};
617 int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 };
618 Cube c;
619 CubeArray *arr, *aux;
620 Trans t;
621
622 if (read_symc_trans_file())
623 return;
624
625 for (i = 0; i < POW2TO11*BINOM12ON4; i++) {
626 for (j = 0; j < 16; j++) {
627 t = trans_group_udfix[j];
628
629 arr = new_cubearray((Cube){0}, pf_edges);
630 int_to_sum_zero_array(i % POW2TO11, 2, 12, arr->eofb);
631 epos_to_compatible_ep((i / POW2TO11)*24, arr->ep, epe);
632 fix_eorleoud(arr);
633 c = arrays_to_cube(arr, pf_edges);
634 free_cubearray(arr, pf_edges);
635
636 c = apply_trans(t, c);
637 trans_eofbepos[t][i] = (c.epose/24)*POW2TO11 + c.eofb;
638 }
639 }
640
641 aux = malloc(sizeof(CubeArray));
642 aux->ep = a;
643 for (i = 0; i < FACTORIAL8; i++) {
644 index_to_perm(i, 8, a);
645 c = arrays_to_cube(aux, pf_ep);
646 for (j = 0; j < 16; j++) {
647 t = trans_group_udfix[j];
648 arr = new_cubearray(apply_trans(t, c), pf_ep);
649 trans_epud[t][i] = perm_to_index(arr->ep, 8);
650 free_cubearray(arr, pf_ep);
651 }
652 }
653 free(aux);
654
655 for (i = 0; i < BINOM8ON4; i++) {
656 cp = cpud_separate_ant[i];
657 for (j = 0; j < 16; j++) {
658 t = trans_group_udfix[j];
659 trans_cpud_separate[t][i] =
660 cpud_separate_ind[cp_ttable[t][cp]];
661 }
662 }
663
664 if (!write_symc_trans_file())
665 fprintf(stderr, "Error writing SymTrans file\n");
666}
667
668void
669init_symcoord()
670{
671 int i;
672
673 static bool initialized = false;
674 if (initialized)
675 return;
676 initialized = true;
677
678 init_coord();
679
680 init_symc_trans();
681
682 for (i = 0; all_sd[i] != NULL; i++)
683 gensym(all_sd[i]);
684
685 init_symc_moves();
686}
687
diff --git a/src/symcoord.h b/src/symcoord.h
deleted file mode 100644
index 0882bff..0000000
--- a/src/symcoord.h
+++ /dev/null
@@ -1,17 +0,0 @@
1#ifndef SYMCOORD_H
2#define SYMCOORD_H
3
4#include "coord.h"
5
6extern Coordinate coord_cp_sym16;
7extern Coordinate coord_eofbepos_sym16;
8extern Coordinate coord_drud_sym16;
9extern Coordinate coord_drudfin_noE_sym16;
10extern Coordinate coord_nxopt31;
11
12extern SymData *all_sd[];
13
14void free_sd(SymData *sd);
15void init_symcoord();
16
17#endif
diff --git a/src/trans.c b/src/trans.c
index e267a17..da2dca3 100644
--- a/src/trans.c
+++ b/src/trans.c
@@ -1,31 +1,23 @@
1#define TRANS_C
2
1#include "trans.h" 3#include "trans.h"
2 4
3/* Local functions ***********************************************************/ 5/* Local functions ***********************************************************/
4 6
5static bool read_ttables_file();
6static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f);
7static bool write_ttables_file();
8
9/* Tables and other data *****************************************************/ 7/* Tables and other data *****************************************************/
10 8
11static int ep_mirror[12] = { 9static Cube mirror_cube = {
12 [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL, 10.ep = { [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL,
13 [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL, 11 [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL,
14 [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL 12 [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL },
15}; 13.cp = { [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL,
16 14 [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL },
17static int cp_mirror[8] = { 15.xp = { [U_center] = U_center, [D_center] = D_center,
18 [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL,
19 [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL
20};
21
22static int cpos_mirror[6] = {
23 [U_center] = U_center, [D_center] = D_center,
24 [R_center] = L_center, [L_center] = R_center, 16 [R_center] = L_center, [L_center] = R_center,
25 [F_center] = F_center, [B_center] = B_center 17 [F_center] = F_center, [B_center] = B_center }
26}; 18};
27 19
28static char rotation_alg_string[100][NROTATIONS] = { 20static char rotation_alg_string[100][NROTATIONS] = {
29 [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", 21 [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3",
30 [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", 22 [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2",
31 [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", 23 [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3",
@@ -34,176 +26,39 @@ static char rotation_alg_string[100][NROTATIONS] = {
34 [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", 26 [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3",
35}; 27};
36 28
37static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ 29static Alg *rotation_alg_arr[NROTATIONS];
38static int eposs_source[NTRANS]; 30Move moves_ttable[NTRANS][NMOVES];
39static int eposm_source[NTRANS]; 31Trans trans_ttable[NTRANS][NTRANS];
40static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ 32Trans trans_itable[NTRANS];
41static int eorl_source[NTRANS];
42static int eoud_source[NTRANS];
43static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */
44static int cofb_source[NTRANS];
45static int corl_source[NTRANS];
46 33
47int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; 34/* Public functions **********************************************************/
48int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8];
49int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8];
50int eo_ttable[NTRANS][POW2TO11];
51int cp_ttable[NTRANS][FACTORIAL8];
52int co_ttable[NTRANS][POW3TO7];
53int cpos_ttable[NTRANS][FACTORIAL6];
54Move moves_ttable[NTRANS][NMOVES];
55
56/* Local functions implementation ********************************************/
57 35
58static bool 36void
59read_ttables_file() 37apply_trans(Trans t, Cube *cube)
60{ 38{
61 init_env(); 39 Cube aux;
62 40 Alg *inv;
63 FILE *f; 41 int i;
64 char fname[strlen(tabledir)+20];
65 int b = sizeof(int);
66 bool r = true;
67 Move m;
68
69 /* Table sizes, used for reading and writing files */
70 uint64_t me[11] = {
71 [0] = FACTORIAL12/FACTORIAL8,
72 [1] = FACTORIAL12/FACTORIAL8,
73 [2] = FACTORIAL12/FACTORIAL8,
74 [3] = POW2TO11,
75 [4] = FACTORIAL8,
76 [5] = POW3TO7,
77 [6] = FACTORIAL6,
78 [7] = NMOVES
79 };
80
81 strcpy(fname, tabledir);
82 strcat(fname, "/");
83 strcat(fname, "ttables");
84 42
85 if ((f = fopen(fname, "rb")) == NULL) 43 inv = inverse_alg(rotation_alg(t % NROTATIONS));
86 return false; 44 copy_cube(cube, &aux);
45 make_solved(cube);
87 46
88 for (m = 0; m < NTRANS; m++) { 47 if (t >= NROTATIONS)
89 r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; 48 compose(&mirror_cube, cube);
90 r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; 49 apply_alg(inv, cube);
91 r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; 50 compose(&aux, cube);
92 r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; 51 apply_alg(rotation_alg(t % NROTATIONS), cube);
93 r = r && fread(cp_ttable[m], b, me[4], f) == me[4]; 52 if (t >= NROTATIONS) {
94 r = r && fread(co_ttable[m], b, me[5], f) == me[5]; 53 compose(&mirror_cube, cube);
95 r = r && fread(cpos_ttable[m], b, me[6], f) == me[6]; 54 for (i = 0; i < 8; i++)
96 r = r && fread(moves_ttable[m], b, me[7], f) == me[7]; 55 cube->co[i] = (3 - cube->co[i]) % 3;
97 } 56 }
98 57
99 fclose(f);
100 return r;
101}
102
103static Cube
104rotate_via_compose(Trans r, Cube c, PieceFilter f)
105{
106 static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
107 static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
108 static CubeArray ma = {
109 .ep = ep_mirror,
110 .eofb = zero12,
111 .eorl = zero12,
112 .eoud = zero12,
113 .cp = cp_mirror,
114 .coud = zero8,
115 .corl = zero8,
116 .cofb = zero8,
117 .cpos = cpos_mirror
118 };
119
120 Alg *inv = inverse_alg(rotation_alg(r));
121 Cube ret = {0};
122
123 if (r >= NROTATIONS)
124 ret = move_via_arrays(&ma, ret, f);
125 ret = apply_alg_generic(inv, ret, f, true);
126
127 ret = compose_filtered(c, ret, f);
128
129 ret = apply_alg_generic(rotation_alg(r), ret, f, true);
130 if (r >= NROTATIONS)
131 ret = move_via_arrays(&ma, ret, f);
132
133 free_alg(inv); 58 free_alg(inv);
134 return ret;
135}
136
137static bool
138write_ttables_file()
139{
140 init_env();
141
142 FILE *f;
143 char fname[strlen(tabledir)+20];
144 bool r = true;
145 int b = sizeof(int);
146 Move m;
147
148 /* Table sizes, used for reading and writing files */
149 uint64_t me[11] = {
150 [0] = FACTORIAL12/FACTORIAL8,
151 [1] = FACTORIAL12/FACTORIAL8,
152 [2] = FACTORIAL12/FACTORIAL8,
153 [3] = POW2TO11,
154 [4] = FACTORIAL8,
155 [5] = POW3TO7,
156 [6] = FACTORIAL6,
157 [7] = NMOVES
158 };
159
160 strcpy(fname, tabledir);
161 strcat(fname, "/ttables");
162
163 if ((f = fopen(fname, "wb")) == NULL)
164 return false;
165
166 for (m = 0; m < NTRANS; m++) {
167 r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0];
168 r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1];
169 r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2];
170 r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3];
171 r = r && fwrite(cp_ttable[m], b, me[4], f) == me[4];
172 r = r && fwrite(co_ttable[m], b, me[5], f) == me[5];
173 r = r && fwrite(cpos_ttable[m], b, me[6], f) == me[6];
174 r = r && fwrite(moves_ttable[m], b, me[7], f) == me[7];
175 }
176
177 fclose(f);
178 return r;
179}
180
181/* Public functions **********************************************************/
182
183Cube
184apply_trans(Trans t, Cube cube)
185{
186 /*init_trans();*/
187
188 int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm };
189 int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb };
190 int aux_co[3] = { cube.coud, cube.corl, cube.cofb };
191
192 return (Cube) {
193 .epose = epose_ttable[t][aux_epos[epose_source[t]]],
194 .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]],
195 .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]],
196 .eofb = eo_ttable[t][aux_eo[eofb_source[t]]],
197 .eorl = eo_ttable[t][aux_eo[eorl_source[t]]],
198 .eoud = eo_ttable[t][aux_eo[eoud_source[t]]],
199 .coud = co_ttable[t][aux_co[coud_source[t]]],
200 .corl = co_ttable[t][aux_co[corl_source[t]]],
201 .cofb = co_ttable[t][aux_co[cofb_source[t]]],
202 .cp = cp_ttable[t][cube.cp],
203 .cpos = cpos_ttable[t][cube.cpos]
204 };
205} 59}
206 60
61/*
207Trans 62Trans
208inverse_trans(Trans t) 63inverse_trans(Trans t)
209{ 64{
@@ -231,23 +86,18 @@ inverse_trans(Trans t)
231 86
232 return inverse_trans_aux[t]; 87 return inverse_trans_aux[t];
233} 88}
89*/
234 90
235Alg * 91Trans
236rotation_alg(Trans t) 92inverse_trans(Trans t)
237{ 93{
238 int i; 94 return trans_itable[t];
239 95}
240 static Alg *rotation_alg_arr[NROTATIONS];
241 static bool initialized = false;
242
243 if (!initialized) {
244 for (i = 0; i < NROTATIONS; i++)
245 rotation_alg_arr[i] = new_alg(rotation_alg_string[i]);
246
247 initialized = true;
248 }
249 96
250 return rotation_alg_arr[t % NROTATIONS]; 97Alg *
98rotation_alg(Trans i)
99{
100 return rotation_alg_arr[i % NROTATIONS];
251} 101}
252 102
253void 103void
@@ -255,10 +105,20 @@ transform_alg(Trans t, Alg *alg)
255{ 105{
256 int i; 106 int i;
257 107
258 /*init_trans();*/
259
260 for (i = 0; i < alg->len; i++) 108 for (i = 0; i < alg->len; i++)
261 alg->move[i] = moves_ttable[t][alg->move[i]]; 109 alg->move[i] = transform_move(t, alg->move[i]);
110}
111
112Move
113transform_move(Trans t, Move m)
114{
115 return moves_ttable[t][m];
116}
117
118Trans
119transform_trans(Trans t, Trans m)
120{
121 return trans_ttable[t][m];
262} 122}
263 123
264void 124void
@@ -268,106 +128,63 @@ init_trans() {
268 return; 128 return;
269 initialized = true; 129 initialized = true;
270 130
271 init_moves(); 131 int i;
272 132 Alg *nonsym_alg, *nonsym_inv;
273 Cube aux, cube, c[3]; 133 Cube aux, cube;
274 CubeArray epcp;
275 int i, eparr[12], eoarr[12], cparr[8], coarr[8];
276 unsigned int ui;
277 Move mi, move; 134 Move mi, move;
278 Trans m; 135 Trans t, u, v;
279 136
280 /* Compute sources */ 137 init_moves();
281 for (i = 0; i < NTRANS; i++) {
282 cube = apply_alg(rotation_alg(i), (Cube){0});
283
284 epose_source[i] = edge_slice(what_edge_at(cube, FR));
285 eposs_source[i] = edge_slice(what_edge_at(cube, UR));
286 eposm_source[i] = edge_slice(what_edge_at(cube, UF));
287 eofb_source[i] = what_center_at(cube, F_center)/2;
288 eorl_source[i] = what_center_at(cube, R_center)/2;
289 eoud_source[i] = what_center_at(cube, U_center)/2;
290 coud_source[i] = what_center_at(cube, U_center)/2;
291 cofb_source[i] = what_center_at(cube, F_center)/2;
292 corl_source[i] = what_center_at(cube, R_center)/2;
293 }
294
295 if (read_ttables_file())
296 return;
297
298 fprintf(stderr, "Cannot load %s, generating it\n", "ttables");
299
300 /* Initialize tables */
301 for (m = 0; m < NTRANS; m++) {
302 epcp = (CubeArray){ .ep = eparr, .cp = cparr };
303 cube = apply_alg(rotation_alg(m), (Cube){0});
304 cube_to_arrays(cube, &epcp, pf_epcp);
305 if (m >= NROTATIONS) {
306 apply_permutation(ep_mirror, eparr, 12);
307 apply_permutation(cp_mirror, cparr, 8);
308 }
309
310 for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) {
311 c[0] = admissible_ep((Cube){ .epose = ui }, pf_e);
312 c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s);
313 c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m);
314
315 cube = rotate_via_compose(m,c[epose_source[m]],pf_ep);
316 epose_ttable[m][ui] = cube.epose;
317 138
318 cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); 139 for (i = 0; i < NROTATIONS; i++)
319 eposs_ttable[m][ui] = cube.eposs; 140 rotation_alg_arr[i] = new_alg(rotation_alg_string[i]);
320 141
321 cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); 142 for (t = 0; t < NTRANS; t++) {
322 eposm_ttable[m][ui] = cube.eposm;
323 }
324 for (ui = 0; ui < POW2TO11; ui++ ) {
325 int_to_sum_zero_array(ui, 2, 12, eoarr);
326 apply_permutation(eparr, eoarr, 12);
327 eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2);
328 }
329 for (ui = 0; ui < POW3TO7; ui++) {
330 int_to_sum_zero_array(ui, 3, 8, coarr);
331 apply_permutation(cparr, coarr, 8);
332 co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3);
333 if (m >= NROTATIONS)
334 co_ttable[m][ui] =
335 invert_digits(co_ttable[m][ui], 3, 7);
336 }
337 for (ui = 0; ui < FACTORIAL8; ui++) {
338 cube = (Cube){ .cp = ui };
339 cube = rotate_via_compose(m, cube, pf_cp);
340 cp_ttable[m][ui] = cube.cp;
341 }
342 for (ui = 0; ui < FACTORIAL6; ui++) {
343 cube = (Cube){ .cpos = ui };
344 cube = rotate_via_compose(m, cube, pf_cpos);
345 cpos_ttable[m][ui] = cube.cpos;
346 }
347 for (mi = 0; mi < NMOVES; mi++) { 143 for (mi = 0; mi < NMOVES; mi++) {
348 /* Old version: 144 make_solved(&aux);
349 * 145 apply_move(mi, &aux);
350 aux = apply_trans(m, apply_move(mi, (Cube){0})); 146 apply_trans(t, &aux);
351 for (move = 0; move < NMOVES; move++) { 147 for (move = 0; move < NMOVES; move++) {
352 cube = apply_move(inverse_move(move), aux); 148 copy_cube(&aux, &cube);
353 mirr = apply_trans(uf_mirror, cube); 149 apply_move(inverse_move(move), &cube);
354 if (is_solved(cube) || is_solved(mirr)) 150 if (is_solved(&cube)) {
355 moves_ttable[m][mi] = move; 151 moves_ttable[t][mi] = move;
152 break;
153 }
356 } 154 }
357 */ 155 }
156 }
358 157
359 aux = apply_trans(m, apply_move(mi, (Cube){0})); 158 nonsym_alg = new_alg("R' U' F");
360 for (move = 0; move < NMOVES; move++) { 159 nonsym_inv = inverse_alg(nonsym_alg);
361 cube = apply_move(inverse_move(move), aux); 160
362 if (is_solved(cube)) { 161 for (t = 0; t < NTRANS; t++) {
363 moves_ttable[m][mi] = move; 162 for (u = 0; u < NTRANS; u++) {
163 make_solved(&aux);
164 apply_alg(nonsym_alg, &aux);
165 apply_trans(u, &aux);
166 apply_trans(t, &aux);
167 for (v = 0; v < NTRANS; v++) {
168 copy_cube(&aux, &cube);
169 apply_trans(v, &cube);
170 apply_alg(nonsym_inv, &cube);
171 if (is_solved(&cube)) {
172 /* This is the inverse of the correct
173 value, it will be inverted later */
174 trans_ttable[t][u] = v;
175 if (v == uf)
176 trans_itable[t] = u;
364 break; 177 break;
365 } 178 }
366 } 179 }
367 } 180 }
368 } 181 }
182 for (t = 0; t < NTRANS; t++)
183 for (u = 0; u < NTRANS; u++)
184 trans_ttable[t][u] = trans_itable[trans_ttable[t][u]];
185
369 186
370 if (!write_ttables_file()) 187 free_alg(nonsym_alg);
371 fprintf(stderr, "Error writing ttables\n"); 188 free_alg(nonsym_inv);
372} 189}
373 190
diff --git a/src/trans.h b/src/trans.h
index 51df12f..0cc8cef 100644
--- a/src/trans.h
+++ b/src/trans.h
@@ -3,24 +3,30 @@
3 3
4#include "moves.h" 4#include "moves.h"
5 5
6/* 6void apply_trans(Trans t, Cube *cube);
7 * Tables are exposed to allow faster partial transformations in some
8 * specific cases (in symcoord)
9 */
10extern int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8];
11extern int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8];
12extern int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8];
13extern int eo_ttable[NTRANS][POW2TO11];
14extern int cp_ttable[NTRANS][FACTORIAL8];
15extern int co_ttable[NTRANS][POW3TO7];
16extern int cpos_ttable[NTRANS][FACTORIAL6];
17extern Move moves_ttable[NTRANS][NMOVES];
18
19Cube apply_trans(Trans t, Cube cube);
20Trans inverse_trans(Trans t); 7Trans inverse_trans(Trans t);
21Alg * rotation_alg(Trans i); 8Alg * rotation_alg(Trans i);
22void transform_alg(Trans i, Alg *alg); 9void transform_alg(Trans t, Alg *alg);
10Move transform_move(Trans t, Move m);
11Trans transform_trans(Trans t, Trans m);
23 12
24void init_trans(); 13void init_trans();
25 14
15#ifndef TRANS_C
16
17extern TransGroup tgrp_udfix;
18
19#else
20
21TransGroup
22tgrp_udfix = {
23 .n = 16,
24 .t = { uf, ur, ub, ul,
25 df, dr, db, dl,
26 uf_mirror, ur_mirror, ub_mirror, ul_mirror,
27 df_mirror, dr_mirror, db_mirror, dl_mirror },
28};
29
30#endif
31
26#endif 32#endif
diff --git a/src/utils.c b/src/utils.c
index e0d3268..cbf951e 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,3 +1,5 @@
1#define UTILS_C
2
1#include "utils.h" 3#include "utils.h"
2 4
3void 5void
@@ -159,24 +161,24 @@ is_perm(int *a, int n)
159{ 161{
160 int *aux = malloc(n * sizeof(int)); 162 int *aux = malloc(n * sizeof(int));
161 int i; 163 int i;
164 bool ret = true;
162 165
163 for (i = 0; i < n; i++) 166 for (i = 0; i < n; i++)
164 aux[i] = 0; 167 aux[i] = 0;
165 168
166 for (i = 0; i < n; i++) { 169 for (i = 0; i < n; i++) {
167 if (a[i] < 0 || a[i] >= n) 170 if (a[i] < 0 || a[i] >= n)
168 return false; 171 ret = false;
169 else 172 else
170 aux[a[i]] = 1; 173 aux[a[i]] = 1;
171 } 174 }
172 175
173 for (i = 0; i < n; i++) 176 for (i = 0; i < n; i++)
174 if (!aux[i]) 177 if (!aux[i])
175 return false; 178 ret = false;
176 179
177 free(aux); 180 free(aux);
178 181 return ret;
179 return true;
180} 182}
181 183
182bool 184bool
@@ -195,7 +197,7 @@ perm_sign(int *a, int n)
195{ 197{
196 int i, j, ret = 0; 198 int i, j, ret = 0;
197 199
198 if (!is_perm(a,n)) 200 if (!is_perm(a, n))
199 return -1; 201 return -1;
200 202
201 for (i = 0; i < n; i++) 203 for (i = 0; i < n; i++)
@@ -211,7 +213,7 @@ perm_to_index(int *a, int n)
211 int i, j, c, ret = 0; 213 int i, j, c, ret = 0;
212 214
213 if (!is_perm(a, n)) 215 if (!is_perm(a, n))
214 return -1; 216 return factorial(n);
215 217
216 for (i = 0; i < n; i++) { 218 for (i = 0; i < n; i++) {
217 c = 0; 219 c = 0;

Generated with cgit - Back to sebastiano.tronto.net