moves.h (5589B)
1 #define MOVE(M, c) compose(c, MOVE_CUBE_ ## M) 2 #define PREMOVE(M, c) compose(MOVE_CUBE_ ## M, c) 3 4 STATIC_INLINE bool allowednextmove(uint8_t *, uint8_t); 5 6 STATIC_INLINE uint8_t inverse_trans(uint8_t); 7 STATIC_INLINE uint8_t movebase(uint8_t); 8 STATIC_INLINE uint8_t moveaxis(uint8_t); 9 STATIC_INLINE uint32_t disable_moves(uint32_t, uint8_t); 10 11 STATIC cube_t move(cube_t, uint8_t); 12 STATIC cube_t premove(cube_t, uint8_t); 13 STATIC uint8_t inverse_move(uint8_t); 14 STATIC void invertmoves(uint8_t *, uint8_t, uint8_t *); 15 16 STATIC int readmoves(const char *, int, uint8_t *); 17 STATIC cube_t applymoves(cube_t, const char *); 18 STATIC cube_t frommoves(const char *); 19 20 #define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ 21 LABEL_ERROR, ARG_ACTION) \ 22 const char *VAR_B; \ 23 uint8_t VAR_MOVE_NOMOD, VAR_MOD; \ 24 for (VAR_B = ARG_BUF, ARG_C = 0; *VAR_B != '\0'; VAR_B++, ARG_C++) { \ 25 while (*VAR_B == ' ' || *VAR_B == '\t' || *VAR_B == '\n') \ 26 VAR_B++; \ 27 if (*VAR_B == '\0' || ARG_C == ARG_MAX) \ 28 break; \ 29 if ((VAR_MOVE_NOMOD = readmove(*VAR_B)) == UINT8_ERROR) \ 30 goto LABEL_ERROR; \ 31 if ((VAR_MOD = readmodifier(*(VAR_B+1))) != 0) \ 32 VAR_B++; \ 33 ARG_MOVE = VAR_MOVE_NOMOD + VAR_MOD; \ 34 ARG_ACTION \ 35 } 36 37 STATIC bool 38 allowednextmove(uint8_t *moves, uint8_t n) 39 { 40 uint8_t base[3], axis[3]; 41 42 if (n < 2) 43 return true; 44 45 base[0] = movebase(moves[n-1]); 46 axis[0] = moveaxis(moves[n-1]); 47 base[1] = movebase(moves[n-2]); 48 axis[1] = moveaxis(moves[n-2]); 49 50 if (base[0] == base[1] || (axis[0] == axis[1] && base[0] < base[1])) 51 return false; 52 53 if (n == 2) 54 return true; 55 56 base[2] = movebase(moves[n-3]); 57 axis[2] = moveaxis(moves[n-3]); 58 59 return axis[1] != axis[2] || base[0] != base[2]; 60 } 61 62 STATIC_INLINE uint32_t 63 disable_moves(uint32_t current_result, uint8_t base_index) 64 { 65 return current_result & ~(7 << base_index); 66 } 67 68 STATIC_INLINE uint8_t 69 inverse_trans(uint8_t t) 70 { 71 return inverse_trans_table[t]; 72 } 73 74 STATIC_INLINE uint8_t 75 movebase(uint8_t move) 76 { 77 return move / 3; 78 } 79 80 STATIC_INLINE uint8_t 81 moveaxis(uint8_t move) 82 { 83 return move / 6; 84 } 85 86 STATIC cube_t 87 move(cube_t c, uint8_t m) 88 { 89 switch (m) { 90 case MOVE_U: 91 return MOVE(U, c); 92 case MOVE_U2: 93 return MOVE(U2, c); 94 case MOVE_U3: 95 return MOVE(U3, c); 96 case MOVE_D: 97 return MOVE(D, c); 98 case MOVE_D2: 99 return MOVE(D2, c); 100 case MOVE_D3: 101 return MOVE(D3, c); 102 case MOVE_R: 103 return MOVE(R, c); 104 case MOVE_R2: 105 return MOVE(R2, c); 106 case MOVE_R3: 107 return MOVE(R3, c); 108 case MOVE_L: 109 return MOVE(L, c); 110 case MOVE_L2: 111 return MOVE(L2, c); 112 case MOVE_L3: 113 return MOVE(L3, c); 114 case MOVE_F: 115 return MOVE(F, c); 116 case MOVE_F2: 117 return MOVE(F2, c); 118 case MOVE_F3: 119 return MOVE(F3, c); 120 case MOVE_B: 121 return MOVE(B, c); 122 case MOVE_B2: 123 return MOVE(B2, c); 124 case MOVE_B3: 125 return MOVE(B3, c); 126 default: 127 LOG("move error, unknown move\n"); 128 return ZERO_CUBE; 129 } 130 } 131 132 /* Applies the INVERSE of m BEFORE the scramble corresponding to c */ 133 STATIC cube_t 134 premove(cube_t c, uint8_t m) 135 { 136 switch (m) { 137 case MOVE_U: 138 return PREMOVE(U3, c); 139 case MOVE_U2: 140 return PREMOVE(U2, c); 141 case MOVE_U3: 142 return PREMOVE(U, c); 143 case MOVE_D: 144 return PREMOVE(D3, c); 145 case MOVE_D2: 146 return PREMOVE(D2, c); 147 case MOVE_D3: 148 return PREMOVE(D, c); 149 case MOVE_R: 150 return PREMOVE(R3, c); 151 case MOVE_R2: 152 return PREMOVE(R2, c); 153 case MOVE_R3: 154 return PREMOVE(R, c); 155 case MOVE_L: 156 return PREMOVE(L3, c); 157 case MOVE_L2: 158 return PREMOVE(L2, c); 159 case MOVE_L3: 160 return PREMOVE(L, c); 161 case MOVE_F: 162 return PREMOVE(F3, c); 163 case MOVE_F2: 164 return PREMOVE(F2, c); 165 case MOVE_F3: 166 return PREMOVE(F, c); 167 case MOVE_B: 168 return PREMOVE(B3, c); 169 case MOVE_B2: 170 return PREMOVE(B2, c); 171 case MOVE_B3: 172 return PREMOVE(B, c); 173 default: 174 LOG("move error, unknown move\n"); 175 return ZERO_CUBE; 176 } 177 } 178 179 STATIC uint8_t 180 inverse_move(uint8_t m) 181 { 182 return m - 2 * (m % 3) + 2; 183 } 184 185 /* 186 GCC has issues when -Wstringop-overflow is used together with O3. It produces 187 warnings like the following: 188 189 In function 'invertmoves', 190 inlined from 'solve_h48_appendsolution' at src/solvers/h48/solve.h:81:3, 191 inlined from 'solve_h48_dfs.isra' at src/solvers/h48/solve.h:139:3: 192 warning: writing 32 bytes into a region of size 0 [-Wstringop-overflow=] 193 197 | ret[i] = inverse_move(moves[nmoves - i - 1]); 194 | ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195 In function 'solve_h48_dfs.isra': 196 note: at offset 192 into destination object 'invertedpremoves' of size 20 197 71 | uint8_t invertedpremoves[MAXLEN]; 198 199 Clang does not give any warning. 200 Someone else complained here: https://access.redhat.com/solutions/6755371 201 202 To solve this issue temporarily, we use a lower optimization setting for 203 this function only. 204 205 TODO check if the issue is resolved 206 */ 207 #pragma GCC push_options 208 #pragma GCC optimize ("O2") 209 STATIC void 210 invertmoves(uint8_t *moves, uint8_t nmoves, uint8_t *ret) 211 { 212 uint8_t i; 213 214 for (i = 0; i < nmoves; i++) 215 ret[i] = inverse_move(moves[nmoves - i - 1]); 216 } 217 #pragma GCC pop_options 218 219 STATIC int 220 readmoves(const char *buf, int max, uint8_t *ret) 221 { 222 uint8_t m; 223 int c; 224 225 FOREACH_READMOVE(buf, m, c, max, readmoves_error, 226 ret[c] = m; 227 ) 228 229 return c; 230 231 readmoves_error: 232 LOG("readmoves error\n"); 233 return -1; 234 } 235 236 STATIC cube_t 237 applymoves(cube_t cube, const char *buf) 238 { 239 int c; 240 uint8_t m; 241 242 DBG_ASSERT(isconsistent(cube), ZERO_CUBE, 243 "move error: inconsistent cube\n"); 244 245 FOREACH_READMOVE(buf, m, c, -1, applymoves_error, 246 cube = move(cube, m); 247 ) 248 249 return cube; 250 251 applymoves_error: 252 LOG("applymoves error\n"); 253 return ZERO_CUBE; 254 } 255 256 STATIC cube_t 257 frommoves(const char *buf) 258 { 259 return applymoves(SOLVED_CUBE, buf); 260 }