aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/h48
diff options
context:
space:
mode:
Diffstat (limited to 'src/solvers/h48')
-rw-r--r--src/solvers/h48/solve.h237
1 files changed, 74 insertions, 163 deletions
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index f7565d5..dbd15bb 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -4,27 +4,20 @@
4typedef struct { 4typedef struct {
5 cube_t cube; 5 cube_t cube;
6 uint8_t moves[STARTING_MOVES]; 6 uint8_t moves[STARTING_MOVES];
7 uint64_t symmask0;
8} solve_h48_task_t; 7} solve_h48_task_t;
9 8
10typedef struct { 9typedef struct {
11 cube_t start_cube; 10 cube_t start_cube;
12 uint64_t symmask0;
13 cube_t cube; 11 cube_t cube;
14 cube_t inverse; 12 cube_t inverse;
15 int8_t depth; 13 int8_t target_depth;
16 int8_t nmoves; 14 solution_moves_t *solution_moves;
17 uint8_t moves[MAXLEN]; 15 solution_settings_t *solution_settings;
18 int8_t npremoves; 16 solution_list_t *solution_list;
19 uint8_t premoves[MAXLEN];
20 int8_t lb_normal; 17 int8_t lb_normal;
21 int8_t lb_inverse; 18 int8_t lb_inverse;
22 bool use_lb_normal; 19 bool use_lb_normal;
23 bool use_lb_inverse; 20 bool use_lb_inverse;
24 _Atomic int64_t *nsols;
25 int64_t maxsolutions;
26 int8_t *shortest_sol;
27 int8_t optimal;
28 uint8_t h; 21 uint8_t h;
29 uint8_t k; 22 uint8_t k;
30 uint8_t base; 23 uint8_t base;
@@ -32,9 +25,6 @@ typedef struct {
32 const uint8_t *h48data; 25 const uint8_t *h48data;
33 const uint8_t *h48data_fallback_h0k4; 26 const uint8_t *h48data_fallback_h0k4;
34 const void *h48data_fallback_eoesep; 27 const void *h48data_fallback_eoesep;
35 size_t solutions_size;
36 size_t *solutions_used;
37 char **solutions;
38 uint32_t movemask_normal; 28 uint32_t movemask_normal;
39 uint32_t movemask_inverse; 29 uint32_t movemask_inverse;
40 int64_t nodes_visited; 30 int64_t nodes_visited;
@@ -56,8 +46,6 @@ typedef struct {
56 int8_t *shortest_sol; 46 int8_t *shortest_sol;
57} dfsarg_solve_h48_maketasks_t; 47} dfsarg_solve_h48_maketasks_t;
58 48
59STATIC int64_t solve_h48_appendsolution(dfsarg_solve_h48_t *);
60STATIC int64_t solve_h48_appendallsym(dfsarg_solve_h48_t *);
61STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t *); 49STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t *);
62STATIC int64_t solve_h48_maketasks( 50STATIC int64_t solve_h48_maketasks(
63 dfsarg_solve_h48_t *, dfsarg_solve_h48_maketasks_t *, 51 dfsarg_solve_h48_t *, dfsarg_solve_h48_maketasks_t *,
@@ -65,107 +53,21 @@ STATIC int64_t solve_h48_maketasks(
65STATIC void *solve_h48_runthread(void *); 53STATIC void *solve_h48_runthread(void *);
66STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t *); 54STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t *);
67STATIC int64_t solve_h48(cube_t, int8_t, int8_t, uint64_t, int8_t, int8_t, 55STATIC int64_t solve_h48(cube_t, int8_t, int8_t, uint64_t, int8_t, int8_t,
68 uint64_t, const void *, size_t, char *, 56 uint64_t, const void *, size_t n, char [n],
69 long long [static NISSY_SIZE_SOLVE_STATS]); 57 long long [static NISSY_SIZE_SOLVE_STATS]);
70 58
71STATIC int64_t
72solve_h48_appendsolution(dfsarg_solve_h48_t *arg)
73{
74 if (*arg->nsols >= arg->maxsolutions ||
75 arg->nmoves + arg->npremoves > *arg->shortest_sol + arg->optimal)
76 return 0;
77
78 invertmoves(arg->npremoves, arg->premoves, arg->moves + arg->nmoves);
79
80 /* Sort parallel moves for consistency */
81 sortparallel(arg->nmoves + arg->npremoves, arg->moves);
82
83 /* Do not append the solution in case premoves cancel with normal */
84 if (arg->npremoves > 0 && !allowednextmove(arg->nmoves+1, arg->moves))
85 return 0;
86 if (arg->npremoves > 1 && !allowednextmove(arg->nmoves+2, arg->moves))
87 return 0;
88
89 return solve_h48_appendallsym(arg);
90}
91
92STATIC int64_t
93solve_h48_appendallsym(dfsarg_solve_h48_t *arg)
94{
95 bool eq;
96 uint8_t t, i, j, k, n;
97 int64_t ret, strl, l;
98 char *m;
99 uint8_t all[NTRANS][MAXLEN];
100
101 n = arg->nmoves + arg->npremoves;
102
103 for (t = 0, j = 0; t < NTRANS; t++) {
104 if (!(arg->symmask0 & (UINT64_C(1) << (uint64_t)t)))
105 continue;
106
107 for (i = 0; i < n; i++)
108 all[j][i] = transform_move(arg->moves[i], t);
109
110 /* Sort parallel moves for consistency */
111 sortparallel(n, all[j]);
112
113 /* Check for duplicate solutions */
114 for (k = 0; k < j; k++) {
115 eq = true;
116 for (i = 0; i < n; i++)
117 if (all[k][i] != all[j][i])
118 eq = false;
119
120 /* If a solution was already found, we skip it */
121 if (eq) {
122 j--;
123 break;
124 }
125 }
126
127 j++;
128 }
129
130 /* The solutions are appended */
131 ret = 0;
132 for (k = 0; k < j && *arg->nsols < arg->maxsolutions; k++) {
133 l = arg->solutions_size - *arg->solutions_used;
134 m = *arg->solutions + *arg->solutions_used;
135 strl = writemoves(n, all[k], l, m);
136 if (strl < 0)
137 goto solve_h48_appendallsym_error;
138
139 LOG("Solution found: %s\n", m);
140
141 *arg->solutions_used += MAX(0, strl-1);
142
143 if (!appendchar(arg->solutions_size,
144 *arg->solutions, arg->solutions_used, '\n'))
145 goto solve_h48_appendallsym_error;
146
147 (*arg->nsols)++;
148 *arg->shortest_sol = MIN(*arg->shortest_sol, n);
149 ret++;
150 }
151
152 return ret;
153
154solve_h48_appendallsym_error:
155 LOG("Could not append solution to buffer: size too small\n");
156 return NISSY_ERROR_BUFFER_SIZE;
157}
158
159STATIC_INLINE bool 59STATIC_INLINE bool
160solve_h48_stop(dfsarg_solve_h48_t *arg) 60solve_h48_stop(dfsarg_solve_h48_t *arg)
161{ 61{
162 uint32_t data, data_inv; 62 uint32_t data, data_inv;
163 int64_t coord; 63 int64_t coord;
164 int8_t target, nh; 64 int8_t target, nh, n;
165 uint8_t pval_cocsep, pval_eoesep; 65 uint8_t pval_cocsep, pval_eoesep;
166 66
167 target = arg->depth - arg->nmoves - arg->npremoves; 67 n = arg->solution_moves->nmoves + arg->solution_moves->npremoves;
168 if (target <= 0 || *arg->nsols == arg->maxsolutions) 68 target = arg->target_depth - n;
69 if (target <= 0 ||
70 arg->solution_list->nsols == arg->solution_settings->maxsolutions)
169 return true; 71 return true;
170 72
171 arg->movemask_normal = arg->movemask_inverse = MM_ALLMOVES; 73 arg->movemask_normal = arg->movemask_inverse = MM_ALLMOVES;
@@ -246,16 +148,19 @@ STATIC int64_t
246solve_h48_dfs(dfsarg_solve_h48_t *arg) 148solve_h48_dfs(dfsarg_solve_h48_t *arg)
247{ 149{
248 int64_t ret, n; 150 int64_t ret, n;
249 uint8_t m, lbn, lbi; 151 uint8_t m, nm, lbn, lbi;
250 uint32_t mm_normal, mm_inverse; 152 uint32_t mm_normal, mm_inverse;
251 bool ulbi, ulbn; 153 bool ulbi, ulbn;
252 cube_t backup_cube, backup_inverse; 154 cube_t backup_cube, backup_inverse;
253 155
254 if (issolved(arg->cube)) { 156 if (issolved(arg->cube)) {
255 if (arg->nmoves + arg->npremoves != arg->depth) 157 nm = arg->solution_moves->nmoves
158 + arg->solution_moves->npremoves;
159 if (arg->target_depth != nm)
256 return 0; 160 return 0;
257 pthread_mutex_lock(arg->solutions_mutex); 161 pthread_mutex_lock(arg->solutions_mutex);
258 ret = solve_h48_appendsolution(arg); 162 ret = appendsolution(arg->solution_moves,
163 arg->solution_settings, arg->solution_list);
259 pthread_mutex_unlock(arg->solutions_mutex); 164 pthread_mutex_unlock(arg->solutions_mutex);
260 return ret; 165 return ret;
261 } 166 }
@@ -271,16 +176,17 @@ solve_h48_dfs(dfsarg_solve_h48_t *arg)
271 ulbi = arg->use_lb_inverse; 176 ulbi = arg->use_lb_inverse;
272 177
273 ret = 0; 178 ret = 0;
274 mm_normal = allowednextmove_mask(arg->nmoves, arg->moves) & 179 mm_normal = allowednextmove_mask(arg->solution_moves->nmoves,
275 arg->movemask_normal; 180 arg->solution_moves->moves) & arg->movemask_normal;
276 mm_inverse = allowednextmove_mask(arg->npremoves, arg->premoves) & 181 mm_inverse = allowednextmove_mask(arg->solution_moves->npremoves,
277 arg->movemask_inverse; 182 arg->solution_moves->premoves) & arg->movemask_inverse;
278 if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) { 183 if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) {
279 arg->nmoves++; 184 arg->solution_moves->nmoves++;
280 for (m = 0; m < 18; m++) { 185 for (m = 0; m < 18; m++) {
281 if (!(mm_normal & (UINT32_C(1) << (uint32_t)m))) 186 if (!(mm_normal & (UINT32_C(1) << (uint32_t)m)))
282 continue; 187 continue;
283 arg->moves[arg->nmoves-1] = m; 188 arg->solution_moves->moves[
189 arg->solution_moves->nmoves-1] = m;
284 arg->cube = move(backup_cube, m); 190 arg->cube = move(backup_cube, m);
285 arg->inverse = premove(backup_inverse, m); 191 arg->inverse = premove(backup_inverse, m);
286 arg->lb_inverse = lbi; 192 arg->lb_inverse = lbi;
@@ -291,13 +197,14 @@ solve_h48_dfs(dfsarg_solve_h48_t *arg)
291 return n; 197 return n;
292 ret += n; 198 ret += n;
293 } 199 }
294 arg->nmoves--; 200 arg->solution_moves->nmoves--;
295 } else { 201 } else {
296 arg->npremoves++; 202 arg->solution_moves->npremoves++;
297 for (m = 0; m < 18; m++) { 203 for (m = 0; m < 18; m++) {
298 if(!(mm_inverse & (UINT32_C(1) << (uint32_t)m))) 204 if(!(mm_inverse & (UINT32_C(1) << (uint32_t)m)))
299 continue; 205 continue;
300 arg->premoves[arg->npremoves-1] = m; 206 arg->solution_moves->premoves[
207 arg->solution_moves->npremoves-1] = m;
301 arg->inverse = move(backup_inverse, m); 208 arg->inverse = move(backup_inverse, m);
302 arg->cube = premove(backup_cube, m); 209 arg->cube = premove(backup_cube, m);
303 arg->lb_normal = lbn; 210 arg->lb_normal = lbn;
@@ -308,7 +215,7 @@ solve_h48_dfs(dfsarg_solve_h48_t *arg)
308 return n; 215 return n;
309 ret += n; 216 ret += n;
310 } 217 }
311 arg->npremoves--; 218 arg->solution_moves->npremoves--;
312 } 219 }
313 220
314 arg->cube = backup_cube; 221 arg->cube = backup_cube;
@@ -322,22 +229,23 @@ solve_h48_runthread(void *arg)
322{ 229{
323 int i, j; 230 int i, j;
324 solve_h48_task_t task; 231 solve_h48_task_t task;
325 dfsarg_solve_h48_t * dfsarg; 232 dfsarg_solve_h48_t *dfsarg;
326 cube_t cube;
327 233
328 dfsarg = (dfsarg_solve_h48_t *)arg; 234 dfsarg = (dfsarg_solve_h48_t *)arg;
329 cube = dfsarg->start_cube;
330 235
331 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) { 236 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) {
332 task = dfsarg->tasks[i]; 237 task = dfsarg->tasks[i];
333 memcpy(dfsarg->moves, task.moves, STARTING_MOVES); 238
334 dfsarg->cube = cube; 239 solution_moves_reset(dfsarg->solution_moves);
240 memcpy(
241 dfsarg->solution_moves->moves, task.moves, STARTING_MOVES);
242 dfsarg->solution_moves->nmoves = STARTING_MOVES;
243
244 dfsarg->cube = dfsarg->start_cube;
335 for (j = 0; j < STARTING_MOVES; j++) 245 for (j = 0; j < STARTING_MOVES; j++)
336 dfsarg->cube = move( 246 dfsarg->cube = move(dfsarg->cube, task.moves[j]);
337 dfsarg->cube, dfsarg->moves[j]);
338 dfsarg->inverse = inverse(dfsarg->cube); 247 dfsarg->inverse = inverse(dfsarg->cube);
339 dfsarg->nmoves = STARTING_MOVES; 248
340 dfsarg->npremoves = 0;
341 dfsarg->lb_normal = 0; 249 dfsarg->lb_normal = 0;
342 dfsarg->lb_inverse = 0; 250 dfsarg->lb_inverse = 0;
343 dfsarg->use_lb_normal = false; 251 dfsarg->use_lb_normal = false;
@@ -364,16 +272,22 @@ solve_h48_maketasks(
364 uint8_t m, t; 272 uint8_t m, t;
365 uint32_t mm; 273 uint32_t mm;
366 cube_t backup_cube; 274 cube_t backup_cube;
275 solution_moves_t moves;
367 276
368 if (issolved(maketasks_arg->cube)) { 277 if (issolved(maketasks_arg->cube)) {
369 if (maketasks_arg->nmoves > maketasks_arg->maxmoves || 278 if (maketasks_arg->nmoves > maketasks_arg->maxmoves ||
370 maketasks_arg->nmoves < maketasks_arg->minmoves || 279 maketasks_arg->nmoves < maketasks_arg->minmoves ||
371 *solve_arg->nsols >= solve_arg->maxsolutions) 280 solve_arg->solution_list->nsols >=
281 solve_arg->solution_settings->maxsolutions)
372 return NISSY_OK; 282 return NISSY_OK;
373 memcpy(solve_arg->moves, 283
284 solution_moves_reset(&moves);
285 moves.nmoves = maketasks_arg->nmoves;
286 memcpy(moves.moves,
374 maketasks_arg->moves, maketasks_arg->nmoves); 287 maketasks_arg->moves, maketasks_arg->nmoves);
375 solve_arg->nmoves = maketasks_arg->nmoves; 288
376 appret = solve_h48_appendsolution(solve_arg); 289 appret = appendsolution(&moves,
290 solve_arg->solution_settings, solve_arg->solution_list);
377 return appret < 0 ? appret : NISSY_OK; 291 return appret < 0 ? appret : NISSY_OK;
378 } 292 }
379 293
@@ -402,7 +316,7 @@ solve_h48_maketasks(
402 /* Avoid symmetry-equivalent moves from the starting cube */ 316 /* Avoid symmetry-equivalent moves from the starting cube */
403 if (maketasks_arg->nmoves == 1) 317 if (maketasks_arg->nmoves == 1)
404 for (t = 0; t < NTRANS; t++) 318 for (t = 0; t < NTRANS; t++)
405 if (solve_arg->symmask0 & 319 if (solve_arg->solution_settings->tmask &
406 (UINT64_C(1) << (uint64_t)t)) 320 (UINT64_C(1) << (uint64_t)t))
407 mm &= ~(UINT32_C(1) << 321 mm &= ~(UINT32_C(1) <<
408 (uint32_t)transform_move(m, t)); 322 (uint32_t)transform_move(m, t));
@@ -424,27 +338,31 @@ solve_h48(
424 uint64_t data_size, 338 uint64_t data_size,
425 const void *data, 339 const void *data,
426 size_t solutions_size, 340 size_t solutions_size,
427 char *solutions, 341 char solutions[solutions_size],
428 long long stats[static NISSY_SIZE_SOLVE_STATS] 342 long long stats[static NISSY_SIZE_SOLVE_STATS]
429) 343)
430{ 344{
431 int i, ntasks, eoesep_table_index; 345 int i, ntasks, eoesep_table_index;
432 int8_t d, shortest_sol; 346 int8_t d;
433 _Atomic int64_t nsols;
434 dfsarg_solve_h48_t arg[THREADS]; 347 dfsarg_solve_h48_t arg[THREADS];
435 solve_h48_task_t tasks[STARTING_CUBES]; 348 solve_h48_task_t tasks[STARTING_CUBES];
436 dfsarg_solve_h48_maketasks_t maketasks_arg; 349 dfsarg_solve_h48_maketasks_t maketasks_arg;
437 long double fallback_rate, lookups_per_node; 350 long double fallback_rate, lookups_per_node;
438 uint64_t symmask, offset; 351 uint64_t offset;
439 size_t solutions_used;
440 int64_t nodes_visited, table_lookups, table_fallbacks; 352 int64_t nodes_visited, table_lookups, table_fallbacks;
441 tableinfo_t info, fbinfo, fbinfo2; 353 tableinfo_t info, fbinfo, fbinfo2;
442 const uint32_t *cocsepdata; 354 const uint32_t *cocsepdata;
443 const uint8_t *fallback, *h48data; 355 const uint8_t *fallback, *h48data;
444 const void *fallback2; 356 const void *fallback2;
357 solution_moves_t solution_moves[THREADS];
358 solution_settings_t settings;
359 solution_list_t sollist;
445 pthread_t thread[THREADS]; 360 pthread_t thread[THREADS];
446 pthread_mutex_t solutions_mutex; 361 pthread_mutex_t solutions_mutex;
447 362
363 if (!solution_list_init(&sollist, solutions_size, solutions))
364 goto solve_h48_error_solutions_buffer;
365
448 if (readtableinfo_n(data_size, data, 2, &info) != NISSY_OK) 366 if (readtableinfo_n(data_size, data, 2, &info) != NISSY_OK)
449 goto solve_h48_error_data; 367 goto solve_h48_error_data;
450 368
@@ -475,17 +393,18 @@ solve_h48(
475 goto solve_h48_error_data; 393 goto solve_h48_error_data;
476 fallback2 = h48data + offset; 394 fallback2 = h48data + offset;
477 395
478 symmask = symmetry_mask(cube); 396 settings = (solution_settings_t) {
479 shortest_sol = MAXLEN+1; 397 .tmask = symmetry_mask(cube),
398 .unniss = true,
399 .maxmoves = maxmoves,
400 .maxsolutions = maxsolutions,
401 .optimal = optimal,
402 };
403
480 for (i = 0; i < threads; i++) { 404 for (i = 0; i < threads; i++) {
481 arg[i] = (dfsarg_solve_h48_t) { 405 arg[i] = (dfsarg_solve_h48_t) {
482 .start_cube = cube, 406 .start_cube = cube,
483 .cube = cube, 407 .cube = cube,
484 .symmask0 = symmask,
485 .nsols = &nsols,
486 .shortest_sol = &shortest_sol,
487 .optimal = optimal,
488 .maxsolutions = maxsolutions,
489 .h = info.h48h, 408 .h = info.h48h,
490 .k = info.bits, 409 .k = info.bits,
491 .base = info.base, 410 .base = info.base,
@@ -493,9 +412,9 @@ solve_h48(
493 .h48data = h48data, 412 .h48data = h48data,
494 .h48data_fallback_h0k4 = fallback, 413 .h48data_fallback_h0k4 = fallback,
495 .h48data_fallback_eoesep = fallback2, 414 .h48data_fallback_eoesep = fallback2,
496 .solutions_size = solutions_size, 415 .solution_moves = &solution_moves[i],
497 .solutions_used = &solutions_used, 416 .solution_settings = &settings,
498 .solutions = &solutions, 417 .solution_list = &sollist,
499 .nodes_visited = 0, 418 .nodes_visited = 0,
500 .table_fallbacks = 0, 419 .table_fallbacks = 0,
501 .table_lookups = 0, 420 .table_lookups = 0,
@@ -506,9 +425,6 @@ solve_h48(
506 425
507 } 426 }
508 427
509 nsols = 0;
510 solutions_used = 0;
511
512 pthread_mutex_init(&solutions_mutex, NULL); 428 pthread_mutex_init(&solutions_mutex, NULL);
513 429
514 maketasks_arg = (dfsarg_solve_h48_maketasks_t) { 430 maketasks_arg = (dfsarg_solve_h48_maketasks_t) {
@@ -521,7 +437,7 @@ solve_h48(
521 solve_h48_maketasks(&arg[0], &maketasks_arg, tasks, &ntasks); 437 solve_h48_maketasks(&arg[0], &maketasks_arg, tasks, &ntasks);
522 if (ntasks < 0) 438 if (ntasks < 0)
523 goto solve_h48_error_solutions_buffer; 439 goto solve_h48_error_solutions_buffer;
524 if (*arg[0].nsols >= (int64_t)maxsolutions) 440 if (sollist.nsols >= maxsolutions)
525 goto solve_h48_done; 441 goto solve_h48_done;
526 442
527 for (i = 0; i < threads; i++) { 443 for (i = 0; i < threads; i++) {
@@ -533,15 +449,14 @@ solve_h48(
533 449
534 for ( 450 for (
535 d = MAX(minmoves, STARTING_MOVES + 1); 451 d = MAX(minmoves, STARTING_MOVES + 1);
536 d <= maxmoves && nsols < (int64_t)maxsolutions 452 !solutions_done(&sollist, &settings, d);
537 && !(nsols != 0 && d > shortest_sol + optimal);
538 d++ 453 d++
539 ) { 454 ) {
540 if (d >= 10) 455 if (d >= 10)
541 LOG("Found %" PRId64 " solutions, searching at depth %" 456 LOG("Found %" PRId64 " solutions, searching at depth %"
542 PRId8 "\n", nsols, d); 457 PRId8 "\n", sollist.nsols, d);
543 for (i = 0; i < threads; i++) { 458 for (i = 0; i < threads; i++) {
544 arg[i].depth = d; 459 arg[i].target_depth = d;
545 pthread_create( 460 pthread_create(
546 &thread[i], NULL, solve_h48_runthread, &arg[i]); 461 &thread[i], NULL, solve_h48_runthread, &arg[i]);
547 } 462 }
@@ -550,10 +465,6 @@ solve_h48(
550 } 465 }
551 466
552solve_h48_done: 467solve_h48_done:
553 if (!appendchar(arg[0].solutions_size, *arg[0].solutions,
554 arg[0].solutions_used, '\0'))
555 goto solve_h48_error_solutions_buffer;
556
557 nodes_visited = table_lookups = table_fallbacks = 0; 468 nodes_visited = table_lookups = table_fallbacks = 0;
558 for (i = 0; i < threads; i++) { 469 for (i = 0; i < threads; i++) {
559 nodes_visited += arg[i].nodes_visited; 470 nodes_visited += arg[i].nodes_visited;
@@ -573,7 +484,7 @@ solve_h48_done:
573 LOG("Table fallbacks: %" PRId64 " (%.3Lf%%)\n", 484 LOG("Table fallbacks: %" PRId64 " (%.3Lf%%)\n",
574 table_fallbacks, fallback_rate); 485 table_fallbacks, fallback_rate);
575 486
576 return nsols; 487 return sollist.nsols;
577 488
578solve_h48_error_data: 489solve_h48_error_data:
579 LOG("solve_h48: error reading table\n"); 490 LOG("solve_h48: error reading table\n");

Generated with cgit - Back to sebastiano.tronto.net