aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/h48
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2026-01-12 18:09:43 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2026-01-12 18:09:43 +0100
commit9a013b7c68f94e6be0fe8748c9012a441fe0273f (patch)
treed6bb6de992eace566d033d0824c03da89cf7b9cb /src/solvers/h48
parent83f6533c384a617181e818d1941b08e40aa40b7d (diff)
downloadnissy-core-9a013b7c68f94e6be0fe8748c9012a441fe0273f.tar.gz
nissy-core-9a013b7c68f94e6be0fe8748c9012a441fe0273f.zip
Improve performance of H48 solver with prefetching
With this commit we re-structure how the node expansion in the H48 solution search works to allow prefetching of pruning values, showing performance improvements in the range of 30-45% on x86, depending on table size and solution length. A small bug fix related to appending solutions is included in this commit.
Diffstat (limited to 'src/solvers/h48')
-rw-r--r--src/solvers/h48/solve.h375
1 files changed, 242 insertions, 133 deletions
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index 4aa3799..15ac6ea 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -1,11 +1,5 @@
1#define H48_STARTING_MOVES 4 1#define H48_STARTING_MOVES 4
2 2#define H48_STARTING_CUBES 43254
3#if H48_STARTING_MOVES == 3
4#define H48_STARTING_CUBES 3240 /* Number of 3-move sequences */
5#elif H48_STARTING_MOVES == 4
6#define H48_STARTING_CUBES 43254 /* Number of 4-move sequences */
7#endif
8
9#define H48_SORT_TASKS_MIN_DEPTH 16 3#define H48_SORT_TASKS_MIN_DEPTH 16
10#define H48_LOG_PROGRESS_MIN_DEPTH 15 4#define H48_LOG_PROGRESS_MIN_DEPTH 15
11 5
@@ -14,6 +8,7 @@ typedef struct {
14 uint8_t moves[H48_STARTING_MOVES]; 8 uint8_t moves[H48_STARTING_MOVES];
15 int64_t rank; 9 int64_t rank;
16 uint64_t tmask[H48_STARTING_MOVES]; 10 uint64_t tmask[H48_STARTING_MOVES];
11 uint8_t pval;
17} solve_h48_task_t; 12} solve_h48_task_t;
18 13
19typedef struct { 14typedef struct {
@@ -25,15 +20,13 @@ typedef struct {
25 solution_settings_t *solution_settings; 20 solution_settings_t *solution_settings;
26 const uint64_t *tmask; 21 const uint64_t *tmask;
27 solution_list_t *solution_list; 22 solution_list_t *solution_list;
28 int8_t lb_normal; 23 uint8_t lb_normal;
29 int8_t lb_inverse; 24 uint8_t lb_inverse;
30 bool use_lb_normal;
31 bool use_lb_inverse;
32 uint8_t h; 25 uint8_t h;
33 uint8_t base; 26 uint8_t base;
34 const uint32_t *cocsepdata; 27 const uint32_t *cocsepdata;
35 const unsigned char *h48data; 28 const unsigned char *h48data;
36 const unsigned char *h48data_fallback_eoesep; 29 const unsigned char *eoesepdata;
37 uint64_t movemask_normal; 30 uint64_t movemask_normal;
38 uint64_t movemask_inverse; 31 uint64_t movemask_inverse;
39 uint64_t nodes_visited; 32 uint64_t nodes_visited;
@@ -58,11 +51,30 @@ typedef struct {
58 uint64_t tmask[H48_STARTING_MOVES]; 51 uint64_t tmask[H48_STARTING_MOVES];
59} dfsarg_solve_h48_maketasks_t; 52} dfsarg_solve_h48_maketasks_t;
60 53
54typedef struct {
55 cube_t cube;
56 cube_t inverse;
57 uint64_t coord;
58 uint8_t m;
59 uint8_t pn;
60 uint8_t pi;
61 uint8_t stop;
62} h48_prune_t;
63
61STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, 64STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned,
62 unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, 65 unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long,
63 const unsigned char *, unsigned, char *, 66 const unsigned char *, unsigned, char *,
64 long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); 67 long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *);
65STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); 68STATIC_INLINE void h48_prune_pipeline(dfsarg_solve_h48_t [static 1],
69 h48_prune_t [static NMOVES], uint8_t, bool);
70STATIC_INLINE uint8_t h48_prune_lookup(
71 uint64_t, cube_t, dfsarg_solve_h48_t [static 1]);
72STATIC_INLINE uint8_t h48_prune_lookup_nocoord(
73 cube_t, dfsarg_solve_h48_t [static 1]);
74STATIC_INLINE void h48_prune_restore_normal(const h48_prune_t [static 1],
75 dfsarg_solve_h48_t [static 1], uint8_t);
76STATIC_INLINE void h48_prune_restore_inverse(const h48_prune_t [static 1],
77 dfsarg_solve_h48_t [static 1], uint8_t);
66STATIC int64_t solve_h48_maketasks( 78STATIC int64_t solve_h48_maketasks(
67 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], 79 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1],
68 solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]); 80 solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]);
@@ -104,151 +116,242 @@ STATIC long long solve_h48_dispatch(
104 poll_status, poll_status_data); 116 poll_status, poll_status_data);
105} 117}
106 118
107STATIC_INLINE bool 119STATIC_INLINE uint8_t
108solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) 120h48_prune_lookup(
121 uint64_t coord,
122 cube_t cube,
123 dfsarg_solve_h48_t arg[static 1]
124)
109{ 125{
110 uint32_t data, data_inv; 126 uint8_t p, pmin, pe;
111 int64_t coord;
112 int8_t target, nh, n;
113 uint8_t pval, pval_min, pval_eoesep;
114 127
115 arg->movemask_normal = arg->movemask_inverse = MM18_ALLMOVES; 128 arg->table_lookups++;
116 arg->nodes_visited++; 129 p = get_h48_pval_and_min(arg->h48data, coord, &pmin);
130 if (p == 0) {
131 arg->table_fallbacks++;
132 pe = get_eoesep_pval_cube(arg->eoesepdata, cube);
133 return MAX(pmin, pe);
134 } else {
135 return p + arg->base;
136 }
137}
117 138
118 n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; 139STATIC_INLINE uint8_t
119 target = arg->target_depth - n; 140h48_prune_lookup_nocoord(
141 cube_t cube,
142 dfsarg_solve_h48_t arg[static 1]
143)
144{
145 uint32_t cdata;
146 uint64_t coord;
120 147
121 /* We'll never get a bound higher than base + 3 */ 148 get_h48_cdata(cube, arg->cocsepdata, &cdata);
122 if (arg->base + 3 <= target) 149 coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), arg->h);
123 return false; 150 return h48_prune_lookup(coord, cube, arg);
151}
124 152
125 /* Preliminary probing using last computed bound, if possible */ 153STATIC_INLINE void
154h48_prune_pipeline(
155 dfsarg_solve_h48_t arg[static 1],
156 h48_prune_t prune[static NMOVES],
157 uint8_t target,
158 bool normal
159)
160{
161 uint64_t i;
162 uint32_t cdata;
163 uint8_t m, p;
126 164
127 if ((arg->use_lb_normal && arg->lb_normal > target) || 165 /* Stage 0: initialize the neighbors array */
128 (arg->use_lb_inverse && arg->lb_inverse > target)) 166 memset(prune, 0, NMOVES * sizeof(h48_prune_t));
129 return true; 167 if (normal) {
168 for (m = 0; m < NMOVES; m++) {
169 prune[m].pi = m % 3 == 1 ? arg->lb_inverse : 0;
170 if (!(arg->movemask_normal & MM_SINGLE(m)) ||
171 prune[m].pi > target) {
172 prune[m].stop = 1;
173 continue;
174 }
175 prune[m].cube = move(arg->cube, m);
176 prune[m].inverse = premove(arg->inverse, m);
177 prune[m].m = m;
178 arg->nodes_visited++;
179 }
180 } else {
181 for (m = 0; m < NMOVES; m++) {
182 prune[m].pi = m % 3 == 1 ? arg->lb_normal : 0;
183 if (!(arg->movemask_inverse & MM_SINGLE(m)) ||
184 prune[m].pi > target) {
185 prune[m].stop = 1;
186 continue;
187 }
188 prune[m].cube = move(arg->inverse, m);
189 prune[m].inverse = premove(arg->cube, m);
190 prune[m].m = m;
191 arg->nodes_visited++;
192 }
193 }
130 194
131 /* Preliminary corner probing */ 195 /* We'll never get a bound higher than base + 3 */
196 if (target > arg->base + 3)
197 return;
132 198
133 if (get_h48_cdata(arg->cube, arg->cocsepdata, &data) > target || 199 /* Stage 1: cdata and prefetch inverse */
134 get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv) > target) 200 for (m = 0; m < NMOVES; m++) {
135 return true; 201 if (prune[m].stop)
202 continue;
136 203
137 /* Inverse probing */ 204 p = get_h48_cdata(prune[m].inverse, arg->cocsepdata, &cdata);
205 if (p > target) {
206 prune[m].stop = 1;
207 continue;
208 }
209 if (prune[m].pi == 0) {
210 prune[m].coord = coord_h48_edges(prune[m].inverse,
211 COCLASS(cdata), TTREP(cdata), arg->h);
212 i = H48_INDEX(H48_LINE_EXT(prune[m].coord));
213 prefetch(arg->h48data, i);
214 }
215 }
138 216
139 if (!arg->use_lb_inverse) { 217 /* Stage 2: get pval from inverse, prefetch normal */
140 arg->table_lookups++; 218 for (m = 0; m < NMOVES; m++) {
141 arg->use_lb_inverse = true; 219 if (prune[m].stop)
142 coord = coord_h48_edges( 220 continue;
143 arg->inverse, COCLASS(data_inv), TTREP(data_inv), arg->h);
144 pval = get_h48_pval_and_min(arg->h48data, coord, &pval_min);
145 221
146 if (pval == 0) { 222 if (prune[m].pi == 0) {
147 arg->table_fallbacks++; 223 prune[m].pi = h48_prune_lookup(
224 prune[m].coord, prune[m].inverse, arg);
225 if (prune[m].pi > target) {
226 prune[m].stop = 1;
227 continue;
228 }
229 }
148 230
149 pval_eoesep = get_eoesep_pval_cube( 231 p = get_h48_cdata(prune[m].cube, arg->cocsepdata, &cdata);
150 arg->h48data_fallback_eoesep, arg->inverse); 232 if (p > target) {
151 pval = MAX(pval_min, pval_eoesep); 233 prune[m].stop = 1;
152 } else { 234 continue;
153 pval += arg->base;
154 } 235 }
236 prune[m].coord = coord_h48_edges(
237 prune[m].cube, COCLASS(cdata), TTREP(cdata), arg->h);
238 i = H48_INDEX(H48_LINE_EXT(prune[m].coord));
239 prefetch(arg->h48data, i);
240 }
155 241
156 arg->lb_inverse = pval; 242 /* Stage 3: get pval from normal */
243 for (m = 0; m < NMOVES; m++) {
244 if (prune[m].stop)
245 continue;
246
247 prune[m].pn = h48_prune_lookup(
248 prune[m].coord, prune[m].cube, arg);
249 prune[m].stop = prune[m].pn > target;
157 } 250 }
251}
158 252
159 if (arg->lb_inverse > target) 253STATIC_INLINE void
160 return true; 254h48_prune_restore_normal(
161 nh = arg->lb_inverse == target; 255 const h48_prune_t prune[static 1],
162 arg->movemask_normal = nh * MM18_NOHALFTURNS + (1-nh) * MM18_ALLMOVES; 256 dfsarg_solve_h48_t arg[static 1],
257 uint8_t target
258)
259{
260 uint8_t nm;
163 261
164 /* Normal probing */ 262 arg->cube = prune->cube;
263 arg->inverse = prune->inverse;
264 arg->lb_inverse = prune->pi;
265 arg->lb_normal = prune->pn;
165 266
166 if (!arg->use_lb_normal) { 267 nm = arg->solution_moves->nmoves;
167 arg->table_lookups++; 268 arg->solution_moves->moves[nm-1] = prune->m;
168 arg->use_lb_normal = true; 269 arg->movemask_normal = allowedmask[movebase(prune->m)];
169 coord = coord_h48_edges(
170 arg->cube, COCLASS(data), TTREP(data), arg->h);
171 pval = get_h48_pval_and_min(arg->h48data, coord, &pval_min);
172 270
173 if (pval == 0) { 271 if (arg->lb_inverse == target)
174 arg->table_fallbacks++; 272 arg->movemask_normal &= MM18_NOHALFTURNS;
273 if (arg->lb_normal == target)
274 arg->movemask_inverse &= MM18_NOHALFTURNS;
275}
175 276
176 pval_eoesep = get_eoesep_pval_cube( 277STATIC_INLINE void
177 arg->h48data_fallback_eoesep, arg->cube); 278h48_prune_restore_inverse(
178 pval = MAX(pval_min, pval_eoesep); 279 const h48_prune_t prune[static 1],
179 } else { 280 dfsarg_solve_h48_t arg[static 1],
180 pval += arg->base; 281 uint8_t target
181 } 282)
283{
284 uint8_t nm;
182 285
183 arg->lb_normal = pval; 286 arg->cube = prune->inverse;
184 } 287 arg->inverse = prune->cube;
288 arg->lb_inverse = prune->pn;
289 arg->lb_normal = prune->pi;
185 290
186 if (arg->lb_normal > target) 291 nm = arg->solution_moves->npremoves;
187 return true; 292 arg->solution_moves->premoves[nm-1] = prune->m;
188 nh = arg->lb_normal == target; 293 arg->movemask_inverse = allowedmask[movebase(prune->m)];
189 arg->movemask_inverse = nh * MM18_NOHALFTURNS + (1-nh) * MM18_ALLMOVES;
190 294
191 return false; 295 if (arg->lb_inverse == target)
296 arg->movemask_normal &= MM18_NOHALFTURNS;
297 if (arg->lb_normal == target)
298 arg->movemask_inverse &= MM18_NOHALFTURNS;
192} 299}
193 300
194STATIC int64_t 301STATIC int64_t
195solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) 302solve_h48_dfs(dfsarg_solve_h48_t arg[static 1])
196{ 303{
197 int64_t ret, n; 304 int64_t ret, n;
198 uint8_t m, nm, lbn, lbi, t; 305 uint8_t m, nm, nn, ni, target;
199 uint64_t mm_normal, mm_inverse; 306 uint64_t mm_normal, mm_inverse;
200 bool ulbi, ulbn; 307 cube_t cube, backup_cube, backup_inverse;
201 cube_t backup_cube, backup_inverse; 308 h48_prune_t prune[NMOVES];
202
203 nm = arg->solution_moves->nmoves + arg->solution_moves->npremoves;
204 if (equal(arg->cube, SOLVED_CUBE)) {
205 if (arg->target_depth != nm)
206 return 0;
207 wrapthread_mutex_lock(arg->solutions_mutex);
208 ret = appendsolution(arg->solution_moves, H48_STARTING_MOVES,
209 arg->tmask, arg->solution_settings, arg->solution_list);
210 wrapthread_mutex_unlock(arg->solutions_mutex);
211 return ret;
212 }
213 309
214 if (solve_h48_stop(arg)) 310 if (equal(arg->cube, SOLVED_CUBE) || /* Solved before target depth */
311 arg->solution_list->nsols >= arg->solution_settings->maxsolutions)
215 return 0; 312 return 0;
216 313
217 t = arg->solution_list->shortest_sol + arg->solution_settings->optimal; 314 nn = arg->solution_moves->nmoves;
218 if (nm + 1 > MIN(t, arg->target_depth) || 315 ni = arg->solution_moves->npremoves;
219 arg->solution_list->nsols >= arg->solution_settings->maxsolutions) 316 nm = nn + ni;
317 target = arg->target_depth - (nm + 1);
318 mm_normal = arg->movemask_normal;
319 mm_inverse = arg->movemask_inverse;
320 if (target == 0) { /* Last move */
321 arg->solution_moves->nmoves++;
322 for (m = 0; m < NMOVES; m++) {
323 if (!(mm_normal & mm_inverse & MM_SINGLE(m)))
324 continue;
325 cube = move(arg->cube, m);
326 arg->solution_moves->moves[nn] = m;
327 arg->nodes_visited++;
328 if (!equal(cube, SOLVED_CUBE))
329 continue;
330 wrapthread_mutex_lock(arg->solutions_mutex);
331 ret = appendsolution(arg->solution_moves,
332 H48_STARTING_MOVES, arg->tmask,
333 arg->solution_settings, arg->solution_list);
334 wrapthread_mutex_unlock(arg->solutions_mutex);
335 arg->solution_moves->nmoves--;
336 return ret;
337 }
338 arg->solution_moves->nmoves--;
220 return 0; 339 return 0;
340 }
221 341
222 backup_cube = arg->cube; 342 backup_cube = arg->cube;
223 backup_inverse = arg->inverse; 343 backup_inverse = arg->inverse;
224 lbn = arg->lb_normal;
225 lbi = arg->lb_inverse;
226 ulbn = arg->use_lb_normal;
227 ulbi = arg->use_lb_inverse;
228 344
229 ret = 0; 345 ret = 0;
230 mm_normal = arg->movemask_normal;
231 if (arg->solution_moves->nmoves > 0) {
232 m = arg->solution_moves->moves[arg->solution_moves->nmoves-1];
233 mm_normal &= allowedmask[movebase(m)];
234 }
235 mm_inverse = arg->movemask_inverse;
236 if (arg->solution_moves->npremoves > 0) {
237 m = arg->solution_moves->premoves[arg->solution_moves->npremoves-1];
238 mm_inverse &= allowedmask[movebase(m)];
239 }
240 if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) { 346 if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) {
347 h48_prune_pipeline(arg, prune, target, true);
241 arg->solution_moves->nmoves++; 348 arg->solution_moves->nmoves++;
242 for (m = 0; m < 18; m++) { 349 for (m = 0; m < NMOVES; m++) {
243 if (!(mm_normal & MM_SINGLE(m))) 350 if (prune[m].stop)
244 continue; 351 continue;
245 arg->solution_moves->moves[ 352 arg->movemask_normal = mm_normal;
246 arg->solution_moves->nmoves-1] = m; 353 arg->movemask_inverse = mm_inverse;
247 arg->cube = move(backup_cube, m); 354 h48_prune_restore_normal(&prune[m], arg, target);
248 arg->inverse = premove(backup_inverse, m);
249 arg->lb_inverse = lbi;
250 arg->use_lb_normal = false;
251 arg->use_lb_inverse = ulbi && m % 3 == 1;
252 n = solve_h48_dfs(arg); 355 n = solve_h48_dfs(arg);
253 if (n < 0) 356 if (n < 0)
254 return n; 357 return n;
@@ -256,17 +359,14 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1])
256 } 359 }
257 arg->solution_moves->nmoves--; 360 arg->solution_moves->nmoves--;
258 } else { 361 } else {
362 h48_prune_pipeline(arg, prune, target, false);
259 arg->solution_moves->npremoves++; 363 arg->solution_moves->npremoves++;
260 for (m = 0; m < 18; m++) { 364 for (m = 0; m < NMOVES; m++) {
261 if(!(mm_inverse & MM_SINGLE(m))) 365 if (prune[m].stop)
262 continue; 366 continue;
263 arg->solution_moves->premoves[ 367 arg->movemask_normal = mm_normal;
264 arg->solution_moves->npremoves-1] = m; 368 arg->movemask_inverse = mm_inverse;
265 arg->inverse = move(backup_inverse, m); 369 h48_prune_restore_inverse(&prune[m], arg, target);
266 arg->cube = premove(backup_cube, m);
267 arg->lb_normal = lbn;
268 arg->use_lb_inverse = false;
269 arg->use_lb_normal = ulbn && m % 3 == 1;
270 n = solve_h48_dfs(arg); 370 n = solve_h48_dfs(arg);
271 if (n < 0) 371 if (n < 0)
272 return n; 372 return n;
@@ -277,6 +377,8 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1])
277 377
278 arg->cube = backup_cube; 378 arg->cube = backup_cube;
279 arg->inverse = backup_inverse; 379 arg->inverse = backup_inverse;
380 arg->movemask_normal = mm_normal;
381 arg->movemask_inverse = mm_inverse;
280 382
281 return ret; 383 return ret;
282} 384}
@@ -286,7 +388,7 @@ solve_h48_runthread(void *arg)
286{ 388{
287 int i, j; 389 int i, j;
288 uint8_t lastmove; 390 uint8_t lastmove;
289 int64_t nprev; 391 int64_t d, f, nprev;
290 dfsarg_solve_h48_t *dfsarg; 392 dfsarg_solve_h48_t *dfsarg;
291 393
292 dfsarg = (dfsarg_solve_h48_t *)arg; 394 dfsarg = (dfsarg_solve_h48_t *)arg;
@@ -309,11 +411,15 @@ solve_h48_runthread(void *arg)
309 move(dfsarg->cube, dfsarg->tasks[i].moves[j]); 411 move(dfsarg->cube, dfsarg->tasks[i].moves[j]);
310 dfsarg->inverse = inverse(dfsarg->cube); 412 dfsarg->inverse = inverse(dfsarg->cube);
311 413
414 dfsarg->nodes_visited++;
415 if (dfsarg->tasks[i].pval + H48_STARTING_MOVES
416 > dfsarg->target_depth)
417 continue;
418
312 dfsarg->lb_normal = 0; 419 dfsarg->lb_normal = 0;
313 dfsarg->lb_inverse = 0; 420 dfsarg->lb_inverse = 0;
314 dfsarg->use_lb_normal = false; 421 dfsarg->movemask_normal = allowedmask[
315 dfsarg->use_lb_inverse = false; 422 movebase(dfsarg->tasks[i].moves[H48_STARTING_MOVES-1])];
316 dfsarg->movemask_normal = MM18_ALLMOVES;
317 dfsarg->movemask_inverse = MM18_ALLMOVES; 423 dfsarg->movemask_inverse = MM18_ALLMOVES;
318 dfsarg->tmask = dfsarg->tasks[i].tmask; 424 dfsarg->tmask = dfsarg->tasks[i].tmask;
319 425
@@ -331,8 +437,9 @@ solve_h48_runthread(void *arg)
331 inspired by Andrew Skalski's vcube. 437 inspired by Andrew Skalski's vcube.
332 */ 438 */
333 lastmove = dfsarg->tasks[i].moves[H48_STARTING_MOVES-1]; 439 lastmove = dfsarg->tasks[i].moves[H48_STARTING_MOVES-1];
334 dfsarg->tasks[i].rank = (dfsarg->nodes_visited - nprev) * 440 d = (int64_t)dfsarg->nodes_visited - nprev;
335 (movebase(lastmove) % 2 == 0 ? 47525 : 58206); 441 f = movebase(lastmove) % 2 == 0 ? 47525 : 58206;
442 dfsarg->tasks[i].rank = d * f;
336 nprev = dfsarg->nodes_visited; 443 nprev = dfsarg->nodes_visited;
337 } 444 }
338 445
@@ -374,6 +481,8 @@ solve_h48_maketasks(
374 481
375 if (mtarg->nmoves == H48_STARTING_MOVES) { 482 if (mtarg->nmoves == H48_STARTING_MOVES) {
376 tasks[*ntasks].cube = mtarg->cube; 483 tasks[*ntasks].cube = mtarg->cube;
484 tasks[*ntasks].pval =
485 h48_prune_lookup_nocoord(mtarg->cube, solve_arg);
377 memcpy(tasks[*ntasks].moves, mtarg->moves, 486 memcpy(tasks[*ntasks].moves, mtarg->moves,
378 H48_STARTING_MOVES * sizeof(uint8_t)); 487 H48_STARTING_MOVES * sizeof(uint8_t));
379 memcpy(tasks[*ntasks].tmask, mtarg->tmask, 488 memcpy(tasks[*ntasks].tmask, mtarg->tmask,
@@ -393,7 +502,7 @@ solve_h48_maketasks(
393 502
394 mtarg->nmoves++; 503 mtarg->nmoves++;
395 backup_cube = mtarg->cube; 504 backup_cube = mtarg->cube;
396 for (m = 0; m < 18; m++) { 505 for (m = 0; m < NMOVES; m++) {
397 if (!(mm & MM_SINGLE(m))) 506 if (!(mm & MM_SINGLE(m)))
398 continue; 507 continue;
399 508
@@ -514,7 +623,7 @@ solve_h48(
514 .base = info.base, 623 .base = info.base,
515 .cocsepdata = cocsepdata, 624 .cocsepdata = cocsepdata,
516 .h48data = h48data, 625 .h48data = h48data,
517 .h48data_fallback_eoesep = eoesep, 626 .eoesepdata = eoesep,
518 .solution_moves = &solution_moves[i], 627 .solution_moves = &solution_moves[i],
519 .solution_settings = &settings, 628 .solution_settings = &settings,
520 .solution_list = &sollist, 629 .solution_list = &sollist,

Generated with cgit - Back to sebastiano.tronto.net