diff options
Diffstat (limited to '')
| -rwxr-xr-x | configure.sh | 5 | ||||
| -rw-r--r-- | cpp/examples/solve_h48h3k2.cpp | 2 | ||||
| -rw-r--r-- | cpp/nissy.cpp | 13 | ||||
| -rw-r--r-- | cpp/nissy.h | 12 | ||||
| -rw-r--r-- | python/nissy_module.c | 6 | ||||
| -rw-r--r-- | shell/shell.c | 2 | ||||
| -rw-r--r-- | src/nissy.c | 24 | ||||
| -rw-r--r-- | src/nissy.h | 53 | ||||
| -rw-r--r-- | src/solvers/coord/solve.h | 14 | ||||
| -rw-r--r-- | src/solvers/h48/solve.h | 69 | ||||
| -rw-r--r-- | src/utils/sleep.h | 48 | ||||
| -rw-r--r-- | src/utils/utils.h | 1 | ||||
| -rw-r--r-- | tools/300_solve_small/solve_small.c | 3 | ||||
| -rw-r--r-- | tools/301_solve_file/solve_file.c | 3 | ||||
| -rw-r--r-- | tools/302_solve_multisol/solve_multisol.c | 3 | ||||
| -rw-r--r-- | tools/400_solvetest/solve_test.c | 6 |
16 files changed, 213 insertions, 51 deletions
diff --git a/configure.sh b/configure.sh index e31e650..4a60ed4 100755 --- a/configure.sh +++ b/configure.sh | |||
| @@ -85,6 +85,7 @@ validatethreads | |||
| 85 | validatearch | 85 | validatearch |
| 86 | 86 | ||
| 87 | STD="-std=c11" | 87 | STD="-std=c11" |
| 88 | POSIX="-D_POSIX_C_SOURCE=199309L" | ||
| 88 | WFLAGS="-pedantic -Wall -Wextra" | 89 | WFLAGS="-pedantic -Wall -Wextra" |
| 89 | WNOFLAGS="-Wno-unused-parameter -Wno-unused-function -Wno-unknown-pragmas" | 90 | WNOFLAGS="-Wno-unused-parameter -Wno-unused-function -Wno-unknown-pragmas" |
| 90 | WNOFLAGS="$WNOFLAGS -Wno-unused-command-line-argument" | 91 | WNOFLAGS="$WNOFLAGS -Wno-unused-command-line-argument" |
| @@ -99,8 +100,8 @@ if [ -n "$SANITIZE" ]; then | |||
| 99 | fi | 100 | fi |
| 100 | LIBS="-lpthread" | 101 | LIBS="-lpthread" |
| 101 | 102 | ||
| 102 | CFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS $AVX -O3 -fPIC -D$ARCH" | 103 | CFLAGS="$STD $POSIX $LIBS $WFLAGS $WNOFLAGS $AVX -O3 -fPIC -D$ARCH" |
| 103 | DBGFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS $SAN $AVX -g3 -DDEBUG -fPIC -D$ARCH" | 104 | DBGFLAGS="$STD $POSIX $LIBS $WFLAGS $WNOFLAGS $SAN $AVX -g3 -DDEBUG -fPIC -D$ARCH" |
| 104 | WASMFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS -O3 -fPIC" | 105 | WASMFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS -O3 -fPIC" |
| 105 | MACROS="-DTHREADS=$THREADS" | 106 | MACROS="-DTHREADS=$THREADS" |
| 106 | 107 | ||
diff --git a/cpp/examples/solve_h48h3k2.cpp b/cpp/examples/solve_h48h3k2.cpp index f7ba235..f0d6f2f 100644 --- a/cpp/examples/solve_h48h3k2.cpp +++ b/cpp/examples/solve_h48h3k2.cpp | |||
| @@ -68,7 +68,7 @@ int main() { | |||
| 68 | 68 | ||
| 69 | // Solve | 69 | // Solve |
| 70 | auto solve_result = h48h3k2.solve(c, nissy::nissflag::NORMAL, | 70 | auto solve_result = h48h3k2.solve(c, nissy::nissflag::NORMAL, |
| 71 | 0, maxmoves, 1, 20, 8); | 71 | 0, maxmoves, 1, 20, 8, NULL, NULL); |
| 72 | 72 | ||
| 73 | // Write the result | 73 | // Write the result |
| 74 | if (!solve_result.err.ok()) { | 74 | if (!solve_result.err.ok()) { |
diff --git a/cpp/nissy.cpp b/cpp/nissy.cpp index 118a072..2faea6f 100644 --- a/cpp/nissy.cpp +++ b/cpp/nissy.cpp | |||
| @@ -20,7 +20,8 @@ extern "C" { | |||
| 20 | long long nissy_checkdata(unsigned long long, const unsigned char *); | 20 | long long nissy_checkdata(unsigned long long, const unsigned char *); |
| 21 | long long nissy_solve(const char *, const char *, unsigned, unsigned, | 21 | long long nissy_solve(const char *, const char *, unsigned, unsigned, |
| 22 | unsigned, unsigned, unsigned, unsigned, unsigned long long, | 22 | unsigned, unsigned, unsigned, unsigned, unsigned long long, |
| 23 | const unsigned char *, unsigned, char *, long long *); | 23 | const unsigned char *, unsigned, char *, long long *, |
| 24 | int (*)(void *), void *); | ||
| 24 | long long nissy_countmoves(const char *); | 25 | long long nissy_countmoves(const char *); |
| 25 | long long nissy_setlogger(void (*)(const char *, void *), void *); | 26 | long long nissy_setlogger(void (*)(const char *, void *), void *); |
| 26 | } | 27 | } |
| @@ -47,6 +48,10 @@ namespace nissy { | |||
| 47 | const error error::OPTIONS{-80}; | 48 | const error error::OPTIONS{-80}; |
| 48 | const error error::UNKNOWN{-999}; | 49 | const error error::UNKNOWN{-999}; |
| 49 | 50 | ||
| 51 | const status status::run{0}; | ||
| 52 | const status status::stop{1}; | ||
| 53 | const status status::pause{2}; | ||
| 54 | |||
| 50 | namespace size { | 55 | namespace size { |
| 51 | constexpr size_t CUBE = 22; | 56 | constexpr size_t CUBE = 22; |
| 52 | constexpr size_t TRANSFORMATION = 12; | 57 | constexpr size_t TRANSFORMATION = 12; |
| @@ -154,7 +159,8 @@ namespace nissy { | |||
| 154 | solver::solve_result | 159 | solver::solve_result |
| 155 | solver::solve(const cube& cube, nissflag niss, unsigned minmoves, | 160 | solver::solve(const cube& cube, nissflag niss, unsigned minmoves, |
| 156 | unsigned maxmoves, unsigned maxsols, unsigned optimal, | 161 | unsigned maxmoves, unsigned maxsols, unsigned optimal, |
| 157 | unsigned threads) | 162 | unsigned threads, int (*poll_status)(void *), |
| 163 | void *poll_status_data) | ||
| 158 | { | 164 | { |
| 159 | solver::solve_result result; | 165 | solver::solve_result result; |
| 160 | 166 | ||
| @@ -171,7 +177,8 @@ namespace nissy { | |||
| 171 | name.c_str(), niss.value, minmoves, maxmoves, maxsols, | 177 | name.c_str(), niss.value, minmoves, maxmoves, maxsols, |
| 172 | optimal, threads, data.size(), | 178 | optimal, threads, data.size(), |
| 173 | reinterpret_cast<const unsigned char *>(data.data()), len, | 179 | reinterpret_cast<const unsigned char *>(data.data()), len, |
| 174 | csols.data(), result.stats.data()); | 180 | csols.data(), result.stats.data(), poll_status, |
| 181 | poll_status_data); | ||
| 175 | result.err = error{err}; | 182 | result.err = error{err}; |
| 176 | 183 | ||
| 177 | if (err < 0) | 184 | if (err < 0) |
diff --git a/cpp/nissy.h b/cpp/nissy.h index 4fa98ad..41d3876 100644 --- a/cpp/nissy.h +++ b/cpp/nissy.h | |||
| @@ -46,6 +46,15 @@ namespace nissy { | |||
| 46 | static const error UNKNOWN; | 46 | static const error UNKNOWN; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | class status { | ||
| 50 | public: | ||
| 51 | int value; | ||
| 52 | |||
| 53 | static const status run; | ||
| 54 | static const status stop; | ||
| 55 | static const status pause; | ||
| 56 | }; | ||
| 57 | |||
| 49 | class cube { | 58 | class cube { |
| 50 | public: | 59 | public: |
| 51 | cube(); | 60 | cube(); |
| @@ -86,7 +95,8 @@ namespace nissy { | |||
| 86 | void unload_data(); | 95 | void unload_data(); |
| 87 | solve_result solve(const cube&, nissflag, unsigned minmoves, | 96 | solve_result solve(const cube&, nissflag, unsigned minmoves, |
| 88 | unsigned maxmoves, unsigned maxsols, unsigned optimal, | 97 | unsigned maxmoves, unsigned maxsols, unsigned optimal, |
| 89 | unsigned threads); | 98 | unsigned threads, int (*poll_status)(void *), |
| 99 | void *poll_status_data); | ||
| 90 | 100 | ||
| 91 | static std::variant<solver, error> get(const std::string&); | 101 | static std::variant<solver, error> get(const std::string&); |
| 92 | private: | 102 | private: |
diff --git a/python/nissy_module.c b/python/nissy_module.c index bf5a71a..069dea0 100644 --- a/python/nissy_module.c +++ b/python/nissy_module.c | |||
| @@ -300,7 +300,7 @@ solve(PyObject *self, PyObject *args) | |||
| 300 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, | 300 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, |
| 301 | maxsolutions, optimal, threads, data->ob_alloc, | 301 | maxsolutions, optimal, threads, data->ob_alloc, |
| 302 | (unsigned char *)data->ob_bytes, MAX_SOLUTIONS_SIZE, solutions, | 302 | (unsigned char *)data->ob_bytes, MAX_SOLUTIONS_SIZE, solutions, |
| 303 | stats); | 303 | stats, NULL, NULL); |
| 304 | Py_END_ALLOW_THREADS | 304 | Py_END_ALLOW_THREADS |
| 305 | 305 | ||
| 306 | if(!check_error(result)) { | 306 | if(!check_error(result)) { |
| @@ -350,9 +350,9 @@ static PyMethodDef nissy_methods[] = { | |||
| 350 | { "getcube", getcube, METH_VARARGS, getcube_doc }, | 350 | { "getcube", getcube, METH_VARARGS, getcube_doc }, |
| 351 | { "solverinfo", solverinfo, METH_VARARGS, solverinfo_doc }, | 351 | { "solverinfo", solverinfo, METH_VARARGS, solverinfo_doc }, |
| 352 | { "gendata", gendata, METH_VARARGS, gendata_doc }, | 352 | { "gendata", gendata, METH_VARARGS, gendata_doc }, |
| 353 | { "checkdata", checkdata, METH_VARARGS, checkdata_doc }, | 353 | { "checkdata", _checkdata, METH_VARARGS, checkdata_doc }, |
| 354 | { "solve", solve, METH_VARARGS, solve_doc }, | 354 | { "solve", solve, METH_VARARGS, solve_doc }, |
| 355 | { "countmoves", countmoves, METH_VARARGS, countmoves_doc }, | 355 | { "countmoves", _countmoves, METH_VARARGS, countmoves_doc }, |
| 356 | { NULL, NULL, 0, NULL } | 356 | { NULL, NULL, 0, NULL } |
| 357 | }; | 357 | }; |
| 358 | 358 | ||
diff --git a/shell/shell.c b/shell/shell.c index 3ee69c4..1fa854f 100644 --- a/shell/shell.c +++ b/shell/shell.c | |||
| @@ -435,7 +435,7 @@ solve_exec(args_t *args) | |||
| 435 | ret = nissy_solve( | 435 | ret = nissy_solve( |
| 436 | args->cube, args->str_solver, nissflag, args->minmoves, | 436 | args->cube, args->str_solver, nissflag, args->minmoves, |
| 437 | args->maxmoves, args->maxsolutions, args->optimal, args->threads, | 437 | args->maxmoves, args->maxsolutions, args->optimal, args->threads, |
| 438 | size, buf, SOLUTIONS_BUFFER_SIZE, solutions, stats); | 438 | size, buf, SOLUTIONS_BUFFER_SIZE, solutions, stats, NULL, NULL); |
| 439 | 439 | ||
| 440 | free(buf); | 440 | free(buf); |
| 441 | 441 | ||
diff --git a/src/nissy.c b/src/nissy.c index 2dd5a41..acf6ebe 100644 --- a/src/nissy.c +++ b/src/nissy.c | |||
| @@ -460,7 +460,9 @@ nissy_solve( | |||
| 460 | const unsigned char data[data_size], | 460 | const unsigned char data[data_size], |
| 461 | unsigned sols_size, | 461 | unsigned sols_size, |
| 462 | char sols[sols_size], | 462 | char sols[sols_size], |
| 463 | long long stats[static NISSY_SIZE_SOLVE_STATS] | 463 | long long stats[static NISSY_SIZE_SOLVE_STATS], |
| 464 | int (*poll_status)(void *), | ||
| 465 | void *poll_status_data | ||
| 464 | ) | 466 | ) |
| 465 | { | 467 | { |
| 466 | oriented_cube_t oc; | 468 | oriented_cube_t oc; |
| @@ -475,14 +477,23 @@ nissy_solve( | |||
| 475 | 477 | ||
| 476 | oc = readcube(cube); | 478 | oc = readcube(cube); |
| 477 | 479 | ||
| 478 | /* TODO: solve should handle oriented cubes */ | ||
| 479 | |||
| 480 | if (!isconsistent(oc)) { | 480 | if (!isconsistent(oc)) { |
| 481 | LOG("[solve] Error: cube is invalid\n"); | 481 | LOG("[solve] Error: cube is invalid\n"); |
| 482 | return NISSY_ERROR_INVALID_CUBE; | 482 | return NISSY_ERROR_INVALID_CUBE; |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | /* TODO: checks for minmoves, maxmoves, nissflag */ | 485 | if (maxmoves > 20) { |
| 486 | LOG("[solve] 'maxmoves' larger than 20 not supported yet, " | ||
| 487 | "setting it to 20\n"); | ||
| 488 | maxmoves = 20; | ||
| 489 | } | ||
| 490 | |||
| 491 | if (minmoves > maxmoves) { | ||
| 492 | LOG("[solve] value provided for 'minmoves' (%u) is larger " | ||
| 493 | "than that provided for 'maxmoves' (%u), setting " | ||
| 494 | "'minmoves' to %u\n", minmoves, maxmoves, maxmoves); | ||
| 495 | minmoves = maxmoves; | ||
| 496 | } | ||
| 486 | 497 | ||
| 487 | if (maxsols == 0) { | 498 | if (maxsols == 0) { |
| 488 | LOG("[solve] 'maxsols' is 0, returning no solution\n"); | 499 | LOG("[solve] 'maxsols' is 0, returning no solution\n"); |
| @@ -505,11 +516,12 @@ nissy_solve( | |||
| 505 | if (parse_ret != NISSY_OK) | 516 | if (parse_ret != NISSY_OK) |
| 506 | return parse_ret; | 517 | return parse_ret; |
| 507 | return solve_h48(oc, minmoves, maxmoves, maxsols, | 518 | return solve_h48(oc, minmoves, maxmoves, maxsols, |
| 508 | optimal, t, data_size, data, sols_size, sols, stats); | 519 | optimal, t, data_size, data, sols_size, sols, stats, |
| 520 | poll_status, poll_status_data); | ||
| 509 | } else if (!strncmp(solver, "coord_", 6)) { | 521 | } else if (!strncmp(solver, "coord_", 6)) { |
| 510 | return solve_coord_dispatch(oc, solver + 6, nissflag, | 522 | return solve_coord_dispatch(oc, solver + 6, nissflag, |
| 511 | minmoves, maxmoves, maxsols, optimal, t, data_size, data, | 523 | minmoves, maxmoves, maxsols, optimal, t, data_size, data, |
| 512 | sols_size, sols); | 524 | sols_size, sols, poll_status, poll_status_data); |
| 513 | } else { | 525 | } else { |
| 514 | LOG("[solve] Error: unknown solver '%s'\n", solver); | 526 | LOG("[solve] Error: unknown solver '%s'\n", solver); |
| 515 | return NISSY_ERROR_INVALID_SOLVER; | 527 | return NISSY_ERROR_INVALID_SOLVER; |
diff --git a/src/nissy.h b/src/nissy.h index 5800490..2fa4a75 100644 --- a/src/nissy.h +++ b/src/nissy.h | |||
| @@ -37,6 +37,11 @@ for example 'rotation UF' or 'mirrored BL'. | |||
| 37 | #define NISSY_NISSFLAG_ALL \ | 37 | #define NISSY_NISSFLAG_ALL \ |
| 38 | (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED) | 38 | (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED) |
| 39 | 39 | ||
| 40 | /* Status for stopping / pausing / resuming a solver */ | ||
| 41 | #define NISSY_STATUS_RUN 0 | ||
| 42 | #define NISSY_STATUS_STOP 1 | ||
| 43 | #define NISSY_STATUS_PAUSE 2 | ||
| 44 | |||
| 40 | /* The solved cube */ | 45 | /* The solved cube */ |
| 41 | #define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A" | 46 | #define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A" |
| 42 | 47 | ||
| @@ -296,24 +301,32 @@ nissy_checkdata( | |||
| 296 | Solve the given cube using the given solver and options. | 301 | Solve the given cube using the given solver and options. |
| 297 | 302 | ||
| 298 | Parameters: | 303 | Parameters: |
| 299 | cube - The cube to solver. | 304 | cube - The cube to solver. |
| 300 | solver - The name of the solver. | 305 | solver - The name of the solver. |
| 301 | nissflag - The flags for NISS (linear, inverse, mixed, or combinations). | 306 | nissflag - The flags for NISS (linear, inverse, mixed, or |
| 302 | minmoves - The minimum number of moves for a solution. | 307 | combinations; see the constants at the top of this file). |
| 303 | maxmoves - The maximum number of moves for a solution. | 308 | minmoves - The minimum number of moves for a solution. |
| 304 | maxsols - The maximum number of solutions. | 309 | maxmoves - The maximum number of moves for a solution. |
| 305 | optimal - The maximum number of moves above the optimal solution length. | 310 | maxsols - The maximum number of solutions. |
| 306 | threads - The number of threads to use. Must be less than or equalt to | 311 | optimal - The maximum number of moves above the optimal solution. |
| 307 | the value of the compile-time constant THREADS. If set to 0, | 312 | threads - The number of threads to use. Must be less than or equal |
| 308 | the default value THREADS will be used. | 313 | to the value of the compile-time constant THREADS. If set |
| 309 | data_size - The size of the data buffer. | 314 | to 0, the default value THREADS will be used. |
| 310 | data - The data for the solver. Can be computed with gendata. | 315 | data_size - The size of the data buffer. |
| 311 | This buffer must have 8-byte alignment. | 316 | data - The data for the solver. Can be computed with gendata. |
| 312 | sols_size - The size of the solutions buffer. | 317 | This buffer must have 8-byte alignment. |
| 313 | sols - The return parameter for the solutions. The solutions are | 318 | sols_size - The size of the solutions buffer. |
| 314 | separated by a '\n' (newline) and a '\0' (NULL character) | 319 | sols - The return parameter for the solutions. The solutions are |
| 315 | terminates the list. | 320 | separated by a '\n' (newline) and a '\0' (NULL character) |
| 316 | stats - An array to store some statistics about the solve. | 321 | terminates the list. |
| 322 | stats - An array to store some statistics about the solve. | ||
| 323 | poll_status - A callback function that should return the current | ||
| 324 | requested status for the solver (e.g. run, stop, pause, | ||
| 325 | resume; see the constants at the top of this file). The | ||
| 326 | way this status is polled and honored is solver-specific. | ||
| 327 | If this parameter is NULL, the status will always assumed | ||
| 328 | to be "run". | ||
| 329 | poll_status_data - Auxiliary data for the poll_status callback function. | ||
| 317 | 330 | ||
| 318 | Return values: | 331 | Return values: |
| 319 | NISSY_OK - Cube solved succesfully. | 332 | NISSY_OK - Cube solved succesfully. |
| @@ -340,7 +353,9 @@ nissy_solve( | |||
| 340 | const unsigned char data[data_size], | 353 | const unsigned char data[data_size], |
| 341 | unsigned sols_size, | 354 | unsigned sols_size, |
| 342 | char sols[sols_size], | 355 | char sols[sols_size], |
| 343 | long long stats[static NISSY_SIZE_SOLVE_STATS] | 356 | long long stats[static NISSY_SIZE_SOLVE_STATS], |
| 357 | int (*poll_status)(void *), | ||
| 358 | void *poll_status_data | ||
| 344 | ); | 359 | ); |
| 345 | 360 | ||
| 346 | /* | 361 | /* |
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h index 48cc704..8eb3e9d 100644 --- a/src/solvers/coord/solve.h +++ b/src/solvers/coord/solve.h | |||
| @@ -14,10 +14,10 @@ typedef struct { | |||
| 14 | 14 | ||
| 15 | STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t, | 15 | STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t, |
| 16 | uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, | 16 | uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, |
| 17 | const unsigned char *, size_t n, char [n]); | 17 | const unsigned char *, size_t n, char [n], int (*)(void *), void *); |
| 18 | STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t, | 18 | STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t, |
| 19 | uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, | 19 | uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, |
| 20 | const unsigned char *, size_t n, char [n]); | 20 | const unsigned char *, size_t n, char [n], int (*)(void *), void *); |
| 21 | STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); | 21 | STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); |
| 22 | STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); | 22 | STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); |
| 23 | STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); | 23 | STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); |
| @@ -211,7 +211,9 @@ solve_coord_dispatch( | |||
| 211 | uint64_t data_size, | 211 | uint64_t data_size, |
| 212 | const unsigned char *data, | 212 | const unsigned char *data, |
| 213 | size_t solutions_size, | 213 | size_t solutions_size, |
| 214 | char sols[solutions_size] | 214 | char sols[solutions_size], |
| 215 | int (*poll_status)(void *), | ||
| 216 | void *poll_status_data | ||
| 215 | ) | 217 | ) |
| 216 | { | 218 | { |
| 217 | coord_t *coord; | 219 | coord_t *coord; |
| @@ -233,7 +235,7 @@ solve_coord_dispatch( | |||
| 233 | 235 | ||
| 234 | return solve_coord(oc, coord, axis, nissflag, minmoves, maxmoves, | 236 | return solve_coord(oc, coord, axis, nissflag, minmoves, maxmoves, |
| 235 | maxsolutions, optimal, threads, data_size, data, | 237 | maxsolutions, optimal, threads, data_size, data, |
| 236 | solutions_size, sols); | 238 | solutions_size, sols, poll_status, poll_status_data); |
| 237 | } | 239 | } |
| 238 | 240 | ||
| 239 | STATIC int64_t | 241 | STATIC int64_t |
| @@ -250,7 +252,9 @@ solve_coord( | |||
| 250 | uint64_t data_size, | 252 | uint64_t data_size, |
| 251 | const unsigned char *data, | 253 | const unsigned char *data, |
| 252 | size_t solutions_size, | 254 | size_t solutions_size, |
| 253 | char sols[solutions_size] | 255 | char sols[solutions_size], |
| 256 | int (*poll_status)(void *), | ||
| 257 | void *poll_status_data | ||
| 254 | ) | 258 | ) |
| 255 | { | 259 | { |
| 256 | int8_t d; | 260 | int8_t d; |
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h index e3ef9b9..f2967ed 100644 --- a/src/solvers/h48/solve.h +++ b/src/solvers/h48/solve.h | |||
| @@ -35,6 +35,10 @@ typedef struct { | |||
| 35 | solve_h48_task_t *tasks; | 35 | solve_h48_task_t *tasks; |
| 36 | int thread_id; | 36 | int thread_id; |
| 37 | pthread_mutex_t *solutions_mutex; | 37 | pthread_mutex_t *solutions_mutex; |
| 38 | int (*poll_status)(void *); | ||
| 39 | void *poll_status_data; | ||
| 40 | _Atomic bool cancelled; | ||
| 41 | _Atomic bool cantsleep; | ||
| 38 | } dfsarg_solve_h48_t; | 42 | } dfsarg_solve_h48_t; |
| 39 | 43 | ||
| 40 | typedef struct { | 44 | typedef struct { |
| @@ -50,11 +54,12 @@ STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); | |||
| 50 | STATIC int64_t solve_h48_maketasks( | 54 | STATIC int64_t solve_h48_maketasks( |
| 51 | dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], | 55 | dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], |
| 52 | solve_h48_task_t [static STARTING_CUBES], int [static 1]); | 56 | solve_h48_task_t [static STARTING_CUBES], int [static 1]); |
| 57 | STATIC bool solve_h48_runthread_continue(dfsarg_solve_h48_t *); | ||
| 53 | STATIC void *solve_h48_runthread(void *); | 58 | STATIC void *solve_h48_runthread(void *); |
| 54 | STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); | 59 | STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); |
| 55 | STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, | 60 | STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, |
| 56 | uint8_t, uint64_t, const unsigned char *, size_t n, char [n], | 61 | uint8_t, uint64_t, const unsigned char *, size_t n, char [n], |
| 57 | long long [static NISSY_SIZE_SOLVE_STATS]); | 62 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); |
| 58 | 63 | ||
| 59 | STATIC_INLINE bool | 64 | STATIC_INLINE bool |
| 60 | solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) | 65 | solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) |
| @@ -232,16 +237,42 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 232 | return ret; | 237 | return ret; |
| 233 | } | 238 | } |
| 234 | 239 | ||
| 240 | STATIC bool | ||
| 241 | solve_h48_runthread_continue(dfsarg_solve_h48_t *arg) | ||
| 242 | { | ||
| 243 | int status; | ||
| 244 | |||
| 245 | for (status = NISSY_STATUS_PAUSE; status == NISSY_STATUS_PAUSE; ) { | ||
| 246 | status = arg->poll_status == NULL ? NISSY_STATUS_RUN : | ||
| 247 | arg->poll_status(arg->poll_status_data); | ||
| 248 | msleep(500); | ||
| 249 | } | ||
| 250 | |||
| 251 | return status == NISSY_STATUS_RUN; | ||
| 252 | } | ||
| 253 | |||
| 235 | STATIC void * | 254 | STATIC void * |
| 236 | solve_h48_runthread(void *arg) | 255 | solve_h48_runthread(void *arg) |
| 237 | { | 256 | { |
| 238 | int i, j; | 257 | int i, j, status; |
| 239 | solve_h48_task_t task; | 258 | solve_h48_task_t task; |
| 240 | dfsarg_solve_h48_t *dfsarg; | 259 | dfsarg_solve_h48_t *dfsarg; |
| 241 | 260 | ||
| 242 | dfsarg = (dfsarg_solve_h48_t *)arg; | 261 | dfsarg = (dfsarg_solve_h48_t *)arg; |
| 243 | 262 | ||
| 244 | for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) { | 263 | for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) { |
| 264 | status = dfsarg->poll_status == NULL ? NISSY_STATUS_RUN : | ||
| 265 | dfsarg->poll_status(dfsarg->poll_status_data); | ||
| 266 | switch (status) { | ||
| 267 | case NISSY_STATUS_STOP: | ||
| 268 | goto solve_h48_runthread_cancel; | ||
| 269 | case NISSY_STATUS_PAUSE: | ||
| 270 | if (!NISSY_CANSLEEP) | ||
| 271 | goto solve_h48_runthread_cantsleep; | ||
| 272 | if (!solve_h48_runthread_continue(dfsarg)) | ||
| 273 | goto solve_h48_runthread_cancel; | ||
| 274 | } | ||
| 275 | |||
| 245 | task = dfsarg->tasks[i]; | 276 | task = dfsarg->tasks[i]; |
| 246 | 277 | ||
| 247 | solution_moves_reset(dfsarg->solution_moves); | 278 | solution_moves_reset(dfsarg->solution_moves); |
| @@ -265,6 +296,12 @@ solve_h48_runthread(void *arg) | |||
| 265 | } | 296 | } |
| 266 | 297 | ||
| 267 | return NULL; | 298 | return NULL; |
| 299 | |||
| 300 | solve_h48_runthread_cantsleep: | ||
| 301 | dfsarg->cantsleep = true; | ||
| 302 | solve_h48_runthread_cancel: | ||
| 303 | dfsarg->cancelled = true; | ||
| 304 | return NULL; | ||
| 268 | } | 305 | } |
| 269 | 306 | ||
| 270 | STATIC int64_t | 307 | STATIC int64_t |
| @@ -351,9 +388,12 @@ solve_h48( | |||
| 351 | const unsigned char *data, | 388 | const unsigned char *data, |
| 352 | size_t solutions_size, | 389 | size_t solutions_size, |
| 353 | char solutions[solutions_size], | 390 | char solutions[solutions_size], |
| 354 | long long stats[static NISSY_SIZE_SOLVE_STATS] | 391 | long long stats[static NISSY_SIZE_SOLVE_STATS], |
| 392 | int (*poll_status)(void *), | ||
| 393 | void *poll_status_data | ||
| 355 | ) | 394 | ) |
| 356 | { | 395 | { |
| 396 | bool anycancelled, anycantsleep; | ||
| 357 | int i, ntasks, eoesep_table_index; | 397 | int i, ntasks, eoesep_table_index; |
| 358 | int8_t d; | 398 | int8_t d; |
| 359 | dfsarg_solve_h48_t arg[THREADS]; | 399 | dfsarg_solve_h48_t arg[THREADS]; |
| @@ -434,6 +474,10 @@ solve_h48( | |||
| 434 | .threads = threads, | 474 | .threads = threads, |
| 435 | .thread_id = i, | 475 | .thread_id = i, |
| 436 | .solutions_mutex = &solutions_mutex, | 476 | .solutions_mutex = &solutions_mutex, |
| 477 | .poll_status = poll_status, | ||
| 478 | .poll_status_data = poll_status_data, | ||
| 479 | .cancelled = false, | ||
| 480 | .cantsleep = false, | ||
| 437 | }; | 481 | }; |
| 438 | 482 | ||
| 439 | } | 483 | } |
| @@ -460,9 +504,10 @@ solve_h48( | |||
| 460 | 504 | ||
| 461 | LOG("[H48 solve] Prepared %d tasks\n", ntasks); | 505 | LOG("[H48 solve] Prepared %d tasks\n", ntasks); |
| 462 | 506 | ||
| 507 | anycancelled = anycantsleep = false; | ||
| 463 | for ( | 508 | for ( |
| 464 | d = MAX(minmoves, STARTING_MOVES + 1); | 509 | d = MAX(minmoves, STARTING_MOVES + 1); |
| 465 | !solutions_done(&sollist, &settings, d); | 510 | !(solutions_done(&sollist, &settings, d) || anycancelled); |
| 466 | d++ | 511 | d++ |
| 467 | ) { | 512 | ) { |
| 468 | if (d >= 15) | 513 | if (d >= 15) |
| @@ -474,8 +519,22 @@ solve_h48( | |||
| 474 | pthread_create( | 519 | pthread_create( |
| 475 | &thread[i], NULL, solve_h48_runthread, &arg[i]); | 520 | &thread[i], NULL, solve_h48_runthread, &arg[i]); |
| 476 | } | 521 | } |
| 477 | for (i = 0; i < threads; i++) | 522 | for (i = 0; i < threads; i++) { |
| 478 | pthread_join(thread[i], NULL); | 523 | pthread_join(thread[i], NULL); |
| 524 | anycancelled = anycancelled || arg[i].cancelled; | ||
| 525 | anycantsleep = anycantsleep || arg[i].cantsleep; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | if (anycantsleep) { | ||
| 530 | LOG("[H48 solve] Received pause request, but this feature is " | ||
| 531 | "not available on this system. " | ||
| 532 | "Taking it as a stop request.\n"); | ||
| 533 | } | ||
| 534 | |||
| 535 | if (anycancelled) { | ||
| 536 | LOG("[H48 solve] Received stop request, ending solution " | ||
| 537 | "search early.\n"); | ||
| 479 | } | 538 | } |
| 480 | 539 | ||
| 481 | solve_h48_done: | 540 | solve_h48_done: |
diff --git a/src/utils/sleep.h b/src/utils/sleep.h new file mode 100644 index 0000000..d618e9b --- /dev/null +++ b/src/utils/sleep.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | STATIC void msleep(int); | ||
| 2 | |||
| 3 | #if defined(WIN32) | ||
| 4 | |||
| 5 | #define NISSY_CANSLEEP true | ||
| 6 | |||
| 7 | STATIC void | ||
| 8 | msleep(int milliseconds) | ||
| 9 | { | ||
| 10 | Sleep(milliseconds); | ||
| 11 | } | ||
| 12 | |||
| 13 | #elif defined(__wasm__) | ||
| 14 | |||
| 15 | #include <emscripten.h> | ||
| 16 | |||
| 17 | #define NISSY_CANSLEEP true | ||
| 18 | |||
| 19 | STATIC void | ||
| 20 | msleep(int milliseconds) | ||
| 21 | { | ||
| 22 | emscripten_sleep(milliseconds); | ||
| 23 | } | ||
| 24 | |||
| 25 | #elif defined(__unix__) | ||
| 26 | |||
| 27 | #include <time.h> | ||
| 28 | |||
| 29 | #define NISSY_CANSLEEP true | ||
| 30 | |||
| 31 | STATIC void | ||
| 32 | msleep(int milliseconds) | ||
| 33 | { | ||
| 34 | struct timespec t; | ||
| 35 | t.tv_sec = milliseconds / 1000; | ||
| 36 | t.tv_nsec = (milliseconds % 1000) * 1000000; | ||
| 37 | nanosleep(&t, NULL); | ||
| 38 | } | ||
| 39 | |||
| 40 | #else | ||
| 41 | |||
| 42 | #define NISSY_CANSLEEP false | ||
| 43 | STATIC void | ||
| 44 | msleep(int milliseconds) | ||
| 45 | { | ||
| 46 | } | ||
| 47 | |||
| 48 | #endif | ||
diff --git a/src/utils/utils.h b/src/utils/utils.h index ce4355e..d14b285 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include "dbg_log.h" | 1 | #include "dbg_log.h" |
| 2 | #include "constants.h" | 2 | #include "constants.h" |
| 3 | #include "math.h" | 3 | #include "math.h" |
| 4 | #include "sleep.h" | ||
diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c index dcd47c1..83a712a 100644 --- a/tools/300_solve_small/solve_small.c +++ b/tools/300_solve_small/solve_small.c | |||
| @@ -37,7 +37,8 @@ void run(void) { | |||
| 37 | continue; | 37 | continue; |
| 38 | } | 38 | } |
| 39 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, | 39 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, |
| 40 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats); | 40 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats, |
| 41 | NULL, NULL); | ||
| 41 | if (n == 0) | 42 | if (n == 0) |
| 42 | printf("No solution found\n"); | 43 | printf("No solution found\n"); |
| 43 | else | 44 | else |
diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c index d9084fd..be4d1f5 100644 --- a/tools/301_solve_file/solve_file.c +++ b/tools/301_solve_file/solve_file.c | |||
| @@ -24,7 +24,8 @@ void run(void) { | |||
| 24 | continue; | 24 | continue; |
| 25 | } | 25 | } |
| 26 | nsols = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, | 26 | nsols = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, |
| 27 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats); | 27 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats, |
| 28 | NULL, NULL); | ||
| 28 | if (nsols == 0) | 29 | if (nsols == 0) |
| 29 | printf("No solution found\n"); | 30 | printf("No solution found\n"); |
| 30 | else | 31 | else |
diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c index a2896a9..8f04b5f 100644 --- a/tools/302_solve_multisol/solve_multisol.c +++ b/tools/302_solve_multisol/solve_multisol.c | |||
| @@ -30,7 +30,8 @@ void run(void) { | |||
| 30 | continue; | 30 | continue; |
| 31 | } | 31 | } |
| 32 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, | 32 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, |
| 33 | 0, 20, nsol, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats); | 33 | 0, 20, nsol, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats, |
| 34 | NULL, NULL); | ||
| 34 | if (n == 0) | 35 | if (n == 0) |
| 35 | printf("No solution found\n"); | 36 | printf("No solution found\n"); |
| 36 | else | 37 | else |
diff --git a/tools/400_solvetest/solve_test.c b/tools/400_solvetest/solve_test.c index 1bfe851..73e6e8e 100644 --- a/tools/400_solvetest/solve_test.c +++ b/tools/400_solvetest/solve_test.c | |||
| @@ -57,7 +57,8 @@ void run(void) { | |||
| 57 | continue; | 57 | continue; |
| 58 | } | 58 | } |
| 59 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, | 59 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, |
| 60 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats); | 60 | 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats, |
| 61 | NULL, NULL); | ||
| 61 | if (n == 0) { | 62 | if (n == 0) { |
| 62 | printf("Error: no solution\n"); | 63 | printf("Error: no solution\n"); |
| 63 | return; | 64 | return; |
| @@ -78,7 +79,8 @@ void run(void) { | |||
| 78 | continue; | 79 | continue; |
| 79 | } | 80 | } |
| 80 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, | 81 | n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, |
| 81 | 0, 20, 100, 0, 0, size, buf, SOL_BUFFER_LEN, sol, stats); | 82 | 0, 20, 100, 0, 0, size, buf, SOL_BUFFER_LEN, sol, stats, |
| 83 | NULL, NULL); | ||
| 82 | if (check_all(sol, s[i].solutions)) { | 84 | if (check_all(sol, s[i].solutions)) { |
| 83 | printf("All solutions are correct\n"); | 85 | printf("All solutions are correct\n"); |
| 84 | } else { | 86 | } else { |
