coord.c (13242B)
1 #include "coord.h" 2 3 static uint64_t index_eofb(Cube cube); 4 static uint64_t index_eofbepos(Cube cube); 5 static uint64_t index_epud(Cube cube); 6 static uint64_t index_coud(Cube cube); 7 static uint64_t index_corners(Cube cube); 8 static uint64_t index_cp(Cube cube); 9 static uint64_t index_cphtr(Cube cube); 10 static uint64_t index_cornershtr(Cube cube); 11 static uint64_t index_cornershtrfin(Cube cube); 12 static uint64_t index_drud(Cube cube); 13 static uint64_t index_drud_eofb(Cube cube); 14 static uint64_t index_htr_drud(Cube cube); 15 static uint64_t index_htrfin(Cube cube); 16 static uint64_t index_cpud_separate(Cube cube); 17 18 static uint64_t move_eofb(Move m, uint64_t ind); 19 static uint64_t move_eofbepos(Move m, uint64_t ind); 20 static uint64_t move_epud(Move m, uint64_t ind); 21 static uint64_t move_coud(Move m, uint64_t ind); 22 static uint64_t move_corners(Move m, uint64_t ind); 23 static uint64_t move_cp(Move m, uint64_t ind); 24 static uint64_t move_cphtr(Move m, uint64_t ind); 25 static uint64_t move_cornershtr(Move m, uint64_t ind); 26 static uint64_t move_cornershtrfin(Move m, uint64_t ind); 27 static uint64_t move_drud(Move m, uint64_t ind); 28 static uint64_t move_drud_eofb(Move m, uint64_t ind); 29 static uint64_t move_htr_drud(Move m, uint64_t ind); 30 static uint64_t move_htrfin(Move m, uint64_t ind); 31 static uint64_t move_cpud_separate(Move m, uint64_t ind); 32 33 static void init_cphtr_cosets(void); 34 static void init_cphtr_left_cosets_bfs(int i, int c); 35 static void init_cphtr_right_cosets_color(int i, int c); 36 static void init_cpud_separate(void); 37 static void init_cornershtrfin(void); 38 static void init_htr_eposs(void); 39 static void init_move_epud(void); 40 static void init_move_cphtr(void); 41 42 43 /* All sorts of useful costants and tables **********************************/ 44 45 static int cphtr_left_cosets[FACTORIAL8]; 46 static int cphtr_right_cosets[FACTORIAL8]; 47 static int cphtr_right_rep[BINOM8ON4*6]; 48 int cpud_separate_ind[FACTORIAL8]; 49 int cpud_separate_ant[BINOM8ON4]; 50 static int cornershtrfin_ind[FACTORIAL8]; 51 int cornershtrfin_ant[24*24/6]; 52 static int htr_eposs_ind[BINOM12ON4]; 53 static int htr_eposs_ant[BINOM8ON4]; 54 static int move_cphtr_aux[NMOVES][BINOM8ON4*6]; 55 static int move_epud_aux[NMOVES][FACTORIAL8]; 56 57 /* Coordinates and their implementation **************************************/ 58 59 Coordinate 60 coord_eofb = { 61 .index = index_eofb, 62 .max = POW2TO11, 63 .move = move_eofb, 64 }; 65 66 Coordinate 67 coord_eofbepos = { 68 .index = index_eofbepos, 69 .max = POW2TO11 * BINOM12ON4, 70 .move = move_eofbepos, 71 }; 72 73 Coordinate 74 coord_coud = { 75 .index = index_coud, 76 .max = POW3TO7, 77 .move = move_coud, 78 }; 79 80 Coordinate 81 coord_corners = { 82 .index = index_corners, 83 .max = POW3TO7 * FACTORIAL8, 84 .move = move_corners, 85 }; 86 87 Coordinate 88 coord_cp = { 89 .index = index_cp, 90 .max = FACTORIAL8, 91 .move = move_cp, 92 }; 93 94 Coordinate 95 coord_cphtr = { 96 .index = index_cphtr, 97 .max = BINOM8ON4 * 6, 98 .move = move_cphtr, 99 }; 100 101 Coordinate 102 coord_cornershtr = { 103 .index = index_cornershtr, 104 .max = POW3TO7 * BINOM8ON4 * 6, 105 .move = move_cornershtr, 106 }; 107 108 Coordinate 109 coord_cornershtrfin = { 110 .index = index_cornershtrfin, 111 .max = 24*24/6, 112 .move = move_cornershtrfin, 113 }; 114 115 Coordinate 116 coord_epud = { 117 .index = index_epud, 118 .max = FACTORIAL8, 119 .move = move_epud, 120 }; 121 122 Coordinate 123 coord_drud = { 124 .index = index_drud, 125 .max = POW2TO11 * POW3TO7 * BINOM12ON4, 126 .move = move_drud, 127 }; 128 129 Coordinate 130 coord_htr_drud = { 131 .index = index_htr_drud, 132 .max = BINOM8ON4 * 6 * BINOM8ON4, 133 .move = move_htr_drud, 134 }; 135 136 Coordinate 137 coord_htrfin = { 138 .index = index_htrfin, 139 .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */ 140 .move = move_htrfin, 141 }; 142 143 Coordinate 144 coord_drud_eofb = { 145 .index = index_drud_eofb, 146 .max = POW3TO7 * BINOM12ON4, 147 .move = move_drud_eofb, 148 }; 149 150 Coordinate 151 coord_cpud_separate = { 152 .index = index_cpud_separate, 153 .max = BINOM8ON4, 154 .move = move_cpud_separate, 155 }; 156 157 /* Indexers ******************************************************************/ 158 159 static uint64_t 160 index_eofb(Cube cube) 161 { 162 return cube.eofb; 163 } 164 165 static uint64_t 166 index_eofbepos(Cube cube) 167 { 168 return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; 169 } 170 171 static uint64_t 172 index_epud(Cube cube) 173 { 174 uint64_t ret; 175 CubeArray *arr = new_cubearray(cube, pf_ep); 176 177 ret = perm_to_index(arr->ep, 8); 178 free_cubearray(arr, pf_ep); 179 180 return ret; 181 } 182 183 static uint64_t 184 index_coud(Cube cube) 185 { 186 return cube.coud; 187 } 188 189 static uint64_t 190 index_corners(Cube cube) 191 { 192 return cube.coud * FACTORIAL8 + cube.cp; 193 } 194 195 static uint64_t 196 index_cp(Cube cube) 197 { 198 return cube.cp; 199 } 200 201 static uint64_t 202 index_cphtr(Cube cube) 203 { 204 return cphtr_right_cosets[cube.cp]; 205 } 206 207 static uint64_t 208 index_cornershtr(Cube cube) 209 { 210 return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube); 211 } 212 213 static uint64_t 214 index_cornershtrfin(Cube cube) 215 { 216 return cornershtrfin_ind[cube.cp]; 217 } 218 219 static uint64_t 220 index_drud(Cube cube) 221 { 222 uint64_t a, b, c; 223 224 a = cube.eofb; 225 b = cube.coud; 226 c = cube.epose / FACTORIAL4; 227 228 b *= POW2TO11; 229 c *= POW2TO11 * POW3TO7; 230 231 return a + b + c; 232 } 233 234 static uint64_t 235 index_drud_eofb(Cube cube) 236 { 237 return index_drud(cube) / POW2TO11; 238 } 239 240 static uint64_t 241 index_htr_drud(Cube cube) 242 { 243 uint64_t a, b; 244 245 a = index_cphtr(cube); 246 b = htr_eposs_ind[cube.eposs/24]; 247 248 return a * BINOM8ON4 + b; 249 } 250 251 static uint64_t 252 index_htrfin(Cube cube) 253 { 254 uint64_t epe, eps, epm, cp, ep; 255 256 epe = cube.epose % 24; 257 eps = cube.eposs % 24; 258 epm = cube.eposm % 24; 259 ep = (epe * 24 + eps) *24 + epm; 260 cp = index_cornershtrfin(cube); 261 262 return cp * 24 * 24 * 24 + ep; 263 } 264 265 static uint64_t 266 index_cpud_separate(Cube cube) 267 { 268 return cpud_separate_ind[cube.cp]; 269 } 270 271 /* Coordinate movers *********************************************************/ 272 273 static uint64_t 274 move_eofb(Move m, uint64_t ind) 275 { 276 return eofb_mtable[m][ind]; 277 } 278 279 static uint64_t 280 move_eofbepos(Move m, uint64_t ind) 281 { 282 uint64_t a, b; 283 284 a = epose_mtable[m][(ind / POW2TO11)*24]; 285 b = eofb_mtable[m][ind % POW2TO11]; 286 287 return (a/24) * POW2TO11 + b; 288 } 289 290 static uint64_t 291 move_epud(Move m, uint64_t ind) 292 { 293 static int shortlist[NMOVES] = { 294 [U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5, 295 [R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9 296 }; 297 298 return move_epud_aux[shortlist[m]][ind]; 299 } 300 301 static uint64_t 302 move_coud(Move m, uint64_t ind) 303 { 304 return coud_mtable[m][ind]; 305 } 306 307 static uint64_t 308 move_corners(Move m, uint64_t ind) 309 { 310 uint64_t a, b; 311 312 a = coud_mtable[m][ind / FACTORIAL8]; 313 b = cp_mtable[m][ind % FACTORIAL8]; 314 315 return a * FACTORIAL8 + b; 316 } 317 318 static uint64_t 319 move_cp(Move m, uint64_t ind) 320 { 321 return cp_mtable[m][ind]; 322 } 323 324 static uint64_t 325 move_cphtr(Move m, uint64_t ind) 326 { 327 return move_cphtr_aux[m][ind]; 328 } 329 330 static uint64_t 331 move_cornershtr(Move m, uint64_t ind) 332 { 333 uint64_t a, b; 334 335 a = coud_mtable[m][ind/(BINOM8ON4 * 6)]; 336 b = move_cphtr(m, ind % (BINOM8ON4 * 6)); 337 338 return a * BINOM8ON4 * 6 + b; 339 } 340 341 static uint64_t 342 move_cornershtrfin(Move m, uint64_t ind) 343 { 344 int a; 345 346 a = cp_mtable[m][cornershtrfin_ant[ind]]; 347 348 return cornershtrfin_ind[a]; 349 } 350 351 static uint64_t 352 move_drud(Move m, uint64_t ind) 353 { 354 uint64_t a, b, c; 355 356 a = eofb_mtable[m][ind % POW2TO11]; 357 b = coud_mtable[m][(ind / POW2TO11) % POW3TO7]; 358 c = epose_mtable[m][ind / (POW2TO11 * POW3TO7)]; 359 360 return a + (b + c * POW3TO7) * POW2TO11; 361 } 362 363 static uint64_t 364 move_drud_eofb(Move m, uint64_t ind) 365 { 366 uint64_t a, b; 367 368 a = coud_mtable[m][ind % POW3TO7]; 369 b = epose_mtable[m][(ind / POW3TO7) * 24] / 24; 370 371 return a + b * POW3TO7; 372 } 373 374 static uint64_t 375 move_htr_drud(Move m, uint64_t ind) 376 { 377 uint64_t a, b; 378 379 a = move_cphtr(m, ind/BINOM8ON4); 380 b = eposs_mtable[m][htr_eposs_ant[ind%BINOM8ON4]]; 381 382 return a*BINOM8ON4 + htr_eposs_ind[b/24]; 383 } 384 385 static uint64_t 386 move_htrfin(Move m, uint64_t ind) 387 { 388 uint64_t a, b, bm, bs, be; 389 390 a = move_cornershtrfin(m, ind / (24*24*24)); 391 bm = eposm_mtable[m][ind%24] % 24; 392 bs = eposs_mtable[m][(ind/24)%24] % 24; 393 be = epose_mtable[m][(ind/(24*24))%24] % 24; 394 b = (be * 24 + bs) * 24 + bm; 395 396 return a * (24*24*24) + b; 397 } 398 399 static uint64_t 400 move_cpud_separate(Move m, uint64_t ind) 401 { 402 return cpud_separate_ind[cp_mtable[m][cpud_separate_ant[ind]]]; 403 } 404 405 /* Init functions implementation *********************************************/ 406 407 /* 408 * There is certainly a better way to do this, but for now I just use 409 * a "graph coloring" algorithm to compute the left cosets, and I compose 410 * with every possible cp to get the right cosets (it is possible that I am 411 * mixing up left and right). 412 * 413 * For doing it better "Mathematically", we need 3 things: 414 * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other 415 * This is easy and it is done in the commented function cphtr_cp(). 416 * - Check that there is no ep/cp parity 417 * - Check that we are not in the "3c" case; this is the part I don't 418 * know how to do. 419 */ 420 static void 421 init_cphtr_cosets(void) 422 { 423 unsigned int i; 424 int c = 0, d = 0; 425 426 for (i = 0; i < FACTORIAL8; i++) { 427 cphtr_left_cosets[i] = -1; 428 cphtr_right_cosets[i] = -1; 429 } 430 431 /* First we compute left cosets with a bfs */ 432 for (i = 0; i < FACTORIAL8; i++) 433 if (cphtr_left_cosets[i] == -1) 434 init_cphtr_left_cosets_bfs(i, c++); 435 436 /* Then we compute right cosets using compose() */ 437 for (i = 0; i < FACTORIAL8; i++) 438 if (cphtr_right_cosets[i] == -1) 439 init_cphtr_right_cosets_color(i, d++); 440 } 441 442 static void 443 init_cphtr_left_cosets_bfs(int i, int c) 444 { 445 int j, jj, next[FACTORIAL8], next2[FACTORIAL8], n, n2; 446 447 Move k; 448 449 n = 1; 450 next[0] = i; 451 cphtr_left_cosets[i] = c; 452 453 while (n != 0) { 454 for (j = 0, n2 = 0; j < n; j++) { 455 for (k = U2; k < B3; k++) { 456 if (!moveset_htr.allowed(k)) 457 continue; 458 jj = apply_move(k, (Cube){ .cp = next[j] }).cp; 459 460 if (cphtr_left_cosets[jj] == -1) { 461 cphtr_left_cosets[jj] = c; 462 next2[n2++] = jj; 463 } 464 } 465 } 466 467 for (j = 0; j < n2; j++) 468 next[j] = next2[j]; 469 n = n2; 470 } 471 } 472 473 static void 474 init_cphtr_right_cosets_color(int i, int d) 475 { 476 int cp; 477 unsigned int j; 478 479 cphtr_right_rep[d] = i; 480 for (j = 0; j < FACTORIAL8; j++) { 481 if (cphtr_left_cosets[j] == 0) { 482 cp = compose_filtered( 483 (Cube){.cp = i}, (Cube){.cp = j}, pf_cp).cp; 484 cphtr_right_cosets[cp] = d; 485 } 486 } 487 } 488 489 static void 490 init_cpud_separate(void) 491 { 492 unsigned int ui; 493 int i, co[8]; 494 495 for (ui = 0; ui < FACTORIAL8; ui++) { 496 for (i = 0; i < 8; i++) 497 co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ? 1 : 0; 498 cpud_separate_ind[ui] = subset_to_index(co, 8, 4); 499 cpud_separate_ant[cpud_separate_ind[ui]] = ui; 500 } 501 } 502 503 static void 504 init_cornershtrfin(void) 505 { 506 unsigned int i, j; 507 int n, c; 508 Move m; 509 510 for (i = 0; i < FACTORIAL8; i++) 511 cornershtrfin_ind[i] = -1; 512 cornershtrfin_ind[0] = 0; 513 514 /* 10-pass, I think 5 is enough, but just in case */ 515 n = 1; 516 for (i = 0; i < 10; i++) { 517 for (j = 0; j < FACTORIAL8; j++) { 518 if (cornershtrfin_ind[j] == -1) 519 continue; 520 for (m = U; m < NMOVES; m++) { 521 if (moveset_htr.allowed(m)) { 522 c = cp_mtable[m][j]; 523 if (cornershtrfin_ind[c] == -1) { 524 cornershtrfin_ind[c] = n; 525 cornershtrfin_ant[n] = c; 526 n++; 527 } 528 } 529 } 530 } 531 } 532 } 533 534 void 535 init_htr_eposs(void) 536 { 537 int ep[12], ep2[12]; 538 int eps_solved[4] = {UL, UR, DL, DR}; 539 unsigned int i, j; 540 541 /* NOTE: we loop over all possible positions of S-slice edges, * 542 * although some of them are not possible (because the E-slice * 543 * edges are already in the E-slice). Then we discard the invalid * 544 * configurations by checking that the value returned by * 545 * subset_to_index() is acceptable. */ 546 for (i = 0; i < BINOM12ON4; i++) { 547 for (j = 0; j < 12; j++) 548 ep[j] = ep2[j] = 0; 549 epos_to_partial_ep(i*24, ep, eps_solved); 550 for (j = 0; j < 8; j++) 551 ep2[j/2 + 4*(j%2)] = ep[j] ? 1 : 0; 552 htr_eposs_ind[i] = subset_to_index(ep2, 8, 4); 553 if (htr_eposs_ind[i] < (int)BINOM8ON4) 554 htr_eposs_ant[htr_eposs_ind[i]] = i*24; 555 } 556 } 557 558 static void 559 init_move_epud(void) 560 { 561 /* TODO: save to file? */ 562 static int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 }; 563 static int shortlist[NMOVES] = { 564 [U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5, 565 [R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9 566 }; 567 uint64_t ui; 568 int j; 569 Move mj; 570 Cube c; 571 CubeArray *arr, *auxarr; 572 573 auxarr = malloc(sizeof(CubeArray)); 574 auxarr->ep = a; 575 for (ui = 0; ui < coord_epud.max; ui++) { 576 index_to_perm(ui, 8, a); 577 c = arrays_to_cube(auxarr, pf_ep); 578 for (j = 0; moveset_drud.sorted_moves[j] != NULLMOVE; 579 j++) { 580 mj = moveset_drud.sorted_moves[j]; 581 arr = new_cubearray(apply_move(mj, c), pf_ep); 582 move_epud_aux[shortlist[mj]][ui] = 583 perm_to_index(arr->ep, 8); 584 free_cubearray(arr, pf_ep); 585 } 586 } 587 free(auxarr); 588 } 589 590 static void 591 init_move_cphtr(void) 592 { 593 uint64_t ui; 594 Move j; 595 596 for (ui = 0; ui < BINOM8ON4*6; ui++) 597 for (j = U; j < NMOVES; j++) 598 move_cphtr_aux[j][ui] = cphtr_right_cosets[ 599 cp_mtable[j][cphtr_right_rep[ui]]]; 600 } 601 602 603 void 604 init_coord(void) 605 { 606 static bool initialized = false; 607 if (initialized) 608 return; 609 initialized = true; 610 611 init_trans(); 612 613 init_cphtr_cosets(); 614 init_cornershtrfin(); 615 init_htr_eposs(); 616 init_cpud_separate(); 617 618 init_move_epud(); 619 init_move_cphtr(); 620 } 621