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 62d87e063318cc4c842b1b2d8c184f48aeaf6659
parent 8b94d135429a9f3253cc7f25a1453b412065c4a0
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Mon, 19 May 2025 17:45:14 +0200

Refactored checkdata

Relevant changes include:
  - Changed the signature of nissy_checkdata().
  - Removed expected_distribution.h from tools; this data is now included
    in each solver's src/ code.
  - Removed distribution check for cocsep; may add back later.

Diffstat:
Mcpp/nissy.cpp | 5+++--
Mpython/nissy_module.c | 8+++++---
Msrc/nissy.c | 120+++++--------------------------------------------------------------------------
Msrc/nissy.h | 2++
Asrc/solvers/coord/checkdata.h | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/coord/coord.h | 1+
Msrc/solvers/coord/dr.h | 16++++++++++++++++
Msrc/solvers/coord/dreo.h | 14++++++++++++++
Msrc/solvers/coord/eo.h | 11+++++++++++
Msrc/solvers/coord/gendata.h | 2+-
Msrc/solvers/coord/solve.h | 3+--
Msrc/solvers/coord/types_macros.h | 2++
Msrc/solvers/coord/utils.h | 28++++++++++++----------------
Msrc/solvers/dispatch.h | 6+++++-
Msrc/solvers/distribution.h | 27+++++++++++++++++++++++++++
Asrc/solvers/h48/checkdata.h | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/h48/gendata_eoesep.h | 4++--
Msrc/solvers/h48/gendata_h48.h | 90-------------------------------------------------------------------------------
Msrc/solvers/h48/h48.h | 1+
Mtools/000_gendata/gendata.c | 21+++------------------
Dtools/001_derive_h48/derive_h48.c | 40----------------------------------------
Mtools/100_checkdata/checkdata.c | 10++++++----
Dtools/expected_distributions.h | 267-------------------------------------------------------------------------------
Dtools/nissy_extra.h | 14--------------
Mtools/tool.h | 86-------------------------------------------------------------------------------
25 files changed, 418 insertions(+), 659 deletions(-)

diff --git a/cpp/nissy.cpp b/cpp/nissy.cpp @@ -17,7 +17,8 @@ extern "C" { long long nissy_solverinfo(const char *, char *); long long nissy_gendata(const char *, unsigned long long, unsigned char *); - long long nissy_checkdata(unsigned long long, const unsigned char *); + long long nissy_checkdata(const char *, unsigned long long, + const unsigned char *); long long nissy_solve(const char *, const char *, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, const unsigned char *, unsigned, char *, long long *, @@ -144,7 +145,7 @@ namespace nissy { error solver::check_data() { - auto err_value = nissy_checkdata(data.size(), + auto err_value = nissy_checkdata(name.c_str(), data.size(), reinterpret_cast<const unsigned char *>(data.data())); error err{err_value}; data_checked = err.ok(); diff --git a/python/nissy_module.c b/python/nissy_module.c @@ -239,21 +239,23 @@ PyDoc_STRVAR(checkdata_doc, "Checks if the data (pruning table) given is valid or not\n" "\n" "Parameters:\n" -" - data: a bytearray containing the data for a solver" +" - solver: the name of the solver\n" +" - data: a bytearray containing the data for a solver\n" "\n" "Returns: true if the data is valid, false otherwise\n" ); PyObject * checkdata(PyObject *self, PyObject *args) { + const char *solver; long long result; PyByteArrayObject *data; - if (!PyArg_ParseTuple(args, "Y", &data)) + if (!PyArg_ParseTuple(args, "sY", &solver, &data)) return NULL; result = nissy_checkdata( - data->ob_alloc, (unsigned char *)data->ob_bytes); + solver, data->ob_alloc, (unsigned char *)data->ob_bytes); if (check_error(result)) return Py_True; diff --git a/src/nissy.c b/src/nissy.c @@ -12,9 +12,6 @@ #include "core/core.h" #include "solvers/solvers.h" -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 long long nissy_dataid(const char *, char [static NISSY_SIZE_DATAID]); STATIC long long nissy_gendata_unsafe( @@ -30,47 +27,6 @@ struct { GETCUBE_OPTIONS(NULL, NULL) }; -STATIC bool -checkdata(const unsigned char *buf, const tableinfo_t info[static 1]) -{ - uint64_t distr[INFO_DISTRIBUTION_LEN]; - - 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("\n[checkdata] Skipping distribution check for " - "special table %s\n", info->solver); - return true; - } -} - -STATIC bool -distribution_equal( - const uint64_t expected[static INFO_DISTRIBUTION_LEN], - const uint64_t actual[static INFO_DISTRIBUTION_LEN], - uint8_t maxvalue -) -{ - int wrong; - uint8_t i; - - for (i = 0, wrong = 0; i <= MIN(maxvalue, 20); i++) { - if (expected[i] != actual[i]) { - wrong++; - 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]); - } - } - - return wrong == 0; -} - STATIC long long write_result(oriented_cube_t cube, char result[static NISSY_SIZE_CUBE]) { @@ -227,55 +183,6 @@ nissy_getcube( return write_result(oc, result); } -long long -nissy_datainfo( - uint64_t data_size, - const unsigned char data[data_size] -) -{ - uint8_t i; - tableinfo_t info; - long long ret; - - if ((size_t)data % 8 != 0) { - LOG("[datainfo] Error: buffer is not 8-byte aligned\n"); - return NISSY_ERROR_DATA; - } - - ret = readtableinfo(data_size, data, &info); - if (ret != 0) - return ret; - - LOG("\n---------\n\n" - "Table information for '%s'\n\n" - "Size: %" PRIu64 " bytes\n" - "Entries: %" PRIu64 " (%" PRIu8 " bits per entry)\n", - info.solver, info.fullsize, info.entries, info.bits); - - switch (info.type) { - case TABLETYPE_PRUNING: - LOG("\nTable distribution:\nValue\tPositions\n"); - for (i = 0; i <= info.maxvalue; i++) { - LOG("%" PRIu8 "\t%" PRIu64 "\n", - i + info.base, info.distribution[i]); - } - break; - case TABLETYPE_SPECIAL: - LOG("This is an ad-hoc table\n"); - break; - default: - LOG("datainfo: unknown table type\n"); - return NISSY_ERROR_DATA; - } - - if (info.next != 0) - return nissy_datainfo(data_size - info.next, data + info.next); - - LOG("\n---------\n"); - - return NISSY_OK; -} - STATIC long long nissy_dataid(const char *solver, char dataid[static NISSY_SIZE_DATAID]) { @@ -344,33 +251,20 @@ nissy_gendata_unsafe( long long nissy_checkdata( + const char *solver, unsigned long long data_size, const unsigned char data[data_size] ) { - tableinfo_t info; - int64_t err; - - if ((size_t)data % 8 != 0) { - LOG("[checkdata] Error: buffer is not 8-byte aligned\n"); - return NISSY_ERROR_DATA; - } + solver_dispatch_t *dispatch; - for (const unsigned char *buf = data; - (err = readtableinfo(data_size, buf, &info)) == NISSY_OK; - buf += info.next, data_size -= info.next) - { - if (!checkdata(buf, &info)) { - LOG("[checkdata] Error: data for solver '%s' is " - "corrupted!\n", info.solver); - return NISSY_ERROR_DATA; - } - - if (info.next == 0) - break; + dispatch = match_solver(solver); + if (dispatch == NULL) { + LOG("[checkdata] Unknown solver %s\n", solver); + return NISSY_ERROR_INVALID_SOLVER; } - return err; + return dispatch->checkdata(solver, data_size, data); } long long diff --git a/src/nissy.h b/src/nissy.h @@ -283,6 +283,7 @@ nissy_gendata( Check that the data is a valid data table for a solver. Parameters: + solver - The name of the solver. data_size - The size of the data buffer. data - The data for the solver. Can be computed with gendata. This buffer must have 8-byte alignment. @@ -293,6 +294,7 @@ Return values: */ long long nissy_checkdata( + const char *solver, unsigned long long data_size, const unsigned char data[data_size] ); diff --git a/src/solvers/coord/checkdata.h b/src/solvers/coord/checkdata.h @@ -0,0 +1,65 @@ +STATIC long long checkdata_coord( + const char *, unsigned long long n, const unsigned char [n]); + +STATIC long long +checkdata_coord( + const char *solver, + unsigned long long data_size, + const unsigned char data[data_size] +) +{ + coord_t *coord; + const unsigned char *table; + tableinfo_t info; + int64_t err; + uint64_t actual_distribution[INFO_DISTRIBUTION_LEN]; + + if ((size_t)data % 8 != 0) { + LOG("[checkdata] Error: buffer is not 8-byte aligned\n"); + return NISSY_ERROR_DATA; + } + + parse_coord_and_axis(solver, &coord, NULL); + if (coord == NULL) { + LOG("[cehckdata] Unknown coordinate solver '%s'\n", solver); + return NISSY_ERROR_DATA; + } + + table = data + INFOSIZE; + err = readtableinfo(data_size, data, &info); + if (err != NISSY_OK) { + LOG("[checkdata] Data is corrupt\n"); + return err; + } + + if (info.type != TABLETYPE_PRUNING) { + LOG("[checkdata] Skipping '%s'\n", info.solver); + table += info.next; + err = readtableinfo_n(data_size, data, 2, &info); + if (err != NISSY_OK) { + LOG("[checkdata] Data is corrupt\n"); + return err; + } + } + + LOG("[checkdata] Checking distribution for '%s' from " + "table preamble\n", info.solver); + if (!distribution_equal(coord->pruning_distribution, + info.distribution, coord->pruning_max)) { + LOG("[checkdata] Distribution from the table preamble does " + "not match the expected one\n"); + return NISSY_ERROR_DATA; + } + + LOG("\n[checkdata] Checking distribution for '%s' from " + "actual table\n", info.solver); + getdistribution(table, actual_distribution, &info); + if (!distribution_equal(coord->pruning_distribution, + actual_distribution, coord->pruning_max)) { + LOG("[checkdata] Distribution from the actual table does " + "not match the expected one\n"); + return NISSY_ERROR_DATA; + } + + return NISSY_OK; +} diff --git a/src/solvers/coord/coord.h b/src/solvers/coord/coord.h @@ -6,4 +6,5 @@ #include "list.h" #include "utils.h" #include "gendata.h" +#include "checkdata.h" #include "solve.h" diff --git a/src/solvers/coord/dr.h b/src/solvers/coord/dr.h @@ -32,6 +32,22 @@ STATIC coord_t coordinate_dr = { }, .is_admissible = &solution_lastqt_cw, .is_solvable = &is_eoco_solvable, + .pruning_distribution = { + [0] = 1, + [1] = 1, + [2] = 5, + [3] = 44, + [4] = 487, + [5] = 5841, + [6] = 68364, + [7] = 776568, + [8] = 7950748, + [9] = 52098876, + [10] = 76236234, + [11] = 3771112, + [12] = 129, + }, + .pruning_max = 12, .sym = { .classes = DREOESEP_CLASSES, .max = DREOESEP_MAX, diff --git a/src/solvers/coord/dreo.h b/src/solvers/coord/dreo.h @@ -27,6 +27,20 @@ STATIC coord_t coordinate_dreo = { }, .is_admissible = &solution_lastqt_cw, .is_solvable = &is_dreo_solvable, + .pruning_distribution = { + [0] = 1, + [1] = 1, + [2] = 4, + [3] = 22, + [4] = 160, + [5] = 1286, + [6] = 8550, + [7] = 42152, + [8] = 90748, + [9] = 33466, + [10] = 757, + }, + .pruning_max = 10, .sym = { .classes = DRESEP_CLASSES, .max = COMB_12_4, diff --git a/src/solvers/coord/eo.h b/src/solvers/coord/eo.h @@ -20,6 +20,17 @@ STATIC coord_t coordinate_eo = { }, .is_admissible = &solution_lastqt_cw, .is_solvable = &is_eo_even, + .pruning_distribution = { + [0] = 1, + [1] = 2, + [2] = 25, + [3] = 202, + [4] = 620, + [5] = 900, + [6] = 285, + [7] = 13, + }, + .pruning_max = 7, .sym = {0}, }; diff --git a/src/solvers/coord/gendata.h b/src/solvers/coord/gendata.h @@ -22,7 +22,7 @@ gendata_coord_dispatch( { coord_t *coord; - parse_coord_and_axis(strlen(coordstr), coordstr, &coord, NULL); + parse_coord_and_axis(coordstr, &coord, NULL); if (coord == NULL) { LOG("Error: could not parse coordinate '%s'\n", coordstr); diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h @@ -222,8 +222,7 @@ solve_coord_dispatch( coord_t *coord; uint8_t axis; - parse_coord_and_axis( - strlen(coord_and_axis), coord_and_axis, &coord, &axis); + parse_coord_and_axis(coord_and_axis, &coord, &axis); if (coord == NULL) { LOG("Error: could not parse coordinate from '%s'\n", diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -26,6 +26,8 @@ typedef struct { uint8_t axistrans[3]; bool (*is_admissible)(const solution_moves_t[static 1]); bool (*is_solvable)(cube_t); + uint64_t pruning_distribution[INFO_DISTRIBUTION_LEN]; + uint8_t pruning_max; struct { size_t classes; uint64_t max; diff --git a/src/solvers/coord/utils.h b/src/solvers/coord/utils.h @@ -1,7 +1,6 @@ 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 uint8_t parse_axis(const char [static 2]); +STATIC void parse_coord_and_axis(const char *, coord_t **, uint8_t *); STATIC long long dataid_coord(const char *, char [static NISSY_SIZE_DATAID]); STATIC coord_t * @@ -17,13 +16,13 @@ parse_coord(size_t n, const char coord[n]) } STATIC uint8_t -parse_axis(size_t n, const char axis[n]) +parse_axis(const char axis[static 2]) { - if (!strncmp(axis, "UD", n) || !strncmp(axis, "DU", n)) { + if (!strcmp(axis, "UD") || !strcmp(axis, "DU")) { return AXIS_UD; - } else if (!strncmp(axis, "RL", n) || !strncmp(axis, "LR", n)) { + } else if (!strcmp(axis, "RL") || !strcmp(axis, "LR")) { return AXIS_RL; - } else if (!strncmp(axis, "FB", n) || !strncmp(axis, "BF", n)) { + } else if (!strcmp(axis, "FB") || !strcmp(axis, "BF")) { return AXIS_FB; } @@ -32,25 +31,22 @@ parse_axis(size_t n, const char axis[n]) STATIC void parse_coord_and_axis( - size_t n, - const char str[n], + const char *str, coord_t **coord, uint8_t *axis ) { - const char *s; size_t i; - s = str + 6; - for (i = 0; i < n; i++) - if (s[i] == '_') + for (i = 6; i < strlen(str); i++) + if (str[i] == '_') break; if (coord != NULL) - *coord = parse_coord(i, s); + *coord = parse_coord(i-6, str+6); if (axis != NULL) - *axis = i == n ? UINT8_ERROR : parse_axis(n-i-1, s+i+1); + *axis = i == strlen(str) ? UINT8_ERROR : parse_axis(str+i+1); } STATIC long long @@ -58,7 +54,7 @@ dataid_coord(const char *ca, char dataid[static NISSY_SIZE_DATAID]) { coord_t *c; - parse_coord_and_axis(strlen(ca), ca, &c, NULL); + parse_coord_and_axis(ca, &c, NULL); if (c == NULL) { LOG("Error: cannot parse coordinate from '%s'\n", ca); diff --git a/src/solvers/dispatch.h b/src/solvers/dispatch.h @@ -2,7 +2,9 @@ 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 *); + const char *, unsigned long long n, unsigned char [n]); + long long (*checkdata)( + const char *, unsigned long long, const unsigned char *); long long (*solve)(oriented_cube_t, const char *, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, const unsigned char *, unsigned, char *, @@ -17,12 +19,14 @@ solver_dispatch_t solver_dispatchers[] = { .prefix = "h48", .dataid = dataid_h48, .gendata = gendata_h48_dispatch, + .checkdata = checkdata_h48, .solve = solve_h48_dispatch, }, { .prefix = "coord_", .dataid = dataid_coord, .gendata = gendata_coord_dispatch, + .checkdata = checkdata_coord, .solve = solve_coord_dispatch, }, { diff --git a/src/solvers/distribution.h b/src/solvers/distribution.h @@ -13,6 +13,8 @@ typedef struct { STATIC void *getdistribution_runthread(void *); STATIC void getdistribution(const unsigned char *, uint64_t [static INFO_DISTRIBUTION_LEN], 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 void * getdistribution_runthread(void *arg) @@ -75,3 +77,28 @@ getdistribution( distr[pval]++; } } + +STATIC bool +distribution_equal( + const uint64_t expected[static INFO_DISTRIBUTION_LEN], + const uint64_t actual[static INFO_DISTRIBUTION_LEN], + uint8_t maxvalue +) +{ + int wrong; + uint8_t i; + + for (i = 0, wrong = 0; i <= MIN(maxvalue, 20); i++) { + if (expected[i] != actual[i]) { + wrong++; + 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]); + } + } + + return wrong == 0; +} diff --git a/src/solvers/h48/checkdata.h b/src/solvers/h48/checkdata.h @@ -0,0 +1,234 @@ +STATIC long long checkdata_h48( + const char *, unsigned long long n, const unsigned char [n]); + +/* +Currently unused. +TODO: re-introduce check on cocsep table +*/ +uint64_t expected_cocsep[21] = { + [0] = 1, + [1] = 6, + [2] = 63, + [3] = 468, + [4] = 3068, + [5] = 15438, + [6] = 53814, + [7] = 71352, + [8] = 8784, + [9] = 96 +}; + +struct { + uint8_t max; + uint64_t table[21]; +} expected_h48[12][9] = { + [0] = { + [2] = { + .max = 3, + .table = { + [0] = 5473562, + [1] = 34776317, + [2] = 68566704, + [3] = 8750867, + }, + }, + [4] = { + .max = 12, + .table = { + [0] = 1, + [1] = 1, + [2] = 4, + [3] = 34, + [4] = 331, + [5] = 3612, + [6] = 41605, + [7] = 474128, + [8] = 4953846, + [9] = 34776317, + [10] = 68566704, + [11] = 8749194, + [12] = 1673, + }, + }, + }, + [1] = { + [2] = { + .max = 3, + .table = { + [0] = 6012079, + [1] = 45822302, + [2] = 142018732, + [3] = 41281787, + }, + }, + }, + [2] = { + [2] = { + .max = 3, + .table = { + [0] = 6391286, + [1] = 55494785, + [2] = 252389935, + [3] = 155993794, + }, + }, + }, + [3] = { + [2] = { + .max = 3, + .table = { + [0] = 6686828, + [1] = 63867852, + [2] = 392789689, + [3] = 477195231, + }, + }, + }, + [4] = { + [2] = { + .max = 3, + .table = { + [0] = 77147213, + [1] = 543379415, + [2] = 1139570251, + [3] = 120982321, + }, + }, + }, + [5] = { + [2] = { + .max = 3, + .table = { + [0] = 82471284, + [1] = 687850732, + [2] = 2345840746, + [3] = 645995638, + }, + }, + }, + [6] = { + [2] = { + .max = 3, + .table = { + [0] = 85941099, + [1] = 804752968, + [2] = 4077248182, + [3] = 2556374551, + }, + }, + }, + [7] = { + [2] = { + .max = 3, + .table = { + [0] = 88529761, + [1] = 897323475, + [2] = 6126260791, + [3] = 7936519573, + }, + }, + }, + [8] = { + [2] = { + .max = 3, + .table = { + [0] = 1051579940, + [1] = 8136021316, + [2] = 19024479822, + [3] = 18851861220, + }, + }, + }, + [9] = { + [2] = { + .max = 3, + .table = { + [0] = 1102038189, + [1] = 9888265242, + [2] = 38299375805, + [3] = 10904855164, + }, + }, + }, + [10] = { + [2] = { + .max = 3, + .table = { + [0] = 1133240039, + [1] = 11196285614, + [2] = 64164702961, + [3] = 43894840186, + }, + }, + }, + [11] = { + [2] = { + .max = 3, + .table = { + [0] = 1150763161, + [1] = 12045845660, + [2] = 91163433330, + [3] = 136418095449, + }, + }, + }, +}; + +STATIC long long +checkdata_h48( + const char *solver, + unsigned long long data_size, + const unsigned char data[data_size] +) +{ + const unsigned char *table; + tableinfo_t info; + int64_t err; + uint64_t actual_distribution[INFO_DISTRIBUTION_LEN]; + uint8_t em; + uint64_t *ed; + + if ((size_t)data % 8 != 0) { + LOG("[checkdata] Error: buffer is not 8-byte aligned\n"); + return NISSY_ERROR_DATA; + } + + do { + err = readtableinfo(data_size, data, &info); + if (err != NISSY_OK) { + LOG("[checkdata] Data is corrupt\n"); + return NISSY_ERROR_DATA; + } + + table = data + INFOSIZE; + data += info.next; + data_size -= info.next; + + if (info.type != TABLETYPE_PRUNING) { + LOG("[checkdata] Skipping '%s'\n", info.solver); + continue; + } + + ed = expected_h48[info.h48h][info.bits].table; + em = expected_h48[info.h48h][info.bits].max; + + LOG("[checkdata] Checking distribution for '%s' from " + "table preamble\n", info.solver); + if (!distribution_equal(ed, info.distribution, em)) { + LOG("[checkdata] Distribution from the table preamble " + "does not matche the expected one\n"); + return NISSY_ERROR_DATA; + } + + LOG("[checkdata] Checking distribution for '%s' from " + "actual table\n", info.solver); + getdistribution(table, actual_distribution, &info); + if (!distribution_equal(ed, actual_distribution, em)) { + LOG("[checkdata] Distribution from the actual table " + "does not match the expected one\n"); + return NISSY_ERROR_DATA; + } + } while (info.next != 0); + + return NISSY_OK; +} diff --git a/src/solvers/h48/gendata_eoesep.h b/src/solvers/h48/gendata_eoesep.h @@ -79,7 +79,7 @@ gendata_eoesep(unsigned char *buf, uint8_t maxdepth) if (buf == NULL) goto gendata_eoesep_return_size; - LOG("Computing eoesep data\n"); + LOG("[H48 gendata] Computing eoesep data\n"); memset(buf, 0xFF, EOESEP_FULLSIZE); esep_classes = (uint32_t *)(buf + INFOSIZE); buf8 = buf + INFOSIZE + 4*ESEP_MAX; @@ -111,7 +111,7 @@ gendata_eoesep(unsigned char *buf, uint8_t maxdepth) writetableinfo(&info, EOESEP_FULLSIZE, buf); - LOG("eoesep data computed\n"); + LOG("[H48 gendata] eoesep data computed\n"); gendata_eoesep_return_size: return EOESEP_FULLSIZE; diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -25,8 +25,6 @@ STATIC_INLINE uint8_t get_h48_pval_atomic( STATIC_INLINE void set_h48_pval_atomic( _Atomic unsigned char *, int64_t, uint8_t, uint8_t); -size_t gendata_h48_derive(uint8_t, const unsigned char *, unsigned char *); - STATIC long long gendata_h48_dispatch( const char *solver, @@ -711,91 +709,3 @@ set_h48_pval_atomic( table[H48_INDEX(i, k)] = (table[H48_INDEX(i, k)] & (~H48_MASK(i, k))) | (val << H48_SHIFT(i, k)); } - -size_t -gendata_h48_derive(uint8_t h, const unsigned char *fulltable, unsigned char *buf) -{ - size_t cocsepsize, h48size; - uint8_t val_full, val_derive; - const unsigned char *h48full; - unsigned char *h48derive; - int64_t i, j, h48max; - uint64_t bufsize; - gendata_h48_arg_t arg; - tableinfo_t cocsepinfo, fulltableinfo; - - /* Initializing values in case of error */ - /* TODO cleanup this */ - fulltableinfo.h48h = 11; - fulltableinfo.bits = 2; - fulltableinfo.base = 8; - - int64_t TODOlarge = 999999999999; /* TODO: cleanup here */ - - readtableinfo_n(TODOlarge, fulltable, 2, &fulltableinfo); - arg.h = h; - arg.k = fulltableinfo.bits; - arg.maxdepth = 20; - arg.buf = buf; - arg.cocsepdata = (uint32_t *)(buf + INFOSIZE); - arg.base = fulltableinfo.base; - arg.info = makeinfo_h48k2(&arg); - - /* Technically this step is redundant, except that we - need selfsim and crep */ - cocsepsize = gendata_cocsep(buf, arg.selfsim, arg.crep); - arg.h48buf = (_Atomic unsigned char *)buf + cocsepsize; - h48size = H48_TABLESIZE(h, arg.k) + INFOSIZE; - - if (buf == NULL) - goto gendata_h48_derive_return_size; - - bufsize = COCSEP_FULLSIZE + INFOSIZE; - if (readtableinfo(bufsize, buf, &cocsepinfo) != NISSY_OK) { - LOG("[H48 derive gendata] Error: could not read info for " - "cocsep table\n"); - goto gendata_h48_derive_error; - } - - cocsepinfo.next = cocsepsize; - bufsize = COCSEP_FULLSIZE + INFOSIZE; - if (writetableinfo(&cocsepinfo, bufsize, buf) != NISSY_OK) { - LOG("[H48 derive gendata] Error: could not write info for " - "cocsep table with updated 'next' value\n"); - goto gendata_h48_derive_error; - } - - h48full = fulltable + cocsepsize + INFOSIZE; - h48derive = (unsigned char *)arg.h48buf + INFOSIZE; - memset(h48derive, 0xFF, H48_TABLESIZE(h, arg.k)); - memset(arg.info.distribution, 0, - INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); - - h48max = H48_COORDMAX(fulltableinfo.h48h); - for (i = 0; i < h48max; i++) { - if (i % INT64_C(1000000000) == 0 && i > 0) - LOG("[H48 derive gendata] Processing %" PRId64 - "th coordinate\n", i); - j = i >> (int64_t)(fulltableinfo.h48h - h); - val_full = get_h48_pval(h48full, i, arg.k); - val_derive = get_h48_pval(h48derive, j, arg.k); - set_h48_pval( - h48derive, j, arg.k, MIN(val_full, val_derive)); - } - - getdistribution(h48derive, arg.info.distribution, &arg.info); - - bufsize = arg.buf_size - COCSEP_FULLSIZE - INFOSIZE; - if (writetableinfo(&arg.info, bufsize, (unsigned char *)arg.h48buf) - != NISSY_OK) { - LOG("H48 derive gendata] Error: could not write info " - "for table\n"); - goto gendata_h48_derive_error; - } - -gendata_h48_derive_return_size: - return cocsepsize + h48size; - -gendata_h48_derive_error: - return 0; -} diff --git a/src/solvers/h48/h48.h b/src/solvers/h48/h48.h @@ -7,4 +7,5 @@ #include "gendata_cocsep.h" #include "gendata_eoesep.h" #include "gendata_h48.h" +#include "checkdata.h" #include "solve.h" diff --git a/tools/000_gendata/gendata.c b/tools/000_gendata/gendata.c @@ -1,13 +1,10 @@ #include "../tool.h" -#include "../expected_distributions.h" char *solver; -uint64_t *expected; static void run(void) { int64_t size; - bool consistent, expected; char filename[1024], dataid[NISSY_SIZE_DATAID]; unsigned char *buf; @@ -18,20 +15,14 @@ run(void) { case -2: goto gendata_run_finish; default: - nissy_datainfo(size, buf); - consistent = nissy_checkdata(size, buf) == 0; - expected = check_distribution(solver, size, buf); - if (consistent && expected) { + if (nissy_checkdata(solver, size, buf) == NISSY_OK) { printf("\n"); printf("Generated %" PRId64 " bytes.\n", size); sprintf(filename, "tables/%s", dataid); writetable(buf, size, filename); + } else { + printf("Error: table generated incorrectly!\n"); } - if (!consistent) - printf("Error: table is not consistent with info" - " (nissy_checkdata() failed)\n"); - if (!expected) - printf("Error: distribution is not as expected\n"); break; } @@ -40,8 +31,6 @@ gendata_run_finish: } int main(int argc, char **argv) { - uint8_t h, k; - if (argc < 2) { printf("Error: not enough arguments. " "A solver must be given.\n"); @@ -49,11 +38,7 @@ int main(int argc, char **argv) { } solver = argv[1]; - parse_h48_hk(solver, &h, &k); - expected = expected_h48[h][k]; - nissy_setlogger(log_stderr, NULL); - timerun(run); return 0; diff --git a/tools/001_derive_h48/derive_h48.c b/tools/001_derive_h48/derive_h48.c @@ -1,40 +0,0 @@ -/* -This tool is specific to the H48 solver. It can be used to derive small -intermediate tables from larger tables, including the full h11 table. - -When using k=2, the base values for the tables may differ. If you want -to change this value, for example for generating a table with base = 9 -from the h11 table with base = 10, you must re-generate the large table -with the correct base value. The easiest way to do so is to manually -edit the base value in the source code and recompile. -*/ - -#include "../tool.h" - -char *solver_large, *solver_small, *filename_large, *filename_small; - -void run(void) { - derivedata_run(solver_large, solver_small, filename_large, filename_small); -} - -int main(int argc, char **argv) { - if (argc < 5) { - printf("Error: not enough arguments. Required:\n" - "1. Solver name for large table\n" - "2. Solver name for derived table\n" - "3. Filename containing large table\n" - "4. Filename for saving derived table\n"); - return 1; - } - - solver_large = argv[1]; - solver_small = argv[2]; - filename_large = argv[3]; - filename_small = argv[4]; - - nissy_setlogger(log_stderr, NULL); - - timerun(run); - - return 0; -} diff --git a/tools/100_checkdata/checkdata.c b/tools/100_checkdata/checkdata.c @@ -1,11 +1,11 @@ #include "../tool.h" -#include "../expected_distributions.h" char *solver, *filename; static void run(void) { - long long int size, sizeread, result; + bool result; + long long int size, sizeread; char dataid[NISSY_SIZE_DATAID]; unsigned char *buf; FILE *f; @@ -25,10 +25,12 @@ run(void) { buf = malloc(size); sizeread = fread(buf, size, 1, f); fclose(f); - result = sizeread == 1 && nissy_checkdata(size, buf); + if (sizeread != 1) + printf("File has unexpected size\n"); + result = sizeread == 1 && nissy_checkdata(solver, size, buf) == NISSY_OK; free(buf); - printf("checkdata %s\n", result == 0 ? "succeeded" : "failed"); + printf("checkdata %s\n", result ? "succeeded" : "failed"); /* TODO: cross-check with expected distributions? */ } diff --git a/tools/expected_distributions.h b/tools/expected_distributions.h @@ -1,267 +0,0 @@ -uint64_t expected_cocsep[21] = { - [0] = 1, - [1] = 6, - [2] = 63, - [3] = 468, - [4] = 3068, - [5] = 15438, - [6] = 53814, - [7] = 71352, - [8] = 8784, - [9] = 96 -}; - -uint64_t expected_h48[12][9][21] = { - [0] = { - [2] = { - [0] = 5473562, - [1] = 34776317, - [2] = 68566704, - [3] = 8750867, - }, - [4] = { - [0] = 1, - [1] = 1, - [2] = 4, - [3] = 34, - [4] = 331, - [5] = 3612, - [6] = 41605, - [7] = 474128, - [8] = 4953846, - [9] = 34776317, - [10] = 68566704, - [11] = 8749194, - [12] = 1673, - }, - }, - [1] = { - [2] = { - [0] = 6012079, - [1] = 45822302, - [2] = 142018732, - [3] = 41281787, - }, - }, - [2] = { - [2] = { - [0] = 6391286, - [1] = 55494785, - [2] = 252389935, - [3] = 155993794, - }, - }, - [3] = { - [2] = { - [0] = 6686828, - [1] = 63867852, - [2] = 392789689, - [3] = 477195231, - }, - }, - [4] = { - [2] = { - [0] = 77147213, - [1] = 543379415, - [2] = 1139570251, - [3] = 120982321, - }, - }, - [5] = { - [2] = { - [0] = 82471284, - [1] = 687850732, - [2] = 2345840746, - [3] = 645995638, - }, - }, - [6] = { - [2] = { - [0] = 85941099, - [1] = 804752968, - [2] = 4077248182, - [3] = 2556374551, - }, - }, - [7] = { - [2] = { - [0] = 88529761, - [1] = 897323475, - [2] = 6126260791, - [3] = 7936519573, - }, - }, - [8] = { - [2] = { - [0] = 1051579940, - [1] = 8136021316, - [2] = 19024479822, - [3] = 18851861220, - }, - }, - [9] = { - [2] = { - [0] = 1102038189, - [1] = 9888265242, - [2] = 38299375805, - [3] = 10904855164, - }, - }, - [10] = { - [2] = { - [0] = 1133240039, - [1] = 11196285614, - [2] = 64164702961, - [3] = 43894840186, - }, - }, - [11] = { - [2] = { - [0] = 1150763161, - [1] = 12045845660, - [2] = 91163433330, - [3] = 136418095449, - }, - }, -}; - -uint64_t expected_eo[21] = { - [0] = 1, - [1] = 2, - [2] = 25, - [3] = 202, - [4] = 620, - [5] = 900, - [6] = 285, - [7] = 13, -}; - -uint64_t expected_dr[21] = { - [0] = 1, - [1] = 1, - [2] = 5, - [3] = 44, - [4] = 487, - [5] = 5841, - [6] = 68364, - [7] = 776568, - [8] = 7950748, - [9] = 52098876, - [10] = 76236234, - [11] = 3771112, - [12] = 129, -}; - -uint64_t expected_dreo[21] = { - [0] = 1, - [1] = 1, - [2] = 4, - [3] = 22, - [4] = 160, - [5] = 1286, - [6] = 8550, - [7] = 42152, - [8] = 90748, - [9] = 33466, - [10] = 757, -}; - -static bool -distribution_equal(const uint64_t *expected, const uint64_t *actual, int n) -{ - bool equal; - int i; - - for (i = 0, equal = true; i <= n; i++) { - if (expected[i] != actual[i]) { - equal = false; - printf("Wrong value for %d: expected %" PRIu64 - ", actual %" PRIu64 "\n", - i, expected[i], actual[i]); - } - } - - return equal; -} - -STATIC bool -check_table(uint64_t *exp, tableinfo_t *info) -{ - if (!distribution_equal(exp, info->distribution, info->maxvalue)) { - printf("ERROR! Distribution is incorrect\n"); - return false; - } - - printf("Distribution is correct\n"); - return true; -} - -static bool -check_cocsep(size_t data_size, const unsigned char *data) -{ - tableinfo_t info; - - readtableinfo(data_size, data, &info); - return distribution_equal( - expected_cocsep, info.distribution, info.maxvalue); -} - -static bool -unknown_h48(uint8_t h, uint8_t k) -{ - if (k != 2 && k != 4) - return true; - - if (k == 4 && h != 0) - return true; - - return k == 2 && h > 7; -} - -STATIC bool -check_distribution( - const char *solver, - size_t data_size, - const unsigned char *data -) -{ - const char *str; - tableinfo_t info = {0}; - - if (!strncmp(solver, "h48", 3)) { - readtableinfo(data_size, data, &info); - if (!distribution_equal( - expected_cocsep, info.distribution, info.maxvalue)) { - printf("ERROR! cocsep distribution is incorrect\n"); - return false; - } - printf("cocsep distribution is correct\n"); - - readtableinfo_n(data_size, data, 2, &info); - if (unknown_h48(info.h48h, info.bits)) - goto check_distribution_unknown; - - return check_table(expected_h48[info.h48h][info.bits], &info); - } - - if (!strncmp(solver, "coord_", 6)) { - readtableinfo(data_size, data, &info); - if (!strncmp(info.solver, "coord helper table for ", 23)) - readtableinfo_n(data_size, data, 2, &info); - - str = info.solver + 22; /* "coordinate solver for COORD" */ - if (!strcmp(str, "EO")) { - return check_table(expected_eo, &info); - } else if (!strcmp(str, "DR")) { - return check_table(expected_dr, &info); - } else if (!strcmp(str, "DREO")) { - return check_table(expected_dreo, &info); - } else { - goto check_distribution_unknown; - } - } - -check_distribution_unknown: - printf("Distribution unknown, not checked\n"); - return true; -} diff --git a/tools/nissy_extra.h b/tools/nissy_extra.h @@ -1,14 +0,0 @@ -/* -This header file exposes certain functions that are meant to be used -for testing purposes only. -*/ - -#define STATIC static -#define LOG printf - -#include "../src/solvers/tables_types_macros.h" -#include "../src/solvers/tables.h" - -size_t gendata_h48_derive(uint8_t, const unsigned char *, unsigned char *); -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 @@ -7,19 +7,14 @@ #include <string.h> #include "../src/nissy.h" -#include "nissy_extra.h" static void log_stderr(const char *, void *); static double timerun(void (*)(void)); static void writetable(const unsigned char *, int64_t, const char *); static long long int generatetable(const char *, unsigned char **, char [static NISSY_SIZE_DATAID]); -static long long int derivetable( - const char *, const char *, const char *, unsigned char **); static int getdata(const char *, unsigned char **, const char *); static void gendata_run(const char *, uint64_t[static 21]); -static void derivedata_run( - const char *, const char *, const char *, const char *); static void log_stderr(const char *str, void *unused) @@ -100,53 +95,6 @@ generatetable( return gensize; } -static long long int -derivetable( - const char *solver_large, - const char *solver_small, - const char *filename_large, - unsigned char **buf -) -{ - uint8_t h, k; - long long int size, gensize; - char dataid[NISSY_SIZE_DATAID]; - unsigned char *fulltable; - - if (getdata(solver_large, &fulltable, filename_large) != 0) { - printf("Error reading full table.\n"); - gensize = -1; - goto derivetable_error_nofree; - } - - size = nissy_solverinfo(solver_small, dataid); - if (size == -1) { - printf("Error getting table size.\n"); - gensize = -2; - goto derivetable_error; - } - - if (parse_h48_hk(solver_small, &h, &k) != NISSY_OK) { - gensize = -3; - goto derivetable_error; - } - - *buf = malloc(size); - gensize = gendata_h48_derive(h, fulltable, *buf); - - if (gensize != size) { - printf("Error deriving table\n"); - gensize = -4; - goto derivetable_error; - } - -derivetable_error: - free(fulltable); - -derivetable_error_nofree: - return gensize; -} - static int getdata( const char *solver, @@ -206,8 +154,6 @@ gendata_run( case -2: goto gendata_run_finish; default: - nissy_datainfo(size, buf); - printf("\n"); printf("Succesfully generated %lld bytes. " "See above for details on the tables.\n", size); @@ -219,35 +165,3 @@ gendata_run( gendata_run_finish: free(buf); } - -static void -derivedata_run( - const char *solver_large, - const char *solver_small, - const char *filename_large, - const char *filename_small -) -{ - long long int size; - unsigned char *buf; - - buf = NULL; - size = derivetable(solver_large, solver_small, filename_large, &buf); - switch (size) { - case -1: - return; - case -2: - goto derivedata_run_finish; - default: - nissy_datainfo(size, buf); - printf("\n"); - printf("Succesfully generated %lld bytes. " - "See above for details on the tables.\n", size); - - writetable(buf, size, filename_small); - break; - } - -derivedata_run_finish: - free(buf); -}