aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-13 20:40:18 +0100
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-13 20:40:18 +0100
commit1215648b1ba3c592bd9d97b871349673d1702e44 (patch)
tree7dc73a013c76b0cb0976e98d5e07902a0045363f /src
parent296f35b7ed4ea3177c520f28176f44d6ad47d76d (diff)
downloadnissy-1215648b1ba3c592bd9d97b871349673d1702e44.tar.gz
nissy-1215648b1ba3c592bd9d97b871349673d1702e44.zip
Faster optimal solver.
This is a pretty big one, but unfortunately performance only improved by about 5%. I implemented one of the main ideas of nxopt, that is switching to the inverse scramble on the fly if it gives a lower branching factor. On the one hand it makes sense that it does not have such a huge impact, since it only rarely happens that we do have a lower branching factor on inverse, but on the other hand I am quite sad that the improvement is barely noticeable :-( Maybe the problem is that I have introduced a lot of new overhead and I can improve that in the future. Or maybe I am just overlooking something stupid.
Diffstat (limited to 'src')
-rw-r--r--src/alg.c32
-rw-r--r--src/alg.h2
-rw-r--r--src/cubetypes.h32
-rw-r--r--src/solve.c314
-rw-r--r--src/steps.c499
-rw-r--r--src/steps.h8
-rw-r--r--src/utils.c14
-rw-r--r--src/utils.h2
8 files changed, 616 insertions, 287 deletions
diff --git a/src/alg.c b/src/alg.c
index 4e96925..1158eba 100644
--- a/src/alg.c
+++ b/src/alg.c
@@ -373,3 +373,35 @@ realloc_alg(Alg *alg, int n)
373 alg->allocated = n; 373 alg->allocated = n;
374} 374}
375 375
376void
377swapmove(Move *m1, Move *m2)
378{
379 Move aux;
380
381 aux = *m1;
382 *m1 = *m2;
383 *m2 = aux;
384}
385
386void
387unniss(Alg *alg)
388{
389 int i;
390 Alg *aux;
391
392 aux = new_alg("");
393
394 for (i = 0; i < alg->len; i++)
395 if (!alg->inv[i])
396 append_move(aux, alg->move[i], false);
397
398 for (i = alg->len-1; i >= 0; i--)
399 if (alg->inv[i])
400 append_move(aux, inverse_move(alg->move[i]), false);
401
402 for (i = 0; i < alg->len; i++) {
403 alg->move[i] = aux->move[i];
404 alg->inv[i] = false;
405 }
406 free(aux);
407}
diff --git a/src/alg.h b/src/alg.h
index 98900b4..f45b682 100644
--- a/src/alg.h
+++ b/src/alg.h
@@ -30,6 +30,8 @@ AlgList * new_alglist();
30Alg * on_inverse(Alg *alg); 30Alg * on_inverse(Alg *alg);
31void print_alg(Alg *alg, bool l); 31void print_alg(Alg *alg, bool l);
32void print_alglist(AlgList *al, bool l); 32void print_alglist(AlgList *al, bool l);
33void swapmove(Move *m1, Move *m2);
34void unniss(Alg *alg);
33 35
34#endif 36#endif
35 37
diff --git a/src/cubetypes.h b/src/cubetypes.h
index 9ec8620..3ad960b 100644
--- a/src/cubetypes.h
+++ b/src/cubetypes.h
@@ -81,9 +81,8 @@ typedef struct commandargs CommandArgs;
81typedef struct coordinate Coordinate; 81typedef struct coordinate Coordinate;
82typedef struct cube Cube; 82typedef struct cube Cube;
83typedef struct cubearray CubeArray; 83typedef struct cubearray CubeArray;
84typedef struct dfsdata DfsData; 84typedef struct dfsarg DfsArg;
85typedef struct estimatedata EstimateData; 85typedef struct estimatedata EstimateData;
86typedef struct localinfo LocalInfo;
87typedef struct piecefilter PieceFilter; 86typedef struct piecefilter PieceFilter;
88typedef struct prunedata PruneData; 87typedef struct prunedata PruneData;
89typedef struct solveoptions SolveOptions; 88typedef struct solveoptions SolveOptions;
@@ -94,7 +93,7 @@ typedef struct threaddatagenpt ThreadDataGenpt;
94 93
95typedef Cube (*AntiIndexer) (uint64_t); 94typedef Cube (*AntiIndexer) (uint64_t);
96typedef bool (*Checker) (Cube); 95typedef bool (*Checker) (Cube);
97typedef int (*Estimator) (EstimateData *); 96typedef int (*Estimator) (DfsArg *);
98typedef bool (*Validator) (Alg *); 97typedef bool (*Validator) (Alg *);
99typedef void (*Exec) (CommandArgs *); 98typedef void (*Exec) (CommandArgs *);
100typedef uint64_t (*Indexer) (Cube); 99typedef uint64_t (*Indexer) (Cube);
@@ -198,36 +197,31 @@ cubearray
198}; 197};
199 198
200struct 199struct
201dfsdata 200dfsarg
202{ 201{
202 Step * step;
203 SolveOptions * opts;
204 Cube cube;
205 Cube inverse;
203 int d; 206 int d;
204 int m; 207 uint64_t badmoves;
205 int lb; 208 uint64_t badmovesinv;
206 bool niss; 209 bool niss;
207 Move last1; 210 Move last1;
208 Move last2; 211 Move last2;
212 Move last1inv;
213 Move last2inv;
209 EstimateData * ed; 214 EstimateData * ed;
210 AlgList * sols; 215 AlgList * sols;
211 pthread_mutex_t * sols_mutex; 216 pthread_mutex_t * sols_mutex;
212 Alg * current_alg; 217 Alg * current_alg;
213 Move * sorted_moves; 218 Move * sorted_moves;
214 int * move_position; 219 int * move_position;
215 uint8_t * visited;
216}; 220};
217 221
218struct 222struct
219estimatedata 223estimatedata
220{ 224{
221 Cube cube;
222 int target;
223 Move lastmove;
224 uint64_t movebitmask;
225 LocalInfo * li;
226};
227
228struct
229localinfo
230{
231 int corners; 225 int corners;
232 int normal_ud; 226 int normal_ud;
233 int normal_fb; 227 int normal_fb;
@@ -235,7 +229,7 @@ localinfo
235 int inverse_ud; 229 int inverse_ud;
236 int inverse_fb; 230 int inverse_fb;
237 int inverse_rl; 231 int inverse_rl;
238 int prev_ret; 232 int oldret;
239}; 233};
240 234
241struct 235struct
@@ -284,6 +278,8 @@ step
284{ 278{
285 char * shortname; 279 char * shortname;
286 char * name; 280 char * name;
281 bool final;
282 Checker is_done;
287 Estimator estimate; 283 Estimator estimate;
288 Checker ready; 284 Checker ready;
289 char * ready_msg; 285 char * ready_msg;
diff --git a/src/solve.c b/src/solve.c
index ec16935..ea3b7ae 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -2,155 +2,208 @@
2 2
3/* Local functions ***********************************************************/ 3/* Local functions ***********************************************************/
4 4
5static bool allowed_next(Move move, DfsData *dd, uint64_t mm); 5static bool allowed_next(Move move, DfsArg *arg);
6static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd); 6static bool cancel_niss(DfsArg *arg);
7static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); 7static void copy_dfsarg(DfsArg *src, DfsArg *dst);
8static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); 8static void dfs(DfsArg *arg);
9static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); 9static void dfs_branch(DfsArg *arg);
10static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); 10static bool dfs_check_solved(DfsArg *arg);
11static bool dfs_switch_final(DfsArg *arg);
12static void dfs_niss(DfsArg *arg);
13static bool dfs_stop(DfsArg *arg);
11static void * instance_thread(void *arg); 14static void * instance_thread(void *arg);
15static void invert_branch(DfsArg *arg);
12static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d); 16static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d);
17static bool niss_makes_sense(DfsArg *arg);
13 18
14/* Local functions ***********************************************************/ 19/* Local functions ***********************************************************/
15 20
16static bool 21static bool
17allowed_next(Move move, DfsData *dd, uint64_t mm) 22allowed_next(Move m, DfsArg *arg)
18{ 23{
19 if ((1 << move) & mm) 24 if ((1 << m) & arg->badmoves)
20 return false; 25 return false;
21 26
22 if (!possible_next(dd->last2, dd->last1, move)) 27 if (!possible_next(arg->last2, arg->last1, m))
23 return false; 28 return false;
24 29
25 if (commute(dd->last1, move)) 30 if (commute(arg->last1, m))
26 return dd->move_position[dd->last1] < dd->move_position[move]; 31 return arg->move_position[arg->last1] < arg->move_position[m];
27 32
28 return true; 33 return true;
29} 34}
30 35
36static bool
37cancel_niss(DfsArg *arg)
38{
39 return !possible_next(arg->last2, arg->last1, arg->last1inv) &&
40 !(commute(arg->last1inv, arg->last2inv) &&
41 arg->last2inv != NULLMOVE &&
42 possible_next(arg->last2, arg->last1, arg->last2inv));
43}
44
31static void 45static void
32dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 46copy_dfsarg(DfsArg *src, DfsArg *dst)
33{ 47{
34 if (dfs_stop(c, s, opts, dd)) 48 dst->step = src->step;
49 dst->opts = src->opts;
50 dst->cube = src->cube;
51 dst->inverse = src->inverse;
52 dst->d = src->d;
53 dst->badmoves = src->badmoves;
54 dst->badmovesinv = src->badmovesinv;
55 dst->niss = src->niss;
56 dst->last1 = src->last1;
57 dst->last2 = src->last2;
58 dst->last1inv = src->last1inv;
59 dst->last2inv = src->last2inv;
60 dst->sols = src->sols;
61 dst->sols_mutex = src->sols_mutex;
62 dst->current_alg = src->current_alg;
63 dst->sorted_moves = src->sorted_moves;
64 dst->move_position = src->move_position;
65
66 copy_estimatedata(src->ed, dst->ed);
67}
68
69static void
70dfs(DfsArg *arg)
71{
72 bool sw = false;
73
74 if (dfs_stop(arg))
35 return; 75 return;
36 76
37 if (dfs_check_solved(s, opts, dd)) 77 if (dfs_check_solved(arg))
38 return; 78 return;
39 79
40 dfs_branch(c, s, opts, dd); 80 if (arg->step->final && (sw = dfs_switch_final(arg)))
81 invert_branch(arg);
82 dfs_branch(arg);
83
84 if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg))
85 dfs_niss(arg);
41 86
42 if (opts->can_niss && !dd->niss) 87 if (sw)
43 dfs_niss(c, s, opts, dd); 88 invert_branch(arg);
44} 89}
45 90
46static void 91static void
47dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 92dfs_branch(DfsArg *arg)
48{ 93{
49 bool b = false;
50 int i; 94 int i;
51 uint64_t mm; 95 Move m;
52 Move m, l1, l2; 96 DfsArg *newarg;
53 LocalInfo li;
54 97
55 l1 = dd->last1; 98 newarg = malloc(sizeof(DfsArg));
56 l2 = dd->last2; 99 newarg->ed = malloc(sizeof(EstimateData));
57 li = *(dd->ed->li);
58 mm = dd->ed->movebitmask;
59 100
60 for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { 101 for (i = 0; arg->sorted_moves[i] != NULLMOVE; i++) {
61 if (b) 102 m = arg->sorted_moves[i];
62 break; 103 if (allowed_next(m, arg)) {
63 104 copy_dfsarg(arg, newarg);
64 m = dd->sorted_moves[i]; 105 newarg->last2 = arg->last1;
65 if (allowed_next(m, dd, mm)) { 106 newarg->last1 = m;
66 dd->last2 = dd->last1; 107 newarg->cube = apply_move(m, arg->cube);
67 dd->last1 = m; 108 append_move(arg->current_alg, m, newarg->niss);
68 append_move(dd->current_alg, m, dd->niss);
69 109
70 dfs(apply_move(m, c), s, opts, dd); 110 dfs(newarg);
71 111
72 dd->current_alg->len--; 112 arg->current_alg->len--;
73 dd->last2 = l2;
74 dd->last1 = l1;
75 *(dd->ed->li) = li;
76 } 113 }
77 } 114 }
115
116 free(newarg->ed);
117 free(newarg);
78} 118}
79 119
80static bool 120static bool
81dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) 121dfs_check_solved(DfsArg *arg)
82{ 122{
83 if (dd->lb != 0) 123 if (!arg->step->is_done(arg->cube))
84 return false; 124 return false;
85 125
86 if (dd->current_alg->len == dd->d) { 126 if (arg->current_alg->len == arg->d) {
87 if (s->is_valid(dd->current_alg) || opts->all) { 127 if ((arg->step->is_valid(arg->current_alg) || arg->opts->all)
88 pthread_mutex_lock(dd->sols_mutex); 128 && (!arg->step->final || !cancel_niss(arg))) {
89 if (dd->sols->len < opts->max_solutions) 129 pthread_mutex_lock(arg->sols_mutex);
90 append_alg(dd->sols, dd->current_alg); 130 if (arg->sols->len < arg->opts->max_solutions)
91 pthread_mutex_unlock(dd->sols_mutex); 131 append_alg(arg->sols, arg->current_alg);
132 pthread_mutex_unlock(arg->sols_mutex);
92 } 133 }
93 134
94 if (opts->verbose) 135 if (arg->opts->verbose)
95 print_alg(dd->current_alg, false); 136 print_alg(arg->current_alg, false);
96 } 137 }
97 138
98 return true; 139 return true;
99} 140}
100 141
101static void 142static void
102dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 143dfs_niss(DfsArg *arg)
103{ 144{
104 Move l1, l2; 145 DfsArg *newarg;
105 EstimateData *ed;
106
107 l1 = dd->last1;
108 l2 = dd->last2;
109 146
110 ed = malloc(sizeof(EstimateData)); 147 newarg = malloc(sizeof(DfsArg));
111 ed->cube = apply_move(inverse_move(l1), (Cube){0}); 148 newarg->ed = malloc(sizeof(EstimateData));
112 ed->target = 1;
113 149
114 if (dd->current_alg->len == 0 || s->estimate(ed)) { 150 copy_dfsarg(arg, newarg);
115 dd->niss = true; 151 swapmove(&(newarg->last1), &(newarg->last1inv));
116 dd->last1 = NULLMOVE; 152 swapmove(&(newarg->last2), &(newarg->last2inv));
117 dd->last2 = NULLMOVE; 153 newarg->niss = !(arg->niss);
154 newarg->cube = inverse_cube(arg->cube);
118 155
119 dfs(inverse_cube(c), s, opts, dd); 156 dfs(newarg);
120 157
121 dd->last1 = l1; 158 free(newarg->ed);
122 dd->last2 = l2; 159 free(newarg);
123 dd->niss = false;
124 }
125
126 free(ed);
127} 160}
128 161
129static bool 162static bool
130dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 163dfs_stop(DfsArg *arg)
131{ 164{
165 int lowerbound;
132 bool b; 166 bool b;
133 167
134 dd->ed->cube = c; 168 lowerbound = arg->step->estimate(arg);
135 dd->ed->target = dd->d - dd->current_alg->len; 169 if (arg->opts->can_niss && !arg->niss)
136 dd->ed->lastmove = dd->last1; 170 lowerbound = MIN(1, lowerbound);
137 dd->ed->movebitmask = 0;
138
139 dd->lb = s->estimate(dd->ed);
140 if (opts->can_niss && !dd->niss)
141 dd->lb = MIN(1, dd->lb);
142 171
143 if (dd->current_alg->len + dd->lb > dd->d) { 172 if (arg->current_alg->len + lowerbound > arg->d) {
144 b = true; 173 b = true;
145 } else { 174 } else {
146 pthread_mutex_lock(dd->sols_mutex); 175 pthread_mutex_lock(arg->sols_mutex);
147 b = dd->sols->len >= opts->max_solutions; 176 b = arg->sols->len >= arg->opts->max_solutions;
148 pthread_mutex_unlock(dd->sols_mutex); 177 pthread_mutex_unlock(arg->sols_mutex);
149 } 178 }
150 179
151 return b; 180 return b;
152} 181}
153 182
183static bool
184dfs_switch_final(DfsArg *arg)
185{
186 int i, bn, bi;
187
188 for (bn = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++)
189 if (allowed_next(arg->sorted_moves[i], arg))
190 bn++;
191
192 swapmove(&(arg->last1), &(arg->last1inv));
193 swapmove(&(arg->last2), &(arg->last2inv));
194 swapu64(&(arg->badmoves), &(arg->badmovesinv));
195
196 for (bi = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++)
197 if (allowed_next(arg->sorted_moves[i], arg))
198 bi++;
199
200 swapmove(&(arg->last1), &(arg->last1inv));
201 swapmove(&(arg->last2), &(arg->last2inv));
202 swapu64(&(arg->badmoves), &(arg->badmovesinv));
203
204 return bi < bn;
205}
206
154static void * 207static void *
155instance_thread(void *arg) 208instance_thread(void *arg)
156{ 209{
@@ -158,7 +211,7 @@ instance_thread(void *arg)
158 Cube c; 211 Cube c;
159 ThreadDataSolve *td; 212 ThreadDataSolve *td;
160 AlgListNode *node; 213 AlgListNode *node;
161 DfsData dd; 214 DfsArg darg;
162 215
163 td = (ThreadDataSolve *)arg; 216 td = (ThreadDataSolve *)arg;
164 217
@@ -179,34 +232,53 @@ instance_thread(void *arg)
179 apply_move(node->alg->move[0], inverse_cube(td->cube)) : 232 apply_move(node->alg->move[0], inverse_cube(td->cube)) :
180 apply_move(node->alg->move[0], td->cube); 233 apply_move(node->alg->move[0], td->cube);
181 234
182 dd.d = td->depth; 235 darg.step = td->step;
183 dd.m = 1; 236 darg.opts = td->opts;
184 dd.niss = node->alg->inv[0]; 237 darg.cube = c;
185 dd.lb = -1; 238 darg.d = td->depth;
186 dd.last1 = node->alg->move[0]; 239 darg.niss = node->alg->inv[0];
187 dd.last2 = NULLMOVE; 240 darg.last1 = node->alg->move[0];
188 dd.sols = td->sols; 241 darg.last2 = NULLMOVE;
189 dd.sols_mutex = td->sols_mutex; 242 darg.last1inv = NULLMOVE;
190 dd.current_alg = new_alg(""); 243 darg.last2inv = NULLMOVE;
191 append_move(dd.current_alg, node->alg->move[0], 244 darg.sols = td->sols;
245 darg.sols_mutex = td->sols_mutex;
246 darg.current_alg = new_alg("");
247 append_move(darg.current_alg, node->alg->move[0],
192 node->alg->inv[0]); 248 node->alg->inv[0]);
193 dd.sorted_moves = td->sorted_moves; 249 darg.sorted_moves = td->sorted_moves;
194 dd.move_position = td->move_position; 250 darg.move_position = td->move_position;
195 dd.ed = malloc(sizeof(EstimateData)); 251 darg.ed = new_estimatedata();
196 dd.ed->movebitmask = 0; 252 darg.badmoves = 0;
197 dd.ed->li = new_localinfo(); 253 darg.badmovesinv = 0;
198 254
199 dfs(c, td->step, td->opts, &dd); 255 dfs(&darg);
200 256
201 free_alg(dd.current_alg); 257 free_alg(darg.current_alg);
202 free_localinfo(dd.ed->li); 258 free_estimatedata(darg.ed);
203 free(dd.ed);
204 } 259 }
205 260
206 return NULL; 261 return NULL;
207} 262}
208 263
209static void 264static void
265invert_branch(DfsArg *arg)
266{
267 Cube aux;
268
269 aux = arg->cube;
270 arg->cube = is_solved(arg->inverse) ?
271 inverse_cube(arg->cube) : arg->inverse;
272 arg->inverse = aux;
273
274 swapu64(&(arg->badmoves), &(arg->badmovesinv));
275 arg->niss = !(arg->niss);
276 swapmove(&(arg->last1), &(arg->last1inv));
277 swapmove(&(arg->last2), &(arg->last2inv));
278 invert_estimatedata(arg->ed);
279}
280
281static void
210multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) 282multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
211{ 283{
212 int i, *move_position; 284 int i, *move_position;
@@ -233,6 +305,8 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
233 305
234 for (i = 0; sorted_moves[i] != NULLMOVE; i++) { 306 for (i = 0; sorted_moves[i] != NULLMOVE; i++) {
235 alg = new_alg(""); 307 alg = new_alg("");
308 /* TODO: start on inverse also in case of final step
309 and ed->sw true */
236 append_move(alg, sorted_moves[i], false); 310 append_move(alg, sorted_moves[i], false);
237 append_alg(start, alg); 311 append_alg(start, alg);
238 if (opts->can_niss) { 312 if (opts->can_niss) {
@@ -270,6 +344,15 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d)
270 free(sorted_moves); 344 free(sorted_moves);
271} 345}
272 346
347static bool
348niss_makes_sense(DfsArg *arg)
349{
350 Cube testcube;
351
352 testcube = apply_move(inverse_move(arg->last1), (Cube){0});
353 return arg->current_alg->len == 0 || arg->step->is_done(testcube);
354}
355
273/* Public functions **********************************************************/ 356/* Public functions **********************************************************/
274 357
275AlgList * 358AlgList *
@@ -279,10 +362,8 @@ solve(Cube cube, Step *step, SolveOptions *opts)
279 AlgList *sols; 362 AlgList *sols;
280 AlgListNode *node; 363 AlgListNode *node;
281 Cube c; 364 Cube c;
282 EstimateData *ed;
283 bool b;
284 365
285 prepare_step(step, opts->nthreads); 366 prepare_step(step, opts);
286 367
287 if (step->detect != NULL) 368 if (step->detect != NULL)
288 step->pre_trans = step->detect(cube); 369 step->pre_trans = step->detect(cube);
@@ -296,19 +377,9 @@ solve(Cube cube, Step *step, SolveOptions *opts)
296 return sols; 377 return sols;
297 } 378 }
298 379
299 if (opts->min_moves == 0) { 380 if (opts->min_moves == 0 && step->is_done(cube)) {
300 ed = malloc(sizeof(EstimateData)); 381 append_alg(sols, new_alg(""));
301 ed->cube = cube; 382 return sols;
302 ed->target = 0;
303 ed->li = new_localinfo();
304 b = step->estimate(ed) == 0;
305 free_localinfo(ed->li);
306 free(ed);
307
308 if (b) {
309 append_alg(sols, new_alg(""));
310 return sols;
311 }
312 } 383 }
313 384
314 for (d = opts->min_moves; 385 for (d = opts->min_moves;
@@ -323,8 +394,11 @@ solve(Cube cube, Step *step, SolveOptions *opts)
323 multidfs(c, step, opts, sols, d); 394 multidfs(c, step, opts, sols, d);
324 } 395 }
325 396
326 for (node = sols->first; node != NULL; node = node->next) 397 for (node = sols->first; node != NULL; node = node->next) {
327 transform_alg(inverse_trans(step->pre_trans), node->alg); 398 transform_alg(inverse_trans(step->pre_trans), node->alg);
399 if (step->final)
400 unniss(node->alg);
401 }
328 402
329 return sols; 403 return sols;
330} 404}
diff --git a/src/steps.c b/src/steps.c
index abb2918..ccf33df 100644
--- a/src/steps.c
+++ b/src/steps.c
@@ -5,28 +5,37 @@
5/* Checkers, estimators and validators ***************************************/ 5/* Checkers, estimators and validators ***************************************/
6 6
7static bool check_centers(Cube cube); 7static bool check_centers(Cube cube);
8static bool check_coany_HTM(Cube cube);
9static bool check_coud_HTM(Cube cube);
10static bool check_coany_URF(Cube cube);
11static bool check_coud_URF(Cube cube);
12static bool check_corners_HTM(Cube cube);
13static bool check_corners_URF(Cube cube);
14static bool check_cornershtr(Cube cube);
15static bool check_eoany(Cube cube);
8static bool check_eofb(Cube cube); 16static bool check_eofb(Cube cube);
17static bool check_drany(Cube cube);
9static bool check_drud(Cube cube); 18static bool check_drud(Cube cube);
10static bool check_htr(Cube cube); 19static bool check_htr(Cube cube);
11 20
12static int estimate_eoany_HTM(EstimateData *ed); 21static int estimate_eoany_HTM(DfsArg *arg);
13static int estimate_eofb_HTM(EstimateData *ed); 22static int estimate_eofb_HTM(DfsArg *arg);
14static int estimate_coany_HTM(EstimateData *ed); 23static int estimate_coany_HTM(DfsArg *arg);
15static int estimate_coud_HTM(EstimateData *ed); 24static int estimate_coud_HTM(DfsArg *arg);
16static int estimate_coany_URF(EstimateData *ed); 25static int estimate_coany_URF(DfsArg *arg);
17static int estimate_coud_URF(EstimateData *ed); 26static int estimate_coud_URF(DfsArg *arg);
18static int estimate_corners_HTM(EstimateData *ed); 27static int estimate_corners_HTM(DfsArg *arg);
19static int estimate_cornershtr_HTM(EstimateData *ed); 28static int estimate_cornershtr_HTM(DfsArg *arg);
20static int estimate_corners_URF(EstimateData *ed); 29static int estimate_corners_URF(DfsArg *arg);
21static int estimate_cornershtr_URF(EstimateData *ed); 30static int estimate_cornershtr_URF(DfsArg *arg);
22static int estimate_drany_HTM(EstimateData *ed); 31static int estimate_drany_HTM(DfsArg *arg);
23static int estimate_drud_HTM(EstimateData *ed); 32static int estimate_drud_HTM(DfsArg *arg);
24static int estimate_drud_eofb(EstimateData *ed); 33static int estimate_drud_eofb(DfsArg *arg);
25static int estimate_dr_eofb(EstimateData *ed); 34static int estimate_dr_eofb(DfsArg *arg);
26static int estimate_drudfin_drud(EstimateData *ed); 35static int estimate_drudfin_drud(DfsArg *arg);
27static int estimate_htr_drud(EstimateData *ed); 36static int estimate_htr_drud(DfsArg *arg);
28static int estimate_htrfin_htr(EstimateData *ed); 37static int estimate_htrfin_htr(DfsArg *arg);
29static int estimate_optimal_HTM(EstimateData *ed); 38static int estimate_optimal_HTM(DfsArg *arg);
30 39
31static bool always_valid(Alg *alg); 40static bool always_valid(Alg *alg);
32static bool validate_singlecw_ending(Alg *alg); 41static bool validate_singlecw_ending(Alg *alg);
@@ -51,6 +60,8 @@ optimal_HTM = {
51 .shortname = "optimal", 60 .shortname = "optimal",
52 .name = "Optimal solve (in HTM)", 61 .name = "Optimal solve (in HTM)",
53 62
63 .final = true,
64 .is_done = is_solved,
54 .estimate = estimate_optimal_HTM, 65 .estimate = estimate_optimal_HTM,
55 .ready = check_centers, 66 .ready = check_centers,
56 .ready_msg = check_centers_msg, 67 .ready_msg = check_centers_msg,
@@ -69,6 +80,8 @@ eoany_HTM = {
69 .shortname = "eo", 80 .shortname = "eo",
70 .name = "EO on any axis", 81 .name = "EO on any axis",
71 82
83 .final = false,
84 .is_done = check_eoany,
72 .estimate = estimate_eoany_HTM, 85 .estimate = estimate_eoany_HTM,
73 .ready = check_centers, 86 .ready = check_centers,
74 .ready_msg = check_centers_msg, 87 .ready_msg = check_centers_msg,
@@ -86,6 +99,8 @@ eofb_HTM = {
86 .shortname = "eofb", 99 .shortname = "eofb",
87 .name = "EO on F/B", 100 .name = "EO on F/B",
88 101
102 .final = false,
103 .is_done = check_eofb,
89 .estimate = estimate_eofb_HTM, 104 .estimate = estimate_eofb_HTM,
90 .ready = check_centers, 105 .ready = check_centers,
91 .ready_msg = check_centers_msg, 106 .ready_msg = check_centers_msg,
@@ -103,6 +118,8 @@ eorl_HTM = {
103 .shortname = "eorl", 118 .shortname = "eorl",
104 .name = "EO on R/L", 119 .name = "EO on R/L",
105 120
121 .final = false,
122 .is_done = check_eofb,
106 .estimate = estimate_eofb_HTM, 123 .estimate = estimate_eofb_HTM,
107 .ready = check_centers, 124 .ready = check_centers,
108 .ready_msg = check_centers_msg, 125 .ready_msg = check_centers_msg,
@@ -120,6 +137,8 @@ eoud_HTM = {
120 .shortname = "eoud", 137 .shortname = "eoud",
121 .name = "EO on U/D", 138 .name = "EO on U/D",
122 139
140 .final = false,
141 .is_done = check_eofb,
123 .estimate = estimate_eofb_HTM, 142 .estimate = estimate_eofb_HTM,
124 .ready = check_centers, 143 .ready = check_centers,
125 .ready_msg = check_centers_msg, 144 .ready_msg = check_centers_msg,
@@ -138,6 +157,8 @@ coany_HTM = {
138 .shortname = "co", 157 .shortname = "co",
139 .name = "CO on any axis", 158 .name = "CO on any axis",
140 159
160 .final = false,
161 .is_done = check_coany_HTM,
141 .estimate = estimate_coany_HTM, 162 .estimate = estimate_coany_HTM,
142 .ready = NULL, 163 .ready = NULL,
143 .is_valid = validate_singlecw_ending, 164 .is_valid = validate_singlecw_ending,
@@ -154,6 +175,8 @@ coud_HTM = {
154 .shortname = "coud", 175 .shortname = "coud",
155 .name = "CO on U/D", 176 .name = "CO on U/D",
156 177
178 .final = false,
179 .is_done = check_coud_HTM,
157 .estimate = estimate_coud_HTM, 180 .estimate = estimate_coud_HTM,
158 .ready = NULL, 181 .ready = NULL,
159 .is_valid = validate_singlecw_ending, 182 .is_valid = validate_singlecw_ending,
@@ -170,6 +193,8 @@ corl_HTM = {
170 .shortname = "corl", 193 .shortname = "corl",
171 .name = "CO on R/L", 194 .name = "CO on R/L",
172 195
196 .final = false,
197 .is_done = check_coud_HTM,
173 .estimate = estimate_coud_HTM, 198 .estimate = estimate_coud_HTM,
174 .ready = NULL, 199 .ready = NULL,
175 .is_valid = validate_singlecw_ending, 200 .is_valid = validate_singlecw_ending,
@@ -186,6 +211,8 @@ cofb_HTM = {
186 .shortname = "cofb", 211 .shortname = "cofb",
187 .name = "CO on F/B", 212 .name = "CO on F/B",
188 213
214 .final = false,
215 .is_done = check_coud_HTM,
189 .estimate = estimate_coud_HTM, 216 .estimate = estimate_coud_HTM,
190 .ready = NULL, 217 .ready = NULL,
191 .is_valid = validate_singlecw_ending, 218 .is_valid = validate_singlecw_ending,
@@ -202,6 +229,8 @@ coany_URF = {
202 .shortname = "co-URF", 229 .shortname = "co-URF",
203 .name = "CO any axis (URF moveset)", 230 .name = "CO any axis (URF moveset)",
204 231
232 .final = false,
233 .is_done = check_coany_URF,
205 .estimate = estimate_coany_URF, 234 .estimate = estimate_coany_URF,
206 .ready = NULL, 235 .ready = NULL,
207 .is_valid = validate_singlecw_ending, 236 .is_valid = validate_singlecw_ending,
@@ -218,6 +247,8 @@ coud_URF = {
218 .shortname = "coud-URF", 247 .shortname = "coud-URF",
219 .name = "CO on U/D (URF moveset)", 248 .name = "CO on U/D (URF moveset)",
220 249
250 .final = false,
251 .is_done = check_coud_URF,
221 .estimate = estimate_coud_URF, 252 .estimate = estimate_coud_URF,
222 .ready = NULL, 253 .ready = NULL,
223 .is_valid = validate_singlecw_ending, 254 .is_valid = validate_singlecw_ending,
@@ -234,6 +265,8 @@ corl_URF = {
234 .shortname = "corl-URF", 265 .shortname = "corl-URF",
235 .name = "CO on R/L (URF moveset)", 266 .name = "CO on R/L (URF moveset)",
236 267
268 .final = false,
269 .is_done = check_coud_URF,
237 .estimate = estimate_coud_URF, 270 .estimate = estimate_coud_URF,
238 .ready = NULL, 271 .ready = NULL,
239 .is_valid = validate_singlecw_ending, 272 .is_valid = validate_singlecw_ending,
@@ -250,6 +283,8 @@ cofb_URF = {
250 .shortname = "cofb-URF", 283 .shortname = "cofb-URF",
251 .name = "CO on F/B (URF moveset)", 284 .name = "CO on F/B (URF moveset)",
252 285
286 .final = false,
287 .is_done = check_coud_URF,
253 .estimate = estimate_coud_URF, 288 .estimate = estimate_coud_URF,
254 .ready = NULL, 289 .ready = NULL,
255 .is_valid = validate_singlecw_ending, 290 .is_valid = validate_singlecw_ending,
@@ -267,6 +302,8 @@ cornershtr_HTM = {
267 .shortname = "chtr", 302 .shortname = "chtr",
268 .name = "Solve corners to HTR state", 303 .name = "Solve corners to HTR state",
269 304
305 .final = false,
306 .is_done = check_cornershtr,
270 .estimate = estimate_cornershtr_HTM, 307 .estimate = estimate_cornershtr_HTM,
271 .ready = NULL, 308 .ready = NULL,
272 .is_valid = validate_singlecw_ending, 309 .is_valid = validate_singlecw_ending,
@@ -283,6 +320,8 @@ cornershtr_URF = {
283 .shortname = "chtr-URF", 320 .shortname = "chtr-URF",
284 .name = "Solve corners to HTR state (URF moveset)", 321 .name = "Solve corners to HTR state (URF moveset)",
285 322
323 .final = false,
324 .is_done = check_cornershtr,
286 .estimate = estimate_cornershtr_URF, 325 .estimate = estimate_cornershtr_URF,
287 .ready = NULL, 326 .ready = NULL,
288 .is_valid = validate_singlecw_ending, 327 .is_valid = validate_singlecw_ending,
@@ -299,6 +338,8 @@ corners_HTM = {
299 .shortname = "corners", 338 .shortname = "corners",
300 .name = "Solve corners", 339 .name = "Solve corners",
301 340
341 .final = true,
342 .is_done = check_corners_HTM,
302 .estimate = estimate_corners_HTM, 343 .estimate = estimate_corners_HTM,
303 .ready = NULL, 344 .ready = NULL,
304 .is_valid = always_valid, 345 .is_valid = always_valid,
@@ -315,6 +356,8 @@ corners_URF = {
315 .shortname = "corners-URF", 356 .shortname = "corners-URF",
316 .name = "Solve corners (URF moveset)", 357 .name = "Solve corners (URF moveset)",
317 358
359 .final = true, /* TODO: check if this works with reorient */
360 .is_done = check_corners_URF,
318 .estimate = estimate_corners_URF, 361 .estimate = estimate_corners_URF,
319 .ready = NULL, 362 .ready = NULL,
320 .is_valid = always_valid, 363 .is_valid = always_valid,
@@ -332,6 +375,8 @@ drany_HTM = {
332 .shortname = "dr", 375 .shortname = "dr",
333 .name = "DR on any axis", 376 .name = "DR on any axis",
334 377
378 .final = false,
379 .is_done = check_drany,
335 .estimate = estimate_drany_HTM, 380 .estimate = estimate_drany_HTM,
336 .ready = check_centers, 381 .ready = check_centers,
337 .ready_msg = check_centers_msg, 382 .ready_msg = check_centers_msg,
@@ -349,6 +394,8 @@ drud_HTM = {
349 .shortname = "drud", 394 .shortname = "drud",
350 .name = "DR on U/D", 395 .name = "DR on U/D",
351 396
397 .final = false,
398 .is_done = check_drud,
352 .estimate = estimate_drud_HTM, 399 .estimate = estimate_drud_HTM,
353 .ready = check_centers, 400 .ready = check_centers,
354 .ready_msg = check_centers_msg, 401 .ready_msg = check_centers_msg,
@@ -366,6 +413,8 @@ drrl_HTM = {
366 .shortname = "drrl", 413 .shortname = "drrl",
367 .name = "DR on R/L", 414 .name = "DR on R/L",
368 415
416 .final = false,
417 .is_done = check_drud,
369 .estimate = estimate_drud_HTM, 418 .estimate = estimate_drud_HTM,
370 .ready = check_centers, 419 .ready = check_centers,
371 .ready_msg = check_centers_msg, 420 .ready_msg = check_centers_msg,
@@ -383,6 +432,8 @@ drfb_HTM = {
383 .shortname = "drfb", 432 .shortname = "drfb",
384 .name = "DR on F/B", 433 .name = "DR on F/B",
385 434
435 .final = false,
436 .is_done = check_drud,
386 .estimate = estimate_drud_HTM, 437 .estimate = estimate_drud_HTM,
387 .ready = check_centers, 438 .ready = check_centers,
388 .ready_msg = check_centers_msg, 439 .ready_msg = check_centers_msg,
@@ -401,6 +452,8 @@ dr_eo = {
401 .shortname = "dr-eo", 452 .shortname = "dr-eo",
402 .name = "DR without breaking EO (automatically detected)", 453 .name = "DR without breaking EO (automatically detected)",
403 454
455 .final = false,
456 .is_done = check_drud,
404 .estimate = estimate_dr_eofb, 457 .estimate = estimate_dr_eofb,
405 .ready = check_eofb, 458 .ready = check_eofb,
406 .ready_msg = check_eo_msg, 459 .ready_msg = check_eo_msg,
@@ -418,6 +471,8 @@ dr_eofb = {
418 .shortname = "dr-eofb", 471 .shortname = "dr-eofb",
419 .name = "DR on U/D or R/L without breaking EO on F/B", 472 .name = "DR on U/D or R/L without breaking EO on F/B",
420 473
474 .final = false,
475 .is_done = check_drud,
421 .estimate = estimate_dr_eofb, 476 .estimate = estimate_dr_eofb,
422 .ready = check_eofb, 477 .ready = check_eofb,
423 .ready_msg = check_eo_msg, 478 .ready_msg = check_eo_msg,
@@ -435,6 +490,8 @@ dr_eorl = {
435 .shortname = "dr-eorl", 490 .shortname = "dr-eorl",
436 .name = "DR on U/D or F/B without breaking EO on R/L", 491 .name = "DR on U/D or F/B without breaking EO on R/L",
437 492
493 .final = false,
494 .is_done = check_drud,
438 .estimate = estimate_dr_eofb, 495 .estimate = estimate_dr_eofb,
439 .ready = check_eofb, 496 .ready = check_eofb,
440 .ready_msg = check_eo_msg, 497 .ready_msg = check_eo_msg,
@@ -452,6 +509,8 @@ dr_eoud = {
452 .shortname = "dr-eoud", 509 .shortname = "dr-eoud",
453 .name = "DR on R/L or F/B without breaking EO on U/D", 510 .name = "DR on R/L or F/B without breaking EO on U/D",
454 511
512 .final = false,
513 .is_done = check_drud,
455 .estimate = estimate_dr_eofb, 514 .estimate = estimate_dr_eofb,
456 .ready = check_eofb, 515 .ready = check_eofb,
457 .ready_msg = check_eo_msg, 516 .ready_msg = check_eo_msg,
@@ -469,6 +528,8 @@ drud_eofb = {
469 .shortname = "drud-eofb", 528 .shortname = "drud-eofb",
470 .name = "DR on U/D without breaking EO on F/B", 529 .name = "DR on U/D without breaking EO on F/B",
471 530
531 .final = false,
532 .is_done = check_drud,
472 .estimate = estimate_drud_eofb, 533 .estimate = estimate_drud_eofb,
473 .ready = check_eofb, 534 .ready = check_eofb,
474 .ready_msg = check_eo_msg, 535 .ready_msg = check_eo_msg,
@@ -486,6 +547,8 @@ drrl_eofb = {
486 .shortname = "drrl-eofb", 547 .shortname = "drrl-eofb",
487 .name = "DR on R/L without breaking EO on F/B", 548 .name = "DR on R/L without breaking EO on F/B",
488 549
550 .final = false,
551 .is_done = check_drud,
489 .estimate = estimate_drud_eofb, 552 .estimate = estimate_drud_eofb,
490 .ready = check_eofb, 553 .ready = check_eofb,
491 .ready_msg = check_eo_msg, 554 .ready_msg = check_eo_msg,
@@ -503,6 +566,8 @@ drud_eorl = {
503 .shortname = "drud-eorl", 566 .shortname = "drud-eorl",
504 .name = "DR on U/D without breaking EO on R/L", 567 .name = "DR on U/D without breaking EO on R/L",
505 568
569 .final = false,
570 .is_done = check_drud,
506 .estimate = estimate_drud_eofb, 571 .estimate = estimate_drud_eofb,
507 .ready = check_eofb, 572 .ready = check_eofb,
508 .ready_msg = check_eo_msg, 573 .ready_msg = check_eo_msg,
@@ -520,6 +585,8 @@ drfb_eorl = {
520 .shortname = "drfb-eorl", 585 .shortname = "drfb-eorl",
521 .name = "DR on F/B without breaking EO on R/L", 586 .name = "DR on F/B without breaking EO on R/L",
522 587
588 .final = false,
589 .is_done = check_drud,
523 .estimate = estimate_drud_eofb, 590 .estimate = estimate_drud_eofb,
524 .ready = check_eofb, 591 .ready = check_eofb,
525 .ready_msg = check_eo_msg, 592 .ready_msg = check_eo_msg,
@@ -537,6 +604,8 @@ drfb_eoud = {
537 .shortname = "drfb-eoud", 604 .shortname = "drfb-eoud",
538 .name = "DR on F/B without breaking EO on U/D", 605 .name = "DR on F/B without breaking EO on U/D",
539 606
607 .final = false,
608 .is_done = check_drud,
540 .estimate = estimate_drud_eofb, 609 .estimate = estimate_drud_eofb,
541 .ready = check_eofb, 610 .ready = check_eofb,
542 .ready_msg = check_eo_msg, 611 .ready_msg = check_eo_msg,
@@ -554,6 +623,8 @@ drrl_eoud = {
554 .shortname = "drrl-eoud", 623 .shortname = "drrl-eoud",
555 .name = "DR on R/L without breaking EO on U/D", 624 .name = "DR on R/L without breaking EO on U/D",
556 625
626 .final = false,
627 .is_done = check_drud,
557 .estimate = estimate_drud_eofb, 628 .estimate = estimate_drud_eofb,
558 .ready = check_eofb, 629 .ready = check_eofb,
559 .ready_msg = check_eo_msg, 630 .ready_msg = check_eo_msg,
@@ -572,6 +643,8 @@ dranyfin_DR = {
572 .shortname = "drfin", 643 .shortname = "drfin",
573 .name = "DR finish on any axis without breaking DR", 644 .name = "DR finish on any axis without breaking DR",
574 645
646 .final = true,
647 .is_done = is_solved,
575 .estimate = estimate_drudfin_drud, 648 .estimate = estimate_drudfin_drud,
576 .ready = check_drud, 649 .ready = check_drud,
577 .ready_msg = check_drany_msg, 650 .ready_msg = check_drany_msg,
@@ -589,6 +662,8 @@ drudfin_drud = {
589 .shortname = "drudfin", 662 .shortname = "drudfin",
590 .name = "DR finish on U/D without breaking DR", 663 .name = "DR finish on U/D without breaking DR",
591 664
665 .final = true,
666 .is_done = is_solved,
592 .estimate = estimate_drudfin_drud, 667 .estimate = estimate_drudfin_drud,
593 .ready = check_drud, 668 .ready = check_drud,
594 .ready_msg = check_dr_msg, 669 .ready_msg = check_dr_msg,
@@ -606,6 +681,8 @@ drrlfin_drrl = {
606 .shortname = "drrlfin", 681 .shortname = "drrlfin",
607 .name = "DR finish on R/L without breaking DR", 682 .name = "DR finish on R/L without breaking DR",
608 683
684 .final = true,
685 .is_done = is_solved,
609 .estimate = estimate_drudfin_drud, 686 .estimate = estimate_drudfin_drud,
610 .ready = check_drud, 687 .ready = check_drud,
611 .ready_msg = check_dr_msg, 688 .ready_msg = check_dr_msg,
@@ -623,6 +700,8 @@ drfbfin_drfb = {
623 .shortname = "drfbfin", 700 .shortname = "drfbfin",
624 .name = "DR finish on F/B without breaking DR", 701 .name = "DR finish on F/B without breaking DR",
625 702
703 .final = true,
704 .is_done = is_solved,
626 .estimate = estimate_drudfin_drud, 705 .estimate = estimate_drudfin_drud,
627 .ready = check_drud, 706 .ready = check_drud,
628 .ready_msg = check_dr_msg, 707 .ready_msg = check_dr_msg,
@@ -641,6 +720,8 @@ htr_any = {
641 .shortname = "htr", 720 .shortname = "htr",
642 .name = "HTR from DR", 721 .name = "HTR from DR",
643 722
723 .final = false,
724 .is_done = check_htr,
644 .estimate = estimate_htr_drud, 725 .estimate = estimate_htr_drud,
645 .ready = check_drud, 726 .ready = check_drud,
646 .ready_msg = check_drany_msg, 727 .ready_msg = check_drany_msg,
@@ -658,6 +739,8 @@ htr_drud = {
658 .shortname = "htr-drud", 739 .shortname = "htr-drud",
659 .name = "HTR from DR on U/D", 740 .name = "HTR from DR on U/D",
660 741
742 .final = false,
743 .is_done = check_htr,
661 .estimate = estimate_htr_drud, 744 .estimate = estimate_htr_drud,
662 .ready = check_drud, 745 .ready = check_drud,
663 .ready_msg = check_dr_msg, 746 .ready_msg = check_dr_msg,
@@ -675,6 +758,8 @@ htr_drrl = {
675 .shortname = "htr-drrl", 758 .shortname = "htr-drrl",
676 .name = "HTR from DR on R/L", 759 .name = "HTR from DR on R/L",
677 760
761 .final = false,
762 .is_done = check_htr,
678 .estimate = estimate_htr_drud, 763 .estimate = estimate_htr_drud,
679 .ready = check_drud, 764 .ready = check_drud,
680 .ready_msg = check_dr_msg, 765 .ready_msg = check_dr_msg,
@@ -692,6 +777,8 @@ htr_drfb = {
692 .shortname = "htr-drfb", 777 .shortname = "htr-drfb",
693 .name = "HTR from DR on F/B", 778 .name = "HTR from DR on F/B",
694 779
780 .final = false,
781 .is_done = check_htr,
695 .estimate = estimate_htr_drud, 782 .estimate = estimate_htr_drud,
696 .ready = check_drud, 783 .ready = check_drud,
697 .ready_msg = check_dr_msg, 784 .ready_msg = check_dr_msg,
@@ -710,6 +797,8 @@ htrfin_htr = {
710 .shortname = "htrfin", 797 .shortname = "htrfin",
711 .name = "HTR finish without breaking HTR", 798 .name = "HTR finish without breaking HTR",
712 799
800 .final = true,
801 .is_done = is_solved,
713 .estimate = estimate_htrfin_htr, 802 .estimate = estimate_htrfin_htr,
714 .ready = check_htr, 803 .ready = check_htr,
715 .ready_msg = check_htr_msg, 804 .ready_msg = check_htr_msg,
@@ -783,12 +872,89 @@ check_centers(Cube cube)
783} 872}
784 873
785static bool 874static bool
875check_coany_HTM(Cube cube)
876{
877 return cube.cofb == 0 || cube.corl == 0 || cube.coud == 0;
878}
879
880static bool
881check_coud_HTM(Cube cube)
882{
883 return cube.coud == 0;
884}
885
886static bool
887check_coany_URF(Cube cube)
888{
889 Cube c2, c3;
890
891 c2 = apply_move(y, apply_move(z, cube));
892 c3 = apply_move(y, apply_move(x, cube));
893
894 return check_coany_HTM(cube) ||
895 check_coany_HTM(c2) ||
896 check_coany_HTM(c3);
897}
898
899static bool
900check_coud_URF(Cube cube)
901{
902 Cube c2, c3;
903
904 c2 = apply_move(z, cube);
905 c3 = apply_move(x, cube);
906
907 return cube.coud == 0 || c2.coud == 0 || c3.coud == 0;
908}
909
910static bool
911check_corners_URF(Cube cube)
912{
913 Cube c;
914 Trans i;
915
916 for (i = 0; i < NROTATIONS; i++) {
917 c = apply_alg(rotation_alg(i), cube);
918 if (c.cp && c.coud)
919 return true;
920 }
921
922 return false;
923}
924
925static bool
926check_corners_HTM(Cube cube)
927{
928 return cube.cp == 0 && cube.coud == 0;
929}
930
931static bool
932check_cornershtr(Cube cube)
933{
934 return coord_cornershtr.index(cube) == 0;
935}
936
937static bool
938check_eoany(Cube cube)
939{
940 return cube.eofb == 0 || cube.eorl == 0 || cube.eoud == 0;
941}
942
943static bool
786check_eofb(Cube cube) 944check_eofb(Cube cube)
787{ 945{
788 return cube.eofb == 0; 946 return cube.eofb == 0;
789} 947}
790 948
791static bool 949static bool
950check_drany(Cube cube)
951{
952 return (cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0) ||
953 (cube.eorl == 0 && cube.eoud == 0 && cube.cofb == 0) ||
954 (cube.eoud == 0 && cube.eofb == 0 && cube.corl == 0);
955}
956
957static bool
792check_drud(Cube cube) 958check_drud(Cube cube)
793{ 959{
794 return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; 960 return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0;
@@ -801,265 +967,283 @@ check_htr(Cube cube)
801} 967}
802 968
803static int 969static int
804estimate_eoany_HTM(EstimateData *ed) 970estimate_eoany_HTM(DfsArg *arg)
805{ 971{
806 int r1, r2, r3; 972 int r1, r2, r3;
807 973
808 r1 = ptableval(&pd_eofb_HTM, ed->cube); 974 r1 = ptableval(&pd_eofb_HTM, arg->cube);
809 r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, ed->cube)); 975 r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, arg->cube));
810 r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, ed->cube)); 976 r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, arg->cube));
811 977
812 return MIN(r1, MIN(r2, r3)); 978 return MIN(r1, MIN(r2, r3));
813} 979}
814 980
815static int 981static int
816estimate_eofb_HTM(EstimateData *ed) 982estimate_eofb_HTM(DfsArg *arg)
817{ 983{
818 return ptableval(&pd_eofb_HTM, ed->cube); 984 return ptableval(&pd_eofb_HTM, arg->cube);
819} 985}
820 986
821static int 987static int
822estimate_coany_HTM(EstimateData *ed) 988estimate_coany_HTM(DfsArg *arg)
823{ 989{
824 int r1, r2, r3; 990 int r1, r2, r3;
825 991
826 r1 = ptableval(&pd_coud_HTM, ed->cube); 992 r1 = ptableval(&pd_coud_HTM, arg->cube);
827 r2 = ptableval(&pd_coud_HTM, apply_trans(rf, ed->cube)); 993 r2 = ptableval(&pd_coud_HTM, apply_trans(rf, arg->cube));
828 r3 = ptableval(&pd_coud_HTM, apply_trans(fd, ed->cube)); 994 r3 = ptableval(&pd_coud_HTM, apply_trans(fd, arg->cube));
829 995
830 return MIN(r1, MIN(r2, r3)); 996 return MIN(r1, MIN(r2, r3));
831} 997}
832 998
833static int 999static int
834estimate_coud_HTM(EstimateData *ed) 1000estimate_coud_HTM(DfsArg *arg)
835{ 1001{
836 return ptableval(&pd_coud_HTM, ed->cube); 1002 return ptableval(&pd_coud_HTM, arg->cube);
837} 1003}
838 1004
839static int 1005static int
840estimate_coany_URF(EstimateData *ed) 1006estimate_coany_URF(DfsArg *arg)
841{ 1007{
842 int r1, r2, r3; 1008 int r1, r2, r3;
843 EstimateData *ed2, *ed3; 1009 Cube c;
844 1010
845 ed2 = malloc(sizeof(EstimateData)); 1011 c = arg->cube;
846 ed3 = malloc(sizeof(EstimateData));
847 1012
848 ed2->cube = apply_trans(rf, ed->cube); 1013 r1 = estimate_coud_URF(arg);
849 ed2->target = ed->target; 1014 arg->cube = apply_trans(rf, c);
1015 r2 = estimate_coud_URF(arg);
1016 arg->cube = apply_trans(fd, c);
1017 r3 = estimate_coud_URF(arg);
850 1018
851 ed3->cube = apply_trans(fd, ed->cube); 1019 arg->cube = c;
852 ed3->target = ed->target;
853
854 r1 = estimate_coud_URF(ed);
855 r2 = estimate_coud_URF(ed2);
856 r3 = estimate_coud_URF(ed3);
857
858 free(ed2);
859 free(ed3);
860 1020
861 return MIN(r1, MIN(r2, r3)); 1021 return MIN(r1, MIN(r2, r3));
862} 1022}
863 1023
864static int 1024static int
865estimate_coud_URF(EstimateData *ed) 1025estimate_coud_URF(DfsArg *arg)
866{ 1026{
867 /* TODO: I can improve this by checking first the orientation of 1027 /* TODO: I can improve this by checking first the orientation of
868 * the corner in DBL and use that as a reference */ 1028 * the corner in DBL and use that as a reference */
869 1029
870 EstimateData *ed2, *ed3; 1030 Cube c;
871
872 ed2 = malloc(sizeof(EstimateData));
873 ed2->cube = apply_move(z, ed->cube);
874 ed2->target = ed->target;
875 1031
876 ed3 = malloc(sizeof(EstimateData)); 1032 c = arg->cube;
877 ed3->cube = apply_move(x, ed->cube);
878 ed3->target = ed->target;
879 1033
880 int ud = estimate_coud_HTM(ed); 1034 int ud = estimate_coud_HTM(arg);
881 int rl = estimate_coud_HTM(ed2); 1035 arg->cube = apply_move(z, c);
882 int fb = estimate_coud_HTM(ed3); 1036 int rl = estimate_coud_HTM(arg);
1037 arg->cube = apply_move(x, c);
1038 int fb = estimate_coud_HTM(arg);
883 1039
884 free(ed2); 1040 arg->cube = c;
885 free(ed3);
886 1041
887 return MIN(ud, MIN(rl, fb)); 1042 return MIN(ud, MIN(rl, fb));
888} 1043}
889 1044
890static int 1045static int
891estimate_corners_HTM(EstimateData *ed) 1046estimate_corners_HTM(DfsArg *arg)
892{ 1047{
893 return ptableval(&pd_corners_HTM, ed->cube); 1048 return ptableval(&pd_corners_HTM, arg->cube);
894} 1049}
895 1050
896static int 1051static int
897estimate_cornershtr_HTM(EstimateData *ed) 1052estimate_cornershtr_HTM(DfsArg *arg)
898{ 1053{
899 return ptableval(&pd_cornershtr_HTM, ed->cube); 1054 return ptableval(&pd_cornershtr_HTM, arg->cube);
900} 1055}
901 1056
902static int 1057static int
903estimate_cornershtr_URF(EstimateData *ed) 1058estimate_cornershtr_URF(DfsArg *arg)
904{ 1059{
905 /* TODO: I can improve this by checking first the corner in DBL 1060 /* TODO: I can improve this by checking first the corner in DBL
906 * and use that as a reference */ 1061 * and use that as a reference */
907 1062
908 int c, ret = 15; 1063 int ret;
1064 Cube c;
909 Trans i; 1065 Trans i;
910 1066
1067 c = arg->cube;
1068 ret = 15;
1069
911 for (i = 0; i < NROTATIONS; i++) { 1070 for (i = 0; i < NROTATIONS; i++) {
912 ed->cube = apply_alg(rotation_alg(i), ed->cube); 1071 arg->cube = apply_alg(rotation_alg(i), c);
913 c = estimate_cornershtr_HTM(ed); 1072 ret = MIN(ret, estimate_cornershtr_HTM(arg));
914 ret = MIN(ret, c);
915 } 1073 }
916 1074
1075 arg->cube = c;
1076
917 return ret; 1077 return ret;
918} 1078}
919 1079
920static int 1080static int
921estimate_corners_URF(EstimateData *ed) 1081estimate_corners_URF(DfsArg *arg)
922{ 1082{
923 /* TODO: I can improve this by checking first the corner in DBL 1083 /* TODO: I can improve this by checking first the corner in DBL
924 * and use that as a reference */ 1084 * and use that as a reference */
925 1085
926 int c, ret = 15; 1086 int ret;
1087 Cube c;
927 Trans i; 1088 Trans i;
928 1089
1090 c = arg->cube;
1091 ret = 15;
1092
929 for (i = 0; i < NROTATIONS; i++) { 1093 for (i = 0; i < NROTATIONS; i++) {
930 ed->cube = apply_alg(rotation_alg(i), ed->cube); 1094 arg->cube = apply_alg(rotation_alg(i), c);
931 c = estimate_corners_HTM(ed); 1095 ret = MIN(ret, estimate_corners_HTM(arg));
932 ret = MIN(ret, c);
933 } 1096 }
934 1097
1098 arg->cube = c;
1099
935 return ret; 1100 return ret;
936} 1101}
937 1102
938static int 1103static int
939estimate_drany_HTM(EstimateData *ed) 1104estimate_drany_HTM(DfsArg *arg)
940{ 1105{
941 int r1, r2, r3; 1106 int r1, r2, r3;
942 1107
943 r1 = ptableval(&pd_drud_sym16_HTM, ed->cube); 1108 r1 = ptableval(&pd_drud_sym16_HTM, arg->cube);
944 r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, ed->cube)); 1109 r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, arg->cube));
945 r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, ed->cube)); 1110 r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, arg->cube));
946 1111
947 return MIN(r1, MIN(r2, r3)); 1112 return MIN(r1, MIN(r2, r3));
948} 1113}
949 1114
950static int 1115static int
951estimate_drud_HTM(EstimateData *ed) 1116estimate_drud_HTM(DfsArg *arg)
952{ 1117{
953 return ptableval(&pd_drud_sym16_HTM, ed->cube); 1118 return ptableval(&pd_drud_sym16_HTM, arg->cube);
954} 1119}
955 1120
956static int 1121static int
957estimate_drud_eofb(EstimateData *ed) 1122estimate_drud_eofb(DfsArg *arg)
958{ 1123{
959 return ptableval(&pd_drud_eofb, ed->cube); 1124 return ptableval(&pd_drud_eofb, arg->cube);
960} 1125}
961 1126
962static int 1127static int
963estimate_dr_eofb(EstimateData *ed) 1128estimate_dr_eofb(DfsArg *arg)
964{ 1129{
965 int r1, r2; 1130 int r1, r2;
966 1131
967 r1 = ptableval(&pd_drud_eofb, ed->cube); 1132 r1 = ptableval(&pd_drud_eofb, arg->cube);
968 r2 = ptableval(&pd_drud_eofb, apply_trans(rf, ed->cube)); 1133 r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube));
969 1134
970 return MIN(r1, r2); 1135 return MIN(r1, r2);
971} 1136}
972 1137
973static int 1138static int
974estimate_drudfin_drud(EstimateData *ed) 1139estimate_drudfin_drud(DfsArg *arg)
975{ 1140{
976 int val = ptableval(&pd_drudfin_noE_sym16_drud, ed->cube); 1141 int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube);
977 1142
978 if (val != 0) 1143 if (val != 0)
979 return val; 1144 return val;
980 1145
981 return ed->cube.epose % 24 == 0 ? 0 : 1; 1146 return arg->cube.epose % 24 == 0 ? 0 : 1;
982} 1147}
983 1148
984static int 1149static int
985estimate_htr_drud(EstimateData *ed) 1150estimate_htr_drud(DfsArg *arg)
986{ 1151{
987 return ptableval(&pd_htr_drud, ed->cube); 1152 return ptableval(&pd_htr_drud, arg->cube);
988} 1153}
989 1154
990static int 1155static int
991estimate_htrfin_htr(EstimateData *ed) 1156estimate_htrfin_htr(DfsArg *arg)
992{ 1157{
993 return ptableval(&pd_htrfin_htr, ed->cube); 1158 return ptableval(&pd_htrfin_htr, arg->cube);
994} 1159}
995 1160
996static int 1161static int
997estimate_optimal_HTM(EstimateData *ed) 1162estimate_optimal_HTM(DfsArg *arg)
998{ 1163{
999 int ret = -1; 1164 int target, ret;
1000 Move lbase; 1165 Move lbase;
1001 Cube cubeaux, inv; 1166 Cube aux;
1002 1167
1003 ed->li->corners = ptableval(&pd_corners_HTM, ed->cube); 1168 target = arg->d - arg->current_alg->len;
1004 UPDATECHECKSTOP(ret, ed->li->corners, ed->target); 1169 ret = -1;
1170 arg->inverse = (Cube){0};
1171 arg->badmovesinv = 0;
1172 arg->badmoves = 0;
1005 1173
1006 ed->li->normal_ud = ptableval(&pd_khuge_HTM, ed->cube); 1174 arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube);
1007 UPDATECHECKSTOP(ret, ed->li->normal_ud, ed->target); 1175 UPDATECHECKSTOP(ret, arg->ed->corners, target);
1008 1176
1009 cubeaux = apply_trans(fd, ed->cube); 1177 arg->ed->normal_ud = ptableval(&pd_khuge_HTM, arg->cube);
1010 ed->li->normal_fb = ptableval(&pd_khuge_HTM, cubeaux); 1178 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target);
1011 UPDATECHECKSTOP(ret, ed->li->normal_fb, ed->target); 1179 if (arg->ed->normal_ud == target) {
1180 arg->badmovesinv |= (1<<U) | (1<<U2) | (1<<U3) |
1181 (1<<D) | (1<<D2) | (1<<D3);
1182 }
1012 1183
1013 cubeaux = apply_trans(rf, ed->cube); 1184 aux = apply_trans(fd, arg->cube);
1014 ed->li->normal_rl = ptableval(&pd_khuge_HTM, cubeaux); 1185 arg->ed->normal_fb = ptableval(&pd_khuge_HTM, aux);
1015 UPDATECHECKSTOP(ret, ed->li->normal_rl, ed->target); 1186 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target);
1187 if (arg->ed->normal_fb == target) {
1188 arg->badmovesinv |= (1<<F) | (1<<F2) | (1<<F3) |
1189 (1<<B) | (1<<B2) | (1<<B3);
1190 }
1191
1192 aux = apply_trans(rf, arg->cube);
1193 arg->ed->normal_rl = ptableval(&pd_khuge_HTM, aux);
1194 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target);
1195 if (arg->ed->normal_rl == target) {
1196 arg->badmovesinv |= (1<<R) | (1<<R2) | (1<<R3) |
1197 (1<<L) | (1<<L2) | (1<<L3);
1198 }
1016 1199
1017 if (ret == 0) 1200 if (ret == 0)
1018 return ret; 1201 return ret;
1019 1202
1020 if (ed->li->normal_ud == ed->li->normal_fb && 1203 if (arg->ed->normal_ud == arg->ed->normal_fb &&
1021 ed->li->normal_fb == ed->li->normal_rl) 1204 arg->ed->normal_fb == arg->ed->normal_rl)
1022 UPDATECHECKSTOP(ret, ed->li->normal_ud + 1, ed->target); 1205 UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target);
1023 1206
1024 /* TODO: avoid computation of inverse if unnecessary */ 1207 /* TODO: avoid computation of inverse if unnecessary */
1025 lbase = base_move(ed->lastmove); 1208 lbase = base_move(arg->last1);
1026 inv = inverse_cube(ed->cube); 1209 arg->inverse = inverse_cube(arg->cube);
1027 1210
1028 if ((lbase != U && lbase != D) || 1211 if ((lbase != U && lbase != D) || (arg->ed->inverse_ud == -1)) {
1029 (ed->li->inverse_ud == -1)) { 1212 arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, arg->inverse);
1030 ed->li->inverse_ud = ptableval(&pd_khuge_HTM, inv);
1031 } 1213 }
1032 UPDATECHECKSTOP(ret, ed->li->inverse_ud, ed->target); 1214 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target);
1033 1215
1034 if ((lbase != F && lbase != B) || 1216 if ((lbase != F && lbase != B) || (arg->ed->inverse_fb == -1)) {
1035 (ed->li->inverse_fb == -1)) { 1217 aux = apply_trans(fd, arg->inverse);
1036 cubeaux = apply_trans(fd, inv); 1218 arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux);
1037 ed->li->inverse_fb = ptableval(&pd_khuge_HTM, cubeaux);
1038 } 1219 }
1039 UPDATECHECKSTOP(ret, ed->li->inverse_fb, ed->target); 1220 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target);
1040 1221
1041 if ((lbase != R && lbase != L) || 1222 if ((lbase != R && lbase != L) || (arg->ed->inverse_rl == -1)) {
1042 (ed->li->inverse_rl == -1)) { 1223 aux = apply_trans(rf, arg->inverse);
1043 cubeaux = apply_trans(rf, inv); 1224 arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux);
1044 ed->li->inverse_rl = ptableval(&pd_khuge_HTM, cubeaux);
1045 } 1225 }
1046 UPDATECHECKSTOP(ret, ed->li->inverse_rl, ed->target); 1226 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target);
1047 1227
1048 if (ed->li->inverse_ud == ed->li->inverse_fb && 1228 if (arg->ed->inverse_ud == arg->ed->inverse_fb &&
1049 ed->li->inverse_fb == ed->li->inverse_rl) 1229 arg->ed->inverse_fb == arg->ed->inverse_rl) {
1050 UPDATECHECKSTOP(ret, ed->li->inverse_ud + 1, ed->target); 1230 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target);
1231 }
1051 1232
1052 if (ed->li->inverse_ud == ed->target) 1233 if (arg->ed->inverse_ud == target) {
1053 ed->movebitmask |= (1<<U) | (1<<U2) | (1<<U3) | 1234 arg->badmoves |= (1<<U) | (1<<U2) | (1<<U3) |
1054 (1<<D) | (1<<D2) | (1<<D3); 1235 (1<<D) | (1<<D2) | (1<<D3);
1055 if (ed->li->inverse_fb == ed->target) 1236 }
1056 ed->movebitmask |= (1<<F) | (1<<F2) | (1<<F3) | 1237 if (arg->ed->inverse_fb == target) {
1057 (1<<B) | (1<<B2) | (1<<B3); 1238 arg->badmoves |= (1<<F) | (1<<F2) | (1<<F3) |
1058 if (ed->li->inverse_rl == ed->target) 1239 (1<<B) | (1<<B2) | (1<<B3);
1059 ed->movebitmask |= (1<<R) | (1<<R2) | (1<<R3) | 1240 }
1060 (1<<L) | (1<<L2) | (1<<L3); 1241 if (arg->ed->inverse_rl == target) {
1242 arg->badmoves |= (1<<R) | (1<<R2) | (1<<R3) |
1243 (1<<L) | (1<<L2) | (1<<L3);
1244 }
1061 1245
1062 return ret; 1246 return arg->ed->oldret = ret;
1063} 1247}
1064 1248
1065static bool 1249static bool
@@ -1120,15 +1304,36 @@ detect_pretrans_drud(Cube cube)
1120/* Public functions **********************************************************/ 1304/* Public functions **********************************************************/
1121 1305
1122void 1306void
1123free_localinfo(LocalInfo *li) 1307copy_estimatedata(EstimateData *src, EstimateData *dst)
1124{ 1308{
1125 free(li); 1309 dst->corners = src->corners;
1310 dst->normal_ud = src->normal_ud;
1311 dst->normal_fb = src->normal_fb;
1312 dst->normal_rl = src->normal_rl;
1313 dst->inverse_ud = src->inverse_ud;
1314 dst->inverse_fb = src->inverse_fb;
1315 dst->inverse_rl = src->inverse_rl;
1316 dst->oldret = src->oldret;
1126} 1317}
1127 1318
1128LocalInfo * 1319void
1129new_localinfo() 1320free_estimatedata(EstimateData *ed)
1130{ 1321{
1131 LocalInfo *ret = malloc(sizeof(LocalInfo)); 1322 free(ed);
1323}
1324
1325void
1326invert_estimatedata(EstimateData *ed)
1327{
1328 swap(&(ed->normal_ud), &(ed->inverse_ud));
1329 swap(&(ed->normal_fb), &(ed->inverse_fb));
1330 swap(&(ed->normal_rl), &(ed->inverse_rl));
1331}
1332
1333EstimateData *
1334new_estimatedata()
1335{
1336 EstimateData *ret = malloc(sizeof(EstimateData));
1132 1337
1133 ret->corners = -1; 1338 ret->corners = -1;
1134 ret->normal_ud = -1; 1339 ret->normal_ud = -1;
@@ -1137,16 +1342,22 @@ new_localinfo()
1137 ret->inverse_ud = -1; 1342 ret->inverse_ud = -1;
1138 ret->inverse_fb = -1; 1343 ret->inverse_fb = -1;
1139 ret->inverse_rl = -1; 1344 ret->inverse_rl = -1;
1140 ret->prev_ret = -1; 1345 ret->oldret = -1;
1141 1346
1142 return ret; 1347 return ret;
1143} 1348}
1144 1349
1145void 1350void
1146prepare_step(Step *step, int nthreads) 1351prepare_step(Step *step, SolveOptions *opts)
1147{ 1352{
1148 int i; 1353 int i;
1149 1354
1355 if (step->final && opts->can_niss) {
1356 opts->can_niss = false;
1357 fprintf(stderr, "Step if final, niss not used"
1358 "(-n ignored)\n");
1359 }
1360
1150 for (i = 0; i < step->ntables; i++) 1361 for (i = 0; i < step->ntables; i++)
1151 genptable(step->tables[i], nthreads); 1362 genptable(step->tables[i], opts->nthreads);
1152} 1363}
diff --git a/src/steps.h b/src/steps.h
index e145c64..a55a101 100644
--- a/src/steps.h
+++ b/src/steps.h
@@ -7,8 +7,10 @@
7 7
8extern Step * steps[NSTEPS]; 8extern Step * steps[NSTEPS];
9 9
10void free_localinfo(LocalInfo *li); 10void copy_estimatedata(EstimateData *s, EstimateData *d);
11LocalInfo * new_localinfo(); 11void free_estimatedata(EstimateData *ed);
12void prepare_step(Step *step, int nthreads); 12void invert_estimatedata(EstimateData *ed);
13EstimateData * new_estimatedata();
14void prepare_step(Step *step, SolveOptions *opts);
13 15
14#endif 16#endif
diff --git a/src/utils.c b/src/utils.c
index 1c829c4..e0d3268 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -272,7 +272,17 @@ swap(int *a, int *b)
272 int aux; 272 int aux;
273 273
274 aux = *a; 274 aux = *a;
275 *a = *b; 275 *a = *b;
276 *b = aux; 276 *b = aux;
277}
278
279void
280swapu64(uint64_t *a, uint64_t *b)
281{
282 uint64_t aux;
283
284 aux = *a;
285 *a = *b;
286 *b = aux;
277} 287}
278 288
diff --git a/src/utils.h b/src/utils.h
index 80c33ae..9ba228d 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -2,6 +2,7 @@
2#define UTILS_H 2#define UTILS_H
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include <stdint.h>
5#include <stdlib.h> 6#include <stdlib.h>
6#include <string.h> 7#include <string.h>
7 8
@@ -37,5 +38,6 @@ int powint(int a, int b);
37int subset_to_index(int *a, int n, int k); 38int subset_to_index(int *a, int n, int k);
38void sum_arrays_mod(int *src, int *dst, int n, int m); 39void sum_arrays_mod(int *src, int *dst, int n, int m);
39void swap(int *a, int *b); 40void swap(int *a, int *b);
41void swapu64(uint64_t *a, uint64_t *b);
40 42
41#endif 43#endif

Generated with cgit - Back to sebastiano.tronto.net