aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-03-24 23:09:26 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2025-03-24 23:09:26 +0100
commitd45e1595ec1cffeab83ac6602b748250b66bea03 (patch)
tree44b35714cdae22026fc5e15648e91684a2fbb154 /src/core
parentce3f1cc0ef9f46d70ab5387b1458e9098b40711d (diff)
downloadnissy-core-d45e1595ec1cffeab83ac6602b748250b66bea03.tar.gz
nissy-core-d45e1595ec1cffeab83ac6602b748250b66bea03.zip
Big cleanup for appendsolution()
With this PR the appendsolution routine is extracted from the h48 solver and the new coordinate solver and made generic. This has many advantages: - less repetition (even if the two versions are different enough that *for now* it was not a big deal) - smaller h48/solve.h file, which is already a big beast - easier to test the appendsolution() routine separately
Diffstat (limited to 'src/core')
-rw-r--r--src/core/io_moves.h41
-rw-r--r--src/core/moves.h68
2 files changed, 55 insertions, 54 deletions
diff --git a/src/core/io_moves.h b/src/core/io_moves.h
index fa91e8b..8c56a9f 100644
--- a/src/core/io_moves.h
+++ b/src/core/io_moves.h
@@ -1,6 +1,26 @@
1STATIC uint8_t readmove(char); 1STATIC uint8_t readmove(char);
2STATIC int64_t readmoves(const char *, size_t n, uint8_t [n]);
2STATIC uint8_t readmodifier(char); 3STATIC uint8_t readmodifier(char);
3STATIC int64_t writemoves(size_t n, uint8_t [n], size_t m, char [m]); 4STATIC int64_t writemoves(size_t n, const uint8_t [n], size_t m, char [m]);
5
6#define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \
7 RET_ERROR, ARG_ACTION) \
8 const char *VAR_B; \
9 uint8_t VAR_MOVE_NOMOD, VAR_MOD; \
10 for (VAR_B = ARG_BUF, ARG_C = 0; *VAR_B != '\0'; VAR_B++, ARG_C++) { \
11 while (*VAR_B == ' ' || *VAR_B == '\t' || *VAR_B == '\n') \
12 VAR_B++; \
13 if (*VAR_B == '\0' || ARG_C == ARG_MAX) \
14 break; \
15 if ((VAR_MOVE_NOMOD = readmove(*VAR_B)) == UINT8_ERROR) { \
16 LOG("Error: unknown move '%c'\n", *VAR_B); \
17 return RET_ERROR; \
18 } \
19 if ((VAR_MOD = readmodifier(*(VAR_B+1))) != 0) \
20 VAR_B++; \
21 ARG_MOVE = VAR_MOVE_NOMOD + VAR_MOD; \
22 ARG_ACTION \
23 }
4 24
5STATIC uint8_t 25STATIC uint8_t
6readmove(char c) 26readmove(char c)
@@ -39,9 +59,22 @@ readmodifier(char c)
39} 59}
40 60
41STATIC int64_t 61STATIC int64_t
62readmoves(const char *buf, size_t n, uint8_t ret[n])
63{
64 uint8_t m;
65 uint64_t c;
66
67 FOREACH_READMOVE(buf, m, c, n, NISSY_ERROR_INVALID_MOVES,
68 ret[c] = m;
69 )
70
71 return (int64_t)c;
72}
73
74STATIC int64_t
42writemoves( 75writemoves(
43 size_t nmoves, 76 size_t nmoves,
44 uint8_t m[nmoves], 77 const uint8_t m[nmoves],
45 size_t buf_size, 78 size_t buf_size,
46 char buf[buf_size] 79 char buf[buf_size]
47) 80)
@@ -69,7 +102,9 @@ writemoves(
69 *b = ' '; 102 *b = ' ';
70 } 103 }
71 104
72 if (b != buf) 105 if (b == buf)
106 written = 1; /* Nothing written, only NULL-terminator */
107 else
73 b--; /* Remove last space */ 108 b--; /* Remove last space */
74 *b = '\0'; 109 *b = '\0';
75 110
diff --git a/src/core/moves.h b/src/core/moves.h
index 820406b..e56d5c8 100644
--- a/src/core/moves.h
+++ b/src/core/moves.h
@@ -3,6 +3,7 @@
3 3
4STATIC_INLINE bool allowednextmove(size_t n, const uint8_t [n]); 4STATIC_INLINE bool allowednextmove(size_t n, const uint8_t [n]);
5STATIC_INLINE uint32_t allowednextmove_mask(size_t n, const uint8_t [n]); 5STATIC_INLINE uint32_t allowednextmove_mask(size_t n, const uint8_t [n]);
6STATIC bool allowedmoves(size_t n, const uint8_t [n]);
6 7
7STATIC_INLINE uint8_t movebase(uint8_t); 8STATIC_INLINE uint8_t movebase(uint8_t);
8STATIC_INLINE uint8_t moveaxis(uint8_t); 9STATIC_INLINE uint8_t moveaxis(uint8_t);
@@ -13,11 +14,9 @@ STATIC_INLINE uint32_t disable_moves(uint32_t, uint8_t);
13STATIC cube_t move(cube_t, uint8_t); 14STATIC cube_t move(cube_t, uint8_t);
14STATIC cube_t premove(cube_t, uint8_t); 15STATIC cube_t premove(cube_t, uint8_t);
15STATIC uint8_t inverse_move(uint8_t); 16STATIC uint8_t inverse_move(uint8_t);
16STATIC void invertmoves(size_t n, const uint8_t [n], uint8_t [n]); 17STATIC void sortparallel_moves(size_t n, uint8_t [n]);
17STATIC void sortparallel(size_t n, uint8_t [n]);
18STATIC bool are_lastmoves_singlecw(size_t n, uint8_t [n]); 18STATIC bool are_lastmoves_singlecw(size_t n, uint8_t [n]);
19 19
20STATIC int readmoves(const char *, int, uint8_t *);
21STATIC cube_t applymoves(cube_t, const char *); 20STATIC cube_t applymoves(cube_t, const char *);
22 21
23#define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ 22#define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \
@@ -75,6 +74,18 @@ allowednextmove_mask(size_t n, const uint8_t moves[n])
75 return result; 74 return result;
76} 75}
77 76
77STATIC bool
78allowedmoves(size_t n, const uint8_t moves[n])
79{
80 uint8_t j;
81
82 for (j = 2; j < n; j++)
83 if (!allowednextmove(j, moves))
84 return false;
85
86 return true;
87}
88
78STATIC_INLINE uint32_t 89STATIC_INLINE uint32_t
79disable_moves(uint32_t current_result, uint8_t base_index) 90disable_moves(uint32_t current_result, uint8_t base_index)
80{ 91{
@@ -210,44 +221,13 @@ inverse_move(uint8_t m)
210 return m - 2 * (m % 3) + 2; 221 return m - 2 * (m % 3) + 2;
211} 222}
212 223
213/*
214GCC has issues when -Wstringop-overflow is used together with O3. It produces
215warnings like the following:
216
217In function 'invertmoves',
218 inlined from 'solve_h48_appendsolution' at src/solvers/h48/solve.h:81:3,
219 inlined from 'solve_h48_dfs.isra' at src/solvers/h48/solve.h:139:3:
220warning: writing 32 bytes into a region of size 0 [-Wstringop-overflow=]
221 197 | ret[i] = inverse_move(moves[nmoves - i - 1]);
222 | ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223In function 'solve_h48_dfs.isra':
224note: at offset 192 into destination object 'invertedpremoves' of size 20
225 71 | uint8_t invertedpremoves[MAXLEN];
226
227Clang does not give any warning.
228Someone else complained here: https://access.redhat.com/solutions/6755371
229
230To solve this issue temporarily, we use a lower optimization setting for
231this function only.
232
233TODO check if the issue is resolved
234*/
235#pragma GCC push_options
236#pragma GCC optimize ("O2")
237STATIC void 224STATIC void
238invertmoves(size_t n, const uint8_t moves[n], uint8_t ret[n]) 225sortparallel_moves(size_t n, uint8_t moves[n])
239{ 226{
240 uint8_t i; 227 uint8_t i;
241 228
242 for (i = 0; i < n; i++) 229 if (n < 2)
243 ret[i] = inverse_move(moves[n - i - 1]); 230 return;
244}
245#pragma GCC pop_options
246
247STATIC void
248sortparallel(size_t n, uint8_t moves[n])
249{
250 uint8_t i;
251 231
252 for (i = 0; i < n-1; i++) 232 for (i = 0; i < n-1; i++)
253 if (moveaxis(moves[i]) == moveaxis(moves[i+1]) && 233 if (moveaxis(moves[i]) == moveaxis(moves[i+1]) &&
@@ -268,20 +248,6 @@ are_lastmoves_singlecw(size_t n, uint8_t moves[n])
268 return isbase(moves[n-1]) && (!two || isbase(moves[n-2])); 248 return isbase(moves[n-1]) && (!two || isbase(moves[n-2]));
269} 249}
270 250
271STATIC int
272readmoves(const char *buf, int max, uint8_t *ret)
273{
274 uint8_t m;
275 int c;
276
277 FOREACH_READMOVE(buf, m, c, max, NISSY_ERROR_INVALID_MOVES,
278 if (ret != NULL)
279 ret[c] = m;
280 )
281
282 return c;
283}
284
285STATIC cube_t 251STATIC cube_t
286applymoves(cube_t cube, const char *buf) 252applymoves(cube_t cube, const char *buf)
287{ 253{

Generated with cgit - Back to sebastiano.tronto.net