cube.c (20155B)
1 #include "cube.h" 2 3 /* Local functions ***********************************************************/ 4 5 static void init_inverse(void); 6 static bool read_invtables_file(void); 7 static bool write_invtables_file(void); 8 9 /* Tables ********************************************************************/ 10 11 static uint16_t eo_invtable_e[POW2TO11][BINOM12ON4*FACTORIAL4]; 12 static uint16_t eo_invtable_s[POW2TO11][BINOM12ON4*FACTORIAL4]; 13 static uint16_t eo_invtable_m[POW2TO11][BINOM12ON4*FACTORIAL4]; 14 static uint16_t co_invtable[POW3TO7][FACTORIAL8]; 15 static uint16_t cp_invtable[FACTORIAL8]; 16 static uint16_t cpos_invtable[FACTORIAL6]; 17 18 /* Functions implementation **************************************************/ 19 20 int 21 array_ep_to_epos(int *ep, int *ss) 22 { 23 int epos[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 24 int eps[4]; 25 int i, j, is; 26 27 for (i = 0, is = 0; i < 12; i++) { 28 for (j = 0; j < 4; j++) { 29 if (ep[i] == ss[j]) { 30 eps[is++] = j; 31 epos[i] = 1; 32 } 33 } 34 } 35 36 for (i = 0; i < 4; i++) 37 swap(&epos[ss[i]], &epos[i+8]); 38 39 return 24 * subset_to_index(epos, 12, 4) + perm_to_index(eps, 4); 40 } 41 42 Cube 43 arrays_to_cube(CubeArray *arr, PieceFilter f) 44 { 45 Cube ret = {0}; 46 47 static int epe_solved[4] = {FR, FL, BL, BR}; 48 static int eps_solved[4] = {UL, UR, DL, DR}; 49 static int epm_solved[4] = {UF, UB, DF, DB}; 50 51 if (f.epose) 52 ret.epose = array_ep_to_epos(arr->ep, epe_solved); 53 if (f.eposs) 54 ret.eposs = array_ep_to_epos(arr->ep, eps_solved); 55 if (f.eposm) 56 ret.eposm = array_ep_to_epos(arr->ep, epm_solved); 57 if (f.eofb) 58 ret.eofb = digit_array_to_int(arr->eofb, 11, 2); 59 if (f.eorl) 60 ret.eorl = digit_array_to_int(arr->eorl, 11, 2); 61 if (f.eoud) 62 ret.eoud = digit_array_to_int(arr->eoud, 11, 2); 63 if (f.cp) 64 ret.cp = perm_to_index(arr->cp, 8); 65 if (f.coud) 66 ret.coud = digit_array_to_int(arr->coud, 7, 3); 67 if (f.corl) 68 ret.corl = digit_array_to_int(arr->corl, 7, 3); 69 if (f.cofb) 70 ret.cofb = digit_array_to_int(arr->cofb, 7, 3); 71 if (f.cpos) 72 ret.cpos = perm_to_index(arr->cpos, 6); 73 74 return ret; 75 } 76 77 Cube 78 compose_filtered(Cube c2, Cube c1, PieceFilter f) 79 { 80 CubeArray *arr = new_cubearray(c2, f); 81 Cube ret; 82 83 ret = move_via_arrays(arr, c1, f); 84 free_cubearray(arr, f); 85 86 return ret; 87 } 88 89 void 90 cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) 91 { 92 int i; 93 94 static int epe_solved[4] = {FR, FL, BL, BR}; 95 static int eps_solved[4] = {UL, UR, DL, DR}; 96 static int epm_solved[4] = {UF, UB, DF, DB}; 97 98 if (f.epose || f.eposs || f.eposm) 99 for (i = 0; i < 12; i++) 100 arr->ep[i] = -1; 101 102 if (f.epose) 103 epos_to_partial_ep(cube.epose, arr->ep, epe_solved); 104 if (f.eposs) 105 epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); 106 if (f.eposm) 107 epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); 108 if (f.eofb) 109 int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); 110 if (f.eorl) 111 int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); 112 if (f.eoud) 113 int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); 114 if (f.cp) 115 index_to_perm(cube.cp, 8, arr->cp); 116 if (f.coud) 117 int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); 118 if (f.corl) 119 int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); 120 if (f.cofb) 121 int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); 122 if (f.cpos) 123 index_to_perm(cube.cpos, 6, arr->cpos); 124 } 125 126 void 127 epos_to_compatible_ep(int epos, int *ep, int *ss) 128 { 129 int i, j, k, other[8]; 130 bool flag; 131 132 for (i = 0; i < 12; i++) 133 ep[i] = -1; 134 135 epos_to_partial_ep(epos, ep, ss); 136 137 for (i = 0, j = 0; i < 12; i++) { 138 flag = false; 139 for (k = 0; k < 4; k++) 140 flag = flag || (i == ss[k]); 141 if (!flag) 142 other[j++] = i; 143 } 144 145 for (i = 0, j = 0; i < 12; i++) 146 if (ep[i] == -1) 147 ep[i] = other[j++]; 148 } 149 150 void 151 epos_to_partial_ep(int epos, int *ep, int *ss) 152 { 153 int i, is, eposs[12], eps[4]; 154 155 index_to_perm(epos % FACTORIAL4, 4, eps); 156 index_to_subset(epos / FACTORIAL4, 12, 4, eposs); 157 158 for (i = 0; i < 4; i++) 159 swap(&eposs[ss[i]], &eposs[i+8]); 160 161 for (i = 0, is = 0; i < 12; i++) 162 if (eposs[i]) 163 ep[i] = ss[eps[is++]]; 164 } 165 166 void 167 fix_eorleoud(CubeArray *arr) 168 { 169 int i; 170 171 for (i = 0; i < 12; i++) { 172 if ((edge_slice(i) == 0 && edge_slice(arr->ep[i]) != 0) || 173 (edge_slice(i) != 0 && edge_slice(arr->ep[i]) == 0)) { 174 arr->eorl[i] = 1 - arr->eofb[i]; 175 } else { 176 arr->eorl[i] = arr->eofb[i]; 177 } 178 179 if ((edge_slice(i) == 2 && edge_slice(arr->ep[i]) != 2) || 180 (edge_slice(i) != 2 && edge_slice(arr->ep[i]) == 2)) { 181 arr->eoud[i] = 1 - arr->eofb[i]; 182 } else { 183 arr->eoud[i] = arr->eofb[i]; 184 } 185 } 186 } 187 188 void 189 fix_cofbcorl(CubeArray *arr) 190 { 191 int i; 192 193 for (i = 0; i < 8; i++) { 194 if (i % 2 == arr->cp[i] % 2) { 195 arr->cofb[i] = arr->coud[i]; 196 arr->corl[i] = arr->coud[i]; 197 } else { 198 if (arr->cp[i] % 2 == 0) { 199 arr->cofb[i] = (arr->coud[i]+1)%3; 200 arr->corl[i] = (arr->coud[i]+2)%3; 201 } else { 202 arr->cofb[i] = (arr->coud[i]+2)%3; 203 arr->corl[i] = (arr->coud[i]+1)%3; 204 } 205 } 206 } 207 } 208 209 Cube 210 fourval_to_cube(int eofb, int ep, int coud, int cp) 211 { 212 CubeArray *arr; 213 214 arr = new_cubearray((Cube){0}, pf_all); 215 216 index_to_perm(ep, 12, arr->ep); 217 index_to_perm(cp, 8, arr->cp); 218 int_to_sum_zero_array(eofb, 2, 12, arr->eofb); 219 int_to_sum_zero_array(coud, 3, 8, arr->coud); 220 221 /* fix parity */ 222 if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) 223 swap(&(arr->ep[0]), &(arr->ep[1])); 224 225 fix_eorleoud(arr); 226 fix_cofbcorl(arr); 227 228 return arrays_to_cube(arr, pf_all); 229 } 230 231 void 232 free_cubearray(CubeArray *arr, PieceFilter f) 233 { 234 if (f.epose || f.eposs || f.eposm) 235 free(arr->ep); 236 if (f.eofb) 237 free(arr->eofb); 238 if (f.eorl) 239 free(arr->eorl); 240 if (f.eoud) 241 free(arr->eoud); 242 if (f.cp) 243 free(arr->cp); 244 if (f.coud) 245 free(arr->coud); 246 if (f.corl) 247 free(arr->corl); 248 if (f.cofb) 249 free(arr->cofb); 250 if (f.cpos) 251 free(arr->cpos); 252 253 free(arr); 254 } 255 256 Cube 257 move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) 258 { 259 CubeArray *arrc = new_cubearray(c, f); 260 Cube ret; 261 262 if (f.epose || f.eposs || f.eposm) 263 apply_permutation(arr->ep, arrc->ep, 12); 264 265 if (f.eofb) { 266 apply_permutation(arr->ep, arrc->eofb, 12); 267 sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); 268 } 269 270 if (f.eorl) { 271 apply_permutation(arr->ep, arrc->eorl, 12); 272 sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); 273 } 274 275 if (f.eoud) { 276 apply_permutation(arr->ep, arrc->eoud, 12); 277 sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); 278 } 279 280 if (f.cp) 281 apply_permutation(arr->cp, arrc->cp, 8); 282 283 if (f.coud) { 284 apply_permutation(arr->cp, arrc->coud, 8); 285 sum_arrays_mod(arr->coud, arrc->coud, 8, 3); 286 } 287 288 if (f.corl) { 289 apply_permutation(arr->cp, arrc->corl, 8); 290 sum_arrays_mod(arr->corl, arrc->corl, 8, 3); 291 } 292 293 if (f.cofb) { 294 apply_permutation(arr->cp, arrc->cofb, 8); 295 sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); 296 } 297 298 if (f.cpos) 299 apply_permutation(arr->cpos, arrc->cpos, 6); 300 301 ret = arrays_to_cube(arrc, f); 302 free_cubearray(arrc, f); 303 304 return ret; 305 } 306 307 CubeArray * 308 new_cubearray(Cube cube, PieceFilter f) 309 { 310 CubeArray *arr = malloc(sizeof(CubeArray)); 311 312 if (f.epose || f.eposs || f.eposm) 313 arr->ep = malloc(12 * sizeof(int)); 314 if (f.eofb) 315 arr->eofb = malloc(12 * sizeof(int)); 316 if (f.eorl) 317 arr->eorl = malloc(12 * sizeof(int)); 318 if (f.eoud) 319 arr->eoud = malloc(12 * sizeof(int)); 320 if (f.cp) 321 arr->cp = malloc(8 * sizeof(int)); 322 if (f.coud) 323 arr->coud = malloc(8 * sizeof(int)); 324 if (f.corl) 325 arr->corl = malloc(8 * sizeof(int)); 326 if (f.cofb) 327 arr->cofb = malloc(8 * sizeof(int)); 328 if (f.cpos) 329 arr->cpos = malloc(6 * sizeof(int)); 330 331 cube_to_arrays(cube, arr, f); 332 333 return arr; 334 } 335 336 Cube 337 admissible_ep(Cube cube, PieceFilter f) 338 { 339 CubeArray *arr = new_cubearray(cube, f); 340 Cube ret; 341 bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 342 int i, j; 343 344 for (i = 0; i < 12; i++) 345 if (arr->ep[i] != -1) 346 used[arr->ep[i]] = true; 347 348 for (i = 0, j = 0; i < 12; i++) { 349 for ( ; j < 11 && used[j]; j++); 350 if (arr->ep[i] == -1) 351 arr->ep[i] = j++; 352 } 353 354 ret = arrays_to_cube(arr, pf_ep); 355 free_cubearray(arr, f); 356 357 return ret; 358 } 359 360 Cube 361 compose(Cube c2, Cube c1) 362 { 363 return compose_filtered(c2, c1, pf_all); 364 } 365 366 int 367 edge_slice(Edge e) { 368 if (e < 0 || e > 11) 369 return -1; 370 371 if (e == FR || e == FL || e == BL || e == BR) 372 return 0; 373 if (e == UR || e == UL || e == DR || e == DL) 374 return 1; 375 376 return 2; 377 } 378 379 bool 380 equal(Cube c1, Cube c2) 381 { 382 return c1.eofb == c2.eofb && 383 c1.epose == c2.epose && 384 c1.eposs == c2.eposs && 385 c1.eposm == c2.eposm && 386 c1.coud == c2.coud && 387 c1.cp == c2.cp && 388 c1.cpos == c2.cpos; 389 } 390 391 Cube 392 inverse_cube(Cube cube) 393 { 394 CubeArray inv; 395 Cube ret; 396 int i, ep[12]; 397 398 for (i = 0; i < 12; i++) 399 ep[i] = where_is_edge(cube, i); 400 inv = (CubeArray){.ep = ep}; 401 ret = arrays_to_cube(&inv, pf_ep); 402 403 ret.eofb = ((int)eo_invtable_e[cube.eofb][cube.epose]) | 404 ((int)eo_invtable_m[cube.eofb][cube.eposm]) | 405 ((int)eo_invtable_s[cube.eofb][cube.eposs]); 406 ret.eorl = ((int)eo_invtable_e[cube.eorl][cube.epose]) | 407 ((int)eo_invtable_m[cube.eorl][cube.eposm]) | 408 ((int)eo_invtable_s[cube.eorl][cube.eposs]); 409 ret.eoud = ((int)eo_invtable_e[cube.eoud][cube.epose]) | 410 ((int)eo_invtable_m[cube.eoud][cube.eposm]) | 411 ((int)eo_invtable_s[cube.eoud][cube.eposs]); 412 ret.cp = cp_invtable[cube.cp]; 413 ret.cpos = cpos_invtable[cube.cpos]; 414 ret.coud = co_invtable[cube.coud][cube.cp]; 415 ret.corl = co_invtable[cube.corl][cube.cp]; 416 ret.cofb = co_invtable[cube.cofb][cube.cp]; 417 418 return ret; 419 } 420 421 bool 422 is_admissible(Cube cube) { 423 424 /* TODO: this should check consistency of different orientations */ 425 /* check also that centers are opposite and admissible */ 426 427 CubeArray *a = new_cubearray(cube, pf_all); 428 int parity; 429 bool perm; 430 431 perm = is_perm(a->ep, 12) && 432 is_perm(a->cp, 8) && 433 is_perm(a->cpos, 6); 434 parity = perm_sign(a->ep, 12) + 435 perm_sign(a->cp, 8) + 436 perm_sign(a->cpos, 6); 437 438 free_cubearray(a, pf_all); 439 440 return perm && parity % 2 == 0; 441 } 442 443 bool 444 is_solved(Cube cube) 445 { 446 return equal(cube, (Cube){0}); 447 } 448 449 bool 450 is_block_solved(Cube cube, Block block) 451 { 452 int i; 453 454 for (i = 0; i < 12; i++) 455 if (block.edge[i] && !is_solved_edge(cube, i)) 456 return false; 457 for (i = 0; i < 8; i++) 458 if (block.corner[i] && !is_solved_corner(cube, i)) 459 return false; 460 for (i = 0; i < 6; i++) 461 if (block.center[i] && !is_solved_center(cube, i)) 462 return false; 463 464 return true; 465 } 466 467 bool 468 is_solved_center(Cube cube, Center c) 469 { 470 return what_center_at(cube, c) == c; 471 } 472 473 bool 474 is_solved_corner(Cube cube, Corner c) 475 { 476 return what_corner_at(cube, c) == c && 477 what_orientation_corner(cube.coud, c); 478 } 479 480 bool 481 is_solved_edge(Cube cube, Edge e) 482 { 483 return what_edge_at(cube, e) == e && 484 what_orientation_edge(cube.eofb, e); 485 } 486 487 int 488 piece_orientation(Cube cube, int piece, char *orientation) 489 { 490 int arr[12], n, b, x; 491 492 if (!strcmp(orientation, "eofb")) { 493 x = cube.eofb; 494 n = 12; 495 b = 2; 496 } else if (!strcmp(orientation, "eorl")) { 497 x = cube.eorl; 498 n = 12; 499 b = 2; 500 } else if (!strcmp(orientation, "eoud")) { 501 x = cube.eoud; 502 n = 12; 503 b = 2; 504 } else if (!strcmp(orientation, "coud")) { 505 x = cube.coud; 506 n = 8; 507 b = 3; 508 } else if (!strcmp(orientation, "corl")) { 509 x = cube.corl; 510 n = 8; 511 b = 3; 512 } else if (!strcmp(orientation, "cofb")) { 513 x = cube.cofb; 514 n = 8; 515 b = 3; 516 } else { 517 return -1; 518 } 519 520 int_to_sum_zero_array(x, b, n, arr); 521 if (piece < n) 522 return arr[piece]; 523 524 return -1; 525 } 526 527 void 528 print_cube(Cube cube) 529 { 530 static char edge_string[12][7] = { 531 [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", 532 [DF] = "DF", [DL] = "DL", [DB] = "DB", [DR] = "DR", 533 [FR] = "FR", [FL] = "FL", [BL] = "BL", [BR] = "BR" 534 }; 535 536 static char corner_string[8][7] = { 537 [UFR] = "UFR", [UFL] = "UFL", [UBL] = "UBL", [UBR] = "UBR", 538 [DFR] = "DFR", [DFL] = "DFL", [DBL] = "DBL", [DBR] = "DBR" 539 }; 540 541 static char center_string[6][7] = { 542 [U_center] = "U", [D_center] = "D", 543 [R_center] = "R", [L_center] = "L", 544 [F_center] = "F", [B_center] = "B" 545 }; 546 547 for (int i = 0; i < 12; i++) 548 printf(" %s ", edge_string[what_edge_at(cube, i)]); 549 printf("\n"); 550 551 for (int i = 0; i < 12; i++) 552 printf(" %d ", what_orientation_edge(cube.eofb, i)); 553 printf("\n"); 554 555 for (int i = 0; i < 8; i++) 556 printf("%s ", corner_string[what_corner_at(cube, i)]); 557 printf("\n"); 558 559 for (int i = 0; i < 8; i++) 560 printf(" %d ", what_orientation_corner(cube.coud, i)); 561 printf("\n"); 562 563 for (int i = 0; i < 6; i++) 564 printf(" %s ", center_string[what_center_at(cube, i)]); 565 printf("\n"); 566 } 567 568 Center 569 what_center_at(Cube cube, Center c) 570 { 571 static bool initialized = false; 572 static Center aux[FACTORIAL6][6]; 573 static int i; 574 static unsigned int ui; 575 static CubeArray *arr; 576 577 if (!initialized) { 578 for (ui = 0; ui < FACTORIAL6; ui++) { 579 arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); 580 for (i = 0; i < 6; i++) 581 aux[ui][i] = arr->cpos[i]; 582 free_cubearray(arr, pf_cpos); 583 } 584 585 initialized = true; 586 } 587 588 return aux[cube.cpos][c]; 589 } 590 591 Corner 592 what_corner_at(Cube cube, Corner c) 593 { 594 int i; 595 unsigned int ui; 596 CubeArray *arr; 597 598 static bool initialized = false; 599 static Corner aux[FACTORIAL8][8]; 600 601 if (!initialized) { 602 for (ui = 0; ui < FACTORIAL8; ui++) { 603 arr = new_cubearray((Cube){.cp = ui}, pf_cp); 604 for (i = 0; i < 8; i++) 605 aux[ui][i] = arr->cp[i]; 606 free_cubearray(arr, pf_cp); 607 } 608 609 initialized = true; 610 } 611 612 return aux[cube.cp][c]; 613 } 614 615 Edge 616 what_edge_at(Cube cube, Edge e) 617 { 618 Edge ret; 619 CubeArray *arr = new_cubearray(cube, pf_ep); 620 621 ret = arr->ep[e]; 622 623 free_cubearray(arr, pf_ep); 624 return ret; 625 } 626 627 int 628 what_orientation_corner(int co, Corner c) 629 { 630 static bool initialized = false; 631 static int auxlast[POW3TO7]; 632 static int auxarr[8]; 633 static unsigned int ui; 634 635 if (!initialized) { 636 for (ui = 0; ui < POW3TO7; ui++) { 637 int_to_sum_zero_array(ui, 3, 8, auxarr); 638 auxlast[ui] = auxarr[7]; 639 } 640 641 initialized = true; 642 } 643 644 if (c < 7) 645 return (co / powint(3, c)) % 3; 646 else 647 return auxlast[co]; 648 } 649 650 int 651 what_orientation_edge(int eo, Edge e) 652 { 653 static bool initialized = false; 654 static int auxlast[POW2TO11]; 655 static int auxarr[12]; 656 static unsigned int ui; 657 658 if (!initialized) { 659 for (ui = 0; ui < POW2TO11; ui++) { 660 int_to_sum_zero_array(ui, 2, 12, auxarr); 661 auxlast[ui] = auxarr[11]; 662 } 663 664 initialized = true; 665 } 666 667 if (e < 11) 668 return (eo & (1 << e)) ? 1 : 0; 669 else 670 return auxlast[eo]; 671 } 672 673 Center 674 where_is_center(Cube cube, Center c) 675 { 676 static bool initialized = false; 677 static Center aux[FACTORIAL6][6]; 678 static int i; 679 static unsigned int ui; 680 static CubeArray *arr; 681 682 if (!initialized) { 683 for (ui = 0; ui < FACTORIAL6; ui++) { 684 arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); 685 for (i = 0; i < 6; i++) 686 aux[ui][arr->cpos[i]] = i; 687 free_cubearray(arr, pf_cpos); 688 } 689 690 initialized = true; 691 } 692 693 return aux[cube.cpos][c]; 694 } 695 696 Corner 697 where_is_corner(Cube cube, Corner c) 698 { 699 static bool initialized = false; 700 static Corner aux[FACTORIAL8][8]; 701 static int i; 702 static unsigned int ui; 703 static CubeArray *arr; 704 705 if (!initialized) { 706 for (ui = 0; ui < FACTORIAL8; ui++) { 707 arr = new_cubearray((Cube){.cp = ui}, pf_cp); 708 for (i = 0; i < 8; i++) 709 aux[ui][arr->cp[i]] = i; 710 free_cubearray(arr, pf_cp); 711 } 712 713 initialized = true; 714 } 715 return aux[cube.cp][c]; 716 } 717 718 Edge 719 where_is_edge(Cube c, Edge e) 720 { 721 int r0, r1, r2; 722 723 static bool initialized = false; 724 static int aux[3][BINOM12ON4*FACTORIAL4][12]; 725 static int i, j; 726 static unsigned int ui; 727 static CubeArray *arr; 728 729 if (!initialized) { 730 for (ui = 0; ui < BINOM12ON4*FACTORIAL4; ui++) { 731 for (i = 0; i < 3; i++) 732 for (j = 0; j < 12; j++) 733 aux[i][ui][j] = -1; 734 735 arr = new_cubearray((Cube){.epose = ui}, pf_e); 736 for (i = 0; i < 12; i++) 737 if (edge_slice(arr->ep[i]) == 0) 738 aux[0][ui][arr->ep[i]] = i; 739 free_cubearray(arr, pf_e); 740 741 arr = new_cubearray((Cube){.eposs = ui}, pf_s); 742 for (i = 0; i < 12; i++) 743 if (edge_slice(arr->ep[i]) == 1) 744 aux[1][ui][arr->ep[i]] = i; 745 free_cubearray(arr, pf_s); 746 747 arr = new_cubearray((Cube){.eposm = ui}, pf_m); 748 for (i = 0; i < 12; i++) 749 if (edge_slice(arr->ep[i]) == 2) 750 aux[2][ui][arr->ep[i]] = i; 751 free_cubearray(arr, pf_m); 752 } 753 754 initialized = true; 755 } 756 757 r0 = aux[0][c.epose][e]; 758 r1 = aux[1][c.eposs][e]; 759 r2 = aux[2][c.eposm][e]; 760 return MAX(r0, MAX(r1, r2)); 761 } 762 763 static bool 764 read_invtables_file(void) 765 { 766 init_env(); 767 768 FILE *f; 769 char fname[strlen(tabledir)+20]; 770 int b; 771 unsigned int ui, meeo, meco, mecp, mecpos; 772 bool r; 773 774 strcpy(fname, tabledir); 775 strcat(fname, "/invtables"); 776 777 if ((f = fopen(fname, "rb")) == NULL) 778 return false; 779 780 b = sizeof(uint16_t); 781 r = true; 782 meeo = BINOM12ON4*FACTORIAL4; 783 meco = FACTORIAL8; 784 mecp = FACTORIAL8; 785 mecpos = FACTORIAL6; 786 787 for (ui = 0; ui < POW2TO11; ui++) { 788 r = r && fread(eo_invtable_e[ui], b, meeo, f) == meeo; 789 r = r && fread(eo_invtable_m[ui], b, meeo, f) == meeo; 790 r = r && fread(eo_invtable_s[ui], b, meeo, f) == meeo; 791 } 792 793 for (ui = 0; ui < POW3TO7; ui++) { 794 r = r && fread(co_invtable[ui], b, meco, f) == meco; 795 } 796 797 r = r && fread(cp_invtable, b, mecp, f) == mecp; 798 r = r && fread(cpos_invtable, b, mecpos, f) == mecpos; 799 800 fclose(f); 801 return r; 802 } 803 804 static bool 805 write_invtables_file(void) 806 { 807 init_env(); 808 809 FILE *f; 810 char fname[strlen(tabledir)+20]; 811 unsigned int ui, meeo, meco, mecp, mecpos; 812 int b; 813 bool r; 814 815 strcpy(fname, tabledir); 816 strcat(fname, "/invtables"); 817 818 if ((f = fopen(fname, "wb")) == NULL) 819 return false; 820 821 b = sizeof(uint16_t); 822 r = true; 823 meeo = BINOM12ON4*FACTORIAL4; 824 meco = FACTORIAL8; 825 mecp = FACTORIAL8; 826 mecpos = FACTORIAL6; 827 828 for (ui = 0; ui < POW2TO11; ui++) { 829 r = r && fwrite(eo_invtable_e[ui], b, meeo, f) == meeo; 830 r = r && fwrite(eo_invtable_m[ui], b, meeo, f) == meeo; 831 r = r && fwrite(eo_invtable_s[ui], b, meeo, f) == meeo; 832 } 833 834 for (ui = 0; ui < POW3TO7; ui++) { 835 r = r && fwrite(co_invtable[ui], b, meco, f) == meco; 836 } 837 838 r = r && fwrite(cp_invtable, b, mecp, f) == mecp; 839 r = r && fwrite(cpos_invtable, b, mecpos, f) == mecpos; 840 841 fclose(f); 842 return r; 843 } 844 845 void 846 init_inverse(void) 847 { 848 static bool initialized = false; 849 if (initialized) 850 return; 851 initialized = true; 852 853 if (read_invtables_file()) 854 return; 855 856 fprintf(stderr, "Cannot load invtables, generating it\n"); 857 858 CubeArray *aux, *inv; 859 Cube c; 860 int i, j, eoaux[12], eoinv[12]; 861 unsigned int ui, uj; 862 863 aux = new_cubearray((Cube){0}, pf_all); 864 inv = new_cubearray((Cube){0}, pf_all); 865 866 for (ui = 0; ui < POW2TO11; ui++) { 867 int_to_sum_zero_array(ui, 2, 12, eoaux); 868 for (uj = 0; uj < BINOM12ON4*FACTORIAL4; uj++) { 869 for (j = 0; j < 12; j++) 870 eoinv[j] = 0; 871 c = (Cube){.epose = uj, .eposm = 0, .eposs = 0}; 872 eoinv[FR] = eoaux[where_is_edge(c, FR)]; 873 eoinv[FL] = eoaux[where_is_edge(c, FL)]; 874 eoinv[BL] = eoaux[where_is_edge(c, BL)]; 875 eoinv[BR] = eoaux[where_is_edge(c, BR)]; 876 eo_invtable_e[ui][uj] = digit_array_to_int(eoinv,11,2); 877 878 for (j = 0; j < 12; j++) 879 eoinv[j] = 0; 880 c = (Cube){.epose = 0, .eposm = uj, .eposs = 0}; 881 eoinv[UF] = eoaux[where_is_edge(c, UF)]; 882 eoinv[UB] = eoaux[where_is_edge(c, UB)]; 883 eoinv[DF] = eoaux[where_is_edge(c, DF)]; 884 eoinv[DB] = eoaux[where_is_edge(c, DB)]; 885 eo_invtable_m[ui][uj] = digit_array_to_int(eoinv,11,2); 886 887 for (j = 0; j < 12; j++) 888 eoinv[j] = 0; 889 c = (Cube){.epose = 0, .eposm = 0, .eposs = uj}; 890 eoinv[UL] = eoaux[where_is_edge(c, UL)]; 891 eoinv[UR] = eoaux[where_is_edge(c, UR)]; 892 eoinv[DL] = eoaux[where_is_edge(c, DL)]; 893 eoinv[DR] = eoaux[where_is_edge(c, DR)]; 894 eo_invtable_s[ui][uj] = digit_array_to_int(eoinv,11,2); 895 } 896 } 897 898 for (ui = 0; ui < FACTORIAL8; ui++) { 899 cube_to_arrays((Cube){.cp = ui}, aux, pf_cp); 900 for (i = 0; i < 8; i++) 901 inv->cp[aux->cp[i]] = i; 902 cp_invtable[ui] = (uint16_t)arrays_to_cube(inv, pf_cp).cp; 903 904 for (uj = 0; uj < POW3TO7; uj++) { 905 cube_to_arrays((Cube){.coud = uj}, aux, pf_coud); 906 for (i = 0; i < 8; i++) 907 inv->coud[aux->cp[i]] = (3-aux->coud[i])%3; 908 co_invtable[uj][ui] = 909 (uint16_t)arrays_to_cube(inv, pf_coud).coud; 910 } 911 } 912 913 for (ui = 0; ui < FACTORIAL6; ui++) { 914 cube_to_arrays((Cube){.cpos = ui}, aux, pf_cpos); 915 for (i = 0; i < 6; i++) 916 inv->cpos[aux->cpos[i]] = i; 917 cpos_invtable[ui] = 918 (uint16_t)arrays_to_cube(inv, pf_cpos).cpos; 919 } 920 921 free_cubearray(aux, pf_all); 922 free_cubearray(inv, pf_all); 923 924 if (!write_invtables_file()) 925 fprintf(stderr, "Error writing invtables\n"); 926 } 927 928 void 929 init_cube(void) 930 { 931 init_inverse(); 932 }