nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

commit 8b94d135429a9f3253cc7f25a1453b412065c4a0
parent 30b43f08955158d4f2066f4b50fe8d1241b3177b
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sun, 18 May 2025 08:48:13 +0200

Refactor solver dispatch and checkdata

Diffstat:
Msrc/nissy.c | 143+++++++++++++++++--------------------------------------------------------------
Msrc/solvers/coord/gendata.h | 35++++++++---------------------------
Msrc/solvers/coord/solve.h | 35+++++++++++++++++++----------------
Msrc/solvers/coord/utils.h | 12+++++++-----
Asrc/solvers/dispatch.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/solvers/distribution.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/h48/gendata_cocsep.h | 16----------------
Msrc/solvers/h48/gendata_h48.h | 86++++++++++++++++++++++---------------------------------------------------------
Msrc/solvers/h48/gendata_types_macros.h | 8--------
Msrc/solvers/h48/h48.h | 1+
Msrc/solvers/h48/solve.h | 34++++++++++++++++++++++++++++++++++
Asrc/solvers/h48/utils.h | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/solvers.h | 2++
Mtest/120_gendata_eo/gendata_eo_tests.c | 5+++--
Mtools/000_gendata/gendata.c | 2+-
Mtools/expected_distributions.h | 2+-
Mtools/nissy_extra.h | 2+-
Mtools/tool.h | 2+-
18 files changed, 325 insertions(+), 252 deletions(-)

diff --git a/src/nissy.c b/src/nissy.c @@ -12,13 +12,10 @@ #include "core/core.h" #include "solvers/solvers.h" -long long parse_h48_solver( - const char *, uint8_t [static 1], uint8_t [static 1]); STATIC bool checkdata(const unsigned char *, const tableinfo_t [static 1]); STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN], const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t); STATIC long long write_result(oriented_cube_t, char [static NISSY_SIZE_CUBE]); -STATIC size_t my_strnlen(const char *, size_t); STATIC long long nissy_dataid(const char *, char [static NISSY_SIZE_DATAID]); STATIC long long nissy_gendata_unsafe( const char *, unsigned long long, unsigned char *); @@ -33,67 +30,20 @@ struct { GETCUBE_OPTIONS(NULL, NULL) }; -long long -parse_h48_solver(const char *buf, uint8_t h[static 1], uint8_t k[static 1]) -{ - const char *fullbuf = buf; - - buf += 3; - - if (*buf != 'h') - goto parse_h48_solver_error; - buf++; - - *h = atoi(buf); - - for ( ; *buf >= 0 + '0' && *buf <= 9 + '0'; buf++) - if (*buf == 0) - goto parse_h48_solver_error; - - if (*buf != 'k') - goto parse_h48_solver_error; - buf++; - - *k = atoi(buf); - - return *h < 12 && (*k == 2 || (*k == 4 && *h == 0)) ? 0 : 1; - -parse_h48_solver_error: - *h = 0; - *k = 0; - LOG("Error parsing H48 solver: must be in \"h48h*k*\" format," - " but got %s\n", fullbuf); - return NISSY_ERROR_INVALID_SOLVER; -} - STATIC bool checkdata(const unsigned char *buf, const tableinfo_t info[static 1]) { uint64_t distr[INFO_DISTRIBUTION_LEN]; - if (my_strnlen(info->solver, INFO_SOLVER_STRLEN) - == INFO_SOLVER_STRLEN) { - LOG("[checkdata] Error reading table info\n"); - return false; - } else if (!strncmp(info->solver, "cocsep", 6)) { - getdistribution_cocsep( - (uint32_t *)((char *)buf + INFOSIZE), distr); - } else if (!strncmp(info->solver, "h48", 3)) { - getdistribution_h48(buf + INFOSIZE, distr, - info->h48h, info->bits); - } else if (!strncmp(info->solver, "coordinate solver for ", 22)) { - getdistribution_coord(buf + INFOSIZE, - info->solver + 22, distr); - } else if (!strncmp(info->solver, "eoesep data for h48", 19)) { - return true; - } else if (!strncmp(info->solver, "coord helper table for ", 23)) { - return true; + if (info->type == TABLETYPE_PRUNING) { + getdistribution(buf + INFOSIZE, distr, info); + LOG("\n[checkdata] Checking distribution for %s\n", info->solver); + return distribution_equal(info->distribution, distr, info->maxvalue); } else { - LOG("[checkdata] unknown solver %s\n", info->solver); - return false; + LOG("\n[checkdata] Skipping distribution check for " + "special table %s\n", info->solver); + return true; } - - return distribution_equal(info->distribution, distr, info->maxvalue); } STATIC bool @@ -109,8 +59,12 @@ distribution_equal( for (i = 0, wrong = 0; i <= MIN(maxvalue, 20); i++) { if (expected[i] != actual[i]) { wrong++; - LOG("Value %" PRIu8 ": expected %" PRIu64 ", found %" - PRIu64 "\n", i, expected[i], actual[i]); + LOG("[checkdata] Value for depth %" PRIu8 + ": expected %" PRIu64 ", found %" PRIu64 "\n", + i, expected[i], actual[i]); + } else { + LOG("[checkdata] Value for depth %" PRIu8 + " is correct (%" PRIu64 ")\n", i, actual[i]); } } @@ -130,18 +84,6 @@ write_result(oriented_cube_t cube, char result[static NISSY_SIZE_CUBE]) return NISSY_OK; } -STATIC size_t -my_strnlen(const char *str, size_t maxlen) -{ - size_t i; - - for (i = 0; i < maxlen; i++) - if (str[i] == '\0') - return i; - - return maxlen; -} - long long nissy_inverse( const char cube[static NISSY_SIZE_CUBE], @@ -337,22 +279,15 @@ nissy_datainfo( STATIC long long nissy_dataid(const char *solver, char dataid[static NISSY_SIZE_DATAID]) { - if (!strncmp(solver, "h48", 3)) { - uint8_t h, k; - long long err; - if ((err = parse_h48_solver(solver, &h, &k)) != NISSY_OK) - return err; - /* TODO: also check that h and k are admissible */ - else strcpy(dataid, solver); - return err; - /* TODO: do this when moved parser */ - /* return dataid_h48(solver, dataid); */ - } else if (!strncmp(solver, "coord_", 6)) { - return dataid_coord(solver+6, dataid); - } else { - LOG("[gendata] Unknown solver %s\n", solver); + solver_dispatch_t *dispatch; + + dispatch = match_solver(solver); + if (dispatch == NULL) { + LOG("[dataid] Unknown solver %s\n", solver); return NISSY_ERROR_INVALID_SOLVER; } + + return dispatch->dataid(solver, dataid); } long long @@ -386,8 +321,7 @@ nissy_gendata_unsafe( unsigned char *data ) { - long long parse_ret; - gendata_h48_arg_t arg; + solver_dispatch_t *dispatch; if (solver == NULL) { LOG("[gendata] Error: 'solver' argument is NULL\n"); @@ -399,20 +333,13 @@ nissy_gendata_unsafe( return NISSY_ERROR_DATA; } - if (!strncmp(solver, "h48", 3)) { - arg.buf_size = data_size; - arg.buf = data; - parse_ret = parse_h48_solver(solver, &arg.h, &arg.k); - arg.maxdepth = 20; - if (parse_ret != NISSY_OK) - return parse_ret; - return gendata_h48(&arg); - } else if (!strncmp(solver, "coord_", 6)) { - return gendata_coord_dispatch(solver+6, data); - } else { + dispatch = match_solver(solver); + if (dispatch == NULL) { LOG("[gendata] Unknown solver %s\n", solver); return NISSY_ERROR_INVALID_SOLVER; } + + return dispatch->gendata(solver, data_size, data); } long long @@ -466,9 +393,8 @@ nissy_solve( ) { oriented_cube_t oc; - long long parse_ret; - uint8_t h, k; int t; + solver_dispatch_t *dispatch; if (solver == NULL) { LOG("[solve] Error: 'solver' argument is NULL\n"); @@ -511,21 +437,14 @@ nissy_solve( return NISSY_ERROR_DATA; } - if (!strncmp(solver, "h48", 3)) { - parse_ret = parse_h48_solver(solver, &h, &k); - if (parse_ret != NISSY_OK) - return parse_ret; - return solve_h48(oc, minmoves, maxmoves, maxsols, - optimal, t, data_size, data, sols_size, sols, stats, - poll_status, poll_status_data); - } else if (!strncmp(solver, "coord_", 6)) { - return solve_coord_dispatch(oc, solver + 6, nissflag, - minmoves, maxmoves, maxsols, optimal, t, data_size, data, - sols_size, sols, poll_status, poll_status_data); - } else { + dispatch = match_solver(solver); + if (dispatch == NULL) { LOG("[solve] Error: unknown solver '%s'\n", solver); return NISSY_ERROR_INVALID_SOLVER; } + return dispatch->solve(oc, solver, nissflag, minmoves, maxmoves, + maxsols, optimal, t, data_size, data, sols_size, sols, stats, + poll_status, poll_status_data); } long long diff --git a/src/solvers/coord/gendata.h b/src/solvers/coord/gendata.h @@ -1,5 +1,6 @@ STATIC size_t gendata_coord(const coord_t [static 1], unsigned char *); -STATIC int64_t gendata_coord_dispatch(const char *, unsigned char *); +STATIC long long gendata_coord_dispatch(const char *, unsigned long long, + unsigned char *); STATIC tableinfo_t genptable_coord( const coord_t [static 1], const unsigned char *, unsigned char *); STATIC bool switch_to_fromnew(uint64_t, uint64_t, uint64_t); @@ -7,15 +8,17 @@ STATIC uint64_t genptable_coord_fillneighbors(const coord_t [static 1], const unsigned char *, uint64_t, uint8_t, unsigned char *); STATIC uint64_t genptable_coord_fillfromnew(const coord_t [static 1], const unsigned char *, uint64_t, uint8_t, unsigned char *); -STATIC void getdistribution_coord(const unsigned char *, const char *, - uint64_t [static INFO_DISTRIBUTION_LEN]); STATIC uint8_t get_coord_pval( const coord_t [static 1], const unsigned char *, uint64_t); STATIC void set_coord_pval( const coord_t [static 1], unsigned char *, uint64_t, uint8_t); -STATIC int64_t -gendata_coord_dispatch(const char *coordstr, unsigned char *buf) +STATIC long long +gendata_coord_dispatch( + const char *coordstr, + unsigned long long bufsize, + unsigned char *buf +) { coord_t *coord; @@ -249,28 +252,6 @@ genptable_coord_fillfromnew( return tot; } -STATIC void -getdistribution_coord( - const unsigned char *table, - const char *coord, - uint64_t distr[static INFO_DISTRIBUTION_LEN] -) -{ - uint8_t v; - uint64_t i; - coord_t *c; - - memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); - - if((c = parse_coord(strlen(coord), coord)) == NULL) - return; - - for (i = 0; i < c->max; i++) { - v = get_coord_pval(c, table, i); - distr[v]++; - } -} - STATIC uint8_t get_coord_pval( const coord_t coord[static 1], diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h @@ -13,11 +13,13 @@ typedef struct { } dfsarg_solve_coord_t; STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t, - uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, - const unsigned char *, size_t n, char [n], int (*)(void *), void *); -STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t, - uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, - const unsigned char *, size_t n, char [n], int (*)(void *), void *); + uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t n, + const unsigned char [n], size_t m, char [m], int (*)(void *), void *); +STATIC long long solve_coord_dispatch(oriented_cube_t, const char *, unsigned, + unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long n, + const unsigned char [n], unsigned m, char [m], + long long [static NISSY_SIZE_SOLVE_STATS], + int (*)(void *), void *); STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); @@ -198,20 +200,21 @@ solve_coord_dfs(dfsarg_solve_coord_t arg[static 1]) return ret; } -STATIC int64_t +STATIC long long solve_coord_dispatch( oriented_cube_t oc, const char *coord_and_axis, - uint8_t nissflag, - uint8_t minmoves, - uint8_t maxmoves, - uint64_t maxsolutions, - uint8_t optimal, - uint8_t threads, - uint64_t data_size, - const unsigned char *data, - size_t solutions_size, + unsigned nissflag, + unsigned minmoves, + unsigned maxmoves, + unsigned maxsolutions, + unsigned optimal, + unsigned threads, + unsigned long long data_size, + const unsigned char data[data_size], + unsigned solutions_size, char sols[solutions_size], + long long stats[static NISSY_SIZE_SOLVE_STATS], int (*poll_status)(void *), void *poll_status_data ) @@ -250,7 +253,7 @@ solve_coord( uint8_t optimal, uint8_t threads, uint64_t data_size, - const unsigned char *data, + const unsigned char data[data_size], size_t solutions_size, char sols[solutions_size], int (*poll_status)(void *), diff --git a/src/solvers/coord/utils.h b/src/solvers/coord/utils.h @@ -2,7 +2,7 @@ STATIC coord_t *parse_coord(size_t n, const char [n]); STATIC uint8_t parse_axis(size_t n, const char [n]); STATIC void parse_coord_and_axis( size_t n, const char [n], coord_t **, uint8_t *); -STATIC int64_t dataid_coord(const char *, char [static NISSY_SIZE_DATAID]); +STATIC long long dataid_coord(const char *, char [static NISSY_SIZE_DATAID]); STATIC coord_t * parse_coord(size_t n, const char coord[n]) @@ -38,20 +38,22 @@ parse_coord_and_axis( uint8_t *axis ) { + const char *s; size_t i; + s = str + 6; for (i = 0; i < n; i++) - if (str[i] == '_') + if (s[i] == '_') break; if (coord != NULL) - *coord = parse_coord(i, str); + *coord = parse_coord(i, s); if (axis != NULL) - *axis = i == n ? UINT8_ERROR : parse_axis(n-i-1, str+i+1); + *axis = i == n ? UINT8_ERROR : parse_axis(n-i-1, s+i+1); } -STATIC int64_t +STATIC long long dataid_coord(const char *ca, char dataid[static NISSY_SIZE_DATAID]) { coord_t *c; diff --git a/src/solvers/dispatch.h b/src/solvers/dispatch.h @@ -0,0 +1,49 @@ +typedef struct { + const char *prefix; + long long (*dataid)(const char *, char [static NISSY_SIZE_DATAID]); + long long (*gendata)( + const char *, unsigned long long, unsigned char *); + long long (*solve)(oriented_cube_t, const char *, unsigned, unsigned, + unsigned, unsigned, unsigned, unsigned, unsigned long long, + const unsigned char *, unsigned, char *, + long long [static NISSY_SIZE_SOLVE_STATS], + int (*)(void *), void *); +} solver_dispatch_t; + +STATIC solver_dispatch_t *match_solver(const char *); + +solver_dispatch_t solver_dispatchers[] = { +{ + .prefix = "h48", + .dataid = dataid_h48, + .gendata = gendata_h48_dispatch, + .solve = solve_h48_dispatch, +}, +{ + .prefix = "coord_", + .dataid = dataid_coord, + .gendata = gendata_coord_dispatch, + .solve = solve_coord_dispatch, +}, +{ + .prefix = NULL +} +}; + +STATIC solver_dispatch_t * +match_solver(const char *name) +{ + const char *prefix; + int i; + + if (name == NULL) + return NULL; + + for (i = 0; solver_dispatchers[i].prefix != NULL; i++) { + prefix = solver_dispatchers[i].prefix; + if (!strncmp(name, prefix, strlen(prefix))) + return &solver_dispatchers[i]; + } + + return NULL; +} diff --git a/src/solvers/distribution.h b/src/solvers/distribution.h @@ -0,0 +1,77 @@ +#define ENTRIES_PER_BYTE(k) (UINT64_C(8) / (uint64_t)(k)) +#define TABLE_SHIFT(i, k) ((uint8_t)(k) * (uint8_t)((i) % ENTRIES_PER_BYTE(k))) +#define TABLE_MASK(i, k) ((UINT8_BIT(k) - UINT8_C(1)) << TABLE_SHIFT(i, k)) + +typedef struct { + uint64_t min; + uint64_t max; + uint8_t bits; + uint64_t *distr; + const unsigned char *table; +} getdistribution_data_t; + +STATIC void *getdistribution_runthread(void *); +STATIC void getdistribution(const unsigned char *, + uint64_t [static INFO_DISTRIBUTION_LEN], const tableinfo_t [static 1]); + +STATIC void * +getdistribution_runthread(void *arg) +{ + getdistribution_data_t *data = (getdistribution_data_t *)arg; + const unsigned char *table; + uint8_t j, k, m; + uint64_t i; + + memset(data->distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); + + k = data->bits; + table = data->table; + m = TABLE_MASK(0, k); + for (i = data->min; i < data->max; i++) + for (j = 0; j < ENTRIES_PER_BYTE(k); j++) + data->distr[(table[i] & (m << (j*k))) >> (j*k)]++; + + return NULL; +} + +STATIC void +getdistribution( + const unsigned char *table, + uint64_t distr[static INFO_DISTRIBUTION_LEN], + const tableinfo_t info[static 1] +) { + getdistribution_data_t targ[THREADS]; + pthread_t thread[THREADS]; + uint8_t pval, k; + uint64_t local_distr[THREADS][INFO_DISTRIBUTION_LEN]; + uint64_t i, j, nbytes, sz, epb; + + k = info->bits; + epb = ENTRIES_PER_BYTE(k); + nbytes = info->entries / epb; + sz = nbytes / THREADS; + for (i = 0; i < THREADS; i++) { + targ[i] = (getdistribution_data_t) { + .min = i * sz, + .max = i == THREADS - 1 ? nbytes : (i+1) * sz, + .bits = k, + .distr = local_distr[i], + .table = table, + }; + pthread_create(&thread[i], NULL, + getdistribution_runthread, &targ[i]); + } + + for (i = 0; i < THREADS; i++) + pthread_join(thread[i], NULL); + + memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); + for (i = 0; i < THREADS; i++) + for (j = 0; j < INFO_DISTRIBUTION_LEN; j++) + distr[j] += local_distr[i][j]; + + for (i = nbytes * epb; i < info->entries; i++) { + pval = (table[i/epb] & TABLE_MASK(i, k)) >> TABLE_SHIFT(i, k); + distr[pval]++; + } +} diff --git a/src/solvers/h48/gendata_cocsep.h b/src/solvers/h48/gendata_cocsep.h @@ -1,7 +1,5 @@ STATIC size_t gendata_cocsep(unsigned char *, uint64_t *, cube_t *); STATIC uint32_t gendata_cocsep_dfs(cocsep_dfs_arg_t [static 1]); -STATIC void getdistribution_cocsep( - const uint32_t [static COCSEP_TABLESIZE], uint64_t [static 21]); STATIC_INLINE bool gendata_cocsep_get_visited( const uint8_t [static COCSEP_VISITEDSIZE], int64_t); @@ -136,20 +134,6 @@ gendata_cocsep_dfs(cocsep_dfs_arg_t arg[static 1]) return cc; } -STATIC void -getdistribution_cocsep( - const uint32_t table[static COCSEP_TABLESIZE], - uint64_t distr[static 21] -) -{ - size_t i; - - memset(distr, 0, 21 * sizeof(uint64_t)); - - for (i = 0; i < COCSEP_TABLESIZE; i++) - distr[CBOUND(table[i])]++; -} - STATIC_INLINE bool gendata_cocsep_get_visited( const uint8_t a[static COCSEP_VISITEDSIZE], diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -1,3 +1,5 @@ +STATIC long long gendata_h48_dispatch( + const char *, unsigned long long, unsigned char *); STATIC uint64_t gendata_h48short(gendata_h48short_arg_t [static 1]); STATIC int64_t gendata_h48(gendata_h48_arg_t [static 1]); STATIC void gendata_h48h0k4(gendata_h48_arg_t [static 1]); @@ -12,9 +14,6 @@ STATIC_INLINE bool gendata_h48k2_dfs_stop( cube_t, int8_t, h48k2_dfs_arg_t [static 1]); STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t [static 1]); STATIC tableinfo_t makeinfo_h48k2(gendata_h48_arg_t [static 1]); -STATIC void *getdistribution_h48_runthread(void *); -STATIC void getdistribution_h48(const unsigned char *, - uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t, uint8_t); STATIC const uint32_t *get_cocsepdata_constptr(const unsigned char *); STATIC const unsigned char *get_h48data_constptr(const unsigned char *); @@ -28,6 +27,27 @@ STATIC_INLINE void set_h48_pval_atomic( size_t gendata_h48_derive(uint8_t, const unsigned char *, unsigned char *); +STATIC long long +gendata_h48_dispatch( + const char *solver, + unsigned long long data_size, + unsigned char *data +) +{ + long long err; + gendata_h48_arg_t arg; + + err = parse_h48_hk(solver, &arg.h, &arg.k); + if (err != NISSY_OK) + return err; + + arg.buf_size = data_size; + arg.buf = data; + arg.maxdepth = 20; + + return gendata_h48(&arg); +} + STATIC uint64_t gendata_h48short(gendata_h48short_arg_t arg[static 1]) { @@ -649,64 +669,6 @@ makeinfo_h48k2(gendata_h48_arg_t arg[static 1]) return info; } -STATIC void * -getdistribution_h48_runthread(void *arg) -{ - getdistribution_h48_data_t *data = (getdistribution_h48_data_t *)arg; - const unsigned char *table; - uint8_t j, k, m; - int64_t i; - - memset(data->distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); - - k = data->k; - table = data->table; - m = H48_MASK(0, k); - for (i = data->min; i < data->max; i++) - for (j = 0; j < H48_DIV(k); j++) - data->distr[(table[i] & (m << (j*k))) >> (j*k)]++; - - return NULL; -} - -STATIC void -getdistribution_h48( - const unsigned char *table, - uint64_t distr[static INFO_DISTRIBUTION_LEN], - uint8_t h, - uint8_t k -) { - getdistribution_h48_data_t targ[THREADS]; - pthread_t thread[THREADS]; - uint64_t local_distr[THREADS][INFO_DISTRIBUTION_LEN]; - int64_t i, j, nbytes, sz; - - nbytes = H48_COORDMAX(h) / H48_DIV(k); - sz = nbytes / THREADS; - for (i = 0; i < THREADS; i++) { - targ[i] = (getdistribution_h48_data_t) { - .min = i * sz, - .max = i == THREADS - 1 ? nbytes : (i+1) * sz, - .k = k, - .distr = local_distr[i], - .table = table, - }; - pthread_create(&thread[i], NULL, - getdistribution_h48_runthread, &targ[i]); - } - - for (i = 0; i < THREADS; i++) - pthread_join(thread[i], NULL); - - memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); - for (i = 0; i < THREADS; i++) - for (j = 0; j < INFO_DISTRIBUTION_LEN; j++) - distr[j] += local_distr[i][j]; - - for (i = nbytes * H48_DIV(k); i < H48_COORDMAX(h); i++) - distr[get_h48_pval(table, i, k)]++; -} - STATIC const uint32_t * get_cocsepdata_constptr(const unsigned char *data) { @@ -821,7 +783,7 @@ gendata_h48_derive(uint8_t h, const unsigned char *fulltable, unsigned char *buf h48derive, j, arg.k, MIN(val_full, val_derive)); } - getdistribution_h48(h48derive, arg.info.distribution, h, arg.k); + getdistribution(h48derive, arg.info.distribution, &arg.info); bufsize = arg.buf_size - COCSEP_FULLSIZE - INFOSIZE; if (writetableinfo(&arg.info, bufsize, (unsigned char *)arg.h48buf) diff --git a/src/solvers/h48/gendata_types_macros.h b/src/solvers/h48/gendata_types_macros.h @@ -121,11 +121,3 @@ typedef struct { _Atomic unsigned char *table_atomic; pthread_mutex_t **table_mutex; } gendata_h48_mark_t; - -typedef struct { - int64_t min; - int64_t max; - uint8_t k; - uint64_t *distr; - const unsigned char *table; -} getdistribution_h48_data_t; diff --git a/src/solvers/h48/h48.h b/src/solvers/h48/h48.h @@ -1,3 +1,4 @@ +#include "utils.h" #include "coordinate_types_macros.h" #include "map_types_macros.h" #include "gendata_types_macros.h" diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h @@ -50,6 +50,10 @@ typedef struct { int8_t *shortest_sol; } dfsarg_solve_h48_maketasks_t; +STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, + unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long n, + const unsigned char [n], unsigned m, char [m], + long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); STATIC int64_t solve_h48_maketasks( dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], @@ -61,6 +65,36 @@ STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint64_t, const unsigned char *, size_t n, char [n], long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); +STATIC long long solve_h48_dispatch( + oriented_cube_t oc, + const char *solver, + unsigned nissflag, + unsigned minmoves, + unsigned maxmoves, + unsigned maxsols, + unsigned optimal, + unsigned threads, + unsigned long long data_size, + const unsigned char data[data_size], + unsigned sols_size, + char sols[sols_size], + long long stats[static NISSY_SIZE_SOLVE_STATS], + int (*poll_status)(void *), + void *poll_status_data +) +{ + uint8_t h, k; + long long err; + + err = parse_h48_hk(solver, &h, &k); + if (err != NISSY_OK) + return err; + + return solve_h48(oc, minmoves, maxmoves, maxsols, optimal, threads, + data_size, data, sols_size, sols, stats, + poll_status, poll_status_data); +} + STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) { diff --git a/src/solvers/h48/utils.h b/src/solvers/h48/utils.h @@ -0,0 +1,66 @@ +long long parse_h48_hk( + const char *, uint8_t [static 1], uint8_t [static 1]); +STATIC long long dataid_h48(const char *, char [static NISSY_SIZE_DATAID]); + +long long +parse_h48_hk(const char *buf, uint8_t h[static 1], uint8_t k[static 1]) +{ + char format_error_msg[100]; + sprintf(format_error_msg, "[H48] Error parsing H48 solver: must be in " + "'h48h*k*' format, but got '%s'\n", buf); + + buf += 3; + + if (*buf != 'h') { + LOG(format_error_msg); + goto parse_h48_hk_error; + } + buf++; + + *h = atoi(buf); + if (*h > 11) { + LOG("[H48] Invalid value %" PRIu8 " for parameter h\n", *h); + goto parse_h48_hk_error; + } + + for ( ; *buf >= 0 + '0' && *buf <= 9 + '0'; buf++) { + if (*buf == 0) { + LOG(format_error_msg); + goto parse_h48_hk_error; + } + } + + if (*buf != 'k') { + LOG(format_error_msg); + goto parse_h48_hk_error; + } + buf++; + + *k = atoi(buf); + if (!(*k == 2 || (*k == 4 && *h == 0))) { + LOG("[H48] Invalid combinations of values h=%" PRIu8 " and k=%" + PRIu8 " for parameters h and k\n", *h, *k); + goto parse_h48_hk_error; + } + + return NISSY_OK; + +parse_h48_hk_error: + *h = 0; + *k = 0; + return NISSY_ERROR_INVALID_SOLVER; +} + +STATIC long long +dataid_h48(const char *hk, char buf[static NISSY_SIZE_DATAID]) +{ + uint8_t h, k; + long long err; + + err = parse_h48_hk(hk, &h, &k); + if (err < 0) + return err; + + sprintf(buf, "h48h%" PRIu8 "k%" PRIu8, h, k); + return NISSY_OK; +} diff --git a/src/solvers/solvers.h b/src/solvers/solvers.h @@ -2,5 +2,7 @@ #include "solutions.h" #include "tables_types_macros.h" #include "tables.h" +#include "distribution.h" #include "h48/h48.h" #include "coord/coord.h" +#include "dispatch.h" diff --git a/test/120_gendata_eo/gendata_eo_tests.c b/test/120_gendata_eo/gendata_eo_tests.c @@ -17,7 +17,8 @@ Pruning table values (from nissy): unsigned char buf[FULLSIZE]; -int64_t gendata_coord_dispatch(const char *, unsigned char *); +long long gendata_coord_dispatch( + const char *, unsigned long long, unsigned char *); int64_t readtableinfo(size_t, const unsigned char *, tableinfo_t *); void run(void) { @@ -25,7 +26,7 @@ void run(void) { size_t result; tableinfo_t info; - result = gendata_coord_dispatch("EO", buf); + result = gendata_coord_dispatch("coord_EO_FB", FULLSIZE, buf); if (readtableinfo(FULLSIZE, buf, &info) != NISSY_OK) { printf("Error reading info from table\n"); return; diff --git a/tools/000_gendata/gendata.c b/tools/000_gendata/gendata.c @@ -49,7 +49,7 @@ int main(int argc, char **argv) { } solver = argv[1]; - parse_h48_solver(solver, &h, &k); + parse_h48_hk(solver, &h, &k); expected = expected_h48[h][k]; nissy_setlogger(log_stderr, NULL); diff --git a/tools/expected_distributions.h b/tools/expected_distributions.h @@ -160,7 +160,7 @@ uint64_t expected_dreo[21] = { [4] = 160, [5] = 1286, [6] = 8550, - [7] = 42512, + [7] = 42152, [8] = 90748, [9] = 33466, [10] = 757, diff --git a/tools/nissy_extra.h b/tools/nissy_extra.h @@ -10,5 +10,5 @@ for testing purposes only. #include "../src/solvers/tables.h" size_t gendata_h48_derive(uint8_t, const unsigned char *, unsigned char *); -long long parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]); +long long parse_h48_hk(const char *, uint8_t [static 1], uint8_t [static 1]); long long int nissy_datainfo(uint64_t, const unsigned char *); diff --git a/tools/tool.h b/tools/tool.h @@ -126,7 +126,7 @@ derivetable( goto derivetable_error; } - if (parse_h48_solver(solver_small, &h, &k) != 0) { + if (parse_h48_hk(solver_small, &h, &k) != NISSY_OK) { gensize = -3; goto derivetable_error; }