h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit e4f356b9592599ad91aac34bf2265c9bcdfbb81f
parent c5a6ff0443fc9e5e890fe72cb13ea78d4fe2bbcb
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Tue,  8 Apr 2025 15:16:21 +0200

Some minor changes to the interface.

- Simplified logger to accept only a string, not a variadic list
  of args like printf(). This can still use some improvement,
  but now it is easier to use from other languages.
- Fixed some misuses of the logger (wrong types etc)
- Renamed some constants
- Fixed some typos in comments.

Diffstat:
Mpython/nissy_module.c | 12++++--------
Msrc/core/io_cube.h | 10+++++-----
Msrc/nissy.c | 38++++++++++++++++++--------------------
Msrc/nissy.h | 21+++++++++++----------
Msrc/solvers/coord/gendata.h | 2+-
Msrc/solvers/coord/utils.h | 4++--
Msrc/solvers/h48/gendata_h48.h | 2+-
Msrc/utils/dbg_log.h | 21+++++++++++++++++++--
Msrc/utils/math.h | 4++--
Mtest/test.h | 8++------
Mtools/000_gendata/gendata.c | 2+-
Mtools/100_checkdata/checkdata.c | 2+-
Mtools/300_solve_small/solve_small.c | 2+-
Mtools/301_solve_file/solve_file.c | 2+-
Mtools/302_solve_multisol/solve_multisol.c | 2+-
Mtools/400_solvetest/solve_test.c | 2+-
Mtools/nissy_extra.h | 3+--
Mtools/tool.h | 30+++++++++++-------------------
18 files changed, 83 insertions(+), 84 deletions(-)

diff --git a/python/nissy_module.c b/python/nissy_module.c @@ -235,7 +235,7 @@ solverinfo(PyObject *self, PyObject *args) { long long result; const char *solver; - char buf[NISSY_DATAID_SIZE]; + char buf[NISSY_SIZE_DATAID]; PyObject *py_result, *py_buf; if (!PyArg_ParseTuple(args, "s", &solver)) @@ -263,7 +263,7 @@ gendata(PyObject *self, PyObject *args) { long long size, err; const char *solver; - char *buf, dataid[NISSY_DATAID_SIZE]; + char *buf, dataid[NISSY_SIZE_DATAID]; if (!PyArg_ParseTuple(args, "s", &solver)) return NULL; @@ -421,13 +421,9 @@ static struct PyModuleDef nissy_python_module = { }; static void -log_stdout(const char *str, ...) +log_stdout(const char *str) { - va_list args; - - va_start(args, str); - vfprintf(stderr, str, args); - va_end(args); + fprintf(stderr, "%s", str); } PyMODINIT_FUNC PyInit_nissy_python_module(void) { diff --git a/src/core/io_cube.h b/src/core/io_cube.h @@ -269,9 +269,9 @@ writecube_B32(cube_t cube, size_t buf_size, char buf[buf_size]) uint8_t corner[8], edge[12]; if (buf_size < NISSY_SIZE_B32) { - LOG("Cannot write cube in B32 format: buffer size must be " - "at least %" PRIu64 " bytes, but the provided one is %" - PRIu64 " bytes.\n", NISSY_SIZE_B32, buf_size); + LOG("Cannot write cube in B32 format: buffer size must be at " + "least %u bytes, but the provided one is %zu bytes.\n", + NISSY_SIZE_B32, buf_size); return NISSY_ERROR_BUFFER_SIZE; } @@ -298,8 +298,8 @@ writecube_H48(cube_t cube, size_t buf_size, char buf[buf_size]) if (buf_size < NISSY_SIZE_H48) { LOG("Cannot write cube in H48 format: buffer size must be " - "at least %" PRIu64 " bytes, but the provided one is %" - PRIu64 " bytes.\n", NISSY_SIZE_H48, buf_size); + "at least %u bytes, but the provided one is %zu bytes.\n", + NISSY_SIZE_H48, buf_size); return NISSY_ERROR_BUFFER_SIZE; } diff --git a/src/nissy.c b/src/nissy.c @@ -19,7 +19,7 @@ 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(cube_t, char [static NISSY_SIZE_B32]); STATIC size_t my_strnlen(const char *, size_t); -STATIC long long nissy_dataid(const char *, char [static NISSY_DATAID_SIZE]); +STATIC long long nissy_dataid(const char *, char [static NISSY_SIZE_DATAID]); STATIC long long nissy_gendata_unsafe( const char *, unsigned long long, char *); @@ -355,9 +355,8 @@ nissy_getcube( c = getcube(ep, eo, cp, co); if (!isconsistent(c)) { - LOG("Error: could not get cube with ep=%" PRId64 ", eo=%" - PRId64 ", cp=%" PRId64 ", co=%" PRId64 ".\n", - ep, eo, cp, co); + LOG("Error: could not get cube with ep=%lld, eo=%lld, " + "cp=%lld, co=%lld.\n", ep, eo, cp, co); return NISSY_ERROR_OPTIONS; } @@ -368,7 +367,7 @@ long long nissy_datainfo( uint64_t data_size, const char data[data_size], - void (*write)(const char *, ...) + void (*write)(const char *) ) { uint8_t i; @@ -384,25 +383,24 @@ nissy_datainfo( if (ret != 0) return ret; - write("\n---------\n\n"); - write("Table information for '%s'\n", info.solver); - write("\n"); - write("Size: %" PRIu64 " bytes\n", info.fullsize); - write("Entries: %" PRIu64 " (%" PRIu8 " bits per entry)", - info.entries, info.bits); - write("\n"); + write_wrapper(write, + "\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: - write("\n"); - write("Table distribution:\nValue\tPositions\n"); + write_wrapper(write, "\nTable distribution:\n" + "Value\tPositions\n"); for (i = 0; i <= info.maxvalue; i++) { - write("%" PRIu8 "\t%" PRIu64 "\n", + write_wrapper(write, "%" PRIu8 "\t%" PRIu64 "\n", i + info.base, info.distribution[i]); } break; case TABLETYPE_SPECIAL: - write("This is an ad-hoc table\n"); + write_wrapper(write, "This is an ad-hoc table\n"); break; default: LOG("datainfo: unknown table type\n"); @@ -413,13 +411,13 @@ nissy_datainfo( return nissy_datainfo( data_size - info.next, (char *)data + info.next, write); - write("\n---------\n"); + write_wrapper(write, "\n---------\n"); return NISSY_OK; } STATIC long long -nissy_dataid(const char *solver, char dataid[static NISSY_DATAID_SIZE]) +nissy_dataid(const char *solver, char dataid[static NISSY_SIZE_DATAID]) { if (!strncmp(solver, "h48", 3)) { uint8_t h, k; @@ -442,7 +440,7 @@ nissy_dataid(const char *solver, char dataid[static NISSY_DATAID_SIZE]) long long nissy_solverinfo( const char *solver, - char dataid[static NISSY_DATAID_SIZE] + char dataid[static NISSY_SIZE_DATAID] ) { long long err; @@ -626,7 +624,7 @@ nissy_countmoves( long long nissy_setlogger( - void (*log)(const char *, ...) + void (*log)(const char *) ) { nissy_log = log; diff --git a/src/nissy.h b/src/nissy.h @@ -25,7 +25,7 @@ for example 'rotation UF' or 'mirrored BL'. #define NISSY_SIZE_H48 88U #define NISSY_SIZE_TRANSFORMATION 12U #define NISSY_SIZE_SOLVE_STATS 10U -#define NISSY_DATAID_SIZE 255U +#define NISSY_SIZE_DATAID 255U /* Flags for NISS options */ #define NISSY_NISSFLAG_NORMAL 1U @@ -141,7 +141,7 @@ Parameters: format_in - The input format. format_out - The output format. cube_string - The cube, in format_in format. - retult_size - The allocated size of the result array. + result_size - The allocated size of the result array. result - Return parameter for the cube in format_out format. Return values: @@ -198,7 +198,7 @@ the given solver, and other useful information. Parameters: solver - The name of the solver. dataid - An identifier for the data computed for the solver. Different - solver may use equivalent data. This identifier can be used + solvers may use equivalent data. This identifier can be used e.g. as a filename or database key to save and retrieve the correct data for each solver, without duplication. @@ -211,7 +211,7 @@ Return values: long long nissy_solverinfo( const char *solver, - char dataid[static NISSY_DATAID_SIZE] + char dataid[static NISSY_SIZE_DATAID] ); /* @@ -219,8 +219,8 @@ Compute the data for the given solver and store it in generated_data. Parameters: solver - The name of the solver. - data_size - The size of the data buffer. It is advised to use nissy_datasize - to check how much memory is needed. + data_size - The size of the data buffer. It is advised to use + nissy_solverinfo to check how much memory is needed. data - The return parameter for the generated data. This buffer must have 8-byte alignment. @@ -324,18 +324,19 @@ nissy_countmoves( ); /* -Set a global logger function used by this library. +Set a global logger function used by this library. Setting the logger to NULL +disables logging. Parameters: write - A callback writer with the same signature as printf(3). Return values: - NISSY_OK - Logger set succesfully. No warning or error is goind to be given - if the logger is NULL or invalid. + NISSY_OK - Logger set succesfully. No warning or error is going to be given + if the logger is invalid. */ long long nissy_setlogger( - void (*logger_function)(const char *, ...) + void (*logger_function)(const char *) ); diff --git a/src/solvers/coord/gendata.h b/src/solvers/coord/gendata.h @@ -22,7 +22,7 @@ gendata_coord_dispatch(const char *coordstr, void *buf) parse_coord_and_axis(strlen(coordstr), coordstr, &coord, NULL); if (coord == NULL) { - LOG("Could not parse coordinate '%s'\n", coord); + LOG("Could not parse coordinate '%s'\n", coordstr); return NISSY_ERROR_INVALID_SOLVER; } 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_DATAID_SIZE]); +STATIC int64_t dataid_coord(const char *, char [static NISSY_SIZE_DATAID]); STATIC coord_t * parse_coord(size_t n, const char coord[n]) @@ -52,7 +52,7 @@ parse_coord_and_axis( } STATIC int64_t -dataid_coord(const char *ca, char dataid[static NISSY_DATAID_SIZE]) +dataid_coord(const char *ca, char dataid[static NISSY_SIZE_DATAID]) { coord_t *c; diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -232,7 +232,7 @@ gendata_h48h0k4(gendata_h48_arg_t arg[static 1]) bfsarg[t].table_mutex[tt] = &table_mutex[tt]; } for (done = 1, d = 1; done < h48max && d <= arg->maxdepth; d++) { - LOG("h48: generating depth %" PRIu8 "\n", d); + LOG("h48: generating depth %" PRId64 "\n", d); for (t = 0; t < THREADS; t++) { bfsarg[t].depth = d; diff --git a/src/utils/dbg_log.h b/src/utils/dbg_log.h @@ -1,6 +1,23 @@ -void (*nissy_log)(const char *, ...); +#include <stdio.h> -#define LOG(...) if (nissy_log != NULL) nissy_log(__VA_ARGS__); +void (*nissy_log)(const char *); +void write_wrapper(void (*)(const char *), const char *, ...); + +void +write_wrapper(void (*write)(const char *), const char *str, ...) +{ + static const size_t len = 1000; + char message[len]; + va_list args; + + va_start(args, str); + sprintf(message, str, args); + va_end(args); + + write(message); +} + +#define LOG(...) if (nissy_log != NULL) write_wrapper(nissy_log, __VA_ARGS__); #ifdef DEBUG #define STATIC diff --git a/src/utils/math.h b/src/utils/math.h @@ -168,8 +168,8 @@ sumzerotodigits(int64_t d, size_t n, uint8_t b, uint8_t a[n]) size_t i; if (!((n == 8 && b == 3 ) || (n == 12 && b == 2))) { - LOG("Won't compute 'digits' for n=%" PRIu8 "and b=%" PRIu8 - " (use n=8 b=3 or n=12 b=2)\n"); + LOG("Won't compute 'digits' for n=%zu and b=%" PRIu8 + " (use n=8 b=3 or n=12 b=2)\n", n, b); goto sumzerotodigits_error; } diff --git a/test/test.h b/test/test.h @@ -31,13 +31,9 @@ int64_t writecube(const char *, cube_t, size_t n, char [n]); /* Test function to be implemented by all tests */ void run(void); -void log_stderr(const char *str, ...) +void log_stderr(const char *str) { - va_list args; - - va_start(args, str); - vfprintf(stderr, str, args); - va_end(args); + fprintf(stderr, "%s", str); } int main(void) { diff --git a/tools/000_gendata/gendata.c b/tools/000_gendata/gendata.c @@ -8,7 +8,7 @@ static void run(void) { int64_t size; bool consistent, expected; - char *buf, filename[1024], dataid[NISSY_DATAID_SIZE]; + char *buf, filename[1024], dataid[NISSY_SIZE_DATAID]; size = generatetable(solver, &buf, dataid); switch (size) { diff --git a/tools/100_checkdata/checkdata.c b/tools/100_checkdata/checkdata.c @@ -6,7 +6,7 @@ char *solver, *filename; static void run(void) { long long int size, result; - char *buf, dataid[NISSY_DATAID_SIZE]; + char *buf, dataid[NISSY_SIZE_DATAID]; FILE *f; size = nissy_solverinfo(solver, dataid); diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c @@ -46,7 +46,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255], dataid[NISSY_DATAID_SIZE]; + char filename[255], dataid[NISSY_SIZE_DATAID]; if (argc < 2) { printf("Error: not enough arguments. " diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c @@ -33,7 +33,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255], dataid[NISSY_DATAID_SIZE], *scrfilename; + char filename[255], dataid[NISSY_SIZE_DATAID], *scrfilename; FILE *scrfile; if (argc < 3) { diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c @@ -39,7 +39,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255], dataid[NISSY_DATAID_SIZE]; + char filename[255], dataid[NISSY_SIZE_DATAID]; if (argc < 3) { printf("Error: not enough arguments. " diff --git a/tools/400_solvetest/solve_test.c b/tools/400_solvetest/solve_test.c @@ -94,7 +94,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255], dataid[NISSY_DATAID_SIZE]; + char filename[255], dataid[NISSY_SIZE_DATAID]; if (argc < 2) { printf("Error: not enough arguments. " diff --git a/tools/nissy_extra.h b/tools/nissy_extra.h @@ -11,6 +11,5 @@ for testing purposes only. size_t gendata_h48_derive(uint8_t, const void *, void *); int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]); -long long int nissy_datainfo( - uint64_t, const char *, void (*)(const char *, ...)); +long long int nissy_datainfo(uint64_t, const char *, void (*)(const char *)); long long int nissy_derivedata(const char *, const void *, void *); diff --git a/tools/tool.h b/tools/tool.h @@ -9,12 +9,12 @@ #include "../src/nissy.h" #include "nissy_extra.h" -static void log_stderr(const char *, ...); -static void log_stdout(const char *, ...); +static void log_stderr(const char *); +static void log_stdout(const char *); static double timerun(void (*)(void)); static void writetable(const char *, int64_t, const char *); static long long int generatetable(const char *, char **, - char [static NISSY_DATAID_SIZE]); + char [static NISSY_SIZE_DATAID]); static long long int derivetable( const char *, const char *, const char *, char **); static int getdata(const char *, char **, const char *); @@ -23,23 +23,15 @@ static void derivedata_run( const char *, const char *, const char *, const char *); static void -log_stderr(const char *str, ...) +log_stderr(const char *str) { - va_list args; - - va_start(args, str); - vfprintf(stderr, str, args); - va_end(args); + fprintf(stderr, "%s", str); } static void -write_stdout(const char *str, ...) +write_stdout(const char *str) { - va_list args; - - va_start(args, str); - vfprintf(stdout, str, args); - va_end(args); + fprintf(stdout, "%s", str); } static double @@ -90,7 +82,7 @@ static long long int generatetable( const char *solver, char **buf, - char dataid[static NISSY_DATAID_SIZE] + char dataid[static NISSY_SIZE_DATAID] ) { long long int size, gensize; @@ -125,7 +117,7 @@ derivetable( { uint8_t h, k; long long int size, gensize; - char *fulltable, dataid[NISSY_DATAID_SIZE]; + char *fulltable, dataid[NISSY_SIZE_DATAID]; if (getdata(solver_large, &fulltable, filename_large) != 0) { printf("Error reading full table.\n"); @@ -169,7 +161,7 @@ getdata( ) { long long int size, sizeread; FILE *f; - char dataid[NISSY_DATAID_SIZE]; + char dataid[NISSY_SIZE_DATAID]; if ((f = fopen(filename, "rb")) == NULL) { printf("Table file not found, generating it.\n"); @@ -209,7 +201,7 @@ gendata_run( uint64_t expected[static 21] ) { long long int size; - char *buf, filename[1024], dataid[NISSY_DATAID_SIZE]; + char *buf, filename[1024], dataid[NISSY_SIZE_DATAID]; size = generatetable(solver, &buf, dataid); sprintf(filename, "tables/%s", dataid);