aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-16 19:25:58 +0100
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-16 19:25:58 +0100
commit2f924f942bd6e7126e8f1d8692e475c95bd9fe82 (patch)
treedd5877c2fd836f43523263e48632946423401093
parent4e2b4e603c7e84c7556f489d7d8dab06915b3a9b (diff)
downloadnissy-2f924f942bd6e7126e8f1d8692e475c95bd9fe82.tar.gz
nissy-2f924f942bd6e7126e8f1d8692e475c95bd9fe82.zip
Added a new pruning table (equivalent to nxopt31). I have not tested it yet, it takes a while to generate.
Plus I have done a whole lot of refactoring in random places because I cannot focus on one thing at the time.
Diffstat (limited to '')
-rw-r--r--TODO.md17
-rwxr-xr-xnissybin192888 -> 320064 bytes
-rw-r--r--src/alg.c180
-rw-r--r--src/alg.h15
-rw-r--r--src/commands.c2
-rw-r--r--src/coord.c86
-rw-r--r--src/coord.h2
-rw-r--r--src/cubetypes.h23
-rw-r--r--src/moves.c51
-rw-r--r--src/moves.h2
-rw-r--r--src/pruning.c95
-rw-r--r--src/pruning.h1
-rw-r--r--src/solve.c80
-rw-r--r--src/steps.c246
-rw-r--r--src/symcoord.c85
-rw-r--r--src/symcoord.h2
16 files changed, 555 insertions, 332 deletions
diff --git a/TODO.md b/TODO.md
index 790b520..91907b2 100644
--- a/TODO.md
+++ b/TODO.md
@@ -14,13 +14,11 @@ It's more of a personal reminder than anything else.
14* invert an alg 14* invert an alg
15 15
16### More steps for `solve` 16### More steps for `solve`
17* QTM optimal solving 17* QTM optimal solving (important: fix possible_next, which works only for HTM now)
18* Block-building steps (cross, roux blocks, ...) 18* Block-building steps (cross, roux blocks, ...)
19* Other common steps (LSE, ...) 19* Other common steps (LSE, ...)
20 20
21### Improvements to currently implemented commands 21### Improvements to currently implemented commands
22* batch mode: add separator / info on which command it is executing
23(also change man page for this)
24* solve should re-orient first if needed and not just give up if centers are off 22* solve should re-orient first if needed and not just give up if centers are off
25* solve should try up to a small bound without loading the large pruning table 23* solve should try up to a small bound without loading the large pruning table
26* drfin for HTR scrambles should try all 3 axis and pick the best solutions; 24* drfin for HTR scrambles should try all 3 axis and pick the best solutions;
@@ -42,7 +40,12 @@ It's more of a personal reminder than anything else.
42 40
43## Technical stuff 41## Technical stuff
44 42
45## Performance 43### Memory management
44* Check if memory is enough for loading pruning tables; if not, abort
45* For optimal solver: choose largest that fits in memory between
46 khuge, shug6 and light
47
48### Performance
46* solve (allow_next): filter out based on base_move; only check once for each 49* solve (allow_next): filter out based on base_move; only check once for each
47 triple of moves; how to deal with different movesets? 50 triple of moves; how to deal with different movesets?
48* try htr corners + edges in slice but not oriented (300Mb table); 51* try htr corners + edges in slice but not oriented (300Mb table);
@@ -51,12 +54,8 @@ It's more of a personal reminder than anything else.
51 (like in light optimal solver) 54 (like in light optimal solver)
52* Another idea: DR + cornershtr (5Gb table); same as above, de Bondt's trick 55* Another idea: DR + cornershtr (5Gb table); same as above, de Bondt's trick
53 does not work but I can use half-turn trick 56 does not work but I can use half-turn trick
54* On the contrary: DR + separate UD corners allow dB's trick, but no ht-trick
55 57
56## Coordinates, symmetries, pruning tables 58### Coordinates, symmetries, pruning tables
57* Cleanup symcoord.c: some coordinates and symdata are never actually used;
58remove also sd_eofbepos and just use sd_coud for khuge (this changes the
59coordinate so the whole table must be generated again!) or viceversa
60* Use pruning values mod 4 instead of mod 16 (or maybe not, I like the 59* Use pruning values mod 4 instead of mod 16 (or maybe not, I like the
61current system) 60current system)
62 61
diff --git a/nissy b/nissy
index 3b42c76..6ff9c22 100755
--- a/nissy
+++ b/nissy
Binary files differ
diff --git a/src/alg.c b/src/alg.c
index 1158eba..ffe1679 100644
--- a/src/alg.c
+++ b/src/alg.c
@@ -2,27 +2,76 @@
2 2
3/* Local functions ***********************************************************/ 3/* Local functions ***********************************************************/
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);
12
5static void free_alglistnode(AlgListNode *aln); 13static void free_alglistnode(AlgListNode *aln);
6static void realloc_alg(Alg *alg, int n); 14static void realloc_alg(Alg *alg, int n);
7 15
8/* Movesets ******************************************************************/ 16/* Movesets ******************************************************************/
9 17
10bool 18Moveset
11moveset_HTM(Move m) 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)
12{ 61{
13 return m >= U && m <= B3; 62 return m >= U && m <= B3;
14} 63}
15 64
16bool 65static bool
17moveset_URF(Move m) 66allowed_URF(Move m)
18{ 67{
19 Move b = base_move(m); 68 Move b = base_move(m);
20 69
21 return b == U || b == R || b == F; 70 return b == U || b == R || b == F;
22} 71}
23 72
24bool 73static bool
25moveset_eofb(Move m) 74allowed_eofb(Move m)
26{ 75{
27 Move b = base_move(m); 76 Move b = base_move(m);
28 77
@@ -30,8 +79,8 @@ moveset_eofb(Move m)
30 ((b == F || b == B) && m == b+1); 79 ((b == F || b == B) && m == b+1);
31} 80}
32 81
33bool 82static bool
34moveset_drud(Move m) 83allowed_drud(Move m)
35{ 84{
36 Move b = base_move(m); 85 Move b = base_move(m);
37 86
@@ -39,16 +88,65 @@ moveset_drud(Move m)
39 ((b == R || b == L || b == F || b == B) && m == b + 1); 88 ((b == R || b == L || b == F || b == B) && m == b + 1);
40} 89}
41 90
42bool 91static bool
43moveset_htr(Move m) 92allowed_htr(Move m)
44{ 93{
45 Move b = base_move(m); 94 Move b = base_move(m);
46 95
47 return moveset_HTM(m) && m == b + 1; 96 return moveset_HTM.allowed(m) && m == b + 1;
48} 97}
49 98
99static bool
100allowed_next_HTM(Move l2, Move l1, Move m)
101{
102 bool p, q;
50 103
51/* Functions *****************************************************************/ 104 p = l1 != NULLMOVE && base_move(l1) == base_move(m);
105 q = l2 != NULLMOVE && base_move(l2) == base_move(m);
106
107 return !(p || (commute(l1, l2) && q));
108}
109
110static int
111axis(Move m)
112{
113 Move i;
114
115 static bool initialized = false;
116 static int aux[NMOVES];
117
118 if (!initialized) {
119 for (i = 0; i < NMOVES; i++) {
120 if (i == NULLMOVE)
121 aux[i] = 0;
122
123 if (i >= U && i <= B3)
124 aux[i] = (i-1)/6 + 1;
125
126 if (i >= Uw && i <= Bw3)
127 aux[i] = (i-1)/6 - 2;
128
129 if (base_move(i) == E || base_move(i) == y)
130 aux[i] = 1;
131
132 if (base_move(i) == M || base_move(i) == x)
133 aux[i] = 2;
134
135 if (base_move(i) == S || base_move(i) == z)
136 aux[i] = 3;
137 }
138
139 initialized = true;
140 }
141
142 return aux[m];
143}
144
145bool
146commute(Move m1, Move m2)
147{
148 return axis(m1) == axis(m2);
149}
52 150
53void 151void
54append_alg(AlgList *l, Alg *alg) 152append_alg(AlgList *l, Alg *alg)
@@ -171,33 +269,6 @@ move_string(Move m)
171 return move_string_aux[m]; 269 return move_string_aux[m];
172} 270}
173 271
174void
175movelist_to_position(Move *movelist, int *position)
176{
177 Move m;
178
179 for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++)
180 position[movelist[m]] = m;
181}
182
183void
184moveset_to_list(Moveset ms, Move *r)
185{
186 int n = 0;
187 Move i;
188
189 if (ms == NULL) {
190 fprintf(stderr, "Error: no moveset given\n");
191 return;
192 }
193
194 for (i = U; i < NMOVES; i++)
195 if (ms(i))
196 r[n++] = i;
197
198 r[n] = NULLMOVE;
199}
200
201Alg * 272Alg *
202new_alg(char *str) 273new_alg(char *str)
203{ 274{
@@ -405,3 +476,34 @@ unniss(Alg *alg)
405 } 476 }
406 free(aux); 477 free(aux);
407} 478}
479
480void
481init_movesets()
482{
483 int i, j;
484 uint64_t l, one;
485 Move m, l2, l1;
486 Moveset *ms;
487
488 one = 1;
489
490 for (i = 0; i < nmoveset; i++) {
491 ms = all_ms[i];
492
493 for (j = 0, m = U; m < NMOVES; m++)
494 if (ms->allowed(m))
495 ms->sorted_moves[j++] = m;
496 ms->sorted_moves[j] = NULLMOVE;
497
498 for (l1 = 0; l1 < NMOVES; l1++) {
499 for (l2 = 0; l2 < NMOVES; l2++) {
500 ms->mask[l2][l1] = 0;
501 for (l=0; ms->sorted_moves[l]!=NULLMOVE; l++) {
502 m = ms->sorted_moves[l];
503 if (ms->allowed_next(l2, l1, m))
504 ms->mask[l2][l1] |= (one<<m);
505 }
506 }
507 }
508 }
509}
diff --git a/src/alg.h b/src/alg.h
index f45b682..e046526 100644
--- a/src/alg.h
+++ b/src/alg.h
@@ -8,16 +8,17 @@
8#include "cubetypes.h" 8#include "cubetypes.h"
9#include "utils.h" 9#include "utils.h"
10 10
11bool moveset_HTM(Move m); 11extern Moveset moveset_HTM;
12bool moveset_URF(Move m); 12extern Moveset moveset_URF;
13bool moveset_eofb(Move m); 13extern Moveset moveset_eofb;
14bool moveset_drud(Move m); 14extern Moveset moveset_drud;
15bool moveset_htr(Move m); 15extern Moveset moveset_htr;
16 16
17void append_alg(AlgList *l, Alg *alg); 17void append_alg(AlgList *l, Alg *alg);
18void append_move(Alg *alg, Move m, bool inverse); 18void append_move(Alg *alg, Move m, bool inverse);
19void compose_alg(Alg *alg1, Alg *alg2);
20Move base_move(Move m); 19Move base_move(Move m);
20void compose_alg(Alg *alg1, Alg *alg2);
21bool commute(Move m1, Move m2);
21void free_alg(Alg *alg); 22void free_alg(Alg *alg);
22void free_alglist(AlgList *l); 23void free_alglist(AlgList *l);
23Alg * inverse_alg(Alg *alg); 24Alg * inverse_alg(Alg *alg);
@@ -33,5 +34,7 @@ void print_alglist(AlgList *al, bool l);
33void swapmove(Move *m1, Move *m2); 34void swapmove(Move *m1, Move *m2);
34void unniss(Alg *alg); 35void unniss(Alg *alg);
35 36
37void init_movesets();
38
36#endif 39#endif
37 40
diff --git a/src/commands.c b/src/commands.c
index b90a7f5..9a2ad51 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -259,6 +259,7 @@ solve_exec(CommandArgs *args)
259 Cube c; 259 Cube c;
260 AlgList *sols; 260 AlgList *sols;
261 261
262 init_movesets();
262 init_symcoord(); 263 init_symcoord();
263 264
264 c = apply_alg(args->scramble, (Cube){0}); 265 c = apply_alg(args->scramble, (Cube){0});
@@ -274,6 +275,7 @@ gen_exec(CommandArgs *args)
274 int i; 275 int i;
275 276
276 fprintf(stderr, "Generating coordinates...\n"); 277 fprintf(stderr, "Generating coordinates...\n");
278 init_movesets();
277 init_symcoord(); 279 init_symcoord();
278 280
279 fprintf(stderr, "Generating pruning tables...\n"); 281 fprintf(stderr, "Generating pruning tables...\n");
diff --git a/src/coord.c b/src/coord.c
index c9a28c4..3bbda22 100644
--- a/src/coord.c
+++ b/src/coord.c
@@ -13,6 +13,7 @@ static Cube antindex_drud(uint64_t ind);
13static Cube antindex_drud_eofb(uint64_t ind); 13static Cube antindex_drud_eofb(uint64_t ind);
14static Cube antindex_htr_drud(uint64_t ind); 14static Cube antindex_htr_drud(uint64_t ind);
15static Cube antindex_htrfin(uint64_t ind); 15static Cube antindex_htrfin(uint64_t ind);
16static Cube antindex_cpud_separate(uint64_t ind);
16 17
17static uint64_t index_eofb(Cube cube); 18static uint64_t index_eofb(Cube cube);
18static uint64_t index_eofbepos(Cube cube); 19static uint64_t index_eofbepos(Cube cube);
@@ -27,6 +28,7 @@ static uint64_t index_drud(Cube cube);
27static uint64_t index_drud_eofb(Cube cube); 28static uint64_t index_drud_eofb(Cube cube);
28static uint64_t index_htr_drud(Cube cube); 29static uint64_t index_htr_drud(Cube cube);
29static uint64_t index_htrfin(Cube cube); 30static uint64_t index_htrfin(Cube cube);
31static uint64_t index_cpud_separate(Cube cube);
30 32
31static void init_cphtr_cosets(); 33static void init_cphtr_cosets();
32static void init_cphtr_left_cosets_bfs(int i, int c); 34static void init_cphtr_left_cosets_bfs(int i, int c);
@@ -135,6 +137,13 @@ coord_drud_eofb = {
135 .max = POW3TO7 * BINOM12ON4, 137 .max = POW3TO7 * BINOM12ON4,
136}; 138};
137 139
140Coordinate
141coord_cpud_separate = {
142 .index = index_cpud_separate,
143 .cube = antindex_cpud_separate,
144 .max = BINOM8ON4,
145};
146
138/* Antindexers ***************************************************************/ 147/* Antindexers ***************************************************************/
139 148
140static Cube 149static Cube
@@ -356,6 +365,31 @@ antindex_htrfin(uint64_t ind)
356 return ret; 365 return ret;
357} 366}
358 367
368static Cube
369antindex_cpud_separate(uint64_t ind)
370{
371 /* Not consistent because of side corner orientations and cp */
372 unsigned int ui;
373 int i, co[8], cp[8];
374 Corner u, d;
375
376 static Cube aux[BINOM8ON4];
377 static bool initialized = false;
378
379 if (!initialized) {
380 for (ui = 0; ui < BINOM8ON4; ui++) {
381 index_to_subset(ui, 8, 4, co);
382 for (i = 0, u = UFR, d = DFR; i < 8; i++)
383 cp[i] = co[i] ? d++ : u++;
384 aux[ui] = (Cube){.cp = perm_to_index(cp, 8)};
385 }
386
387 initialized = true;
388 }
389
390 return aux[ind];
391}
392
359/* Indexers ******************************************************************/ 393/* Indexers ******************************************************************/
360 394
361static uint64_t 395static uint64_t
@@ -477,6 +511,29 @@ index_htrfin(Cube cube)
477 return cp * 24 * 24 * 24 + ep; 511 return cp * 24 * 24 * 24 + ep;
478} 512}
479 513
514static uint64_t
515index_cpud_separate(Cube cube)
516{
517 unsigned int ui;
518 int i, co[8];
519
520 static int aux[FACTORIAL8];
521 static bool initialized = false;
522
523 if (!initialized) {
524 for (ui = 0; ui < FACTORIAL8; ui++) {
525 for (i = 0; i < 8; i++)
526 co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ?
527 1 : 0;
528 aux[ui] = subset_to_index(co, 8, 4);
529 }
530
531 initialized = true;
532 }
533
534 return aux[cube.cp];
535}
536
480/* Init functions implementation *********************************************/ 537/* Init functions implementation *********************************************/
481 538
482/* 539/*
@@ -528,7 +585,7 @@ init_cphtr_left_cosets_bfs(int i, int c)
528 while (n != 0) { 585 while (n != 0) {
529 for (j = 0, n2 = 0; j < n; j++) { 586 for (j = 0, n2 = 0; j < n; j++) {
530 for (k = U2; k < B3; k++) { 587 for (k = U2; k < B3; k++) {
531 if (!moveset_htr(k)) 588 if (!moveset_htr.allowed(k))
532 continue; 589 continue;
533 jj = apply_move(k, (Cube){ .cp = next[j] }).cp; 590 jj = apply_move(k, (Cube){ .cp = next[j] }).cp;
534 591
@@ -578,7 +635,7 @@ init_cornershtrfin()
578 if (cornershtrfin_ind[j] == -1) 635 if (cornershtrfin_ind[j] == -1)
579 continue; 636 continue;
580 for (m = U; m < NMOVES; m++) { 637 for (m = U; m < NMOVES; m++) {
581 if (moveset_htr(m)) { 638 if (moveset_htr.allowed(m)) {
582 c = apply_move(m, (Cube){.cp = j}).cp; 639 c = apply_move(m, (Cube){.cp = j}).cp;
583 if (cornershtrfin_ind[c] == -1) { 640 if (cornershtrfin_ind[c] == -1) {
584 cornershtrfin_ind[c] = n; 641 cornershtrfin_ind[c] = n;
@@ -592,6 +649,31 @@ init_cornershtrfin()
592} 649}
593 650
594void 651void
652test_coord(Coordinate *coord)
653{
654 bool passed;
655 uint64_t ui, failcount;
656
657 if (!(passed = (coord->index((Cube){0}) == 0))) {
658 printf("Failed: coordinate of solved cube is "
659 "%" PRIu64 "\n", coord->index((Cube){0}));
660 }
661
662 printf("Testing %" PRIu64 " coordinates\n", coord->max);
663 for (failcount = 0, ui = 0; ui < coord->max; ui++) {
664 if (!(passed = (coord->index(coord->cube(ui)) == ui))) {
665 printf("Failed at %" PRIu64 "\n", ui);
666 failcount++;
667 }
668 }
669
670 if (passed)
671 printf("Ok\n");
672 else
673 printf("Test failed in %" PRIu64 " cases\n", failcount);
674}
675
676void
595init_coord() 677init_coord()
596{ 678{
597 static bool initialized = false; 679 static bool initialized = false;
diff --git a/src/coord.h b/src/coord.h
index be41b96..81e5866 100644
--- a/src/coord.h
+++ b/src/coord.h
@@ -16,7 +16,9 @@ extern Coordinate coord_drud;
16extern Coordinate coord_drud_eofb; 16extern Coordinate coord_drud_eofb;
17extern Coordinate coord_htr_drud; 17extern Coordinate coord_htr_drud;
18extern Coordinate coord_htrfin; 18extern Coordinate coord_htrfin;
19extern Coordinate coord_cpud_separate;
19 20
21void test_coord(Coordinate *coord);
20void init_coord(); 22void init_coord();
21 23
22#endif 24#endif
diff --git a/src/cubetypes.h b/src/cubetypes.h
index 3ad960b..d1d36b2 100644
--- a/src/cubetypes.h
+++ b/src/cubetypes.h
@@ -8,6 +8,7 @@
8#define NMOVES 55 /* Actually 54, but one is NULLMOVE */ 8#define NMOVES 55 /* Actually 54, but one is NULLMOVE */
9#define NTRANS 48 9#define NTRANS 48
10#define NROTATIONS 24 10#define NROTATIONS 24
11#define entry_group_t uint8_t /* For pruning tables */
11 12
12/* Enums *********************************************************************/ 13/* Enums *********************************************************************/
13 14
@@ -83,6 +84,7 @@ typedef struct cube Cube;
83typedef struct cubearray CubeArray; 84typedef struct cubearray CubeArray;
84typedef struct dfsarg DfsArg; 85typedef struct dfsarg DfsArg;
85typedef struct estimatedata EstimateData; 86typedef struct estimatedata EstimateData;
87typedef struct moveset Moveset;
86typedef struct piecefilter PieceFilter; 88typedef struct piecefilter PieceFilter;
87typedef struct prunedata PruneData; 89typedef struct prunedata PruneData;
88typedef struct solveoptions SolveOptions; 90typedef struct solveoptions SolveOptions;
@@ -97,7 +99,6 @@ typedef int (*Estimator) (DfsArg *);
97typedef bool (*Validator) (Alg *); 99typedef bool (*Validator) (Alg *);
98typedef void (*Exec) (CommandArgs *); 100typedef void (*Exec) (CommandArgs *);
99typedef uint64_t (*Indexer) (Cube); 101typedef uint64_t (*Indexer) (Cube);
100typedef bool (*Moveset) (Move);
101typedef CommandArgs * (*ArgParser) (int, char **); 102typedef CommandArgs * (*ArgParser) (int, char **);
102typedef Trans (*TransDetector) (Cube); 103typedef Trans (*TransDetector) (Cube);
103typedef int (*TransFinder) (uint64_t, Trans *); 104typedef int (*TransFinder) (uint64_t, Trans *);
@@ -215,8 +216,6 @@ dfsarg
215 AlgList * sols; 216 AlgList * sols;
216 pthread_mutex_t * sols_mutex; 217 pthread_mutex_t * sols_mutex;
217 Alg * current_alg; 218 Alg * current_alg;
218 Move * sorted_moves;
219 int * move_position;
220}; 219};
221 220
222struct 221struct
@@ -233,6 +232,15 @@ estimatedata
233}; 232};
234 233
235struct 234struct
235moveset
236{
237 bool (*allowed)(Move);
238 bool (*allowed_next)(Move, Move, Move);
239 Move sorted_moves[NMOVES+1];
240 uint64_t mask[NMOVES][NMOVES];
241};
242
243struct
236piecefilter 244piecefilter
237{ 245{
238 bool epose; 246 bool epose;
@@ -252,11 +260,11 @@ struct
252prunedata 260prunedata
253{ 261{
254 char * filename; 262 char * filename;
255 uint8_t * ptable; 263 entry_group_t * ptable;
256 bool generated; 264 bool generated;
257 uint64_t n; 265 uint64_t n;
258 Coordinate * coord; 266 Coordinate * coord;
259 Moveset moveset; 267 Moveset * moveset;
260}; 268};
261 269
262struct 270struct
@@ -284,7 +292,7 @@ step
284 Checker ready; 292 Checker ready;
285 char * ready_msg; 293 char * ready_msg;
286 Validator is_valid; 294 Validator is_valid;
287 Moveset moveset; 295 Moveset * moveset;
288 Trans pre_trans; 296 Trans pre_trans;
289 TransDetector detect; 297 TransDetector detect;
290 int ntables; 298 int ntables;
@@ -312,8 +320,6 @@ threaddatasolve
312 Cube cube; 320 Cube cube;
313 Step * step; 321 Step * step;
314 int depth; 322 int depth;
315 Move * sorted_moves;
316 int * move_position;
317 SolveOptions * opts; 323 SolveOptions * opts;
318 AlgList * start; 324 AlgList * start;
319 AlgListNode ** node; 325 AlgListNode ** node;
@@ -329,7 +335,6 @@ threaddatagenpt
329 int nthreads; 335 int nthreads;
330 PruneData * pd; 336 PruneData * pd;
331 int d; 337 int d;
332 Move * ms;
333 int nchunks; 338 int nchunks;
334 pthread_mutex_t ** mutex; 339 pthread_mutex_t ** mutex;
335 pthread_mutex_t * upmutex; 340 pthread_mutex_t * upmutex;
diff --git a/src/moves.c b/src/moves.c
index 5aca0ee..9547de9 100644
--- a/src/moves.c
+++ b/src/moves.c
@@ -319,57 +319,6 @@ write_mtables_file()
319 return r; 319 return r;
320} 320}
321 321
322bool
323commute(Move m1, Move m2)
324{
325 static bool initialized = false;
326 static bool commute_aux[NMOVES][NMOVES];
327
328 if (!initialized) {
329 Cube c1, c2;
330 int i, j;
331
332 for (i = 0; i < NMOVES; i++) {
333 for (j = 0; j < NMOVES; j++) {
334 c1 = apply_move(i, apply_move(j, (Cube){0}));
335 c2 = apply_move(j, apply_move(i, (Cube){0}));
336 commute_aux[i][j] = equal(c1, c2) && i && j;
337 }
338 }
339
340 initialized = true;
341 }
342
343 return commute_aux[m1][m2];
344}
345
346bool
347possible_next(Move m1, Move m2, Move m3)
348{
349 static bool initialized = false;
350 static bool paux[NMOVES][NMOVES][NMOVES];
351
352 if (!initialized) {
353 int i, j, k;
354 bool p, q, c;
355
356 for (i = 0; i < NMOVES; i++) {
357 for (j = 0; j < NMOVES; j++) {
358 for (k = 0; k < NMOVES; k++) {
359 p = j && base_move(j) == base_move(k);
360 q = i && base_move(i) == base_move(k);
361 c = commute(i, j);
362 paux[i][j][k] = !(p || (c && q));
363 }
364 }
365 }
366
367 initialized = true;
368 }
369
370 return paux[m1][m2][m3];
371}
372
373void 322void
374init_moves() { 323init_moves() {
375 static bool initialized = false; 324 static bool initialized = false;
diff --git a/src/moves.h b/src/moves.h
index 082a080..4820f65 100644
--- a/src/moves.h
+++ b/src/moves.h
@@ -8,8 +8,6 @@
8Cube apply_alg(Alg *alg, Cube cube); 8Cube apply_alg(Alg *alg, Cube cube);
9Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); 9Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a);
10Cube apply_move(Move m, Cube cube); 10Cube apply_move(Move m, Cube cube);
11bool commute(Move m1, Move m2);
12bool possible_next(Move m1, Move m2, Move m3);
13 11
14void init_moves(); 12void init_moves();
15 13
diff --git a/src/pruning.c b/src/pruning.c
index b305a89..0a6e305 100644
--- a/src/pruning.c
+++ b/src/pruning.c
@@ -1,11 +1,10 @@
1#include "pruning.h" 1#include "pruning.h"
2 2
3/* Chunks for multithreading */ 3#define NCHUNKS 100000
4/* TODO: try smaller */ 4#define ENTRIES_PER_GROUP (2*sizeof(entry_group_t))
5#define NCHUNKS 100000
6 5
7static int findchunk(PruneData *pd, int nchunks, uint64_t i); 6static int findchunk(PruneData *pd, int nchunks, uint64_t i);
8static void genptable_bfs(PruneData *pd,int d,Move *ms,int nt,int nc); 7static void genptable_bfs(PruneData *pd, int d, int nt, int nc);
9static void genptable_fixnasty(PruneData *pd, int d); 8static void genptable_fixnasty(PruneData *pd, int d);
10static void * instance_bfs(void *arg); 9static void * instance_bfs(void *arg);
11static void ptable_update(PruneData *pd, Cube cube, int m); 10static void ptable_update(PruneData *pd, Cube cube, int m);
@@ -18,70 +17,77 @@ PruneData
18pd_eofb_HTM = { 17pd_eofb_HTM = {
19 .filename = "pt_eofb_HTM", 18 .filename = "pt_eofb_HTM",
20 .coord = &coord_eofb, 19 .coord = &coord_eofb,
21 .moveset = moveset_HTM, 20 .moveset = &moveset_HTM,
22}; 21};
23 22
24PruneData 23PruneData
25pd_coud_HTM = { 24pd_coud_HTM = {
26 .filename = "pt_coud_HTM", 25 .filename = "pt_coud_HTM",
27 .coord = &coord_coud, 26 .coord = &coord_coud,
28 .moveset = moveset_HTM, 27 .moveset = &moveset_HTM,
29}; 28};
30 29
31PruneData 30PruneData
32pd_cornershtr_HTM = { 31pd_cornershtr_HTM = {
33 .filename = "pt_cornershtr_HTM", 32 .filename = "pt_cornershtr_HTM",
34 .coord = &coord_cornershtr, 33 .coord = &coord_cornershtr,
35 .moveset = moveset_HTM, 34 .moveset = &moveset_HTM,
36}; 35};
37 36
38PruneData 37PruneData
39pd_corners_HTM = { 38pd_corners_HTM = {
40 .filename = "pt_corners_HTM", 39 .filename = "pt_corners_HTM",
41 .coord = &coord_corners, 40 .coord = &coord_corners,
42 .moveset = moveset_HTM, 41 .moveset = &moveset_HTM,
43}; 42};
44 43
45PruneData 44PruneData
46pd_drud_sym16_HTM = { 45pd_drud_sym16_HTM = {
47 .filename = "pt_drud_sym16_HTM", 46 .filename = "pt_drud_sym16_HTM",
48 .coord = &coord_drud_sym16, 47 .coord = &coord_drud_sym16,
49 .moveset = moveset_HTM, 48 .moveset = &moveset_HTM,
50}; 49};
51 50
52PruneData 51PruneData
53pd_drud_eofb = { 52pd_drud_eofb = {
54 .filename = "pt_drud_eofb", 53 .filename = "pt_drud_eofb",
55 .coord = &coord_drud_eofb, 54 .coord = &coord_drud_eofb,
56 .moveset = moveset_eofb, 55 .moveset = &moveset_eofb,
57}; 56};
58 57
59PruneData 58PruneData
60pd_drudfin_noE_sym16_drud = { 59pd_drudfin_noE_sym16_drud = {
61 .filename = "pt_drudfin_noE_sym16_drud", 60 .filename = "pt_drudfin_noE_sym16_drud",
62 .coord = &coord_drudfin_noE_sym16, 61 .coord = &coord_drudfin_noE_sym16,
63 .moveset = moveset_drud, 62 .moveset = &moveset_drud,
64}; 63};
65 64
66PruneData 65PruneData
67pd_htr_drud = { 66pd_htr_drud = {
68 .filename = "pt_htr_drud", 67 .filename = "pt_htr_drud",
69 .coord = &coord_htr_drud, 68 .coord = &coord_htr_drud,
70 .moveset = moveset_drud, 69 .moveset = &moveset_drud,
71}; 70};
72 71
73PruneData 72PruneData
74pd_htrfin_htr = { 73pd_htrfin_htr = {
75 .filename = "pt_htrfin_htr", 74 .filename = "pt_htrfin_htr",
76 .coord = &coord_htrfin, 75 .coord = &coord_htrfin,
77 .moveset = moveset_htr, 76 .moveset = &moveset_htr,
78}; 77};
79 78
80PruneData 79PruneData
81pd_khuge_HTM = { 80pd_khuge_HTM = {
82 .filename = "pt_khuge_HTM", 81 .filename = "pt_khuge_HTM",
83 .coord = &coord_khuge, 82 .coord = &coord_khuge,
84 .moveset = moveset_HTM, 83 .moveset = &moveset_HTM,
84};
85
86PruneData
87pd_nxopt31_HTM = {
88 .filename = "pt_nxopt31_HTM",
89 .coord = &coord_nxopt31,
90 .moveset = &moveset_HTM,
85}; 91};
86 92
87PruneData * allpd[NPTABLES] = { 93PruneData * allpd[NPTABLES] = {
@@ -95,6 +101,7 @@ PruneData * allpd[NPTABLES] = {
95 &pd_htr_drud, 101 &pd_htr_drud,
96 &pd_htrfin_htr, 102 &pd_htrfin_htr,
97 &pd_khuge_HTM, 103 &pd_khuge_HTM,
104 &pd_nxopt31_HTM,
98}; 105};
99 106
100/* Functions *****************************************************************/ 107/* Functions *****************************************************************/
@@ -105,8 +112,7 @@ findchunk(PruneData *pd, int nchunks, uint64_t i)
105 uint64_t chunksize; 112 uint64_t chunksize;
106 113
107 chunksize = pd->coord->max / (uint64_t)nchunks; 114 chunksize = pd->coord->max / (uint64_t)nchunks;
108 if (chunksize % 2 != 0) 115 chunksize += ENTRIES_PER_GROUP - (chunksize % ENTRIES_PER_GROUP);
109 chunksize++;
110 116
111 return MIN(nchunks-1, (int)(i / chunksize)); 117 return MIN(nchunks-1, (int)(i / chunksize));
112} 118}
@@ -114,15 +120,14 @@ findchunk(PruneData *pd, int nchunks, uint64_t i)
114void 120void
115genptable(PruneData *pd, int nthreads) 121genptable(PruneData *pd, int nthreads)
116{ 122{
117 Move *ms;
118 int d, nchunks; 123 int d, nchunks;
119 uint64_t j, oldn; 124 uint64_t oldn;
120 125
121 if (pd->generated) 126 if (pd->generated)
122 return; 127 return;
123 128
124 /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ 129 /* TODO: check if memory is enough, otherwise maybe exit gracefully? */
125 pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); 130 pd->ptable = malloc(ptablesize(pd) * sizeof(entry_group_t));
126 131
127 if (read_ptable_file(pd)) { 132 if (read_ptable_file(pd)) {
128 pd->generated = true; 133 pd->generated = true;
@@ -130,17 +135,12 @@ genptable(PruneData *pd, int nthreads)
130 } 135 }
131 pd->generated = true; 136 pd->generated = true;
132 137
133 nchunks = MIN(pd->coord->max/2, NCHUNKS); 138 nchunks = MIN(pd->coord->max/ENTRIES_PER_GROUP, NCHUNKS);
134 fprintf(stderr, "Cannot load %s, generating it " 139 fprintf(stderr, "Cannot load %s, generating it "
135 "with %d threads and %d chunks\n", 140 "with %d threads and %d chunks\n",
136 pd->filename, nthreads, nchunks); 141 pd->filename, nthreads, nchunks);
137 142
138 ms = malloc(NMOVES * sizeof(Move)); 143 memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t));
139 moveset_to_list(pd->moveset, ms);
140
141 /* We use 4 bits per value, so any distance >= 15 is set to 15 */
142 for (j = 0; j < pd->coord->max; j++)
143 ptable_update_index(pd, j, 15);
144 144
145 ptable_update(pd, (Cube){0}, 0); 145 ptable_update(pd, (Cube){0}, 0);
146 pd->n = 1; 146 pd->n = 1;
@@ -151,7 +151,7 @@ genptable(PruneData *pd, int nthreads)
151 0, pd->n - oldn, pd->n, pd->coord->max); 151 0, pd->n - oldn, pd->n, pd->coord->max);
152 oldn = pd->n; 152 oldn = pd->n;
153 for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { 153 for (d = 0; d < 15 && pd->n < pd->coord->max; d++) {
154 genptable_bfs(pd, d, ms, nthreads, nchunks); 154 genptable_bfs(pd, d, nthreads, nchunks);
155 genptable_fixnasty(pd, d+1); 155 genptable_fixnasty(pd, d+1);
156 fprintf(stderr, "Depth %d done, generated %" 156 fprintf(stderr, "Depth %d done, generated %"
157 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", 157 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n",
@@ -162,12 +162,10 @@ genptable(PruneData *pd, int nthreads)
162 162
163 if (!write_ptable_file(pd)) 163 if (!write_ptable_file(pd))
164 fprintf(stderr, "Error writing ptable file\n"); 164 fprintf(stderr, "Error writing ptable file\n");
165
166 free(ms);
167} 165}
168 166
169static void 167static void
170genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks) 168genptable_bfs(PruneData *pd, int d, int nthreads, int nchunks)
171{ 169{
172 int i; 170 int i;
173 pthread_t t[nthreads]; 171 pthread_t t[nthreads];
@@ -186,7 +184,6 @@ genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks)
186 td[i].nthreads = nthreads; 184 td[i].nthreads = nthreads;
187 td[i].pd = pd; 185 td[i].pd = pd;
188 td[i].d = d; 186 td[i].d = d;
189 td[i].ms = ms;
190 td[i].nchunks = nchunks; 187 td[i].nchunks = nchunks;
191 td[i].mutex = mtx; 188 td[i].mutex = mtx;
192 td[i].upmutex = upmtx; 189 td[i].upmutex = upmtx;
@@ -237,8 +234,10 @@ instance_bfs(void *arg)
237 uint64_t i, ii, blocksize, rmin, rmax, updated; 234 uint64_t i, ii, blocksize, rmin, rmax, updated;
238 int j, pval, ichunk; 235 int j, pval, ichunk;
239 Cube c, cc; 236 Cube c, cc;
237 Move *ms;
240 238
241 td = (ThreadDataGenpt *)arg; 239 td = (ThreadDataGenpt *)arg;
240 ms = td->pd->moveset->sorted_moves;
242 blocksize = td->pd->coord->max / (uint64_t)td->nthreads; 241 blocksize = td->pd->coord->max / (uint64_t)td->nthreads;
243 rmin = ((uint64_t)td->thid) * blocksize; 242 rmin = ((uint64_t)td->thid) * blocksize;
244 rmax = td->thid == td->nthreads - 1 ? 243 rmax = td->thid == td->nthreads - 1 ?
@@ -253,8 +252,8 @@ instance_bfs(void *arg)
253 pthread_mutex_unlock(td->mutex[ichunk]); 252 pthread_mutex_unlock(td->mutex[ichunk]);
254 if (pval == td->d) { 253 if (pval == td->d) {
255 c = td->pd->coord->cube(i); 254 c = td->pd->coord->cube(i);
256 for (j = 0; td->ms[j] != NULLMOVE; j++) { 255 for (j = 0; ms[j] != NULLMOVE; j++) {
257 cc = apply_move(td->ms[j], c); 256 cc = apply_move(ms[j], c);
258 ii = td->pd->coord->index(cc); 257 ii = td->pd->coord->index(cc);
259 ichunk = findchunk(td->pd, td->nchunks, ii); 258 ichunk = findchunk(td->pd, td->nchunks, ii);
260 pthread_mutex_lock(td->mutex[ichunk]); 259 pthread_mutex_lock(td->mutex[ichunk]);
@@ -296,7 +295,7 @@ print_ptable(PruneData *pd)
296uint64_t 295uint64_t
297ptablesize(PruneData *pd) 296ptablesize(PruneData *pd)
298{ 297{
299 return (pd->coord->max + 1) / 2; 298 return (pd->coord->max + ENTRIES_PER_GROUP - 1) / ENTRIES_PER_GROUP;
300} 299}
301 300
302static void 301static void
@@ -308,14 +307,16 @@ ptable_update(PruneData *pd, Cube cube, int n)
308static void 307static void
309ptable_update_index(PruneData *pd, uint64_t ind, int n) 308ptable_update_index(PruneData *pd, uint64_t ind, int n)
310{ 309{
311 uint8_t oldval2; 310 int sh;
312 int other; 311 entry_group_t mask;
312 uint64_t i;
313 313
314 oldval2 = pd->ptable[ind/2]; 314 sh = 4 * (ind % ENTRIES_PER_GROUP);
315 other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; 315 mask = ((entry_group_t)15) << sh;
316 i = ind/ENTRIES_PER_GROUP;
316 317
317 pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; 318 pd->ptable[i] &= ~mask;
318 /*pd->n++;*/ 319 pd->ptable[i] |= (((entry_group_t)n)&15) << sh;
319} 320}
320 321
321int 322int
@@ -327,6 +328,10 @@ ptableval(PruneData *pd, Cube cube)
327static int 328static int
328ptableval_index(PruneData *pd, uint64_t ind) 329ptableval_index(PruneData *pd, uint64_t ind)
329{ 330{
331 int sh;
332 entry_group_t mask;
333 uint64_t i;
334
330 if (!pd->generated) { 335 if (!pd->generated) {
331 fprintf(stderr, "Warning: request pruning table value" 336 fprintf(stderr, "Warning: request pruning table value"
332 " for uninitialized table %s.\n It's fine, but it" 337 " for uninitialized table %s.\n It's fine, but it"
@@ -335,7 +340,11 @@ ptableval_index(PruneData *pd, uint64_t ind)
335 genptable(pd, 1); /* TODO: set default or remove this case */ 340 genptable(pd, 1); /* TODO: set default or remove this case */
336 } 341 }
337 342
338 return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; 343 sh = 4 * (ind % ENTRIES_PER_GROUP);
344 mask = ((entry_group_t)15) << sh;
345 i = ind/ENTRIES_PER_GROUP;
346
347 return (pd->ptable[i] & mask) >> sh;
339} 348}
340 349
341static bool 350static bool
@@ -354,7 +363,7 @@ read_ptable_file(PruneData *pd)
354 if ((f = fopen(fname, "rb")) == NULL) 363 if ((f = fopen(fname, "rb")) == NULL)
355 return false; 364 return false;
356 365
357 r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); 366 r = fread(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f);
358 fclose(f); 367 fclose(f);
359 368
360 return r == ptablesize(pd); 369 return r == ptablesize(pd);
@@ -376,7 +385,7 @@ write_ptable_file(PruneData *pd)
376 if ((f = fopen(fname, "wb")) == NULL) 385 if ((f = fopen(fname, "wb")) == NULL)
377 return false; 386 return false;
378 387
379 written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); 388 written = fwrite(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f);
380 fclose(f); 389 fclose(f);
381 390
382 return written == ptablesize(pd); 391 return written == ptablesize(pd);
diff --git a/src/pruning.h b/src/pruning.h
index da9e58a..0f20384 100644
--- a/src/pruning.h
+++ b/src/pruning.h
@@ -15,6 +15,7 @@ extern PruneData pd_drudfin_noE_sym16_drud;
15extern PruneData pd_htr_drud; 15extern PruneData pd_htr_drud;
16extern PruneData pd_htrfin_htr; 16extern PruneData pd_htrfin_htr;
17extern PruneData pd_khuge_HTM; 17extern PruneData pd_khuge_HTM;
18extern PruneData pd_nxopt31_HTM;
18 19
19extern PruneData * allpd[NPTABLES]; 20extern PruneData * allpd[NPTABLES];
20 21
diff --git a/src/solve.c b/src/solve.c
index ea3b7ae..a8f9001 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -8,7 +8,7 @@ static void copy_dfsarg(DfsArg *src, DfsArg *dst);
8static void dfs(DfsArg *arg); 8static void dfs(DfsArg *arg);
9static void dfs_branch(DfsArg *arg); 9static void dfs_branch(DfsArg *arg);
10static bool dfs_check_solved(DfsArg *arg); 10static bool dfs_check_solved(DfsArg *arg);
11static bool dfs_switch_final(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_stop(DfsArg *arg);
14static void * instance_thread(void *arg); 14static void * instance_thread(void *arg);
@@ -21,25 +21,43 @@ static bool niss_makes_sense(DfsArg *arg);
21static bool 21static bool
22allowed_next(Move m, DfsArg *arg) 22allowed_next(Move m, DfsArg *arg)
23{ 23{
24 if ((1 << m) & arg->badmoves) 24 bool bad, allowed, order;
25 return false; 25 uint64_t mbit;
26 26
27 if (!possible_next(arg->last2, arg->last1, m)) 27 if (arg->last1 == NULLMOVE)
28 return false; 28 return true;
29 29
30 if (commute(arg->last1, m)) 30 mbit = ((uint64_t)1) << m;
31 return arg->move_position[arg->last1] < arg->move_position[m]; 31 bad = mbit & arg->badmoves;
32 allowed = mbit & arg->step->moveset->mask[arg->last2][arg->last1];
33 order = !commute(arg->last1, m) || arg->last1 < m;
32 34
33 return true; 35 return allowed && !bad && order;
34} 36}
35 37
36static bool 38static bool
37cancel_niss(DfsArg *arg) 39cancel_niss(DfsArg *arg)
38{ 40{
39 return !possible_next(arg->last2, arg->last1, arg->last1inv) && 41 Moveset *ms;
40 !(commute(arg->last1inv, arg->last2inv) && 42 Move i1, i2;
41 arg->last2inv != NULLMOVE && 43 bool p, p1, p2, q, q1, q2;
42 possible_next(arg->last2, arg->last1, arg->last2inv)); 44
45 if (arg->last1inv == NULLMOVE)
46 return false;
47
48 ms = arg->step->moveset;
49 i1 = inverse_move(arg->last1inv);
50 i2 = inverse_move(arg->last2inv);
51
52 p1 = !ms->allowed_next(arg->last2, arg->last1, i1);
53 p2 = !ms->allowed_next(arg->last2, i1, arg->last1);
54 p = p1 || (commute(i1, arg->last1) && p2);
55
56 q1 = !ms->allowed_next(arg->last2, arg->last1, i2);
57 q2 = !ms->allowed_next(arg->last2, i2, arg->last1);
58 q = q1 || (commute(i2, arg->last1) && q2);
59
60 return p || (commute(i1, i2) && q);
43} 61}
44 62
45static void 63static void
@@ -60,8 +78,6 @@ copy_dfsarg(DfsArg *src, DfsArg *dst)
60 dst->sols = src->sols; 78 dst->sols = src->sols;
61 dst->sols_mutex = src->sols_mutex; 79 dst->sols_mutex = src->sols_mutex;
62 dst->current_alg = src->current_alg; 80 dst->current_alg = src->current_alg;
63 dst->sorted_moves = src->sorted_moves;
64 dst->move_position = src->move_position;
65 81
66 copy_estimatedata(src->ed, dst->ed); 82 copy_estimatedata(src->ed, dst->ed);
67} 83}
@@ -77,7 +93,7 @@ dfs(DfsArg *arg)
77 if (dfs_check_solved(arg)) 93 if (dfs_check_solved(arg))
78 return; 94 return;
79 95
80 if (arg->step->final && (sw = dfs_switch_final(arg))) 96 if (arg->step->final && (sw = dfs_switch(arg)))
81 invert_branch(arg); 97 invert_branch(arg);
82 dfs_branch(arg); 98 dfs_branch(arg);
83 99
@@ -98,8 +114,8 @@ dfs_branch(DfsArg *arg)
98 newarg = malloc(sizeof(DfsArg)); 114 newarg = malloc(sizeof(DfsArg));
99 newarg->ed = malloc(sizeof(EstimateData)); 115 newarg->ed = malloc(sizeof(EstimateData));
100 116
101 for (i = 0; arg->sorted_moves[i] != NULLMOVE; i++) { 117 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) {
102 m = arg->sorted_moves[i]; 118 m = arg->step->moveset->sorted_moves[i];
103 if (allowed_next(m, arg)) { 119 if (allowed_next(m, arg)) {
104 copy_dfsarg(arg, newarg); 120 copy_dfsarg(arg, newarg);
105 newarg->last2 = arg->last1; 121 newarg->last2 = arg->last1;
@@ -181,20 +197,22 @@ dfs_stop(DfsArg *arg)
181} 197}
182 198
183static bool 199static bool
184dfs_switch_final(DfsArg *arg) 200dfs_switch(DfsArg *arg)
185{ 201{
186 int i, bn, bi; 202 int i, bn, bi;
187 203
188 for (bn = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) 204 bn = 0;
189 if (allowed_next(arg->sorted_moves[i], arg)) 205 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++)
206 if (allowed_next(arg->step->moveset->sorted_moves[i], arg))
190 bn++; 207 bn++;
191 208
192 swapmove(&(arg->last1), &(arg->last1inv)); 209 swapmove(&(arg->last1), &(arg->last1inv));
193 swapmove(&(arg->last2), &(arg->last2inv)); 210 swapmove(&(arg->last2), &(arg->last2inv));
194 swapu64(&(arg->badmoves), &(arg->badmovesinv)); 211 swapu64(&(arg->badmoves), &(arg->badmovesinv));
195 212
196 for (bi = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) 213 bi = 0;
197 if (allowed_next(arg->sorted_moves[i], arg)) 214 for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++)
215 if (allowed_next(arg->step->moveset->sorted_moves[i], arg))
198 bi++; 216 bi++;
199 217
200 swapmove(&(arg->last1), &(arg->last1inv)); 218 swapmove(&(arg->last1), &(arg->last1inv));
@@ -246,8 +264,6 @@ instance_thread(void *arg)
246 darg.current_alg = new_alg(""); 264 darg.current_alg = new_alg("");
247 append_move(darg.current_alg, node->alg->move[0], 265 append_move(darg.current_alg, node->alg->move[0],
248 node->alg->inv[0]); 266 node->alg->inv[0]);
249 darg.sorted_moves = td->sorted_moves;
250 darg.move_position = td->move_position;
251 darg.ed = new_estimatedata(); 267 darg.ed = new_estimatedata();
252 darg.badmoves = 0; 268 darg.badmoves = 0;
253 darg.badmovesinv = 0; 269 darg.badmovesinv = 0;
@@ -281,8 +297,7 @@ invert_branch(DfsArg *arg)
281static void 297static void
282multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) 298multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
283{ 299{
284 int i, *move_position; 300 int i;
285 Move *sorted_moves;
286 Alg *alg; 301 Alg *alg;
287 AlgList *start; 302 AlgList *start;
288 AlgListNode **node; 303 AlgListNode **node;
@@ -290,8 +305,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
290 ThreadDataSolve td[opts->nthreads]; 305 ThreadDataSolve td[opts->nthreads];
291 pthread_mutex_t *start_mutex, *sols_mutex; 306 pthread_mutex_t *start_mutex, *sols_mutex;
292 307
293 move_position = malloc(NMOVES * sizeof(int));
294 sorted_moves = malloc(NMOVES * sizeof(Move));
295 node = malloc(sizeof(AlgListNode *)); 308 node = malloc(sizeof(AlgListNode *));
296 start_mutex = malloc(sizeof(pthread_mutex_t)); 309 start_mutex = malloc(sizeof(pthread_mutex_t));
297 sols_mutex = malloc(sizeof(pthread_mutex_t)); 310 sols_mutex = malloc(sizeof(pthread_mutex_t));
@@ -300,14 +313,11 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
300 pthread_mutex_init(start_mutex, NULL); 313 pthread_mutex_init(start_mutex, NULL);
301 pthread_mutex_init(sols_mutex, NULL); 314 pthread_mutex_init(sols_mutex, NULL);
302 315
303 moveset_to_list(s->moveset, sorted_moves); 316 for (i = 0; s->moveset->sorted_moves[i] != NULLMOVE; i++) {
304 movelist_to_position(sorted_moves, move_position);
305
306 for (i = 0; sorted_moves[i] != NULLMOVE; i++) {
307 alg = new_alg(""); 317 alg = new_alg("");
308 /* TODO: start on inverse also in case of final step 318 /* TODO: start on inverse also in case of final step
309 and ed->sw true */ 319 and ed->sw true */
310 append_move(alg, sorted_moves[i], false); 320 append_move(alg, s->moveset->sorted_moves[i], false);
311 append_alg(start, alg); 321 append_alg(start, alg);
312 if (opts->can_niss) { 322 if (opts->can_niss) {
313 alg->inv[0] = true; 323 alg->inv[0] = true;
@@ -322,8 +332,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
322 td[i].cube = c; 332 td[i].cube = c;
323 td[i].step = s; 333 td[i].step = s;
324 td[i].depth = d; 334 td[i].depth = d;
325 td[i].sorted_moves = sorted_moves;
326 td[i].move_position = move_position;
327 td[i].opts = opts; 335 td[i].opts = opts;
328 td[i].start = start; 336 td[i].start = start;
329 td[i].node = node; 337 td[i].node = node;
@@ -340,8 +348,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
340 free(node); 348 free(node);
341 free(start_mutex); 349 free(start_mutex);
342 free(sols_mutex); 350 free(sols_mutex);
343 free(move_position);
344 free(sorted_moves);
345} 351}
346 352
347static bool 353static bool
diff --git a/src/steps.c b/src/steps.c
index c4d1279..014b206 100644
--- a/src/steps.c
+++ b/src/steps.c
@@ -36,8 +36,11 @@ static int estimate_drudfin_drud(DfsArg *arg);
36static int estimate_htr_drud(DfsArg *arg); 36static int estimate_htr_drud(DfsArg *arg);
37static int estimate_htrfin_htr(DfsArg *arg); 37static int estimate_htrfin_htr(DfsArg *arg);
38static int estimate_optimal_HTM(DfsArg *arg); 38static int estimate_optimal_HTM(DfsArg *arg);
39static int estimate_nxopt31_HTM(DfsArg *arg);
39static int estimate_light_HTM(DfsArg *arg); 40static int estimate_light_HTM(DfsArg *arg);
40 41
42static int estimate_nxoptlike(DfsArg *arg, PruneData *pd);
43
41static bool always_valid(Alg *alg); 44static bool always_valid(Alg *alg);
42static bool validate_singlecw_ending(Alg *alg); 45static bool validate_singlecw_ending(Alg *alg);
43 46
@@ -68,7 +71,7 @@ optimal_HTM = {
68 .ready = check_centers, 71 .ready = check_centers,
69 .ready_msg = check_centers_msg, 72 .ready_msg = check_centers_msg,
70 .is_valid = always_valid, 73 .is_valid = always_valid,
71 .moveset = moveset_HTM, 74 .moveset = &moveset_HTM,
72 75
73 .pre_trans = uf, 76 .pre_trans = uf,
74 77
@@ -77,6 +80,25 @@ optimal_HTM = {
77}; 80};
78 81
79Step 82Step
83optimal_nxopt31_HTM = {
84 .shortname = "nxopt31",
85 .name = "Optimal solve (in HTM), nxopt31 table",
86
87 .final = true,
88 .is_done = is_solved,
89 .estimate = estimate_nxopt31_HTM,
90 .ready = check_centers,
91 .ready_msg = check_centers_msg,
92 .is_valid = always_valid,
93 .moveset = &moveset_HTM,
94
95 .pre_trans = uf,
96
97 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
98 .ntables = 2,
99};
100
101Step
80optimal_light_HTM = { 102optimal_light_HTM = {
81 .shortname = "light", 103 .shortname = "light",
82 .name = "Optimal solve (in HTM), small table (500Mb RAM total)", 104 .name = "Optimal solve (in HTM), small table (500Mb RAM total)",
@@ -87,7 +109,7 @@ optimal_light_HTM = {
87 .ready = check_centers, 109 .ready = check_centers,
88 .ready_msg = check_centers_msg, 110 .ready_msg = check_centers_msg,
89 .is_valid = always_valid, 111 .is_valid = always_valid,
90 .moveset = moveset_HTM, 112 .moveset = &moveset_HTM,
91 113
92 .pre_trans = uf, 114 .pre_trans = uf,
93 115
@@ -107,7 +129,7 @@ eoany_HTM = {
107 .ready = check_centers, 129 .ready = check_centers,
108 .ready_msg = check_centers_msg, 130 .ready_msg = check_centers_msg,
109 .is_valid = validate_singlecw_ending, 131 .is_valid = validate_singlecw_ending,
110 .moveset = moveset_HTM, 132 .moveset = &moveset_HTM,
111 133
112 .pre_trans = uf, 134 .pre_trans = uf,
113 135
@@ -126,7 +148,7 @@ eofb_HTM = {
126 .ready = check_centers, 148 .ready = check_centers,
127 .ready_msg = check_centers_msg, 149 .ready_msg = check_centers_msg,
128 .is_valid = validate_singlecw_ending, 150 .is_valid = validate_singlecw_ending,
129 .moveset = moveset_HTM, 151 .moveset = &moveset_HTM,
130 152
131 .pre_trans = uf, 153 .pre_trans = uf,
132 154
@@ -145,7 +167,7 @@ eorl_HTM = {
145 .ready = check_centers, 167 .ready = check_centers,
146 .ready_msg = check_centers_msg, 168 .ready_msg = check_centers_msg,
147 .is_valid = validate_singlecw_ending, 169 .is_valid = validate_singlecw_ending,
148 .moveset = moveset_HTM, 170 .moveset = &moveset_HTM,
149 171
150 .pre_trans = ur, 172 .pre_trans = ur,
151 173
@@ -164,7 +186,7 @@ eoud_HTM = {
164 .ready = check_centers, 186 .ready = check_centers,
165 .ready_msg = check_centers_msg, 187 .ready_msg = check_centers_msg,
166 .is_valid = validate_singlecw_ending, 188 .is_valid = validate_singlecw_ending,
167 .moveset = moveset_HTM, 189 .moveset = &moveset_HTM,
168 190
169 .pre_trans = fd, 191 .pre_trans = fd,
170 192
@@ -183,7 +205,7 @@ coany_HTM = {
183 .estimate = estimate_coany_HTM, 205 .estimate = estimate_coany_HTM,
184 .ready = NULL, 206 .ready = NULL,
185 .is_valid = validate_singlecw_ending, 207 .is_valid = validate_singlecw_ending,
186 .moveset = moveset_HTM, 208 .moveset = &moveset_HTM,
187 209
188 .pre_trans = uf, 210 .pre_trans = uf,
189 211
@@ -201,7 +223,7 @@ coud_HTM = {
201 .estimate = estimate_coud_HTM, 223 .estimate = estimate_coud_HTM,
202 .ready = NULL, 224 .ready = NULL,
203 .is_valid = validate_singlecw_ending, 225 .is_valid = validate_singlecw_ending,
204 .moveset = moveset_HTM, 226 .moveset = &moveset_HTM,
205 227
206 .pre_trans = uf, 228 .pre_trans = uf,
207 229
@@ -219,7 +241,7 @@ corl_HTM = {
219 .estimate = estimate_coud_HTM, 241 .estimate = estimate_coud_HTM,
220 .ready = NULL, 242 .ready = NULL,
221 .is_valid = validate_singlecw_ending, 243 .is_valid = validate_singlecw_ending,
222 .moveset = moveset_HTM, 244 .moveset = &moveset_HTM,
223 245
224 .pre_trans = rf, 246 .pre_trans = rf,
225 247
@@ -237,7 +259,7 @@ cofb_HTM = {
237 .estimate = estimate_coud_HTM, 259 .estimate = estimate_coud_HTM,
238 .ready = NULL, 260 .ready = NULL,
239 .is_valid = validate_singlecw_ending, 261 .is_valid = validate_singlecw_ending,
240 .moveset = moveset_HTM, 262 .moveset = &moveset_HTM,
241 263
242 .pre_trans = fd, 264 .pre_trans = fd,
243 265
@@ -255,7 +277,7 @@ coany_URF = {
255 .estimate = estimate_coany_URF, 277 .estimate = estimate_coany_URF,
256 .ready = NULL, 278 .ready = NULL,
257 .is_valid = validate_singlecw_ending, 279 .is_valid = validate_singlecw_ending,
258 .moveset = moveset_URF, 280 .moveset = &moveset_URF,
259 281
260 .pre_trans = uf, 282 .pre_trans = uf,
261 283
@@ -273,7 +295,7 @@ coud_URF = {
273 .estimate = estimate_coud_URF, 295 .estimate = estimate_coud_URF,
274 .ready = NULL, 296 .ready = NULL,
275 .is_valid = validate_singlecw_ending, 297 .is_valid = validate_singlecw_ending,
276 .moveset = moveset_URF, 298 .moveset = &moveset_URF,
277 299
278 .pre_trans = uf, 300 .pre_trans = uf,
279 301
@@ -291,7 +313,7 @@ corl_URF = {
291 .estimate = estimate_coud_URF, 313 .estimate = estimate_coud_URF,
292 .ready = NULL, 314 .ready = NULL,
293 .is_valid = validate_singlecw_ending, 315 .is_valid = validate_singlecw_ending,
294 .moveset = moveset_URF, 316 .moveset = &moveset_URF,
295 317
296 .pre_trans = rf, 318 .pre_trans = rf,
297 319
@@ -309,7 +331,7 @@ cofb_URF = {
309 .estimate = estimate_coud_URF, 331 .estimate = estimate_coud_URF,
310 .ready = NULL, 332 .ready = NULL,
311 .is_valid = validate_singlecw_ending, 333 .is_valid = validate_singlecw_ending,
312 .moveset = moveset_URF, 334 .moveset = &moveset_URF,
313 335
314 .pre_trans = fd, 336 .pre_trans = fd,
315 337
@@ -328,7 +350,7 @@ cornershtr_HTM = {
328 .estimate = estimate_cornershtr_HTM, 350 .estimate = estimate_cornershtr_HTM,
329 .ready = NULL, 351 .ready = NULL,
330 .is_valid = validate_singlecw_ending, 352 .is_valid = validate_singlecw_ending,
331 .moveset = moveset_HTM, 353 .moveset = &moveset_HTM,
332 354
333 .pre_trans = uf, 355 .pre_trans = uf,
334 356
@@ -346,7 +368,7 @@ cornershtr_URF = {
346 .estimate = estimate_cornershtr_URF, 368 .estimate = estimate_cornershtr_URF,
347 .ready = NULL, 369 .ready = NULL,
348 .is_valid = validate_singlecw_ending, 370 .is_valid = validate_singlecw_ending,
349 .moveset = moveset_URF, 371 .moveset = &moveset_URF,
350 372
351 .pre_trans = uf, 373 .pre_trans = uf,
352 374
@@ -364,7 +386,7 @@ corners_HTM = {
364 .estimate = estimate_corners_HTM, 386 .estimate = estimate_corners_HTM,
365 .ready = NULL, 387 .ready = NULL,
366 .is_valid = always_valid, 388 .is_valid = always_valid,
367 .moveset = moveset_HTM, 389 .moveset = &moveset_HTM,
368 390
369 .pre_trans = uf, 391 .pre_trans = uf,
370 392
@@ -382,7 +404,7 @@ corners_URF = {
382 .estimate = estimate_corners_URF, 404 .estimate = estimate_corners_URF,
383 .ready = NULL, 405 .ready = NULL,
384 .is_valid = always_valid, 406 .is_valid = always_valid,
385 .moveset = moveset_URF, 407 .moveset = &moveset_URF,
386 408
387 .pre_trans = uf, 409 .pre_trans = uf,
388 410
@@ -402,7 +424,7 @@ drany_HTM = {
402 .ready = check_centers, 424 .ready = check_centers,
403 .ready_msg = check_centers_msg, 425 .ready_msg = check_centers_msg,
404 .is_valid = validate_singlecw_ending, 426 .is_valid = validate_singlecw_ending,
405 .moveset = moveset_HTM, 427 .moveset = &moveset_HTM,
406 428
407 .pre_trans = uf, 429 .pre_trans = uf,
408 430
@@ -421,7 +443,7 @@ drud_HTM = {
421 .ready = check_centers, 443 .ready = check_centers,
422 .ready_msg = check_centers_msg, 444 .ready_msg = check_centers_msg,
423 .is_valid = validate_singlecw_ending, 445 .is_valid = validate_singlecw_ending,
424 .moveset = moveset_HTM, 446 .moveset = &moveset_HTM,
425 447
426 .pre_trans = uf, 448 .pre_trans = uf,
427 449
@@ -440,7 +462,7 @@ drrl_HTM = {
440 .ready = check_centers, 462 .ready = check_centers,
441 .ready_msg = check_centers_msg, 463 .ready_msg = check_centers_msg,
442 .is_valid = validate_singlecw_ending, 464 .is_valid = validate_singlecw_ending,
443 .moveset = moveset_HTM, 465 .moveset = &moveset_HTM,
444 466
445 .pre_trans = rf, 467 .pre_trans = rf,
446 468
@@ -459,7 +481,7 @@ drfb_HTM = {
459 .ready = check_centers, 481 .ready = check_centers,
460 .ready_msg = check_centers_msg, 482 .ready_msg = check_centers_msg,
461 .is_valid = validate_singlecw_ending, 483 .is_valid = validate_singlecw_ending,
462 .moveset = moveset_HTM, 484 .moveset = &moveset_HTM,
463 485
464 .pre_trans = fd, 486 .pre_trans = fd,
465 487
@@ -479,7 +501,7 @@ dr_eo = {
479 .ready = check_eofb, 501 .ready = check_eofb,
480 .ready_msg = check_eo_msg, 502 .ready_msg = check_eo_msg,
481 .is_valid = validate_singlecw_ending, 503 .is_valid = validate_singlecw_ending,
482 .moveset = moveset_eofb, 504 .moveset = &moveset_eofb,
483 505
484 .detect = detect_pretrans_eofb, 506 .detect = detect_pretrans_eofb,
485 507
@@ -498,7 +520,7 @@ dr_eofb = {
498 .ready = check_eofb, 520 .ready = check_eofb,
499 .ready_msg = check_eo_msg, 521 .ready_msg = check_eo_msg,
500 .is_valid = validate_singlecw_ending, 522 .is_valid = validate_singlecw_ending,
501 .moveset = moveset_eofb, 523 .moveset = &moveset_eofb,
502 524
503 .pre_trans = uf, 525 .pre_trans = uf,
504 526
@@ -517,7 +539,7 @@ dr_eorl = {
517 .ready = check_eofb, 539 .ready = check_eofb,
518 .ready_msg = check_eo_msg, 540 .ready_msg = check_eo_msg,
519 .is_valid = validate_singlecw_ending, 541 .is_valid = validate_singlecw_ending,
520 .moveset = moveset_eofb, 542 .moveset = &moveset_eofb,
521 543
522 .pre_trans = ur, 544 .pre_trans = ur,
523 545
@@ -536,7 +558,7 @@ dr_eoud = {
536 .ready = check_eofb, 558 .ready = check_eofb,
537 .ready_msg = check_eo_msg, 559 .ready_msg = check_eo_msg,
538 .is_valid = validate_singlecw_ending, 560 .is_valid = validate_singlecw_ending,
539 .moveset = moveset_eofb, 561 .moveset = &moveset_eofb,
540 562
541 .pre_trans = fd, 563 .pre_trans = fd,
542 564
@@ -555,7 +577,7 @@ drud_eofb = {
555 .ready = check_eofb, 577 .ready = check_eofb,
556 .ready_msg = check_eo_msg, 578 .ready_msg = check_eo_msg,
557 .is_valid = validate_singlecw_ending, 579 .is_valid = validate_singlecw_ending,
558 .moveset = moveset_eofb, 580 .moveset = &moveset_eofb,
559 581
560 .pre_trans = uf, 582 .pre_trans = uf,
561 583
@@ -574,7 +596,7 @@ drrl_eofb = {
574 .ready = check_eofb, 596 .ready = check_eofb,
575 .ready_msg = check_eo_msg, 597 .ready_msg = check_eo_msg,
576 .is_valid = validate_singlecw_ending, 598 .is_valid = validate_singlecw_ending,
577 .moveset = moveset_eofb, 599 .moveset = &moveset_eofb,
578 600
579 .pre_trans = rf, 601 .pre_trans = rf,
580 602
@@ -593,7 +615,7 @@ drud_eorl = {
593 .ready = check_eofb, 615 .ready = check_eofb,
594 .ready_msg = check_eo_msg, 616 .ready_msg = check_eo_msg,
595 .is_valid = validate_singlecw_ending, 617 .is_valid = validate_singlecw_ending,
596 .moveset = moveset_eofb, 618 .moveset = &moveset_eofb,
597 619
598 .pre_trans = ur, 620 .pre_trans = ur,
599 621
@@ -612,7 +634,7 @@ drfb_eorl = {
612 .ready = check_eofb, 634 .ready = check_eofb,
613 .ready_msg = check_eo_msg, 635 .ready_msg = check_eo_msg,
614 .is_valid = validate_singlecw_ending, 636 .is_valid = validate_singlecw_ending,
615 .moveset = moveset_eofb, 637 .moveset = &moveset_eofb,
616 638
617 .pre_trans = fr, 639 .pre_trans = fr,
618 640
@@ -631,7 +653,7 @@ drfb_eoud = {
631 .ready = check_eofb, 653 .ready = check_eofb,
632 .ready_msg = check_eo_msg, 654 .ready_msg = check_eo_msg,
633 .is_valid = validate_singlecw_ending, 655 .is_valid = validate_singlecw_ending,
634 .moveset = moveset_eofb, 656 .moveset = &moveset_eofb,
635 657
636 .pre_trans = fd, 658 .pre_trans = fd,
637 659
@@ -650,7 +672,7 @@ drrl_eoud = {
650 .ready = check_eofb, 672 .ready = check_eofb,
651 .ready_msg = check_eo_msg, 673 .ready_msg = check_eo_msg,
652 .is_valid = validate_singlecw_ending, 674 .is_valid = validate_singlecw_ending,
653 .moveset = moveset_eofb, 675 .moveset = &moveset_eofb,
654 676
655 .pre_trans = rd, 677 .pre_trans = rd,
656 678
@@ -670,7 +692,7 @@ dranyfin_DR = {
670 .ready = check_drud, 692 .ready = check_drud,
671 .ready_msg = check_drany_msg, 693 .ready_msg = check_drany_msg,
672 .is_valid = always_valid, 694 .is_valid = always_valid,
673 .moveset = moveset_drud, 695 .moveset = &moveset_drud,
674 696
675 .detect = detect_pretrans_drud, 697 .detect = detect_pretrans_drud,
676 698
@@ -689,7 +711,7 @@ drudfin_drud = {
689 .ready = check_drud, 711 .ready = check_drud,
690 .ready_msg = check_dr_msg, 712 .ready_msg = check_dr_msg,
691 .is_valid = always_valid, 713 .is_valid = always_valid,
692 .moveset = moveset_drud, 714 .moveset = &moveset_drud,
693 715
694 .pre_trans = uf, 716 .pre_trans = uf,
695 717
@@ -708,7 +730,7 @@ drrlfin_drrl = {
708 .ready = check_drud, 730 .ready = check_drud,
709 .ready_msg = check_dr_msg, 731 .ready_msg = check_dr_msg,
710 .is_valid = always_valid, 732 .is_valid = always_valid,
711 .moveset = moveset_drud, 733 .moveset = &moveset_drud,
712 734
713 .pre_trans = rf, 735 .pre_trans = rf,
714 736
@@ -727,7 +749,7 @@ drfbfin_drfb = {
727 .ready = check_drud, 749 .ready = check_drud,
728 .ready_msg = check_dr_msg, 750 .ready_msg = check_dr_msg,
729 .is_valid = always_valid, 751 .is_valid = always_valid,
730 .moveset = moveset_drud, 752 .moveset = &moveset_drud,
731 753
732 .pre_trans = fd, 754 .pre_trans = fd,
733 755
@@ -747,7 +769,7 @@ htr_any = {
747 .ready = check_drud, 769 .ready = check_drud,
748 .ready_msg = check_drany_msg, 770 .ready_msg = check_drany_msg,
749 .is_valid = validate_singlecw_ending, 771 .is_valid = validate_singlecw_ending,
750 .moveset = moveset_drud, 772 .moveset = &moveset_drud,
751 773
752 .detect = detect_pretrans_drud, 774 .detect = detect_pretrans_drud,
753 775
@@ -766,7 +788,7 @@ htr_drud = {
766 .ready = check_drud, 788 .ready = check_drud,
767 .ready_msg = check_dr_msg, 789 .ready_msg = check_dr_msg,
768 .is_valid = validate_singlecw_ending, 790 .is_valid = validate_singlecw_ending,
769 .moveset = moveset_drud, 791 .moveset = &moveset_drud,
770 792
771 .pre_trans = uf, 793 .pre_trans = uf,
772 794
@@ -785,7 +807,7 @@ htr_drrl = {
785 .ready = check_drud, 807 .ready = check_drud,
786 .ready_msg = check_dr_msg, 808 .ready_msg = check_dr_msg,
787 .is_valid = validate_singlecw_ending, 809 .is_valid = validate_singlecw_ending,
788 .moveset = moveset_drud, 810 .moveset = &moveset_drud,
789 811
790 .pre_trans = rf, 812 .pre_trans = rf,
791 813
@@ -804,7 +826,7 @@ htr_drfb = {
804 .ready = check_drud, 826 .ready = check_drud,
805 .ready_msg = check_dr_msg, 827 .ready_msg = check_dr_msg,
806 .is_valid = validate_singlecw_ending, 828 .is_valid = validate_singlecw_ending,
807 .moveset = moveset_drud, 829 .moveset = &moveset_drud,
808 830
809 .pre_trans = fd, 831 .pre_trans = fd,
810 832
@@ -824,7 +846,7 @@ htrfin_htr = {
824 .ready = check_htr, 846 .ready = check_htr,
825 .ready_msg = check_htr_msg, 847 .ready_msg = check_htr_msg,
826 .is_valid = always_valid, 848 .is_valid = always_valid,
827 .moveset = moveset_htr, 849 .moveset = &moveset_htr,
828 850
829 .pre_trans = uf, 851 .pre_trans = uf,
830 852
@@ -834,6 +856,7 @@ htrfin_htr = {
834 856
835Step *steps[NSTEPS] = { 857Step *steps[NSTEPS] = {
836 &optimal_HTM, /* first is default */ 858 &optimal_HTM, /* first is default */
859 &optimal_nxopt31_HTM,
837 &optimal_light_HTM, 860 &optimal_light_HTM,
838 861
839 &eoany_HTM, 862 &eoany_HTM,
@@ -1183,6 +1206,19 @@ estimate_htrfin_htr(DfsArg *arg)
1183static int 1206static int
1184estimate_optimal_HTM(DfsArg *arg) 1207estimate_optimal_HTM(DfsArg *arg)
1185{ 1208{
1209 return estimate_nxoptlike(arg, &pd_khuge_HTM);
1210}
1211
1212static int
1213estimate_nxopt31_HTM(DfsArg *arg)
1214{
1215 return estimate_nxoptlike(arg, &pd_nxopt31_HTM);
1216}
1217
1218/* TODO: also use generic procedure for this */
1219static int
1220estimate_light_HTM(DfsArg *arg)
1221{
1186 int target, ret; 1222 int target, ret;
1187 Cube aux; 1223 Cube aux;
1188 1224
@@ -1192,6 +1228,9 @@ estimate_optimal_HTM(DfsArg *arg)
1192 (1<<L) | (1<<L2) | (1<<L3); 1228 (1<<L) | (1<<L2) | (1<<L3);
1193 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | 1229 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) |
1194 (1<<B) | (1<<B2) | (1<<B3); 1230 (1<<B) | (1<<B2) | (1<<B3);
1231 static const uint64_t htmask = (1<<U2) | (1<<D2) |
1232 (1<<R2) | (1<<L2) |
1233 (1<<F2) | (1<<B2);
1195 1234
1196 ret = -1; 1235 ret = -1;
1197 target = arg->d - arg->current_alg->len; 1236 target = arg->d - arg->current_alg->len;
@@ -1204,18 +1243,18 @@ estimate_optimal_HTM(DfsArg *arg)
1204 UPDATECHECKSTOP(ret, arg->ed->corners, target); 1243 UPDATECHECKSTOP(ret, arg->ed->corners, target);
1205 1244
1206 /* Normal probing */ 1245 /* Normal probing */
1207 arg->ed->normal_ud = ptableval(&pd_khuge_HTM, arg->cube); 1246 arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube);
1208 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); 1247 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target);
1209 aux = apply_trans(fd, arg->cube); 1248 aux = apply_trans(fd, arg->cube);
1210 arg->ed->normal_fb = ptableval(&pd_khuge_HTM, aux); 1249 arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux);
1211 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); 1250 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target);
1212 aux = apply_trans(rf, arg->cube); 1251 aux = apply_trans(rf, arg->cube);
1213 arg->ed->normal_rl = ptableval(&pd_khuge_HTM, aux); 1252 arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux);
1214 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); 1253 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target);
1215 1254
1216 /* If ret == 0, it's solved (corners + triple slice solved) */ 1255 /* If ret == 0, it's solved (corners + triple slice solved) */
1217 if (ret == 0) 1256 if (ret == 0)
1218 return 0; 1257 return is_solved(arg->cube) ? 0 : 1;
1219 1258
1220 /* Michel de Bondt's trick*/ 1259 /* Michel de Bondt's trick*/
1221 if (arg->ed->normal_ud == arg->ed->normal_fb && 1260 if (arg->ed->normal_ud == arg->ed->normal_fb &&
@@ -1224,21 +1263,30 @@ estimate_optimal_HTM(DfsArg *arg)
1224 } 1263 }
1225 1264
1226 /* Inverse probing */ 1265 /* Inverse probing */
1227 aux = arg->inverse = inverse_cube(arg->cube); 1266 if (!((1<<arg->last1) & htmask)) {
1228 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { 1267 aux = arg->inverse = inverse_cube(arg->cube);
1229 arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, aux); 1268 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) {
1230 } 1269 arg->ed->inverse_ud =
1231 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); 1270 ptableval(&pd_drud_sym16_HTM, aux);
1232 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { 1271 }
1233 aux = apply_trans(fd, arg->inverse); 1272 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1234 arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); 1273 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) {
1235 } 1274 aux = apply_trans(fd, arg->inverse);
1236 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); 1275 arg->ed->inverse_fb =
1237 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { 1276 ptableval(&pd_drud_sym16_HTM, aux);
1238 aux = apply_trans(rf, arg->inverse); 1277 }
1239 arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); 1278 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1279 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) {
1280 aux = apply_trans(rf, arg->inverse);
1281 arg->ed->inverse_rl =
1282 ptableval(&pd_drud_sym16_HTM, aux);
1283 }
1284 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1285 } else {
1286 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1287 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1288 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1240 } 1289 }
1241 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1242 1290
1243 /* Michel de Bondt's trick*/ 1291 /* Michel de Bondt's trick*/
1244 if (arg->ed->inverse_ud == arg->ed->inverse_fb && 1292 if (arg->ed->inverse_ud == arg->ed->inverse_fb &&
@@ -1246,26 +1294,26 @@ estimate_optimal_HTM(DfsArg *arg)
1246 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); 1294 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target);
1247 } 1295 }
1248 1296
1249 /* nxopt trick */ 1297 /* nxopt trick + half turn trick */
1250 if (arg->ed->normal_ud == target) 1298 if (arg->ed->normal_ud == target)
1251 arg->badmovesinv |= udmask; 1299 arg->badmovesinv |= udmask | htmask;
1252 if (arg->ed->normal_fb == target) 1300 if (arg->ed->normal_fb == target)
1253 arg->badmovesinv |= fbmask; 1301 arg->badmovesinv |= fbmask | htmask;
1254 if (arg->ed->normal_rl == target) 1302 if (arg->ed->normal_rl == target)
1255 arg->badmovesinv |= rlmask; 1303 arg->badmovesinv |= rlmask | htmask;
1256 1304
1257 if (arg->ed->inverse_ud == target) 1305 if (arg->ed->inverse_ud == target)
1258 arg->badmoves |= udmask; 1306 arg->badmoves |= udmask | htmask;
1259 if (arg->ed->inverse_fb == target) 1307 if (arg->ed->inverse_fb == target)
1260 arg->badmoves |= fbmask; 1308 arg->badmoves |= fbmask | htmask;
1261 if (arg->ed->inverse_rl == target) 1309 if (arg->ed->inverse_rl == target)
1262 arg->badmoves |= rlmask; 1310 arg->badmoves |= rlmask | htmask;
1263 1311
1264 return arg->ed->oldret = ret; 1312 return arg->ed->oldret = ret;
1265} 1313}
1266 1314
1267static int 1315static int
1268estimate_light_HTM(DfsArg *arg) 1316estimate_nxoptlike(DfsArg *arg, PruneData *pd)
1269{ 1317{
1270 int target, ret; 1318 int target, ret;
1271 Cube aux; 1319 Cube aux;
@@ -1276,9 +1324,6 @@ estimate_light_HTM(DfsArg *arg)
1276 (1<<L) | (1<<L2) | (1<<L3); 1324 (1<<L) | (1<<L2) | (1<<L3);
1277 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | 1325 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) |
1278 (1<<B) | (1<<B2) | (1<<B3); 1326 (1<<B) | (1<<B2) | (1<<B3);
1279 static const uint64_t htmask = (1<<U2) | (1<<D2) |
1280 (1<<R2) | (1<<L2) |
1281 (1<<F2) | (1<<B2);
1282 1327
1283 ret = -1; 1328 ret = -1;
1284 target = arg->d - arg->current_alg->len; 1329 target = arg->d - arg->current_alg->len;
@@ -1291,18 +1336,17 @@ estimate_light_HTM(DfsArg *arg)
1291 UPDATECHECKSTOP(ret, arg->ed->corners, target); 1336 UPDATECHECKSTOP(ret, arg->ed->corners, target);
1292 1337
1293 /* Normal probing */ 1338 /* Normal probing */
1294 arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); 1339 arg->ed->normal_ud = ptableval(pd, arg->cube);
1295 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); 1340 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target);
1296 aux = apply_trans(fd, arg->cube); 1341 aux = apply_trans(fd, arg->cube);
1297 arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); 1342 arg->ed->normal_fb = ptableval(pd, aux);
1298 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); 1343 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target);
1299 aux = apply_trans(rf, arg->cube); 1344 aux = apply_trans(rf, arg->cube);
1300 arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); 1345 arg->ed->normal_rl = ptableval(pd, aux);
1301 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); 1346 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target);
1302 1347
1303 /* If ret == 0, it's solved (corners + triple slice solved) */
1304 if (ret == 0) 1348 if (ret == 0)
1305 return 0; 1349 return arg->step->is_done(arg->cube) ? 0 : 1;
1306 1350
1307 /* Michel de Bondt's trick*/ 1351 /* Michel de Bondt's trick*/
1308 if (arg->ed->normal_ud == arg->ed->normal_fb && 1352 if (arg->ed->normal_ud == arg->ed->normal_fb &&
@@ -1311,30 +1355,21 @@ estimate_light_HTM(DfsArg *arg)
1311 } 1355 }
1312 1356
1313 /* Inverse probing */ 1357 /* Inverse probing */
1314 if (!((1<<arg->last1) & htmask)) { 1358 aux = arg->inverse = inverse_cube(arg->cube);
1315 aux = arg->inverse = inverse_cube(arg->cube); 1359 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) {
1316 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { 1360 arg->ed->inverse_ud = ptableval(pd, aux);
1317 arg->ed->inverse_ud = 1361 }
1318 ptableval(&pd_drud_sym16_HTM, aux); 1362 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1319 } 1363 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) {
1320 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); 1364 aux = apply_trans(fd, arg->inverse);
1321 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { 1365 arg->ed->inverse_fb = ptableval(pd, aux);
1322 aux = apply_trans(fd, arg->inverse); 1366 }
1323 arg->ed->inverse_fb = 1367 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1324 ptableval(&pd_drud_sym16_HTM, aux); 1368 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) {
1325 } 1369 aux = apply_trans(rf, arg->inverse);
1326 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); 1370 arg->ed->inverse_rl = ptableval(pd, aux);
1327 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) {
1328 aux = apply_trans(rf, arg->inverse);
1329 arg->ed->inverse_rl =
1330 ptableval(&pd_drud_sym16_HTM, aux);
1331 }
1332 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1333 } else {
1334 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1335 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1336 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1337 } 1371 }
1372 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1338 1373
1339 /* Michel de Bondt's trick*/ 1374 /* Michel de Bondt's trick*/
1340 if (arg->ed->inverse_ud == arg->ed->inverse_fb && 1375 if (arg->ed->inverse_ud == arg->ed->inverse_fb &&
@@ -1342,24 +1377,25 @@ estimate_light_HTM(DfsArg *arg)
1342 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); 1377 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target);
1343 } 1378 }
1344 1379
1345 /* nxopt trick + half turn trick */ 1380 /* nxopt trick */
1346 if (arg->ed->normal_ud == target) 1381 if (arg->ed->normal_ud == target)
1347 arg->badmovesinv |= udmask | htmask; 1382 arg->badmovesinv |= udmask;
1348 if (arg->ed->normal_fb == target) 1383 if (arg->ed->normal_fb == target)
1349 arg->badmovesinv |= fbmask | htmask; 1384 arg->badmovesinv |= fbmask;
1350 if (arg->ed->normal_rl == target) 1385 if (arg->ed->normal_rl == target)
1351 arg->badmovesinv |= rlmask | htmask; 1386 arg->badmovesinv |= rlmask;
1352 1387
1353 if (arg->ed->inverse_ud == target) 1388 if (arg->ed->inverse_ud == target)
1354 arg->badmoves |= udmask | htmask; 1389 arg->badmoves |= udmask;
1355 if (arg->ed->inverse_fb == target) 1390 if (arg->ed->inverse_fb == target)
1356 arg->badmoves |= fbmask | htmask; 1391 arg->badmoves |= fbmask;
1357 if (arg->ed->inverse_rl == target) 1392 if (arg->ed->inverse_rl == target)
1358 arg->badmoves |= rlmask | htmask; 1393 arg->badmoves |= rlmask;
1359 1394
1360 return arg->ed->oldret = ret; 1395 return arg->ed->oldret = ret;
1361} 1396}
1362 1397
1398
1363static bool 1399static bool
1364always_valid(Alg *alg) 1400always_valid(Alg *alg)
1365{ 1401{
diff --git a/src/symcoord.c b/src/symcoord.c
index 038449a..707a84e 100644
--- a/src/symcoord.c
+++ b/src/symcoord.c
@@ -4,23 +4,24 @@
4#define CLASSES_CP_16 2768 4#define CLASSES_CP_16 2768
5#define CLASSES_EOFBEPOS_16 64430 5#define CLASSES_EOFBEPOS_16 64430
6 6
7static Cube antindex_coud_sym16(uint64_t ind);
8static Cube antindex_cp_sym16(uint64_t ind); 7static Cube antindex_cp_sym16(uint64_t ind);
9static Cube antindex_eofbepos_sym16(uint64_t ind); 8static Cube antindex_eofbepos_sym16(uint64_t ind);
10static Cube antindex_drud_sym16(uint64_t ind); 9static Cube antindex_drud_sym16(uint64_t ind);
11static Cube antindex_drudfin_noE_sym16(uint64_t ind); 10static Cube antindex_drudfin_noE_sym16(uint64_t ind);
12static Cube antindex_khuge(uint64_t ind); 11static Cube antindex_khuge(uint64_t ind);
12static Cube antindex_nxopt31(uint64_t ind);
13 13
14static uint64_t index_coud_sym16(Cube cube);
15static uint64_t index_cp_sym16(Cube cube); 14static uint64_t index_cp_sym16(Cube cube);
16static uint64_t index_eofbepos_sym16(Cube cube); 15static uint64_t index_eofbepos_sym16(Cube cube);
17static uint64_t index_drud_sym16(Cube cube); 16static uint64_t index_drud_sym16(Cube cube);
18static uint64_t index_drudfin_noE_sym16(Cube cube); 17static uint64_t index_drudfin_noE_sym16(Cube cube);
19static uint64_t index_khuge(Cube cube); 18static uint64_t index_khuge(Cube cube);
19static uint64_t index_nxopt31(Cube cube);
20 20
21static int transfinder_drud_sym16(uint64_t ind, Trans *ret); 21static int transfinder_drud_sym16(uint64_t ind, Trans *ret);
22static int transfinder_drudfin_noE_sym16(uint64_t ind, Trans *ret); 22static int transfinder_drudfin_noE_sym16(uint64_t ind, Trans *ret);
23static int transfinder_khuge(uint64_t ind, Trans *ret); 23static int transfinder_khuge(uint64_t ind, Trans *ret);
24static int transfinder_nxopt31(uint64_t ind, Trans *ret);
24 25
25static void gensym(SymData *sd); 26static void gensym(SymData *sd);
26static bool read_symdata_file(SymData *sd); 27static bool read_symdata_file(SymData *sd);
@@ -38,15 +39,6 @@ trans_group_udfix[16] = {
38}; 39};
39 40
40static SymData 41static SymData
41sd_coud_16 = {
42 .filename = "sd_coud_16",
43 .coord = &coord_coud,
44 .sym_coord = &coord_coud_sym16,
45 .ntrans = 16,
46 .trans = trans_group_udfix
47};
48
49static SymData
50sd_cp_16 = { 42sd_cp_16 = {
51 .filename = "sd_cp_16", 43 .filename = "sd_cp_16",
52 .coord = &coord_cp, 44 .coord = &coord_cp,
@@ -64,9 +56,8 @@ sd_eofbepos_16 = {
64 .trans = trans_group_udfix 56 .trans = trans_group_udfix
65}; 57};
66 58
67static int nsymdata = 3; 59static int nsymdata = 2;
68static SymData * all_sd[] = { 60static SymData * all_sd[] = {
69 &sd_coud_16,
70 &sd_cp_16, 61 &sd_cp_16,
71 &sd_eofbepos_16, 62 &sd_eofbepos_16,
72}; 63};
@@ -81,12 +72,6 @@ coord_eofbepos_sym16 = {
81}; 72};
82 73
83Coordinate 74Coordinate
84coord_coud_sym16 = {
85 .index = index_coud_sym16,
86 .cube = antindex_coud_sym16,
87};
88
89Coordinate
90coord_cp_sym16 = { 75coord_cp_sym16 = {
91 .index = index_cp_sym16, 76 .index = index_cp_sym16,
92 .cube = antindex_cp_sym16, 77 .cube = antindex_cp_sym16,
@@ -116,13 +101,15 @@ coord_khuge = {
116 .trans = transfinder_khuge, 101 .trans = transfinder_khuge,
117}; 102};
118 103
119/* Functions *****************************************************************/ 104Coordinate
105coord_nxopt31 = {
106 .index = index_nxopt31,
107 .cube = antindex_nxopt31,
108 .max = POW3TO7 * BINOM8ON4 * CLASSES_EOFBEPOS_16 ,
109 .trans = transfinder_nxopt31,
110};
120 111
121static Cube 112/* Functions *****************************************************************/
122antindex_coud_sym16(uint64_t ind)
123{
124 return sd_coud_16.rep[ind];
125}
126 113
127static Cube 114static Cube
128antindex_cp_sym16(uint64_t ind) 115antindex_cp_sym16(uint64_t ind)
@@ -173,10 +160,16 @@ antindex_khuge(uint64_t ind)
173 return c; 160 return c;
174} 161}
175 162
176static uint64_t 163static Cube
177index_coud_sym16(Cube cube) 164antindex_nxopt31(uint64_t ind)
178{ 165{
179 return sd_coud_16.class[coord_coud.index(cube)]; 166 Cube c;
167
168 c = antindex_eofbepos_sym16(ind/(BINOM8ON4*POW3TO7));
169 c.cp = coord_cpud_separate.cube((ind/POW3TO7)%BINOM8ON4).cp;
170 c.coud = ind % POW3TO7;
171
172 return c;
180} 173}
181 174
182static uint64_t 175static uint64_t
@@ -229,6 +222,20 @@ index_khuge(Cube cube)
229 return a * POW3TO7 + c.coud; 222 return a * POW3TO7 + c.coud;
230} 223}
231 224
225static uint64_t
226index_nxopt31(Cube cube)
227{
228 Trans t;
229 Cube c;
230 uint64_t a;
231
232 t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)];
233 c = apply_trans(t, cube);
234 a = (index_eofbepos_sym16(c)*BINOM8ON4) + coord_cpud_separate.index(c);
235
236 return a * POW3TO7 + c.coud;
237}
238
232static int 239static int
233transfinder_drud_sym16(uint64_t ind, Trans *ret) 240transfinder_drud_sym16(uint64_t ind, Trans *ret)
234{ 241{
@@ -295,6 +302,28 @@ transfinder_khuge(uint64_t ind, Trans *ret)
295 return naux[trueind]; 302 return naux[trueind];
296} 303}
297 304
305static int
306transfinder_nxopt31(uint64_t ind, Trans *ret)
307{
308 uint64_t i, trueind;
309 int j;
310 static bool initialized = false;
311 static int naux[CLASSES_EOFBEPOS_16];
312 static Trans retaux[CLASSES_EOFBEPOS_16][NTRANS];
313
314 if (!initialized) {
315 for (i = 0; i < CLASSES_EOFBEPOS_16; i++)
316 naux[i] = selfsims(&sd_eofbepos_16, i, retaux[i]);
317
318 initialized = true;
319 }
320
321 trueind = ind/(BINOM8ON4*POW3TO7);
322 for (j = 0; j < naux[trueind]; j++)
323 ret[j] = retaux[trueind][j];
324 return naux[trueind];
325}
326
298/* Other functions ***********************************************************/ 327/* Other functions ***********************************************************/
299 328
300static void 329static void
diff --git a/src/symcoord.h b/src/symcoord.h
index f231c92..4ba3815 100644
--- a/src/symcoord.h
+++ b/src/symcoord.h
@@ -3,12 +3,12 @@
3 3
4#include "coord.h" 4#include "coord.h"
5 5
6extern Coordinate coord_coud_sym16;
7extern Coordinate coord_cp_sym16; 6extern Coordinate coord_cp_sym16;
8extern Coordinate coord_eofbepos_sym16; 7extern Coordinate coord_eofbepos_sym16;
9extern Coordinate coord_drud_sym16; 8extern Coordinate coord_drud_sym16;
10extern Coordinate coord_drudfin_noE_sym16; 9extern Coordinate coord_drudfin_noE_sym16;
11extern Coordinate coord_khuge; 10extern Coordinate coord_khuge;
11extern Coordinate coord_nxopt31;
12 12
13void init_symcoord(); 13void init_symcoord();
14 14

Generated with cgit - Back to sebastiano.tronto.net