You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

4317 lines
130 KiB

  1. /* optimal cube solver by michael reid reid@math.ucf.edu */
  2. /* version 2.1 june 3, 2004 */
  3. /* symmetry mechanism added */
  4. /* malloc.h removed, long string fixed */
  5. #define USE_METRIC QUARTER_TURN_METRIC
  6. #define SEARCH_LIMIT 0
  7. #define USE_SYMMETRY 1
  8. #define ONE_SOLUTION_ONLY 0
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <setjmp.h>
  13. #include <signal.h>
  14. #define QUARTER_TURN_METRIC 0
  15. #define FACE_TURN_METRIC 1
  16. #define N_SYM 16
  17. #define N_TWIST 18
  18. #define N_CORNER 2187
  19. #define N_ELOC 495
  20. #define N_ELOC_CONV 4096
  21. #define N_EFLIP 2048
  22. #define N_FULLEDGE (N_ELOC * N_EFLIP)
  23. #define N_EDGEQUOT 64430
  24. #define N_CORNERPERM 40320
  25. #define N_SLICEEDGE 11880
  26. #define N_CUBESYM 48
  27. #define N_SYMSUBGRP 98
  28. #define SUBGRP_TRIVIAL 97
  29. #define N_DIST_CHARS ((N_EDGEQUOT * N_CORNER) / 2)
  30. #define BACKWARDS_SWITCH_POINT ((2 * N_EDGEQUOT * N_CORNER) / 5)
  31. #define CORNER_START 0
  32. #define EDGE_START 64244
  33. #define CORNERPERM_START 0
  34. #define UD_SLICEEDGE_START 494
  35. #define RL_SLICEEDGE_START 54
  36. #define FB_SLICEEDGE_START 209
  37. #define MAX_PERM_N 12
  38. #define MAX_CHECK_PERM_N 24
  39. #define MAX_TWISTS 43
  40. #define TWIST_F 0
  41. #define TWIST_F2 1
  42. #define TWIST_F3 2
  43. #define TWIST_R 3
  44. #define TWIST_R2 4
  45. #define TWIST_R3 5
  46. #define TWIST_U 6
  47. #define TWIST_U2 7
  48. #define TWIST_U3 8
  49. #define TWIST_B 9
  50. #define TWIST_B2 10
  51. #define TWIST_B3 11
  52. #define TWIST_L 12
  53. #define TWIST_L2 13
  54. #define TWIST_L3 14
  55. #define TWIST_D 15
  56. #define TWIST_D2 16
  57. #define TWIST_D3 17
  58. #define CORNER_UFR 0
  59. #define CORNER_URB 1
  60. #define CORNER_UBL 2
  61. #define CORNER_ULF 3
  62. #define CORNER_DRF 4
  63. #define CORNER_DFL 5
  64. #define CORNER_DLB 6
  65. #define CORNER_DBR 7
  66. #define CORNER_FRU 8
  67. #define CORNER_RBU 9
  68. #define CORNER_BLU 10
  69. #define CORNER_LFU 11
  70. #define CORNER_RFD 12
  71. #define CORNER_FLD 13
  72. #define CORNER_LBD 14
  73. #define CORNER_BRD 15
  74. #define CORNER_RUF 16
  75. #define CORNER_BUR 17
  76. #define CORNER_LUB 18
  77. #define CORNER_FUL 19
  78. #define CORNER_FDR 20
  79. #define CORNER_LDF 21
  80. #define CORNER_BDL 22
  81. #define CORNER_RDB 23
  82. #define EDGE_UF 0
  83. #define EDGE_UR 1
  84. #define EDGE_UB 2
  85. #define EDGE_UL 3
  86. #define EDGE_DF 4
  87. #define EDGE_DR 5
  88. #define EDGE_DB 6
  89. #define EDGE_DL 7
  90. #define EDGE_FR 8
  91. #define EDGE_FL 9
  92. #define EDGE_BR 10
  93. #define EDGE_BL 11
  94. #define EDGE_FU 12
  95. #define EDGE_RU 13
  96. #define EDGE_BU 14
  97. #define EDGE_LU 15
  98. #define EDGE_FD 16
  99. #define EDGE_RD 17
  100. #define EDGE_BD 18
  101. #define EDGE_LD 19
  102. #define EDGE_RF 20
  103. #define EDGE_LF 21
  104. #define EDGE_RB 22
  105. #define EDGE_LB 23
  106. #define FACE_F 0
  107. #define FACE_R 1
  108. #define FACE_U 2
  109. #define FACE_B 3
  110. #define FACE_L 4
  111. #define FACE_D 5
  112. #define N_FOLLOW 873
  113. #define FOLLOW_INVALID 0
  114. #define N_SYLLABLE 32
  115. #define SYLLABLE_INVALID 0
  116. #define SYLLABLE_NONE 1
  117. #define SYLLABLE_F 2
  118. #define SYLLABLE_F2 3
  119. #define SYLLABLE_F3 4
  120. #define SYLLABLE_R 5
  121. #define SYLLABLE_R2 6
  122. #define SYLLABLE_R3 7
  123. #define SYLLABLE_U 8
  124. #define SYLLABLE_U2 9
  125. #define SYLLABLE_U3 10
  126. #define SYLLABLE_B 11
  127. #define SYLLABLE_B2 12
  128. #define SYLLABLE_B3 13
  129. #define SYLLABLE_L 14
  130. #define SYLLABLE_L2 15
  131. #define SYLLABLE_L3 16
  132. #define SYLLABLE_D 17
  133. #define SYLLABLE_D2 18
  134. #define SYLLABLE_D3 19
  135. #define SYLLABLE_FB 20
  136. #define SYLLABLE_FB2 21
  137. #define SYLLABLE_FB3 22
  138. #define SYLLABLE_F2B2 23
  139. #define SYLLABLE_RL 24
  140. #define SYLLABLE_RL2 25
  141. #define SYLLABLE_RL3 26
  142. #define SYLLABLE_R2L2 27
  143. #define SYLLABLE_UD 28
  144. #define SYLLABLE_UD2 29
  145. #define SYLLABLE_UD3 30
  146. #define SYLLABLE_U2D2 31
  147. #define DIST(c, e) (((e) & 0x1) ? (((int)distance[c][(e) >> 1]) >> 4) \
  148. : (((int)distance[c][(e) >> 1]) & 0xF))
  149. typedef struct cube
  150. {
  151. int edges[24];
  152. int corners[24];
  153. }
  154. Cube;
  155. typedef struct coset_coord
  156. {
  157. int corner_state;
  158. int edge_state;
  159. int sym_state;
  160. }
  161. Coset_coord;
  162. typedef struct full_cube
  163. {
  164. Cube cubies;
  165. int cornerperm;
  166. int ud_sliceedge;
  167. int rl_sliceedge;
  168. int fb_sliceedge;
  169. Coset_coord ud;
  170. Coset_coord rl;
  171. Coset_coord fb;
  172. int parity;
  173. int sym_subgrp;
  174. }
  175. Full_cube;
  176. typedef struct search_data
  177. {
  178. int depth;
  179. int found;
  180. int found_quot;
  181. int *multiplicities;
  182. int *stabilizers;
  183. }
  184. Search_data;
  185. typedef struct search_node
  186. {
  187. int remain_depth;
  188. int twist;
  189. int follow_type;
  190. Coset_coord ud;
  191. Coset_coord rl;
  192. Coset_coord fb;
  193. }
  194. Search_node;
  195. typedef struct metric_data
  196. {
  197. int metric;
  198. char metric_char;
  199. int twist_length[N_TWIST];
  200. int increment;
  201. }
  202. Metric_data;
  203. typedef struct options
  204. {
  205. int use_symmetry;
  206. int search_limit;
  207. int one_solution_only;
  208. }
  209. Options;
  210. typedef struct subgroup_list
  211. {
  212. int n_subgroups;
  213. int (*subgroups)[N_CUBESYM];
  214. }
  215. Subgroup_list;
  216. static unsigned char *sym_x_invsym_to_sym[N_SYM];
  217. static unsigned char *invsym_on_twist_ud[N_SYM];
  218. static unsigned char *invsym_on_twist_rl[N_SYM];
  219. static unsigned char *invsym_on_twist_fb[N_SYM];
  220. static unsigned short *twist_on_corner[N_TWIST];
  221. static unsigned short *sym_on_corner[N_SYM];
  222. static unsigned short *fulledge_to_edge;
  223. static unsigned char *fulledge_to_sym;
  224. static unsigned short *twist_on_edge[N_TWIST];
  225. static unsigned char *twist_x_edge_to_sym[N_TWIST];
  226. static unsigned short *twist_on_cornerperm[N_TWIST];
  227. static unsigned short *twist_on_sliceedge[N_TWIST];
  228. static unsigned short *twist_on_follow[N_TWIST];
  229. static unsigned char *distance[N_CORNER];
  230. static char *edge_cubie_str[] = {"UF", "UR", "UB", "UL",
  231. "DF", "DR", "DB", "DL",
  232. "FR", "FL", "BR", "BL",
  233. "FU", "RU", "BU", "LU",
  234. "FD", "RD", "BD", "LD",
  235. "RF", "LF", "RB", "LB"};
  236. static char *corner_cubie_str[] = {"UFR", "URB", "UBL", "ULF",
  237. "DRF", "DFL", "DLB", "DBR",
  238. "FRU", "RBU", "BLU", "LFU",
  239. "RFD", "FLD", "LBD", "BRD",
  240. "RUF", "BUR", "LUB", "FUL",
  241. "FDR", "LDF", "BDL", "RDB"};
  242. static Metric_data *p_current_metric;
  243. static Options *p_current_options;
  244. static unsigned int n_nodes;
  245. static unsigned int n_tests;
  246. static int sol_found;
  247. static sigjmp_buf jump_env;
  248. /* ========================================================================= */
  249. void exit_w_error_message(char *msg)
  250. /* ------------------------------------------------------------------------- */
  251. {
  252. printf("\n%s\n", msg);
  253. exit(EXIT_FAILURE);
  254. return;
  255. }
  256. /* ========================================================================= */
  257. void user_interrupt(int unused_arg)
  258. /* ------------------------------------------------------------------------- */
  259. {
  260. printf("\n-- user interrupt --\n");
  261. fflush(stdout);
  262. siglongjmp(jump_env, 1);
  263. return;
  264. }
  265. /* ========================================================================= */
  266. void perm_n_unpack(int nn, int indx, int array_out[])
  267. /* ------------------------------------------------------------------------- */
  268. {
  269. int ii, jj;
  270. for (ii = nn - 1; ii >= 0; ii--)
  271. {
  272. array_out[ii] = indx % (nn - ii);
  273. indx /= (nn - ii);
  274. for (jj = ii + 1; jj < nn; jj++)
  275. if (array_out[jj] >= array_out[ii])
  276. array_out[jj]++;
  277. }
  278. return;
  279. }
  280. /* ========================================================================= */
  281. int perm_n_pack(int nn, int array_in[])
  282. /* ------------------------------------------------------------------------- */
  283. {
  284. int indx, ii, jj;
  285. indx = 0;
  286. for (ii = 0; ii < nn; ii++)
  287. {
  288. indx *= (nn - ii);
  289. for (jj = ii + 1; jj < nn; jj++)
  290. if (array_in[jj] < array_in[ii])
  291. indx++;
  292. }
  293. return indx;
  294. }
  295. /* ========================================================================= */
  296. int perm_n_check(int nn, int array_in[])
  297. /* ------------------------------------------------------------------------- */
  298. {
  299. int count[MAX_CHECK_PERM_N], ii;
  300. for (ii = 0; ii < nn; ii++)
  301. count[ii] = 0;
  302. for (ii = 0; ii < nn; ii++)
  303. {
  304. if ((array_in[ii] < 0) || (array_in[ii] >= nn))
  305. return 1;
  306. count[array_in[ii]]++;
  307. }
  308. for (ii = 0; ii < nn; ii++)
  309. if (count[ii] != 1)
  310. return 1;
  311. return 0;
  312. }
  313. /* ========================================================================= */
  314. int perm_n_parity(int nn, int array_in[])
  315. /* ------------------------------------------------------------------------- */
  316. {
  317. int temp_array[MAX_CHECK_PERM_N];
  318. int ii, jj, n_cycles;
  319. for (ii = 0; ii < nn; ii++)
  320. temp_array[ii] = 0;
  321. n_cycles = 0;
  322. for (ii = 0; ii < nn; ii++)
  323. if (temp_array[ii] == 0)
  324. {
  325. n_cycles++;
  326. jj = ii;
  327. while (temp_array[jj] == 0)
  328. {
  329. temp_array[jj] = 1;
  330. jj = array_in[jj];
  331. }
  332. }
  333. return (n_cycles + nn) % 2;
  334. }
  335. /* ========================================================================= */
  336. void perm_n_init(int nn, int array_out[])
  337. /* ------------------------------------------------------------------------- */
  338. {
  339. int ii;
  340. for (ii = 0; ii < nn; ii++)
  341. array_out[ii] = ii;
  342. return;
  343. }
  344. /* ========================================================================= */
  345. void perm_n_compose(int nn, int perm0_in[], int perm1_in[],
  346. int perm_out[])
  347. /* ------------------------------------------------------------------------- */
  348. {
  349. int ii;
  350. for (ii = 0; ii < nn; ii++)
  351. perm_out[ii] = perm0_in[perm1_in[ii]];
  352. return;
  353. }
  354. /* ========================================================================= */
  355. void perm_n_conjugate(int nn, int arr_in[], int conjugator[],
  356. int array_out[])
  357. /* ------------------------------------------------------------------------- */
  358. {
  359. int ii;
  360. for (ii = 0; ii < nn; ii++)
  361. array_out[conjugator[ii]] = conjugator[arr_in[ii]];
  362. return;
  363. }
  364. /* ========================================================================= */
  365. void two_cycle(int array[], int ind0, int ind1)
  366. /* ------------------------------------------------------------------------- */
  367. {
  368. int temp;
  369. temp = array[ind0];
  370. array[ind0] = array[ind1];
  371. array[ind1] = temp;
  372. return;
  373. }
  374. /* ========================================================================= */
  375. void three_cycle(int array[], int ind0, int ind1, int ind2)
  376. /* ------------------------------------------------------------------------- */
  377. {
  378. int temp;
  379. temp = array[ind0];
  380. array[ind0] = array[ind1];
  381. array[ind1] = array[ind2];
  382. array[ind2] = temp;
  383. return;
  384. }
  385. /* ========================================================================= */
  386. void four_cycle(int array[], int ind0, int ind1, int ind2, int ind3)
  387. /* ------------------------------------------------------------------------- */
  388. {
  389. int temp;
  390. temp = array[ind0];
  391. array[ind0] = array[ind1];
  392. array[ind1] = array[ind2];
  393. array[ind2] = array[ind3];
  394. array[ind3] = temp;
  395. return;
  396. }
  397. /* ========================================================================= */
  398. void print_cube(Cube *p_cube)
  399. /* ------------------------------------------------------------------------- */
  400. {
  401. printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
  402. edge_cubie_str[p_cube->edges[0]], edge_cubie_str[p_cube->edges[1]],
  403. edge_cubie_str[p_cube->edges[2]], edge_cubie_str[p_cube->edges[3]],
  404. edge_cubie_str[p_cube->edges[4]], edge_cubie_str[p_cube->edges[5]],
  405. edge_cubie_str[p_cube->edges[6]], edge_cubie_str[p_cube->edges[7]],
  406. edge_cubie_str[p_cube->edges[8]], edge_cubie_str[p_cube->edges[9]],
  407. edge_cubie_str[p_cube->edges[10]], edge_cubie_str[p_cube->edges[11]],
  408. corner_cubie_str[p_cube->corners[0]], corner_cubie_str[p_cube->corners[1]],
  409. corner_cubie_str[p_cube->corners[2]], corner_cubie_str[p_cube->corners[3]],
  410. corner_cubie_str[p_cube->corners[4]], corner_cubie_str[p_cube->corners[5]],
  411. corner_cubie_str[p_cube->corners[6]], corner_cubie_str[p_cube->corners[7]]);
  412. return;
  413. }
  414. /* ========================================================================= */
  415. void cube_init(Cube *p_cube)
  416. /* ------------------------------------------------------------------------- */
  417. {
  418. perm_n_init(24, p_cube->edges);
  419. perm_n_init(24, p_cube->corners);
  420. return;
  421. }
  422. /* ========================================================================= */
  423. int cube_compare(Cube *cube0, Cube *cube1)
  424. /* ------------------------------------------------------------------------- */
  425. {
  426. int ii;
  427. for (ii = 0; ii < 24; ii++)
  428. {
  429. if (cube0->edges[ii] < cube1->edges[ii])
  430. return -1;
  431. else if (cube0->edges[ii] > cube1->edges[ii])
  432. return 1;
  433. }
  434. for (ii = 0; ii < 24; ii++)
  435. {
  436. if (cube0->corners[ii] < cube1->corners[ii])
  437. return -1;
  438. else if (cube0->corners[ii] > cube1->corners[ii])
  439. return 1;
  440. }
  441. return 0;
  442. }
  443. /* ========================================================================= */
  444. void cube_compose(Cube *in_cube0, Cube *in_cube1, Cube *out_cube)
  445. /* ------------------------------------------------------------------------- */
  446. {
  447. perm_n_compose(24, in_cube0->edges, in_cube1->edges, out_cube->edges);
  448. perm_n_compose(24, in_cube0->corners, in_cube1->corners, out_cube->corners);
  449. return;
  450. }
  451. /* ========================================================================= */
  452. void cube_conjugate(Cube *p_cube_in, Cube *p_conjugator,
  453. Cube *p_cube_out)
  454. /* ------------------------------------------------------------------------- */
  455. {
  456. perm_n_conjugate(24, p_cube_in->edges, p_conjugator->edges, p_cube_out->edges);
  457. perm_n_conjugate(24, p_cube_in->corners, p_conjugator->corners,
  458. p_cube_out->corners);
  459. return;
  460. }
  461. /* ========================================================================= */
  462. int cube_is_solved(Cube *p_cube)
  463. /* ------------------------------------------------------------------------- */
  464. {
  465. Cube temp_cube;
  466. cube_init(&temp_cube);
  467. return (cube_compare(p_cube, &temp_cube) == 0);
  468. }
  469. /* ========================================================================= */
  470. int metric_q_length(int twist)
  471. /* ------------------------------------------------------------------------- */
  472. {
  473. if ((twist == TWIST_F) || (twist == TWIST_F3) ||
  474. (twist == TWIST_R) || (twist == TWIST_R3) ||
  475. (twist == TWIST_U) || (twist == TWIST_U3) ||
  476. (twist == TWIST_B) || (twist == TWIST_B3) ||
  477. (twist == TWIST_L) || (twist == TWIST_L3) ||
  478. (twist == TWIST_D) || (twist == TWIST_D3))
  479. return 1;
  480. else if ((twist == TWIST_F2) || (twist == TWIST_R2) || (twist == TWIST_U2) ||
  481. (twist == TWIST_B2) || (twist == TWIST_L2) || (twist == TWIST_D2))
  482. return 2;
  483. else
  484. exit_w_error_message("metric_q_length : invalid twist");
  485. return 0;
  486. }
  487. /* ========================================================================= */
  488. int metric_f_length(int twist)
  489. /* ------------------------------------------------------------------------- */
  490. {
  491. if ((twist == TWIST_F) || (twist == TWIST_F2) || (twist == TWIST_F3) ||
  492. (twist == TWIST_R) || (twist == TWIST_R2) || (twist == TWIST_R3) ||
  493. (twist == TWIST_U) || (twist == TWIST_U2) || (twist == TWIST_U3) ||
  494. (twist == TWIST_B) || (twist == TWIST_B2) || (twist == TWIST_B3) ||
  495. (twist == TWIST_L) || (twist == TWIST_L2) || (twist == TWIST_L3) ||
  496. (twist == TWIST_D) || (twist == TWIST_D2) || (twist == TWIST_D3))
  497. return 1;
  498. else
  499. exit_w_error_message("metric_f_length : invalid twist");
  500. return 0;
  501. }
  502. /* ========================================================================= */
  503. void calc_metric_q_length(int lengths[N_TWIST])
  504. /* ------------------------------------------------------------------------- */
  505. {
  506. int twist;
  507. for (twist = 0; twist < N_TWIST; twist++)
  508. lengths[twist] = metric_q_length(twist);
  509. return;
  510. }
  511. /* ========================================================================= */
  512. void calc_metric_f_length(int lengths[N_TWIST])
  513. /* ------------------------------------------------------------------------- */
  514. {
  515. int twist;
  516. for (twist = 0; twist < N_TWIST; twist++)
  517. lengths[twist] = metric_f_length(twist);
  518. return;
  519. }
  520. /* ========================================================================= */
  521. void init_metric(Metric_data *p_metric_data, int use_metric)
  522. /* ------------------------------------------------------------------------- */
  523. {
  524. if ((use_metric != QUARTER_TURN_METRIC) && (use_metric != FACE_TURN_METRIC))
  525. exit_w_error_message("init_metric : unknown metric");
  526. p_metric_data->metric = use_metric;
  527. if (p_metric_data->metric == QUARTER_TURN_METRIC)
  528. {
  529. printf("using quarter turn metric\n");
  530. p_metric_data->metric_char = 'q';
  531. calc_metric_q_length(p_metric_data->twist_length);
  532. p_metric_data->increment = 2;
  533. }
  534. else
  535. {
  536. printf("using face turn metric\n");
  537. p_metric_data->metric_char = 'f';
  538. calc_metric_f_length(p_metric_data->twist_length);
  539. p_metric_data->increment = 1;
  540. }
  541. p_current_metric = p_metric_data;
  542. return;
  543. }
  544. /* ========================================================================= */
  545. void init_options(Metric_data *p_metric_data, Options *p_user_options)
  546. /* ------------------------------------------------------------------------- */
  547. {
  548. init_metric(p_metric_data, USE_METRIC);
  549. p_user_options->search_limit = SEARCH_LIMIT;
  550. if (p_user_options->search_limit <= 0)
  551. printf("no search limit\n");
  552. else
  553. printf("search limit: %d%c\n", p_user_options->search_limit,
  554. p_current_metric->metric_char);
  555. p_user_options->use_symmetry = USE_SYMMETRY;
  556. if (p_user_options->use_symmetry)
  557. printf("using symmetry reductions\n");
  558. else
  559. printf("not using symmetry reductions\n");
  560. p_user_options->one_solution_only = ONE_SOLUTION_ONLY;
  561. if (p_user_options->one_solution_only)
  562. printf("only finding one solution\n");
  563. else
  564. printf("finding all solutions\n");
  565. printf("\n");
  566. p_current_options = p_user_options;
  567. return;
  568. }
  569. /* ========================================================================= */
  570. void calc_group_table(int group_table[N_CUBESYM][N_CUBESYM])
  571. /* ------------------------------------------------------------------------- */
  572. {
  573. int sym_array[N_CUBESYM][6];
  574. int sym_pack[N_CUBESYM];
  575. int temp_array[6];
  576. int ii, jj, kk, pack;
  577. perm_n_init(6, sym_array[0]);
  578. perm_n_init(6, sym_array[1]);
  579. four_cycle(sym_array[1], FACE_F, FACE_L, FACE_B, FACE_R);
  580. for (ii = 2; ii < 4; ii++)
  581. perm_n_compose(6, sym_array[1], sym_array[ii - 1], sym_array[ii]);
  582. perm_n_init(6, sym_array[4]);
  583. two_cycle(sym_array[4], FACE_U, FACE_D);
  584. two_cycle(sym_array[4], FACE_R, FACE_L);
  585. for (ii = 5; ii < 8; ii++)
  586. perm_n_compose(6, sym_array[4], sym_array[ii - 4], sym_array[ii]);
  587. perm_n_init(6, sym_array[8]);
  588. two_cycle(sym_array[8], FACE_U, FACE_D);
  589. for (ii = 9; ii < 16; ii++)
  590. perm_n_compose(6, sym_array[8], sym_array[ii - 8], sym_array[ii]);
  591. perm_n_init(6, sym_array[16]);
  592. three_cycle(sym_array[16], FACE_U, FACE_F, FACE_R);
  593. three_cycle(sym_array[16], FACE_D, FACE_B, FACE_L);
  594. for (ii = 17; ii < 48; ii++)
  595. perm_n_compose(6, sym_array[16], sym_array[ii - 16], sym_array[ii]);
  596. for (ii = 0; ii < N_CUBESYM; ii++)
  597. sym_pack[ii] = perm_n_pack(6, sym_array[ii]);
  598. for (ii = 0; ii < N_CUBESYM; ii++)
  599. for (jj = 0; jj < N_CUBESYM; jj++)
  600. {
  601. perm_n_compose(6, sym_array[ii], sym_array[jj], temp_array);
  602. pack = perm_n_pack(6, temp_array);
  603. for (kk = 0; kk < N_CUBESYM; kk++)
  604. if (sym_pack[kk] == pack)
  605. {
  606. group_table[ii][jj] = kk;
  607. break;
  608. }
  609. if (kk == N_CUBESYM)
  610. exit_w_error_message("calc_group_table : product not found");
  611. }
  612. return;
  613. }
  614. /* ========================================================================= */
  615. void init_sym_x_invsym_to_sym(void)
  616. /* ------------------------------------------------------------------------- */
  617. {
  618. unsigned char (*mem_ptr)[N_SYM];
  619. int group_table[N_CUBESYM][N_CUBESYM];
  620. int group_inverse[N_CUBESYM];
  621. int ii, jj;
  622. /* initialize global array sym_x_invsym_to_sym */
  623. mem_ptr =
  624. (unsigned char (*)[N_SYM])malloc(sizeof(unsigned char [N_SYM][N_SYM]));
  625. if (mem_ptr == NULL)
  626. exit_w_error_message("init_sym_x_invsym_to_sym : couldn't get memory");
  627. for (ii = 0; ii < N_SYM; ii++)
  628. sym_x_invsym_to_sym[ii] = mem_ptr[ii];
  629. calc_group_table(group_table);
  630. for (ii = 0; ii < N_SYM; ii++)
  631. {
  632. for (jj = 0; jj < N_SYM; jj++)
  633. if (group_table[ii][jj] == 0)
  634. {
  635. group_inverse[ii] = jj;
  636. break;
  637. }
  638. if (jj == N_SYM)
  639. exit_w_error_message("init_sym_x_invsym_to_sym : inverse not found");
  640. }
  641. for (ii = 0; ii < N_SYM; ii++)
  642. for (jj = 0; jj < N_SYM; jj++)
  643. sym_x_invsym_to_sym[ii][jj] =
  644. (unsigned char)group_table[ii][group_inverse[jj]];
  645. return;
  646. }
  647. /* ========================================================================= */
  648. void calc_sym_on_twist(int sym_on_twist[N_CUBESYM][N_TWIST])
  649. /* ------------------------------------------------------------------------- */
  650. {
  651. int sym;
  652. perm_n_init(N_TWIST, sym_on_twist[0]);
  653. perm_n_init(N_TWIST, sym_on_twist[1]);
  654. four_cycle(sym_on_twist[1], TWIST_F , TWIST_L , TWIST_B , TWIST_R );
  655. four_cycle(sym_on_twist[1], TWIST_F2, TWIST_L2, TWIST_B2, TWIST_R2);
  656. four_cycle(sym_on_twist[1], TWIST_F3, TWIST_L3, TWIST_B3, TWIST_R3);
  657. for (sym = 2; sym < 4; sym++)
  658. perm_n_compose(N_TWIST, sym_on_twist[1], sym_on_twist[sym - 1],
  659. sym_on_twist[sym]);
  660. perm_n_init(N_TWIST, sym_on_twist[4]);
  661. two_cycle(sym_on_twist[4], TWIST_R , TWIST_L );
  662. two_cycle(sym_on_twist[4], TWIST_R2, TWIST_L2);
  663. two_cycle(sym_on_twist[4], TWIST_R3, TWIST_L3);
  664. two_cycle(sym_on_twist[4], TWIST_U , TWIST_D );
  665. two_cycle(sym_on_twist[4], TWIST_U2, TWIST_D2);
  666. two_cycle(sym_on_twist[4], TWIST_U3, TWIST_D3);
  667. for (sym = 5; sym < 8; sym++)
  668. perm_n_compose(N_TWIST, sym_on_twist[4], sym_on_twist[sym - 4],
  669. sym_on_twist[sym]);
  670. perm_n_init(N_TWIST, sym_on_twist[8]);
  671. two_cycle(sym_on_twist[8], TWIST_F, TWIST_F3);
  672. two_cycle(sym_on_twist[8], TWIST_R, TWIST_R3);
  673. two_cycle(sym_on_twist[8], TWIST_B, TWIST_B3);
  674. two_cycle(sym_on_twist[8], TWIST_L, TWIST_L3);
  675. two_cycle(sym_on_twist[8], TWIST_U , TWIST_D3);
  676. two_cycle(sym_on_twist[8], TWIST_U2, TWIST_D2);
  677. two_cycle(sym_on_twist[8], TWIST_U3, TWIST_D );
  678. for (sym = 9; sym < 16; sym++)
  679. perm_n_compose(N_TWIST, sym_on_twist[8], sym_on_twist[sym - 8],
  680. sym_on_twist[sym]);
  681. perm_n_init(N_TWIST, sym_on_twist[16]);
  682. three_cycle(sym_on_twist[16], TWIST_F , TWIST_R , TWIST_U );
  683. three_cycle(sym_on_twist[16], TWIST_F2, TWIST_R2, TWIST_U2);
  684. three_cycle(sym_on_twist[16], TWIST_F3, TWIST_R3, TWIST_U3);
  685. three_cycle(sym_on_twist[16], TWIST_B , TWIST_L , TWIST_D );
  686. three_cycle(sym_on_twist[16], TWIST_B2, TWIST_L2, TWIST_D2);
  687. three_cycle(sym_on_twist[16], TWIST_B3, TWIST_L3, TWIST_D3);
  688. for (sym = 17; sym < 48; sym++)
  689. perm_n_compose(N_TWIST, sym_on_twist[16], sym_on_twist[sym - 16],
  690. sym_on_twist[sym]);
  691. return;
  692. }
  693. /* ========================================================================= */
  694. void init_invsym_on_twist(void)
  695. /* ------------------------------------------------------------------------- */
  696. {
  697. unsigned char (*mem_ptr)[N_SYM][N_TWIST];
  698. int sym_on_twist[N_CUBESYM][N_TWIST];
  699. int ud_to_rl[N_TWIST], sym, twist;
  700. /* allocate and initialize global arrays */
  701. /* invsym_on_twist_ud , invsym_on_twist_fb and invsym_on_twist_rl */
  702. mem_ptr = (unsigned char (*)[N_SYM][N_TWIST])
  703. malloc(sizeof(unsigned char [3][N_SYM][N_TWIST]));
  704. if (mem_ptr == NULL)
  705. exit_w_error_message("init_invsym_on_twist : couldn't get memory");
  706. for (sym = 0; sym < N_SYM; sym++)
  707. {
  708. invsym_on_twist_ud[sym] = mem_ptr[0][sym];
  709. invsym_on_twist_rl[sym] = mem_ptr[1][sym];
  710. invsym_on_twist_fb[sym] = mem_ptr[2][sym];
  711. }
  712. calc_sym_on_twist(sym_on_twist);
  713. for (sym = 0; sym < N_SYM; sym++)
  714. for (twist = 0; twist < N_TWIST; twist++)
  715. invsym_on_twist_ud[sym][twist] =
  716. (unsigned char)sym_on_twist[(int)sym_x_invsym_to_sym[0][sym]][twist];
  717. perm_n_init(N_TWIST, ud_to_rl);
  718. three_cycle(ud_to_rl, TWIST_F , TWIST_R , TWIST_U );
  719. three_cycle(ud_to_rl, TWIST_F2, TWIST_R2, TWIST_U2);
  720. three_cycle(ud_to_rl, TWIST_F3, TWIST_R3, TWIST_U3);
  721. three_cycle(ud_to_rl, TWIST_B , TWIST_L , TWIST_D );
  722. three_cycle(ud_to_rl, TWIST_B2, TWIST_L2, TWIST_D2);
  723. three_cycle(ud_to_rl, TWIST_B3, TWIST_L3, TWIST_D3);
  724. for (sym = 0; sym < N_SYM; sym++)
  725. for (twist = 0; twist < N_TWIST; twist++)
  726. invsym_on_twist_rl[sym][twist] =
  727. invsym_on_twist_ud[sym][ud_to_rl[twist]];
  728. for (sym = 0; sym < N_SYM; sym++)
  729. for (twist = 0; twist < N_TWIST; twist++)
  730. invsym_on_twist_fb[sym][twist] =
  731. invsym_on_twist_rl[sym][ud_to_rl[twist]];
  732. return;
  733. }
  734. /* ========================================================================= */
  735. void generate_subgroup(int group_table[N_CUBESYM][N_CUBESYM],
  736. int gen_set[N_CUBESYM])
  737. /* ------------------------------------------------------------------------- */
  738. /* gen_set[] is both input and output */
  739. {
  740. int found, ii, jj;
  741. gen_set[0] = 1;
  742. found = 1;
  743. while (found)
  744. {
  745. found = 0;
  746. for (ii = 0; ii < N_CUBESYM; ii++)
  747. if (gen_set[ii] != 0)
  748. for (jj = 0; jj < N_CUBESYM; jj++)
  749. if ((gen_set[jj] != 0) && (gen_set[group_table[ii][jj]] == 0))
  750. {
  751. gen_set[group_table[ii][jj]] = 1;
  752. found = 1;
  753. }
  754. }
  755. return;
  756. }
  757. /* ========================================================================= */
  758. void calc_subgroups_recursive(int group_table[N_CUBESYM][N_CUBESYM],
  759. int contain_list[N_CUBESYM],
  760. int avoid_list[N_CUBESYM],
  761. Subgroup_list *p_output)
  762. /* ------------------------------------------------------------------------- */
  763. {
  764. int local_contain_list[N_CUBESYM], ii, jj;
  765. for (ii = 0; ii < N_CUBESYM; ii++)
  766. if (contain_list[ii] && avoid_list[ii])
  767. return;
  768. for (ii = 0; ii < N_CUBESYM; ii++)
  769. if ((contain_list[ii] == 0) && (avoid_list[ii] == 0))
  770. break;
  771. if (ii < N_CUBESYM)
  772. {
  773. for (jj = 0; jj < N_CUBESYM; jj++)
  774. local_contain_list[jj] = contain_list[jj];
  775. local_contain_list[ii] = 1;
  776. generate_subgroup(group_table, local_contain_list);
  777. calc_subgroups_recursive(group_table, local_contain_list, avoid_list,
  778. p_output);
  779. avoid_list[ii] = 1;
  780. calc_subgroups_recursive(group_table, contain_list, avoid_list, p_output);
  781. avoid_list[ii] = 0;
  782. }
  783. else
  784. {
  785. if (p_output->n_subgroups >= N_SYMSUBGRP)
  786. exit_w_error_message("calc_subgroups_recursive : too many subgroups");
  787. for (ii = 0; ii < N_CUBESYM; ii++)
  788. p_output->subgroups[p_output->n_subgroups][ii] = contain_list[ii];
  789. p_output->n_subgroups++;
  790. }
  791. return;
  792. }
  793. /* ========================================================================= */
  794. void calc_subgroup_list(int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
  795. /* ------------------------------------------------------------------------- */
  796. {
  797. Subgroup_list output_list;
  798. int group_table[N_CUBESYM][N_CUBESYM];
  799. int contain_list[N_CUBESYM];
  800. int avoid_list[N_CUBESYM];
  801. int ii;
  802. calc_group_table(group_table);
  803. output_list.n_subgroups = 0;
  804. output_list.subgroups = subgroup_list;
  805. contain_list[0] = 1;
  806. for (ii = 1; ii < N_CUBESYM; ii++)
  807. contain_list[ii] = 0;
  808. for (ii = 0; ii < N_CUBESYM; ii++)
  809. avoid_list[ii] = 0;
  810. calc_subgroups_recursive(group_table, contain_list, avoid_list, &output_list);
  811. if (output_list.n_subgroups != N_SYMSUBGRP)
  812. exit_w_error_message("calc_subgroup_list : wrong number of subgroups");
  813. return;
  814. }
  815. /* ========================================================================= */
  816. int is_single_twist(int syllable)
  817. /* ------------------------------------------------------------------------- */
  818. {
  819. if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
  820. (syllable == SYLLABLE_F3) ||
  821. (syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
  822. (syllable == SYLLABLE_R3) ||
  823. (syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
  824. (syllable == SYLLABLE_U3) ||
  825. (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  826. (syllable == SYLLABLE_B3) ||
  827. (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  828. (syllable == SYLLABLE_L3) ||
  829. (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  830. (syllable == SYLLABLE_D3))
  831. return 1;
  832. return 0;
  833. }
  834. /* ========================================================================= */
  835. int syllable_to_twist(int syllable)
  836. /* ------------------------------------------------------------------------- */
  837. {
  838. if (syllable == SYLLABLE_F)
  839. return TWIST_F;
  840. else if (syllable == SYLLABLE_F2)
  841. return TWIST_F2;
  842. else if (syllable == SYLLABLE_F3)
  843. return TWIST_F3;
  844. else if (syllable == SYLLABLE_R)
  845. return TWIST_R;
  846. else if (syllable == SYLLABLE_R2)
  847. return TWIST_R2;
  848. else if (syllable == SYLLABLE_R3)
  849. return TWIST_R3;
  850. else if (syllable == SYLLABLE_U)
  851. return TWIST_U;
  852. else if (syllable == SYLLABLE_U2)
  853. return TWIST_U2;
  854. else if (syllable == SYLLABLE_U3)
  855. return TWIST_U3;
  856. else if (syllable == SYLLABLE_B)
  857. return TWIST_B;
  858. else if (syllable == SYLLABLE_B2)
  859. return TWIST_B2;
  860. else if (syllable == SYLLABLE_B3)
  861. return TWIST_B3;
  862. else if (syllable == SYLLABLE_L)
  863. return TWIST_L;
  864. else if (syllable == SYLLABLE_L2)
  865. return TWIST_L2;
  866. else if (syllable == SYLLABLE_L3)
  867. return TWIST_L3;
  868. else if (syllable == SYLLABLE_D)
  869. return TWIST_D;
  870. else if (syllable == SYLLABLE_D2)
  871. return TWIST_D2;
  872. else if (syllable == SYLLABLE_D3)
  873. return TWIST_D3;
  874. else
  875. exit_w_error_message("syllable_to_twist : invalid input");
  876. return -1;
  877. }
  878. /* ========================================================================= */
  879. void syllable_to_two_twists(int syllable, int twists_out[2])
  880. /* ------------------------------------------------------------------------- */
  881. {
  882. if (syllable == SYLLABLE_FB)
  883. {
  884. twists_out[0] = TWIST_F;
  885. twists_out[1] = TWIST_B;
  886. }
  887. else if (syllable == SYLLABLE_FB2)
  888. {
  889. twists_out[0] = TWIST_F;
  890. twists_out[1] = TWIST_B2;
  891. }
  892. else if (syllable == SYLLABLE_FB3)
  893. {
  894. twists_out[0] = TWIST_F;
  895. twists_out[1] = TWIST_B3;
  896. }
  897. else if (syllable == SYLLABLE_F2B2)
  898. {
  899. twists_out[0] = TWIST_F2;
  900. twists_out[1] = TWIST_B2;
  901. }
  902. else if (syllable == SYLLABLE_RL)
  903. {
  904. twists_out[0] = TWIST_R;
  905. twists_out[1] = TWIST_L;
  906. }
  907. else if (syllable == SYLLABLE_RL2)
  908. {
  909. twists_out[0] = TWIST_R;
  910. twists_out[1] = TWIST_L2;
  911. }
  912. else if (syllable == SYLLABLE_RL3)
  913. {
  914. twists_out[0] = TWIST_R;
  915. twists_out[1] = TWIST_L3;
  916. }
  917. else if (syllable == SYLLABLE_R2L2)
  918. {
  919. twists_out[0] = TWIST_R2;
  920. twists_out[1] = TWIST_L2;
  921. }
  922. else if (syllable == SYLLABLE_UD)
  923. {
  924. twists_out[0] = TWIST_U;
  925. twists_out[1] = TWIST_D;
  926. }
  927. else if (syllable == SYLLABLE_UD2)
  928. {
  929. twists_out[0] = TWIST_U;
  930. twists_out[1] = TWIST_D2;
  931. }
  932. else if (syllable == SYLLABLE_UD3)
  933. {
  934. twists_out[0] = TWIST_U;
  935. twists_out[1] = TWIST_D3;
  936. }
  937. else if (syllable == SYLLABLE_U2D2)
  938. {
  939. twists_out[0] = TWIST_U2;
  940. twists_out[1] = TWIST_D2;
  941. }
  942. else
  943. exit_w_error_message("syllable_to_two_twists : invalid input");
  944. return;
  945. }
  946. /* ========================================================================= */
  947. int twists_in_wrong_order(int twists[2])
  948. /* ------------------------------------------------------------------------- */
  949. {
  950. if (((twists[0] == TWIST_B) || (twists[0] == TWIST_B2) ||
  951. (twists[0] == TWIST_B3)) &&
  952. ((twists[1] == TWIST_F) || (twists[1] == TWIST_F2) ||
  953. (twists[1] == TWIST_F3)))
  954. return 1;
  955. if (((twists[0] == TWIST_L) || (twists[0] == TWIST_L2) ||
  956. (twists[0] == TWIST_L3)) &&
  957. ((twists[1] == TWIST_R) || (twists[1] == TWIST_R2) ||
  958. (twists[1] == TWIST_R3)))
  959. return 1;
  960. if (((twists[0] == TWIST_D) || (twists[0] == TWIST_D2) ||
  961. (twists[0] == TWIST_D3)) &&
  962. ((twists[1] == TWIST_U) || (twists[1] == TWIST_U2) ||
  963. (twists[1] == TWIST_U3)))
  964. return 1;
  965. return 0;
  966. }
  967. /* ========================================================================= */
  968. void clean_up_sequence(int twist_sequence[], int n_twists)
  969. /* ------------------------------------------------------------------------- */
  970. {
  971. int ii;
  972. for (ii = 1; ii < n_twists; ii++)
  973. if (twists_in_wrong_order(&twist_sequence[ii - 1]) != 0)
  974. two_cycle(twist_sequence, ii - 1, ii);
  975. return;
  976. }
  977. /* ========================================================================= */
  978. int which_subgroup(int subgroup[N_CUBESYM],
  979. int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
  980. /* ------------------------------------------------------------------------- */
  981. {
  982. int subgrp, sym;
  983. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  984. {
  985. for (sym = 0; sym < N_CUBESYM; sym++)
  986. if ((subgroup[sym] == 0) != (subgroup_list[subgrp][sym] == 0))
  987. break;
  988. if (sym == N_CUBESYM)
  989. return subgrp;
  990. }
  991. return -1;
  992. }
  993. /* ========================================================================= */
  994. void calc_syllable_on_sym(int subgroup_list[N_SYMSUBGRP][N_CUBESYM],
  995. int sym_on_twist[N_CUBESYM][N_TWIST],
  996. int syllable_on_sym[N_SYLLABLE][N_SYMSUBGRP])
  997. /* ------------------------------------------------------------------------- */
  998. {
  999. int subgroup[N_CUBESYM], temp_subgroup[N_CUBESYM];
  1000. int twist_arr[2], temp_arr[2];
  1001. int syllable, sym, subgrp, twist;
  1002. for (syllable = 0; syllable < N_SYLLABLE; syllable++)
  1003. {
  1004. if ((syllable == SYLLABLE_INVALID) || (syllable == SYLLABLE_NONE))
  1005. {
  1006. subgroup[0] = 1;
  1007. for (sym = 1; sym < N_CUBESYM; sym++)
  1008. subgroup[sym] = 0;
  1009. }
  1010. else if (is_single_twist(syllable))
  1011. {
  1012. twist = syllable_to_twist(syllable);
  1013. for (sym = 0; sym < N_CUBESYM; sym++)
  1014. subgroup[sym] = (sym_on_twist[sym][twist] == twist);
  1015. }
  1016. else
  1017. {
  1018. syllable_to_two_twists(syllable, twist_arr);
  1019. for (sym = 0; sym < N_CUBESYM; sym++)
  1020. {
  1021. temp_arr[0] = sym_on_twist[sym][twist_arr[0]];
  1022. temp_arr[1] = sym_on_twist[sym][twist_arr[1]];
  1023. clean_up_sequence(temp_arr, 2);
  1024. if ((temp_arr[0] == twist_arr[0]) &&
  1025. (temp_arr[1] == twist_arr[1]))
  1026. subgroup[sym] = 1;
  1027. else
  1028. subgroup[sym] = 0;
  1029. }
  1030. }
  1031. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1032. {
  1033. for (sym = 0; sym < N_CUBESYM; sym++)
  1034. temp_subgroup[sym] = (subgroup[sym] && subgroup_list[subgrp][sym]);
  1035. syllable_on_sym[syllable][subgrp] = which_subgroup(temp_subgroup,
  1036. subgroup_list);
  1037. if (syllable_on_sym[syllable][subgrp] < 0)
  1038. exit_w_error_message("calc_syllable_on_sym : subgroup not found");
  1039. }
  1040. }
  1041. return;
  1042. }
  1043. /* ========================================================================= */
  1044. int twist_on_syllable(int twist, int syllable)
  1045. /* ------------------------------------------------------------------------- */
  1046. {
  1047. if (syllable == SYLLABLE_INVALID)
  1048. return SYLLABLE_INVALID;
  1049. if (twist == TWIST_F)
  1050. {
  1051. if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
  1052. (syllable == SYLLABLE_F3) ||
  1053. (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1054. (syllable == SYLLABLE_B3) ||
  1055. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1056. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1057. return SYLLABLE_INVALID;
  1058. else
  1059. return SYLLABLE_F;
  1060. }
  1061. else if (twist == TWIST_F2)
  1062. {
  1063. if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
  1064. (syllable == SYLLABLE_F3) ||
  1065. (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1066. (syllable == SYLLABLE_B3) ||
  1067. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1068. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1069. return SYLLABLE_INVALID;
  1070. else
  1071. return SYLLABLE_F2;
  1072. }
  1073. else if (twist == TWIST_F3)
  1074. {
  1075. if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
  1076. (syllable == SYLLABLE_F3) ||
  1077. (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1078. (syllable == SYLLABLE_B3) ||
  1079. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1080. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1081. return SYLLABLE_INVALID;
  1082. else
  1083. return SYLLABLE_F3;
  1084. }
  1085. else if (twist == TWIST_R)
  1086. {
  1087. if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
  1088. (syllable == SYLLABLE_R3) ||
  1089. (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1090. (syllable == SYLLABLE_L3) ||
  1091. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1092. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1093. return SYLLABLE_INVALID;
  1094. else
  1095. return SYLLABLE_R;
  1096. }
  1097. else if (twist == TWIST_R2)
  1098. {
  1099. if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
  1100. (syllable == SYLLABLE_R3) ||
  1101. (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1102. (syllable == SYLLABLE_L3) ||
  1103. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1104. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1105. return SYLLABLE_INVALID;
  1106. else
  1107. return SYLLABLE_R2;
  1108. }
  1109. else if (twist == TWIST_R3)
  1110. {
  1111. if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
  1112. (syllable == SYLLABLE_R3) ||
  1113. (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1114. (syllable == SYLLABLE_L3) ||
  1115. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1116. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1117. return SYLLABLE_INVALID;
  1118. else
  1119. return SYLLABLE_R3;
  1120. }
  1121. else if (twist == TWIST_U)
  1122. {
  1123. if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
  1124. (syllable == SYLLABLE_U3) ||
  1125. (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1126. (syllable == SYLLABLE_D3) ||
  1127. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1128. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1129. return SYLLABLE_INVALID;
  1130. else
  1131. return SYLLABLE_U;
  1132. }
  1133. else if (twist == TWIST_U2)
  1134. {
  1135. if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
  1136. (syllable == SYLLABLE_U3) ||
  1137. (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1138. (syllable == SYLLABLE_D3) ||
  1139. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1140. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1141. return SYLLABLE_INVALID;
  1142. else
  1143. return SYLLABLE_U2;
  1144. }
  1145. else if (twist == TWIST_U3)
  1146. {
  1147. if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
  1148. (syllable == SYLLABLE_U3) ||
  1149. (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1150. (syllable == SYLLABLE_D3) ||
  1151. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1152. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1153. return SYLLABLE_INVALID;
  1154. else
  1155. return SYLLABLE_U3;
  1156. }
  1157. else if (twist == TWIST_B)
  1158. {
  1159. if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1160. (syllable == SYLLABLE_B3) ||
  1161. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1162. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1163. return SYLLABLE_INVALID;
  1164. else if (syllable == SYLLABLE_F)
  1165. return SYLLABLE_FB;
  1166. else if (syllable == SYLLABLE_F2)
  1167. return SYLLABLE_FB2;
  1168. else if (syllable == SYLLABLE_F3)
  1169. return SYLLABLE_FB3;
  1170. else
  1171. return SYLLABLE_B;
  1172. }
  1173. else if (twist == TWIST_B2)
  1174. {
  1175. if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1176. (syllable == SYLLABLE_B3) ||
  1177. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1178. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1179. return SYLLABLE_INVALID;
  1180. else if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F3))
  1181. return SYLLABLE_FB2;
  1182. else if (syllable == SYLLABLE_F2)
  1183. return SYLLABLE_F2B2;
  1184. else
  1185. return SYLLABLE_B2;
  1186. }
  1187. else if (twist == TWIST_B3)
  1188. {
  1189. if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
  1190. (syllable == SYLLABLE_B3) ||
  1191. (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
  1192. (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
  1193. return SYLLABLE_INVALID;
  1194. else if (syllable == SYLLABLE_F)
  1195. return SYLLABLE_FB3;
  1196. else if (syllable == SYLLABLE_F2)
  1197. return SYLLABLE_FB2;
  1198. else if (syllable == SYLLABLE_F3)
  1199. return SYLLABLE_FB;
  1200. else
  1201. return SYLLABLE_B3;
  1202. }
  1203. else if (twist == TWIST_L)
  1204. {
  1205. if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1206. (syllable == SYLLABLE_L3) ||
  1207. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1208. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1209. return SYLLABLE_INVALID;
  1210. else if (syllable == SYLLABLE_R)
  1211. return SYLLABLE_RL;
  1212. else if (syllable == SYLLABLE_R2)
  1213. return SYLLABLE_RL2;
  1214. else if (syllable == SYLLABLE_R3)
  1215. return SYLLABLE_RL3;
  1216. else
  1217. return SYLLABLE_L;
  1218. }
  1219. else if (twist == TWIST_L2)
  1220. {
  1221. if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1222. (syllable == SYLLABLE_L3) ||
  1223. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1224. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1225. return SYLLABLE_INVALID;
  1226. else if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R3))
  1227. return SYLLABLE_RL2;
  1228. else if (syllable == SYLLABLE_R2)
  1229. return SYLLABLE_R2L2;
  1230. else
  1231. return SYLLABLE_L2;
  1232. }
  1233. else if (twist == TWIST_L3)
  1234. {
  1235. if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
  1236. (syllable == SYLLABLE_L3) ||
  1237. (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
  1238. (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
  1239. return SYLLABLE_INVALID;
  1240. else if (syllable == SYLLABLE_R)
  1241. return SYLLABLE_RL3;
  1242. else if (syllable == SYLLABLE_R2)
  1243. return SYLLABLE_RL2;
  1244. else if (syllable == SYLLABLE_R3)
  1245. return SYLLABLE_RL;
  1246. else
  1247. return SYLLABLE_L3;
  1248. }
  1249. else if (twist == TWIST_D)
  1250. {
  1251. if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1252. (syllable == SYLLABLE_D3) ||
  1253. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1254. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1255. return SYLLABLE_INVALID;
  1256. else if (syllable == SYLLABLE_U)
  1257. return SYLLABLE_UD;
  1258. else if (syllable == SYLLABLE_U2)
  1259. return SYLLABLE_UD2;
  1260. else if (syllable == SYLLABLE_U3)
  1261. return SYLLABLE_UD3;
  1262. else
  1263. return SYLLABLE_D;
  1264. }
  1265. else if (twist == TWIST_D2)
  1266. {
  1267. if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1268. (syllable == SYLLABLE_D3) ||
  1269. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1270. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1271. return SYLLABLE_INVALID;
  1272. else if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U3))
  1273. return SYLLABLE_UD2;
  1274. else if (syllable == SYLLABLE_U2)
  1275. return SYLLABLE_U2D2;
  1276. else
  1277. return SYLLABLE_D2;
  1278. }
  1279. else if (twist == TWIST_D3)
  1280. {
  1281. if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
  1282. (syllable == SYLLABLE_D3) ||
  1283. (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
  1284. (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
  1285. return SYLLABLE_INVALID;
  1286. else if (syllable == SYLLABLE_U)
  1287. return SYLLABLE_UD3;
  1288. else if (syllable == SYLLABLE_U2)
  1289. return SYLLABLE_UD2;
  1290. else if (syllable == SYLLABLE_U3)
  1291. return SYLLABLE_UD;
  1292. else
  1293. return SYLLABLE_D3;
  1294. }
  1295. else
  1296. exit_w_error_message("twist_on_syllable : invalid twist");
  1297. return SYLLABLE_INVALID;
  1298. }
  1299. /* ========================================================================= */
  1300. int not_minimal_one_twist(int subgroup[N_CUBESYM],
  1301. int sym_on_twist[N_CUBESYM][N_TWIST],
  1302. int twist)
  1303. /* ------------------------------------------------------------------------- */
  1304. {
  1305. int sym;
  1306. for (sym = 0; sym < N_CUBESYM; sym++)
  1307. if (subgroup[sym] && (sym_on_twist[sym][twist] < twist))
  1308. return 1;
  1309. return 0;
  1310. }
  1311. /* ========================================================================= */
  1312. int not_minimal_two_twists(int subgroup[N_CUBESYM],
  1313. int sym_on_twist[N_CUBESYM][N_TWIST],
  1314. int twist0, int twist1)
  1315. /* ------------------------------------------------------------------------- */
  1316. {
  1317. int twist_arr[2], sym;
  1318. for (sym = 0; sym < N_CUBESYM; sym++)
  1319. if (subgroup[sym])
  1320. {
  1321. twist_arr[0] = sym_on_twist[sym][twist0];
  1322. twist_arr[1] = sym_on_twist[sym][twist1];
  1323. clean_up_sequence(twist_arr, 2);
  1324. if ((twist_arr[0] < twist0) ||
  1325. ((twist_arr[0] == twist0) && (twist_arr[1] < twist1)))
  1326. return 1;
  1327. }
  1328. return 0;
  1329. }
  1330. /* ========================================================================= */
  1331. void calc_twist_on_sylsubgrp(int
  1332. tw_on_sylsubgrp[N_TWIST][N_SYLLABLE * N_SYMSUBGRP])
  1333. /* ------------------------------------------------------------------------- */
  1334. {
  1335. int subgroup_list[N_SYMSUBGRP][N_CUBESYM];
  1336. int sym_on_twist[N_CUBESYM][N_TWIST];
  1337. int syllable_on_subgrp[N_SYLLABLE][N_SYMSUBGRP];
  1338. int syllable, subgrp, subgrp_before, subgrp_after, twist;
  1339. int new_syllable, new_subgrp;
  1340. calc_subgroup_list(subgroup_list);
  1341. calc_sym_on_twist(sym_on_twist);
  1342. calc_syllable_on_sym(subgroup_list, sym_on_twist, syllable_on_subgrp);
  1343. for (syllable = 0; syllable < N_SYLLABLE; syllable++)
  1344. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1345. {
  1346. if (is_single_twist(syllable))
  1347. {
  1348. subgrp_before = subgrp;
  1349. subgrp_after = syllable_on_subgrp[syllable][subgrp];
  1350. }
  1351. else
  1352. {
  1353. subgrp_before = SUBGRP_TRIVIAL;
  1354. if (syllable == SYLLABLE_INVALID)
  1355. subgrp_after = SUBGRP_TRIVIAL;
  1356. else
  1357. subgrp_after = subgrp;
  1358. }
  1359. for (twist = 0; twist < N_TWIST; twist++)
  1360. {
  1361. new_syllable = twist_on_syllable(twist, syllable);
  1362. if (is_single_twist(new_syllable))
  1363. {
  1364. if (not_minimal_one_twist(subgroup_list[subgrp_after],
  1365. sym_on_twist, syllable_to_twist(new_syllable)))
  1366. new_syllable = SYLLABLE_INVALID;
  1367. }
  1368. else if (new_syllable != SYLLABLE_INVALID)
  1369. {
  1370. if (not_minimal_two_twists(subgroup_list[subgrp_before],
  1371. sym_on_twist, syllable_to_twist(syllable), twist))
  1372. new_syllable = SYLLABLE_INVALID;
  1373. }
  1374. if (new_syllable == SYLLABLE_INVALID)
  1375. new_subgrp = SUBGRP_TRIVIAL;
  1376. else if (is_single_twist(new_syllable))
  1377. new_subgrp = subgrp_after;
  1378. else
  1379. new_subgrp = syllable_on_subgrp[new_syllable][subgrp_before];
  1380. tw_on_sylsubgrp[twist][syllable * N_SYMSUBGRP + subgrp] =
  1381. new_syllable * N_SYMSUBGRP + new_subgrp;
  1382. }
  1383. }
  1384. return;
  1385. }
  1386. /* ========================================================================= */
  1387. void init_twist_on_follow(void)
  1388. /* ------------------------------------------------------------------------- */
  1389. {
  1390. unsigned short (*mem_ptr)[N_FOLLOW];
  1391. int tw_on_sylsubgrp[N_TWIST][N_SYLLABLE * N_SYMSUBGRP];
  1392. int occurs[N_SYLLABLE * N_SYMSUBGRP];
  1393. int sylsubgrp_to_follow[N_SYLLABLE * N_SYMSUBGRP];
  1394. int follow_to_sylsubgrp[N_FOLLOW];
  1395. int syllable, subgrp, found, twist, count, follow;
  1396. calc_twist_on_sylsubgrp(tw_on_sylsubgrp);
  1397. for (syllable = 0; syllable < N_SYLLABLE; syllable++)
  1398. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1399. occurs[syllable * N_SYMSUBGRP + subgrp] = 0;
  1400. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1401. occurs[SYLLABLE_NONE * N_SYMSUBGRP + subgrp] = 1;
  1402. found = 1;
  1403. while (found)
  1404. {
  1405. found = 0;
  1406. for (syllable = 0; syllable < N_SYLLABLE; syllable++)
  1407. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1408. for (twist = 0; twist < N_TWIST; twist++)
  1409. if (occurs[tw_on_sylsubgrp[twist]
  1410. [syllable * N_SYMSUBGRP + subgrp]] == 0)
  1411. {
  1412. occurs[tw_on_sylsubgrp[twist]
  1413. [syllable * N_SYMSUBGRP + subgrp]] = 1;
  1414. found = 1;
  1415. }
  1416. }
  1417. count = 0;
  1418. for (syllable = 0; syllable < N_SYLLABLE; syllable++)
  1419. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1420. {
  1421. if (occurs[syllable * N_SYMSUBGRP + subgrp] == 0)
  1422. sylsubgrp_to_follow[syllable * N_SYMSUBGRP + subgrp] = -1;
  1423. else
  1424. {
  1425. sylsubgrp_to_follow[syllable * N_SYMSUBGRP + subgrp] = count;
  1426. follow_to_sylsubgrp[count] = syllable * N_SYMSUBGRP + subgrp;
  1427. count++;
  1428. }
  1429. }
  1430. if (count != N_FOLLOW)
  1431. exit_w_error_message("init_twist_on_follow : wrong number of follow's");
  1432. for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
  1433. if (sylsubgrp_to_follow[SYLLABLE_NONE * N_SYMSUBGRP + subgrp]
  1434. != 1 + subgrp)
  1435. exit_w_error_message("init_twist_on_follow : indexing error");
  1436. mem_ptr = (unsigned short (*)[N_FOLLOW])
  1437. malloc(sizeof(unsigned short [N_TWIST][N_FOLLOW]));
  1438. if (mem_ptr == NULL)
  1439. exit_w_error_message("init_twist_on_follow : couldn't get memory");
  1440. for (twist = 0; twist < N_TWIST; twist++)
  1441. twist_on_follow[twist] = mem_ptr[twist];
  1442. for (twist = 0; twist < N_TWIST; twist++)
  1443. for (follow = 0; follow < N_FOLLOW; follow++)
  1444. twist_on_follow[twist][follow] =
  1445. (unsigned short)sylsubgrp_to_follow[tw_on_sylsubgrp[twist]
  1446. [follow_to_sylsubgrp[follow]]];
  1447. return;
  1448. }
  1449. /* ========================================================================= */
  1450. void corner_unpack(int corner, int array_out[8])
  1451. /* ------------------------------------------------------------------------- */
  1452. /* input: corner
  1453. output: array_out[] */
  1454. {
  1455. int ii;
  1456. for (ii = 0; ii < 7; ii++)
  1457. {
  1458. array_out[ii] = corner % 3;
  1459. corner = corner / 3;
  1460. }
  1461. array_out[7] = (2 * (array_out[0] + array_out[1] + array_out[2] + array_out[3]
  1462. + array_out[4] + array_out[5] + array_out[6])) % 3;
  1463. return;
  1464. }
  1465. /* ========================================================================= */
  1466. int corner_pack(int array_in[8])
  1467. /* ------------------------------------------------------------------------- */
  1468. /* input: array_in[] */
  1469. {
  1470. int corner, ii;
  1471. corner = 0;
  1472. for (ii = 6; ii >= 0; ii--)
  1473. corner = 3 * corner + array_in[ii];
  1474. return corner;
  1475. }
  1476. /* ========================================================================= */
  1477. void corner_adjust(int array[8], int ind0, int ind1, int ind2,
  1478. int ind3)
  1479. /* ------------------------------------------------------------------------- */
  1480. {
  1481. array[ind0] = (array[ind0] + 1) % 3;
  1482. array[ind1] = (array[ind1] + 2) % 3;
  1483. array[ind2] = (array[ind2] + 1) % 3;
  1484. array[ind3] = (array[ind3] + 2) % 3;
  1485. return;
  1486. }
  1487. /* ========================================================================= */
  1488. int twist_f_on_corner(int corner)
  1489. /* ------------------------------------------------------------------------- */
  1490. {
  1491. int temp_arr[8];
  1492. corner_unpack(corner, temp_arr);
  1493. four_cycle(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
  1494. corner_adjust(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
  1495. return corner_pack(temp_arr);
  1496. }
  1497. /* ========================================================================= */
  1498. int twist_r_on_corner(int corner)
  1499. /* ------------------------------------------------------------------------- */
  1500. {
  1501. int temp_arr[8];
  1502. corner_unpack(corner, temp_arr);
  1503. four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
  1504. corner_adjust(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
  1505. return corner_pack(temp_arr);
  1506. }
  1507. /* ========================================================================= */
  1508. int twist_u_on_corner(int corner)
  1509. /* ------------------------------------------------------------------------- */
  1510. {
  1511. int temp_arr[8];
  1512. corner_unpack(corner, temp_arr);
  1513. four_cycle(temp_arr, CORNER_UFR, CORNER_URB, CORNER_UBL, CORNER_ULF);
  1514. return corner_pack(temp_arr);
  1515. }
  1516. /* ========================================================================= */
  1517. int twist_b_on_corner(int corner)
  1518. /* ------------------------------------------------------------------------- */
  1519. {
  1520. int temp_arr[8];
  1521. corner_unpack(corner, temp_arr);
  1522. four_cycle(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
  1523. corner_adjust(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
  1524. return corner_pack(temp_arr);
  1525. }
  1526. /* ========================================================================= */
  1527. int twist_l_on_corner(int corner)
  1528. /* ------------------------------------------------------------------------- */
  1529. {
  1530. int temp_arr[8];
  1531. corner_unpack(corner, temp_arr);
  1532. four_cycle(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
  1533. corner_adjust(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
  1534. return corner_pack(temp_arr);
  1535. }
  1536. /* ========================================================================= */
  1537. int twist_d_on_corner(int corner)
  1538. /* ------------------------------------------------------------------------- */
  1539. {
  1540. int temp_arr[8];
  1541. corner_unpack(corner, temp_arr);
  1542. four_cycle(temp_arr, CORNER_DFL, CORNER_DLB, CORNER_DBR, CORNER_DRF);
  1543. return corner_pack(temp_arr);
  1544. }
  1545. /* ========================================================================= */
  1546. void init_twist_on_corner(void)
  1547. /* ------------------------------------------------------------------------- */
  1548. {
  1549. int twist, corner;
  1550. /* allocate and initialize global array twist_on_corner */
  1551. twist_on_corner[0] =
  1552. (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_CORNER]));
  1553. if (twist_on_corner[0] == NULL)
  1554. exit_w_error_message("init_twist_on_corner : couldn't get memory");
  1555. for (twist = 1; twist < N_TWIST; twist++)
  1556. twist_on_corner[twist] = &twist_on_corner[0][twist * N_CORNER];
  1557. for (corner = 0; corner < N_CORNER; corner++)
  1558. {
  1559. twist_on_corner[TWIST_F][corner] =
  1560. (unsigned short)twist_f_on_corner(corner);
  1561. twist_on_corner[TWIST_R][corner] =
  1562. (unsigned short)twist_r_on_corner(corner);
  1563. twist_on_corner[TWIST_U][corner] =
  1564. (unsigned short)twist_u_on_corner(corner);
  1565. twist_on_corner[TWIST_B][corner] =
  1566. (unsigned short)twist_b_on_corner(corner);
  1567. twist_on_corner[TWIST_L][corner] =
  1568. (unsigned short)twist_l_on_corner(corner);
  1569. twist_on_corner[TWIST_D][corner] =
  1570. (unsigned short)twist_d_on_corner(corner);
  1571. }
  1572. for (corner = 0; corner < N_CORNER; corner++)
  1573. {
  1574. twist_on_corner[TWIST_F2][corner] =
  1575. twist_on_corner[TWIST_F][(int)twist_on_corner[TWIST_F][corner]];
  1576. twist_on_corner[TWIST_R2][corner] =
  1577. twist_on_corner[TWIST_R][(int)twist_on_corner[TWIST_R][corner]];
  1578. twist_on_corner[TWIST_U2][corner] =
  1579. twist_on_corner[TWIST_U][(int)twist_on_corner[TWIST_U][corner]];
  1580. twist_on_corner[TWIST_B2][corner] =
  1581. twist_on_corner[TWIST_B][(int)twist_on_corner[TWIST_B][corner]];
  1582. twist_on_corner[TWIST_L2][corner] =
  1583. twist_on_corner[TWIST_L][(int)twist_on_corner[TWIST_L][corner]];
  1584. twist_on_corner[TWIST_D2][corner] =
  1585. twist_on_corner[TWIST_D][(int)twist_on_corner[TWIST_D][corner]];
  1586. }
  1587. for (corner = 0; corner < N_CORNER; corner++)
  1588. {
  1589. twist_on_corner[TWIST_F3][corner] =
  1590. twist_on_corner[TWIST_F2][(int)twist_on_corner[TWIST_F][corner]];
  1591. twist_on_corner[TWIST_R3][corner] =
  1592. twist_on_corner[TWIST_R2][(int)twist_on_corner[TWIST_R][corner]];
  1593. twist_on_corner[TWIST_U3][corner] =
  1594. twist_on_corner[TWIST_U2][(int)twist_on_corner[TWIST_U][corner]];
  1595. twist_on_corner[TWIST_B3][corner] =
  1596. twist_on_corner[TWIST_B2][(int)twist_on_corner[TWIST_B][corner]];
  1597. twist_on_corner[TWIST_L3][corner] =
  1598. twist_on_corner[TWIST_L2][(int)twist_on_corner[TWIST_L][corner]];
  1599. twist_on_corner[TWIST_D3][corner] =
  1600. twist_on_corner[TWIST_D2][(int)twist_on_corner[TWIST_D][corner]];
  1601. }
  1602. return;
  1603. }
  1604. /* ========================================================================= */
  1605. int sym_cu_on_corner(int corner)
  1606. /* ------------------------------------------------------------------------- */
  1607. {
  1608. int temp_arr[8];
  1609. corner_unpack(corner, temp_arr);
  1610. four_cycle(temp_arr, CORNER_UFR, CORNER_URB, CORNER_UBL, CORNER_ULF);
  1611. four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_DLB, CORNER_DFL);
  1612. return corner_pack(temp_arr);
  1613. }
  1614. /* ========================================================================= */
  1615. int sym_cf2_on_corner(int corner)
  1616. /* ------------------------------------------------------------------------- */
  1617. {
  1618. int temp_arr[8];
  1619. corner_unpack(corner, temp_arr);
  1620. two_cycle(temp_arr, CORNER_UFR, CORNER_DFL);
  1621. two_cycle(temp_arr, CORNER_ULF, CORNER_DRF);
  1622. two_cycle(temp_arr, CORNER_UBL, CORNER_DBR);
  1623. two_cycle(temp_arr, CORNER_URB, CORNER_DLB);
  1624. return corner_pack(temp_arr);
  1625. }
  1626. /* ========================================================================= */
  1627. int sym_rud_on_corner(int corner)
  1628. /* ------------------------------------------------------------------------- */
  1629. {
  1630. int temp_arr[8], ii;
  1631. corner_unpack(corner, temp_arr);
  1632. two_cycle(temp_arr, CORNER_UFR, CORNER_DRF);
  1633. two_cycle(temp_arr, CORNER_ULF, CORNER_DFL);
  1634. two_cycle(temp_arr, CORNER_UBL, CORNER_DLB);
  1635. two_cycle(temp_arr, CORNER_URB, CORNER_DBR);
  1636. for (ii = 0; ii < 8; ii++)
  1637. temp_arr[ii] = (2 * temp_arr[ii]) % 3;
  1638. return corner_pack(temp_arr);
  1639. }
  1640. /* ========================================================================= */
  1641. void init_sym_on_corner(void)
  1642. /* ------------------------------------------------------------------------- */
  1643. {
  1644. int corner, sym;
  1645. /* allocate and initialize global array sym_on_corner */
  1646. sym_on_corner[0] =
  1647. (unsigned short *)malloc(sizeof(unsigned short [N_SYM][N_CORNER]));
  1648. if (sym_on_corner[0] == NULL)
  1649. exit_w_error_message("init_sym_on_corner : couldn't get memory");
  1650. for (sym = 1; sym < N_SYM; sym++)
  1651. sym_on_corner[sym] = &sym_on_corner[0][sym * N_CORNER];
  1652. for (corner = 0; corner < N_CORNER; corner++)
  1653. sym_on_corner[0][corner] = (unsigned short)corner;
  1654. for (corner = 0; corner < N_CORNER; corner++)
  1655. sym_on_corner[1][corner] = (unsigned short)sym_cu_on_corner(corner);
  1656. for (sym = 2; sym < 4; sym++)
  1657. for (corner = 0; corner < N_CORNER; corner++)
  1658. sym_on_corner[sym][corner] =
  1659. sym_on_corner[1][(int)sym_on_corner[sym - 1][corner]];
  1660. for (corner = 0; corner < N_CORNER; corner++)
  1661. sym_on_corner[4][corner] = (unsigned short)sym_cf2_on_corner(corner);
  1662. for (sym = 5; sym < 8; sym++)
  1663. for (corner = 0; corner < N_CORNER; corner++)
  1664. sym_on_corner[sym][corner] =
  1665. sym_on_corner[4][(int)sym_on_corner[sym - 4][corner]];
  1666. for (corner = 0; corner < N_CORNER; corner++)
  1667. sym_on_corner[8][corner] = (unsigned short)sym_rud_on_corner(corner);
  1668. for (sym = 9; sym < 16; sym++)
  1669. for (corner = 0; corner < N_CORNER; corner++)
  1670. sym_on_corner[sym][corner] =
  1671. sym_on_corner[8][(int)sym_on_corner[sym - 8][corner]];
  1672. return;
  1673. }
  1674. /* ========================================================================= */
  1675. void calc_edgeloc_conv(int conv_tab[N_ELOC], int unconv_tab[N_ELOC_CONV])
  1676. /* ------------------------------------------------------------------------- */
  1677. {
  1678. int ii, loc0, loc1, loc2, loc3, count;
  1679. for (ii = 0; ii < N_ELOC; ii++)
  1680. conv_tab[ii] = -1;
  1681. for (ii = 0; ii < N_ELOC_CONV; ii++)
  1682. unconv_tab[ii] = -1;
  1683. count = 0;
  1684. for (loc0 = 0; loc0 < 9; loc0++)
  1685. for (loc1 = loc0 + 1; loc1 < 10; loc1++)
  1686. for (loc2 = loc1 + 1; loc2 < 11; loc2++)
  1687. for (loc3 = loc2 + 1; loc3 < 12; loc3++)
  1688. {
  1689. if (count >= N_ELOC)
  1690. exit_w_error_message("calc_edgeloc_conv : too many eloc's");
  1691. conv_tab[count] = (1 << loc0) | (1 << loc1) |
  1692. (1 << loc2) | (1 << loc3);
  1693. unconv_tab[conv_tab[count]] = count;
  1694. count++;
  1695. }
  1696. if (count != N_ELOC)
  1697. exit_w_error_message("calc_edgeloc_conv : wrong number of eloc's");
  1698. return;
  1699. }
  1700. /* ========================================================================= */
  1701. int edgeloc_conv_or_unconv(int eloc_conv_or_unconv, int convert_flag)
  1702. /* ------------------------------------------------------------------------- */
  1703. {
  1704. static int eloc_conv[N_ELOC];
  1705. static int eloc_unconv[N_ELOC_CONV];
  1706. static int initialized = 0;
  1707. int el_conv, el_unconv;
  1708. if (initialized == 0)
  1709. {
  1710. calc_edgeloc_conv(eloc_conv, eloc_unconv);
  1711. initialized = 1;
  1712. }
  1713. if (convert_flag)
  1714. {
  1715. if ((eloc_conv_or_unconv < 0) || (eloc_conv_or_unconv >= N_ELOC))
  1716. exit_w_error_message("edgeloc_conv_or_unconv : invalid input");
  1717. el_conv = eloc_conv[eloc_conv_or_unconv];
  1718. if (el_conv < 0)
  1719. exit_w_error_message("edgeloc_conv_or_unconv : corrupted data");
  1720. return el_conv;
  1721. }
  1722. else
  1723. {
  1724. if ((eloc_conv_or_unconv < 0) || (eloc_conv_or_unconv >= N_ELOC_CONV))
  1725. exit_w_error_message("edgeloc_conv_or_unconv : invalid input");
  1726. el_unconv = eloc_unconv[eloc_conv_or_unconv];
  1727. if (el_unconv < 0)
  1728. exit_w_error_message("edgeloc_conv_or_unconv : corrupted data");
  1729. return el_unconv;
  1730. }
  1731. }
  1732. /* ========================================================================= */
  1733. int edgeloc_conv(int eloc_unconv)
  1734. /* ------------------------------------------------------------------------- */
  1735. {
  1736. return edgeloc_conv_or_unconv(eloc_unconv, 1);
  1737. }
  1738. /* ========================================================================= */
  1739. int edgeloc_unconv(int eloc_conv)
  1740. /* ------------------------------------------------------------------------- */
  1741. {
  1742. return edgeloc_conv_or_unconv(eloc_conv, 0);
  1743. }
  1744. /* ========================================================================= */
  1745. void eloc_unpack(int eloc, int array_out[12])
  1746. /* ------------------------------------------------------------------------- */
  1747. /* input: eloc
  1748. output: array_out[] */
  1749. {
  1750. int conv, ii;
  1751. conv = edgeloc_conv(eloc);
  1752. for (ii = 0; ii < 12; ii++)
  1753. {
  1754. array_out[ii] = conv % 2;
  1755. conv = conv / 2;
  1756. }
  1757. return;
  1758. }
  1759. /* ========================================================================= */
  1760. int eloc_pack(int array_in[12])
  1761. /* ------------------------------------------------------------------------- */
  1762. {
  1763. int ii, conv;
  1764. conv = 0;
  1765. for (ii = 11; ii >= 0; ii--)
  1766. conv = 2 * conv + array_in[ii];
  1767. return edgeloc_unconv(conv);
  1768. }
  1769. /* ========================================================================= */
  1770. int twist_f_on_eloc(int eloc)
  1771. /* ------------------------------------------------------------------------- */
  1772. {
  1773. int temp_arr[12];
  1774. eloc_unpack(eloc, temp_arr);
  1775. four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
  1776. return eloc_pack(temp_arr);
  1777. }
  1778. /* ========================================================================= */
  1779. int twist_r_on_eloc(int eloc)
  1780. /* ------------------------------------------------------------------------- */
  1781. {
  1782. int temp_arr[12];
  1783. eloc_unpack(eloc, temp_arr);
  1784. four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
  1785. return eloc_pack(temp_arr);
  1786. }
  1787. /* ========================================================================= */
  1788. int twist_u_on_eloc(int eloc)
  1789. /* ------------------------------------------------------------------------- */
  1790. {
  1791. int temp_arr[12];
  1792. eloc_unpack(eloc, temp_arr);
  1793. four_cycle(temp_arr, EDGE_UF, EDGE_UR, EDGE_UB, EDGE_UL);
  1794. return eloc_pack(temp_arr);
  1795. }
  1796. /* ========================================================================= */
  1797. int twist_b_on_eloc(int eloc)
  1798. /* ------------------------------------------------------------------------- */
  1799. {
  1800. int temp_arr[12];
  1801. eloc_unpack(eloc, temp_arr);
  1802. four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
  1803. return eloc_pack(temp_arr);
  1804. }
  1805. /* ========================================================================= */
  1806. int twist_l_on_eloc(int eloc)
  1807. /* ------------------------------------------------------------------------- */
  1808. {
  1809. int temp_arr[12];
  1810. eloc_unpack(eloc, temp_arr);
  1811. four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
  1812. return eloc_pack(temp_arr);
  1813. }
  1814. /* ========================================================================= */
  1815. int twist_d_on_eloc(int eloc)
  1816. /* ------------------------------------------------------------------------- */
  1817. {
  1818. int temp_arr[12];
  1819. eloc_unpack(eloc, temp_arr);
  1820. four_cycle(temp_arr, EDGE_DF, EDGE_DL, EDGE_DB, EDGE_DR);
  1821. return eloc_pack(temp_arr);
  1822. }
  1823. /* ========================================================================= */
  1824. void calc_twist_on_eloc(int table[N_TWIST][N_ELOC])
  1825. /* ------------------------------------------------------------------------- */
  1826. {
  1827. int edgeloc;
  1828. for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
  1829. {
  1830. table[TWIST_F][edgeloc] = twist_f_on_eloc(edgeloc);
  1831. table[TWIST_R][edgeloc] = twist_r_on_eloc(edgeloc);
  1832. table[TWIST_U][edgeloc] = twist_u_on_eloc(edgeloc);
  1833. table[TWIST_B][edgeloc] = twist_b_on_eloc(edgeloc);
  1834. table[TWIST_L][edgeloc] = twist_l_on_eloc(edgeloc);
  1835. table[TWIST_D][edgeloc] = twist_d_on_eloc(edgeloc);
  1836. }
  1837. perm_n_compose(N_ELOC, table[TWIST_F], table[TWIST_F], table[TWIST_F2]);
  1838. perm_n_compose(N_ELOC, table[TWIST_R], table[TWIST_R], table[TWIST_R2]);
  1839. perm_n_compose(N_ELOC, table[TWIST_U], table[TWIST_U], table[TWIST_U2]);
  1840. perm_n_compose(N_ELOC, table[TWIST_B], table[TWIST_B], table[TWIST_B2]);
  1841. perm_n_compose(N_ELOC, table[TWIST_L], table[TWIST_L], table[TWIST_L2]);
  1842. perm_n_compose(N_ELOC, table[TWIST_D], table[TWIST_D], table[TWIST_D2]);
  1843. perm_n_compose(N_ELOC, table[TWIST_F2], table[TWIST_F], table[TWIST_F3]);
  1844. perm_n_compose(N_ELOC, table[TWIST_R2], table[TWIST_R], table[TWIST_R3]);
  1845. perm_n_compose(N_ELOC, table[TWIST_U2], table[TWIST_U], table[TWIST_U3]);
  1846. perm_n_compose(N_ELOC, table[TWIST_B2], table[TWIST_B], table[TWIST_B3]);
  1847. perm_n_compose(N_ELOC, table[TWIST_L2], table[TWIST_L], table[TWIST_L3]);
  1848. perm_n_compose(N_ELOC, table[TWIST_D2], table[TWIST_D], table[TWIST_D3]);
  1849. return;
  1850. }
  1851. /* ========================================================================= */
  1852. int sym_cu_on_eloc(int eloc)
  1853. /* ------------------------------------------------------------------------- */
  1854. {
  1855. int temp_arr[12];
  1856. eloc_unpack(eloc, temp_arr);
  1857. four_cycle(temp_arr, EDGE_UF, EDGE_UR, EDGE_UB, EDGE_UL);
  1858. four_cycle(temp_arr, EDGE_DF, EDGE_DR, EDGE_DB, EDGE_DL);
  1859. four_cycle(temp_arr, EDGE_FR, EDGE_BR, EDGE_BL, EDGE_FL);
  1860. return eloc_pack(temp_arr);
  1861. }
  1862. /* ========================================================================= */
  1863. int sym_cf2_on_eloc(int eloc)
  1864. /* ------------------------------------------------------------------------- */
  1865. {
  1866. int temp_arr[12];
  1867. eloc_unpack(eloc, temp_arr);
  1868. two_cycle(temp_arr, EDGE_UF, EDGE_DF);
  1869. two_cycle(temp_arr, EDGE_UR, EDGE_DL);
  1870. two_cycle(temp_arr, EDGE_UB, EDGE_DB);
  1871. two_cycle(temp_arr, EDGE_UL, EDGE_DR);
  1872. two_cycle(temp_arr, EDGE_FR, EDGE_FL);
  1873. two_cycle(temp_arr, EDGE_BR, EDGE_BL);
  1874. return eloc_pack(temp_arr);
  1875. }
  1876. /* ========================================================================= */
  1877. int sym_rud_on_eloc(int eloc)
  1878. /* ------------------------------------------------------------------------- */
  1879. {
  1880. int temp_arr[12];
  1881. eloc_unpack(eloc, temp_arr);
  1882. two_cycle(temp_arr, EDGE_UF, EDGE_DF);
  1883. two_cycle(temp_arr, EDGE_UR, EDGE_DR);
  1884. two_cycle(temp_arr, EDGE_UB, EDGE_DB);
  1885. two_cycle(temp_arr, EDGE_UL, EDGE_DL);
  1886. return eloc_pack(temp_arr);
  1887. }
  1888. /* ========================================================================= */
  1889. void calc_sym_on_eloc(int table[N_SYM][N_ELOC])
  1890. /* ------------------------------------------------------------------------- */
  1891. {
  1892. int edgeloc, sym;
  1893. perm_n_init(N_ELOC, table[0]);
  1894. for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
  1895. table[1][edgeloc] = sym_cu_on_eloc(edgeloc);
  1896. for (sym = 2; sym < 4; sym++)
  1897. perm_n_compose(N_ELOC, table[1], table[sym - 1], table[sym]);
  1898. for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
  1899. table[4][edgeloc] = sym_cf2_on_eloc(edgeloc);
  1900. for (sym = 5; sym < 8; sym++)
  1901. perm_n_compose(N_ELOC, table[4], table[sym - 4], table[sym]);
  1902. for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
  1903. table[8][edgeloc] = sym_rud_on_eloc(edgeloc);
  1904. for (sym = 9; sym < 16; sym++)
  1905. perm_n_compose(N_ELOC, table[8], table[sym - 8], table[sym]);
  1906. return;
  1907. }
  1908. /* ========================================================================= */
  1909. void eflip_unpack(int eflip, int array_out[12])
  1910. /* ------------------------------------------------------------------------- */
  1911. {
  1912. int ii;
  1913. for (ii = 0; ii < 11; ii++)
  1914. {
  1915. array_out[ii] = eflip % 2;
  1916. eflip = eflip / 2;
  1917. }
  1918. array_out[11] = (array_out[0] + array_out[1] + array_out[2] + array_out[3] +
  1919. array_out[4] + array_out[5] + array_out[6] + array_out[7] +
  1920. array_out[8] + array_out[9] + array_out[10]) % 2;
  1921. return;
  1922. }
  1923. /* ========================================================================= */
  1924. int eflip_pack(int array_in[12])
  1925. /* ------------------------------------------------------------------------- */
  1926. {
  1927. int eflip, ii;
  1928. eflip = 0;
  1929. for (ii = 10; ii >= 0; ii--)
  1930. eflip = 2 * eflip + array_in[ii];
  1931. return eflip;
  1932. }
  1933. /* ========================================================================= */
  1934. void eflip_adjust(int array[12], int ind0, int ind1, int ind2,
  1935. int ind3)
  1936. /* ------------------------------------------------------------------------- */
  1937. {
  1938. array[ind0] = 1 - array[ind0];
  1939. array[ind1] = 1 - array[ind1];
  1940. array[ind2] = 1 - array[ind2];
  1941. array[ind3] = 1 - array[ind3];
  1942. return;
  1943. }
  1944. /* ========================================================================= */
  1945. int twist_f_on_eflip(int eflip)
  1946. /* ------------------------------------------------------------------------- */
  1947. {
  1948. int temp_arr[12];
  1949. eflip_unpack(eflip, temp_arr);
  1950. four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
  1951. eflip_adjust(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
  1952. return eflip_pack(temp_arr);
  1953. }
  1954. /* ========================================================================= */
  1955. int twist_r_on_eflip(int eflip)
  1956. /* ------------------------------------------------------------------------- */
  1957. {
  1958. int temp_arr[12];
  1959. eflip_unpack(eflip, temp_arr);
  1960. four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
  1961. return eflip_pack(temp_arr);
  1962. }
  1963. /* ========================================================================= */
  1964. int twist_u_on_eflip(int eflip)
  1965. /* ------------------------------------------------------------------------- */
  1966. {
  1967. int temp_arr[12];
  1968. eflip_unpack(eflip, temp_arr);
  1969. four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
  1970. return eflip_pack(temp_arr);
  1971. }
  1972. /* ========================================================================= */
  1973. int twist_b_on_eflip(int eflip)
  1974. /* ------------------------------------------------------------------------- */
  1975. {
  1976. int temp_arr[12];
  1977. eflip_unpack(eflip, temp_arr);
  1978. four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
  1979. eflip_adjust(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
  1980. return eflip_pack(temp_arr);
  1981. }
  1982. /* ========================================================================= */
  1983. int twist_l_on_eflip(int eflip)
  1984. /* ------------------------------------------------------------------------- */
  1985. {
  1986. int temp_arr[12];
  1987. eflip_unpack(eflip, temp_arr);
  1988. four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
  1989. return eflip_pack(temp_arr);
  1990. }
  1991. /* ========================================================================= */
  1992. int twist_d_on_eflip(int eflip)
  1993. /* ------------------------------------------------------------------------- */
  1994. {
  1995. int temp_arr[12];
  1996. eflip_unpack(eflip, temp_arr);
  1997. four_cycle(temp_arr, EDGE_DL, EDGE_DB, EDGE_DR, EDGE_DF);
  1998. return eflip_pack(temp_arr);
  1999. }
  2000. /* ========================================================================= */
  2001. void calc_twist_on_eflip(int table[N_TWIST][N_EFLIP])
  2002. /* ------------------------------------------------------------------------- */
  2003. {
  2004. int edgeflip;
  2005. for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
  2006. {
  2007. table[TWIST_F][edgeflip] = twist_f_on_eflip(edgeflip);
  2008. table[TWIST_R][edgeflip] = twist_r_on_eflip(edgeflip);
  2009. table[TWIST_U][edgeflip] = twist_u_on_eflip(edgeflip);
  2010. table[TWIST_B][edgeflip] = twist_b_on_eflip(edgeflip);
  2011. table[TWIST_L][edgeflip] = twist_l_on_eflip(edgeflip);
  2012. table[TWIST_D][edgeflip] = twist_d_on_eflip(edgeflip);
  2013. }
  2014. perm_n_compose(N_EFLIP, table[TWIST_F], table[TWIST_F], table[TWIST_F2]);
  2015. perm_n_compose(N_EFLIP, table[TWIST_R], table[TWIST_R], table[TWIST_R2]);
  2016. perm_n_compose(N_EFLIP, table[TWIST_U], table[TWIST_U], table[TWIST_U2]);
  2017. perm_n_compose(N_EFLIP, table[TWIST_B], table[TWIST_B], table[TWIST_B2]);
  2018. perm_n_compose(N_EFLIP, table[TWIST_L], table[TWIST_L], table[TWIST_L2]);
  2019. perm_n_compose(N_EFLIP, table[TWIST_D], table[TWIST_D], table[TWIST_D2]);
  2020. perm_n_compose(N_EFLIP, table[TWIST_F2], table[TWIST_F], table[TWIST_F3]);
  2021. perm_n_compose(N_EFLIP, table[TWIST_R2], table[TWIST_R], table[TWIST_R3]);
  2022. perm_n_compose(N_EFLIP, table[TWIST_U2], table[TWIST_U], table[TWIST_U3]);
  2023. perm_n_compose(N_EFLIP, table[TWIST_B2], table[TWIST_B], table[TWIST_B3]);
  2024. perm_n_compose(N_EFLIP, table[TWIST_L2], table[TWIST_L], table[TWIST_L3]);
  2025. perm_n_compose(N_EFLIP, table[TWIST_D2], table[TWIST_D], table[TWIST_D3]);
  2026. return;
  2027. }
  2028. /* ========================================================================= */
  2029. int sym_cu2_on_eflip(int eflip)
  2030. /* ------------------------------------------------------------------------- */
  2031. {
  2032. int temp_arr[12];
  2033. eflip_unpack(eflip, temp_arr);
  2034. two_cycle(temp_arr, EDGE_UF, EDGE_UB);
  2035. two_cycle(temp_arr, EDGE_UR, EDGE_UL);
  2036. two_cycle(temp_arr, EDGE_DF, EDGE_DB);
  2037. two_cycle(temp_arr, EDGE_DR, EDGE_DL);
  2038. two_cycle(temp_arr, EDGE_FR, EDGE_BL);
  2039. two_cycle(temp_arr, EDGE_FL, EDGE_BR);
  2040. return eflip_pack(temp_arr);
  2041. }
  2042. /* ========================================================================= */
  2043. int sym_cf2_on_eflip(int eflip)
  2044. /* ------------------------------------------------------------------------- */
  2045. {
  2046. int temp_arr[12];
  2047. eflip_unpack(eflip, temp_arr);
  2048. two_cycle(temp_arr, EDGE_UF, EDGE_DF);
  2049. two_cycle(temp_arr, EDGE_UR, EDGE_DL);
  2050. two_cycle(temp_arr, EDGE_UB, EDGE_DB);
  2051. two_cycle(temp_arr, EDGE_UL, EDGE_DR);
  2052. two_cycle(temp_arr, EDGE_FR, EDGE_FL);
  2053. two_cycle(temp_arr, EDGE_BR, EDGE_BL);
  2054. return eflip_pack(temp_arr);
  2055. }
  2056. /* ========================================================================= */
  2057. int sym_rud_on_eflip(int eflip)
  2058. /* ------------------------------------------------------------------------- */
  2059. {
  2060. int temp_arr[12];
  2061. eflip_unpack(eflip, temp_arr);
  2062. two_cycle(temp_arr, EDGE_UF, EDGE_DF);
  2063. two_cycle(temp_arr, EDGE_UR, EDGE_DR);
  2064. two_cycle(temp_arr, EDGE_UB, EDGE_DB);
  2065. two_cycle(temp_arr, EDGE_UL, EDGE_DL);
  2066. return eflip_pack(temp_arr);
  2067. }
  2068. /* ========================================================================= */
  2069. void calc_sym_on_eflip(int table[N_SYM / 2][N_EFLIP])
  2070. /* ------------------------------------------------------------------------- */
  2071. {
  2072. int edgeflip, sym;
  2073. perm_n_init(N_EFLIP, table[0]);
  2074. for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
  2075. table[1][edgeflip] = sym_cu2_on_eflip(edgeflip);
  2076. for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
  2077. table[2][edgeflip] = sym_cf2_on_eflip(edgeflip);
  2078. perm_n_compose(N_EFLIP, table[2], table[1], table[3]);
  2079. for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
  2080. table[4][edgeflip] = sym_rud_on_eflip(edgeflip);
  2081. for (sym = 5; sym < 8; sym++)
  2082. perm_n_compose(N_EFLIP, table[4], table[sym - 4], table[sym]);
  2083. return;
  2084. }
  2085. /* ========================================================================= */
  2086. int sym_cu_on_fulledge(int fulledge)
  2087. /* ------------------------------------------------------------------------- */
  2088. {
  2089. int edgeloc_arr[12], edgeflip_arr[12], temp_arr[12], ii;
  2090. eloc_unpack(fulledge / N_EFLIP, edgeloc_arr);
  2091. eflip_unpack(fulledge % N_EFLIP, edgeflip_arr);
  2092. for (ii = 0; ii < 12; ii++)
  2093. temp_arr[ii] = (edgeloc_arr[ii] != edgeflip_arr[ii]);
  2094. four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
  2095. four_cycle(temp_arr, EDGE_DR, EDGE_DB, EDGE_DL, EDGE_DF);
  2096. four_cycle(temp_arr, EDGE_BR, EDGE_BL, EDGE_FL, EDGE_FR);
  2097. eflip_adjust(temp_arr, EDGE_FR, EDGE_FL, EDGE_BR, EDGE_BL);
  2098. return sym_cu_on_eloc(fulledge / N_EFLIP) * N_EFLIP + eflip_pack(temp_arr);
  2099. }
  2100. /* ========================================================================= */
  2101. void init_fulledge_to_edgequot(int sym_on_eloc[N_SYM][N_ELOC],
  2102. int sym_on_eflip[N_SYM / 2][N_EFLIP],
  2103. int edge_to_fulledge[N_EDGEQUOT],
  2104. int stabilizers[N_EDGEQUOT],
  2105. int multiplicities[N_EDGEQUOT])
  2106. /* ------------------------------------------------------------------------- */
  2107. {
  2108. int count, sym_count, fulledge, cu_fulledge, sym, min_sym;
  2109. int min_full, new_full, stab;
  2110. fulledge_to_edge =
  2111. (unsigned short *)malloc(sizeof(unsigned short [N_FULLEDGE]));
  2112. fulledge_to_sym = (unsigned char *)malloc(sizeof(unsigned char [N_FULLEDGE]));
  2113. if ((fulledge_to_edge == NULL) || (fulledge_to_sym == NULL))
  2114. exit_w_error_message("init_fulledge_to_edgequot : couldn't get memory");
  2115. count = 0;
  2116. for (fulledge = 0; fulledge < N_FULLEDGE; fulledge++)
  2117. {
  2118. min_full = fulledge;
  2119. min_sym = 0;
  2120. stab = 0;
  2121. sym_count = 0;
  2122. cu_fulledge = sym_cu_on_fulledge(fulledge);
  2123. for (sym = 0; sym < (N_SYM / 2); sym++)
  2124. {
  2125. new_full = sym_on_eloc[2 * sym][fulledge / N_EFLIP] * N_EFLIP +
  2126. sym_on_eflip[sym][fulledge % N_EFLIP];
  2127. if (min_full > new_full)
  2128. {
  2129. min_full = new_full;
  2130. min_sym = 2 * sym;
  2131. }
  2132. else if (min_full == new_full)
  2133. {
  2134. stab |= (1 << (2 * sym));
  2135. sym_count++;
  2136. }
  2137. new_full = sym_on_eloc[2 * sym][cu_fulledge / N_EFLIP] * N_EFLIP +
  2138. sym_on_eflip[sym][cu_fulledge % N_EFLIP];
  2139. if (min_full > new_full)
  2140. {
  2141. min_full = new_full;
  2142. min_sym = 2 * sym + 1;
  2143. }
  2144. else if (min_full == new_full)
  2145. {
  2146. stab |= (1 << (2 * sym + 1));
  2147. sym_count++;
  2148. }
  2149. }
  2150. if (min_sym == 0)
  2151. {
  2152. if (count >= N_EDGEQUOT)
  2153. exit_w_error_message(
  2154. "init_fulledge_to_edgequot : too many edgequot's");
  2155. edge_to_fulledge[count] = fulledge;
  2156. stabilizers[count] = stab;
  2157. multiplicities[count] = N_SYM / sym_count;
  2158. fulledge_to_edge[fulledge] = (unsigned short)count;
  2159. fulledge_to_sym[fulledge] = sym_x_invsym_to_sym[0][0];
  2160. count++;
  2161. }
  2162. else
  2163. {
  2164. fulledge_to_edge[fulledge] = fulledge_to_edge[min_full];
  2165. fulledge_to_sym[fulledge] = sym_x_invsym_to_sym[0][min_sym];
  2166. }
  2167. }
  2168. if (count != N_EDGEQUOT)
  2169. exit_w_error_message(
  2170. "init_fulledge_to_edgequot : wrong number of edgequot's");
  2171. return;
  2172. }
  2173. /* ========================================================================= */
  2174. void init_twist_on_edge(int twist_on_eloc[N_TWIST][N_ELOC],
  2175. int twist_on_eflip[N_TWIST][N_EFLIP],
  2176. int edge_to_fulledge[N_EDGEQUOT])
  2177. /* ------------------------------------------------------------------------- */
  2178. {
  2179. int twist, edge, fulledge, new_edge;
  2180. /* allocate and initialize global arrays */
  2181. /* twist_on_edge and twist_x_edge_to_sym */
  2182. twist_on_edge[0] =
  2183. (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_EDGEQUOT]));
  2184. twist_x_edge_to_sym[0] =
  2185. (unsigned char *)malloc(sizeof(unsigned char [N_TWIST][N_EDGEQUOT]));
  2186. if ((twist_on_edge[0] == NULL) || (twist_x_edge_to_sym[0] == NULL))
  2187. exit_w_error_message("init_twist_on_edge : couldn't get memory");
  2188. for (twist = 1; twist < N_TWIST; twist++)
  2189. {
  2190. twist_on_edge[twist] = &twist_on_edge[0][twist * N_EDGEQUOT];
  2191. twist_x_edge_to_sym[twist] = &twist_x_edge_to_sym[0][twist * N_EDGEQUOT];
  2192. }
  2193. for (twist = 0; twist < N_TWIST; twist++)
  2194. for (edge = 0; edge < N_EDGEQUOT; edge++)
  2195. {
  2196. fulledge = edge_to_fulledge[edge];
  2197. new_edge = twist_on_eloc[twist][fulledge / N_EFLIP] * N_EFLIP +
  2198. twist_on_eflip[twist][fulledge % N_EFLIP];
  2199. twist_on_edge[twist][edge] = fulledge_to_edge[new_edge];
  2200. twist_x_edge_to_sym[twist][edge] =
  2201. sym_x_invsym_to_sym[0][(int)fulledge_to_sym[new_edge]];
  2202. }
  2203. return;
  2204. }
  2205. /* ========================================================================= */
  2206. void init_edge_quotient(int stabilizers[N_EDGEQUOT],
  2207. int multiplicities[N_EDGEQUOT])
  2208. /* ------------------------------------------------------------------------- */
  2209. {
  2210. int twist_on_eloc[N_TWIST][N_ELOC];
  2211. int twist_on_eflip[N_TWIST][N_EFLIP];
  2212. int sym_on_eloc[N_SYM][N_ELOC];
  2213. int sym_on_eflip[N_SYM / 2][N_EFLIP];
  2214. int edge_to_fulledge[N_EDGEQUOT];
  2215. calc_twist_on_eloc(twist_on_eloc);
  2216. calc_sym_on_eloc(sym_on_eloc);
  2217. calc_twist_on_eflip(twist_on_eflip);
  2218. calc_sym_on_eflip(sym_on_eflip);
  2219. init_fulledge_to_edgequot(sym_on_eloc, sym_on_eflip, edge_to_fulledge,
  2220. stabilizers, multiplicities);
  2221. init_twist_on_edge(twist_on_eloc, twist_on_eflip, edge_to_fulledge);
  2222. return;
  2223. }
  2224. /* ========================================================================= */
  2225. void cornerperm_unpack(int cperm, int array_out[8])
  2226. /* ------------------------------------------------------------------------- */
  2227. {
  2228. perm_n_unpack(8, cperm, array_out);
  2229. return;
  2230. }
  2231. /* ========================================================================= */
  2232. int cornerperm_pack(int array_in[8])
  2233. /* ------------------------------------------------------------------------- */
  2234. {
  2235. return perm_n_pack(8, array_in);
  2236. }
  2237. /* ========================================================================= */
  2238. int twist_f_on_cperm(int cperm)
  2239. /* ------------------------------------------------------------------------- */
  2240. {
  2241. int temp_arr[8];
  2242. cornerperm_unpack(cperm, temp_arr);
  2243. four_cycle(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
  2244. return cornerperm_pack(temp_arr);
  2245. }
  2246. /* ========================================================================= */
  2247. int twist_r_on_cperm(int cperm)
  2248. /* ------------------------------------------------------------------------- */
  2249. {
  2250. int temp_arr[8];
  2251. cornerperm_unpack(cperm, temp_arr);
  2252. four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
  2253. return cornerperm_pack(temp_arr);
  2254. }
  2255. /* ========================================================================= */
  2256. int twist_u_on_cperm(int cperm)
  2257. /* ------------------------------------------------------------------------- */
  2258. {
  2259. int temp_arr[8];
  2260. cornerperm_unpack(cperm, temp_arr);
  2261. four_cycle(temp_arr, CORNER_URB, CORNER_UBL, CORNER_ULF, CORNER_UFR);
  2262. return cornerperm_pack(temp_arr);
  2263. }
  2264. /* ========================================================================= */
  2265. int twist_b_on_cperm(int cperm)
  2266. /* ------------------------------------------------------------------------- */
  2267. {
  2268. int temp_arr[8];
  2269. cornerperm_unpack(cperm, temp_arr);
  2270. four_cycle(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
  2271. return cornerperm_pack(temp_arr);
  2272. }
  2273. /* ========================================================================= */
  2274. int twist_l_on_cperm(int cperm)
  2275. /* ------------------------------------------------------------------------- */
  2276. {
  2277. int temp_arr[8];
  2278. cornerperm_unpack(cperm, temp_arr);
  2279. four_cycle(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
  2280. return cornerperm_pack(temp_arr);
  2281. }
  2282. /* ========================================================================= */
  2283. int twist_d_on_cperm(int cperm)
  2284. /* ------------------------------------------------------------------------- */
  2285. {
  2286. int temp_arr[8];
  2287. cornerperm_unpack(cperm, temp_arr);
  2288. four_cycle(temp_arr, CORNER_DFL, CORNER_DLB, CORNER_DBR, CORNER_DRF);
  2289. return cornerperm_pack(temp_arr);
  2290. }
  2291. /* ========================================================================= */
  2292. void init_twist_on_cornerperm(void)
  2293. /* ------------------------------------------------------------------------- */
  2294. {
  2295. int cp, twist;
  2296. /* allocate and initialize global array twist_on_cornerperm */
  2297. twist_on_cornerperm[0] =
  2298. (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_CORNERPERM]));
  2299. if (twist_on_cornerperm[0] == NULL)
  2300. exit_w_error_message("init_twist_on_cornerperm : couldn't get memory");
  2301. for (twist = 1; twist < N_TWIST; twist++)
  2302. twist_on_cornerperm[twist] = &twist_on_cornerperm[0][twist * N_CORNERPERM];
  2303. for (cp = 0; cp < N_CORNERPERM; cp++)
  2304. {
  2305. twist_on_cornerperm[TWIST_F][cp] = (unsigned short)twist_f_on_cperm(cp);
  2306. twist_on_cornerperm[TWIST_R][cp] = (unsigned short)twist_r_on_cperm(cp);
  2307. twist_on_cornerperm[TWIST_U][cp] = (unsigned short)twist_u_on_cperm(cp);
  2308. twist_on_cornerperm[TWIST_B][cp] = (unsigned short)twist_b_on_cperm(cp);
  2309. twist_on_cornerperm[TWIST_L][cp] = (unsigned short)twist_l_on_cperm(cp);
  2310. twist_on_cornerperm[TWIST_D][cp] = (unsigned short)twist_d_on_cperm(cp);
  2311. }
  2312. for (cp = 0; cp < N_CORNERPERM; cp++)
  2313. {
  2314. twist_on_cornerperm[TWIST_F2][cp] =
  2315. twist_on_cornerperm[TWIST_F][(int)twist_on_cornerperm[TWIST_F][cp]];
  2316. twist_on_cornerperm[TWIST_R2][cp] =
  2317. twist_on_cornerperm[TWIST_R][(int)twist_on_cornerperm[TWIST_R][cp]];
  2318. twist_on_cornerperm[TWIST_U2][cp] =
  2319. twist_on_cornerperm[TWIST_U][(int)twist_on_cornerperm[TWIST_U][cp]];
  2320. twist_on_cornerperm[TWIST_B2][cp] =
  2321. twist_on_cornerperm[TWIST_B][(int)twist_on_cornerperm[TWIST_B][cp]];
  2322. twist_on_cornerperm[TWIST_L2][cp] =
  2323. twist_on_cornerperm[TWIST_L][(int)twist_on_cornerperm[TWIST_L][cp]];
  2324. twist_on_cornerperm[TWIST_D2][cp] =
  2325. twist_on_cornerperm[TWIST_D][(int)twist_on_cornerperm[TWIST_D][cp]];
  2326. }
  2327. for (cp = 0; cp < N_CORNERPERM; cp++)
  2328. {
  2329. twist_on_cornerperm[TWIST_F3][cp] =
  2330. twist_on_cornerperm[TWIST_F2][(int)twist_on_cornerperm[TWIST_F][cp]];
  2331. twist_on_cornerperm[TWIST_R3][cp] =
  2332. twist_on_cornerperm[TWIST_R2][(int)twist_on_cornerperm[TWIST_R][cp]];
  2333. twist_on_cornerperm[TWIST_U3][cp] =
  2334. twist_on_cornerperm[TWIST_U2][(int)twist_on_cornerperm[TWIST_U][cp]];
  2335. twist_on_cornerperm[TWIST_B3][cp] =
  2336. twist_on_cornerperm[TWIST_B2][(int)twist_on_cornerperm[TWIST_B][cp]];
  2337. twist_on_cornerperm[TWIST_L3][cp] =
  2338. twist_on_cornerperm[TWIST_L2][(int)twist_on_cornerperm[TWIST_L][cp]];
  2339. twist_on_cornerperm[TWIST_D3][cp] =
  2340. twist_on_cornerperm[TWIST_D2][(int)twist_on_cornerperm[TWIST_D][cp]];
  2341. }
  2342. return;
  2343. }
  2344. /* ========================================================================= */
  2345. void sliceedge_unpack(int sliceedge, int array_out[12])
  2346. /* ------------------------------------------------------------------------- */
  2347. {
  2348. int temp_arr[4], ii, count;
  2349. eloc_unpack(sliceedge % N_ELOC, array_out);
  2350. perm_n_unpack(4, sliceedge / N_ELOC, temp_arr);
  2351. count = 0;
  2352. for (ii = 0; ii < 12; ii++)
  2353. if (array_out[ii] != 0)
  2354. {
  2355. if (count >= 4)
  2356. exit_w_error_message("sliceedge_unpack : corrupted data");
  2357. array_out[ii] = 1 + temp_arr[count++];
  2358. }
  2359. return;
  2360. }
  2361. /* ========================================================================= */
  2362. int sliceedge_pack(int array_in[12])
  2363. /* ------------------------------------------------------------------------- */
  2364. {
  2365. int eloc_arr[12], temp_arr[4], ii, count;
  2366. count = 0;
  2367. for (ii = 0; ii < 12; ii++)
  2368. {
  2369. if (array_in[ii] != 0)
  2370. {
  2371. if (count >= 4)
  2372. exit_w_error_message("sliceedge_pack : invalid input");
  2373. temp_arr[count++] = array_in[ii] - 1;
  2374. }
  2375. eloc_arr[ii] = (array_in[ii] != 0);
  2376. }
  2377. return perm_n_pack(4, temp_arr) * N_ELOC + eloc_pack(eloc_arr);
  2378. }
  2379. /* ========================================================================= */
  2380. int twist_f_on_sliceedge(int sliceedge)
  2381. /* ------------------------------------------------------------------------- */
  2382. {
  2383. int temp_arr[12];
  2384. sliceedge_unpack(sliceedge, temp_arr);
  2385. four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
  2386. return sliceedge_pack(temp_arr);
  2387. }
  2388. /* ========================================================================= */
  2389. int twist_r_on_sliceedge(int sliceedge)
  2390. /* ------------------------------------------------------------------------- */
  2391. {
  2392. int temp_arr[12];
  2393. sliceedge_unpack(sliceedge, temp_arr);
  2394. four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
  2395. return sliceedge_pack(temp_arr);
  2396. }
  2397. /* ========================================================================= */
  2398. int twist_u_on_sliceedge(int sliceedge)
  2399. /* ------------------------------------------------------------------------- */
  2400. {
  2401. int temp_arr[12];
  2402. sliceedge_unpack(sliceedge, temp_arr);
  2403. four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
  2404. return sliceedge_pack(temp_arr);
  2405. }
  2406. /* ========================================================================= */
  2407. int twist_b_on_sliceedge(int sliceedge)
  2408. /* ------------------------------------------------------------------------- */
  2409. {
  2410. int temp_arr[12];
  2411. sliceedge_unpack(sliceedge, temp_arr);
  2412. four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
  2413. return sliceedge_pack(temp_arr);
  2414. }
  2415. /* ========================================================================= */
  2416. int twist_l_on_sliceedge(int sliceedge)
  2417. /* ------------------------------------------------------------------------- */
  2418. {
  2419. int temp_arr[12];
  2420. sliceedge_unpack(sliceedge, temp_arr);
  2421. four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
  2422. return sliceedge_pack(temp_arr);
  2423. }
  2424. /* ========================================================================= */
  2425. int twist_d_on_sliceedge(int sliceedge)
  2426. /* ------------------------------------------------------------------------- */
  2427. {
  2428. int temp_arr[12];
  2429. sliceedge_unpack(sliceedge, temp_arr);
  2430. four_cycle(temp_arr, EDGE_DL, EDGE_DB, EDGE_DR, EDGE_DF);
  2431. return sliceedge_pack(temp_arr);
  2432. }
  2433. /* ========================================================================= */
  2434. void init_twist_on_sliceedge(void)
  2435. /* ------------------------------------------------------------------------- */
  2436. {
  2437. int twist, sl;
  2438. /* allocate and initialize global array twist_on_sliceedge */
  2439. twist_on_sliceedge[0] =
  2440. (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_SLICEEDGE]));
  2441. if (twist_on_sliceedge[0] == NULL)
  2442. exit_w_error_message("init_twist_on_sliceedge : couldn't get memory");
  2443. for (twist = 1; twist < N_TWIST; twist++)
  2444. twist_on_sliceedge[twist] = &twist_on_sliceedge[0][twist * N_SLICEEDGE];
  2445. for (sl = 0; sl < N_SLICEEDGE; sl++)
  2446. {
  2447. twist_on_sliceedge[TWIST_F][sl] = (unsigned short)twist_f_on_sliceedge(sl);
  2448. twist_on_sliceedge[TWIST_R][sl] = (unsigned short)twist_r_on_sliceedge(sl);
  2449. twist_on_sliceedge[TWIST_U][sl] = (unsigned short)twist_u_on_sliceedge(sl);
  2450. twist_on_sliceedge[TWIST_B][sl] = (unsigned short)twist_b_on_sliceedge(sl);
  2451. twist_on_sliceedge[TWIST_L][sl] = (unsigned short)twist_l_on_sliceedge(sl);
  2452. twist_on_sliceedge[TWIST_D][sl] = (unsigned short)twist_d_on_sliceedge(sl);
  2453. }
  2454. for (sl = 0; sl < N_SLICEEDGE; sl++)
  2455. {
  2456. twist_on_sliceedge[TWIST_F2][sl] =
  2457. twist_on_sliceedge[TWIST_F][(int)twist_on_sliceedge[TWIST_F][sl]];
  2458. twist_on_sliceedge[TWIST_R2][sl] =
  2459. twist_on_sliceedge[TWIST_R][(int)twist_on_sliceedge[TWIST_R][sl]];
  2460. twist_on_sliceedge[TWIST_U2][sl] =
  2461. twist_on_sliceedge[TWIST_U][(int)twist_on_sliceedge[TWIST_U][sl]];
  2462. twist_on_sliceedge[TWIST_B2][sl] =
  2463. twist_on_sliceedge[TWIST_B][(int)twist_on_sliceedge[TWIST_B][sl]];
  2464. twist_on_sliceedge[TWIST_L2][sl] =
  2465. twist_on_sliceedge[TWIST_L][(int)twist_on_sliceedge[TWIST_L][sl]];
  2466. twist_on_sliceedge[TWIST_D2][sl] =
  2467. twist_on_sliceedge[TWIST_D][(int)twist_on_sliceedge[TWIST_D][sl]];
  2468. }
  2469. for (sl = 0; sl < N_SLICEEDGE; sl++)
  2470. {
  2471. twist_on_sliceedge[TWIST_F3][sl] =
  2472. twist_on_sliceedge[TWIST_F2][(int)twist_on_sliceedge[TWIST_F][sl]];
  2473. twist_on_sliceedge[TWIST_R3][sl] =
  2474. twist_on_sliceedge[TWIST_R2][(int)twist_on_sliceedge[TWIST_R][sl]];
  2475. twist_on_sliceedge[TWIST_U3][sl] =
  2476. twist_on_sliceedge[TWIST_U2][(int)twist_on_sliceedge[TWIST_U][sl]];
  2477. twist_on_sliceedge[TWIST_B3][sl] =
  2478. twist_on_sliceedge[TWIST_B2][(int)twist_on_sliceedge[TWIST_B][sl]];
  2479. twist_on_sliceedge[TWIST_L3][sl] =
  2480. twist_on_sliceedge[TWIST_L2][(int)twist_on_sliceedge[TWIST_L][sl]];
  2481. twist_on_sliceedge[TWIST_D3][sl] =
  2482. twist_on_sliceedge[TWIST_D2][(int)twist_on_sliceedge[TWIST_D][sl]];
  2483. }
  2484. return;
  2485. }
  2486. /* ========================================================================= */
  2487. int make_current(int corner, int edge, Search_data *p_data)
  2488. /* ------------------------------------------------------------------------- */
  2489. {
  2490. if (DIST(corner, edge) > p_data->depth)
  2491. {
  2492. if (edge & 0x1)
  2493. {
  2494. distance[corner][edge >> 1] &= 0x0F;
  2495. distance[corner][edge >> 1] |= (unsigned char)((p_data->depth) << 4);
  2496. }
  2497. else
  2498. {
  2499. distance[corner][edge >> 1] &= 0xF0;
  2500. distance[corner][edge >> 1] |= (unsigned char)(p_data->depth);
  2501. }
  2502. p_data->found_quot++;
  2503. p_data->found += (p_data->multiplicities)[edge];
  2504. return 1;
  2505. }
  2506. return 0;
  2507. }
  2508. /* ========================================================================= */
  2509. void make_current_all(int corner, int edge, Search_data *p_data)
  2510. /* ------------------------------------------------------------------------- */
  2511. {
  2512. int sym, stab;
  2513. if (make_current(corner, edge, p_data))
  2514. {
  2515. stab = (p_data->stabilizers)[edge];
  2516. for (sym = 1; sym < N_SYM; sym++)
  2517. {
  2518. stab /= 2;
  2519. if (stab % 2)
  2520. make_current((int)sym_on_corner[sym][corner], edge, p_data);
  2521. }
  2522. }
  2523. return;
  2524. }
  2525. /* ========================================================================= */
  2526. void make_neighbors_current(int corner, int edge, Search_data *p_data)
  2527. /* ------------------------------------------------------------------------- */
  2528. {
  2529. int twist, new_edge, new_corner, sym;
  2530. for (twist = 0; twist < N_TWIST; twist++)
  2531. {
  2532. if (p_current_metric->twist_length[twist] != 1)
  2533. continue;
  2534. new_edge = (int)twist_on_edge[twist][edge];
  2535. sym = (int)twist_x_edge_to_sym[twist][edge];
  2536. new_corner = (int)sym_on_corner[sym][(int)twist_on_corner[twist][corner]];
  2537. make_current_all(new_corner, new_edge, p_data);
  2538. }
  2539. return;
  2540. }
  2541. /* ========================================================================= */
  2542. int neighbors_are_previous(int corner, int edge, Search_data *p_data)
  2543. /* ------------------------------------------------------------------------- */
  2544. {
  2545. int twist, new_edge, sym, new_corner;
  2546. for (twist = 0; twist < N_TWIST; twist++)
  2547. {
  2548. if (p_current_metric->twist_length[twist] != 1)
  2549. continue;
  2550. new_edge = (int)twist_on_edge[twist][edge];
  2551. sym = (int)twist_x_edge_to_sym[twist][edge];
  2552. new_corner = (int)sym_on_corner[sym][(int)twist_on_corner[twist][corner]];
  2553. if (DIST(new_corner, new_edge) < p_data->depth)
  2554. return 1;
  2555. }
  2556. return 0;
  2557. }
  2558. /* ========================================================================= */
  2559. void init_distance_table(int edge_stabilizers[N_EDGEQUOT],
  2560. int edge_multiplicities[N_EDGEQUOT])
  2561. /* ------------------------------------------------------------------------- */
  2562. {
  2563. Search_data sdata_struc;
  2564. int total_found_quot, corner, edge, ii, msg_given;
  2565. /* allocate and initialize global array distance */
  2566. distance[0] = (unsigned char *)malloc(sizeof(unsigned char [N_DIST_CHARS]));
  2567. if (distance[0] == NULL)
  2568. exit_w_error_message("init_distance_table : couldn't get memory");
  2569. for (corner = 1; corner < N_CORNER; corner++)
  2570. distance[corner] = &distance[0][corner * (N_EDGEQUOT / 2)];
  2571. for (ii = 0; ii < N_DIST_CHARS; ii++)
  2572. distance[0][ii] = (unsigned char)255;
  2573. msg_given = 0;
  2574. sdata_struc.depth = 0;
  2575. sdata_struc.found_quot = 0;
  2576. sdata_struc.found = 0;
  2577. sdata_struc.stabilizers = edge_stabilizers;
  2578. sdata_struc.multiplicities = edge_multiplicities;
  2579. total_found_quot = 0;
  2580. printf("distance positions (quotient)\n");
  2581. make_current_all(CORNER_START, EDGE_START, &sdata_struc);
  2582. while (sdata_struc.found)
  2583. {
  2584. printf("%7d%c %13d (%8d)\n", sdata_struc.depth,
  2585. p_current_metric->metric_char, sdata_struc.found,
  2586. sdata_struc.found_quot);
  2587. total_found_quot += sdata_struc.found_quot;
  2588. sdata_struc.found_quot = 0;
  2589. sdata_struc.found = 0;
  2590. if (++(sdata_struc.depth) == 15)
  2591. break; /* shouldn't happen */
  2592. if (total_found_quot == 2 * N_DIST_CHARS)
  2593. break;
  2594. if (total_found_quot < BACKWARDS_SWITCH_POINT) /* search forward */
  2595. {
  2596. for (corner = 0; corner < N_CORNER; corner++)
  2597. for (edge = 0; edge < N_EDGEQUOT; edge++)
  2598. if (DIST(corner, edge) == sdata_struc.depth - 1)
  2599. make_neighbors_current(corner, edge, &sdata_struc);
  2600. }
  2601. else /* search backward */
  2602. {
  2603. if (msg_given == 0)
  2604. {
  2605. printf(" switching to backwards searching\n");
  2606. msg_given = 1;
  2607. }
  2608. for (corner = 0; corner < N_CORNER; corner++)
  2609. for (edge = 0; edge < N_EDGEQUOT; edge++)
  2610. if ((DIST(corner, edge) == 15) &&
  2611. neighbors_are_previous(corner, edge, &sdata_struc))
  2612. make_current_all(corner, edge, &sdata_struc);
  2613. }
  2614. }
  2615. return;
  2616. }
  2617. /* ========================================================================= */
  2618. void init_globals(void)
  2619. /* ------------------------------------------------------------------------- */
  2620. {
  2621. int *edge_stabilizers;
  2622. int *edge_multiplicities;
  2623. printf("initializing transformation tables\n");
  2624. init_sym_x_invsym_to_sym();
  2625. init_invsym_on_twist();
  2626. init_twist_on_follow();
  2627. init_twist_on_corner();
  2628. init_sym_on_corner();
  2629. edge_stabilizers = (int *)malloc(sizeof(int [2 * N_EDGEQUOT]));
  2630. if (edge_stabilizers == NULL)
  2631. exit_w_error_message("init_globals : couldn't get memory");
  2632. edge_multiplicities = &edge_stabilizers[N_EDGEQUOT];
  2633. init_edge_quotient(edge_stabilizers, edge_multiplicities);
  2634. init_twist_on_cornerperm();
  2635. init_twist_on_sliceedge();
  2636. printf("initializing distance table ... this will take several minutes\n");
  2637. init_distance_table(edge_stabilizers, edge_multiplicities);
  2638. free((void *)edge_stabilizers);
  2639. return;
  2640. }
  2641. /* ========================================================================= */
  2642. int string_to_cube(char string[], Cube *p_cube, int give_err_msg)
  2643. /* ------------------------------------------------------------------------- */
  2644. /* input: string[] */
  2645. {
  2646. char edge_str[12][3], corner_str[8][4];
  2647. int edge_arr[12], corner_arr[8];
  2648. int ii, jj, twist, flip, edge_par, corner_par, stat;
  2649. stat = 0;
  2650. if (sscanf(string, "%2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %3s %3s %3s %3s %3s %3s %3s %3s",
  2651. edge_str[0], edge_str[1], edge_str[2], edge_str[3],
  2652. edge_str[4], edge_str[5], edge_str[6], edge_str[7],
  2653. edge_str[8], edge_str[9], edge_str[10], edge_str[11],
  2654. corner_str[0], corner_str[1], corner_str[2], corner_str[3],
  2655. corner_str[4], corner_str[5], corner_str[6], corner_str[7]) < 20)
  2656. {
  2657. if (give_err_msg)
  2658. printf("invalid input!\n");
  2659. return 1;
  2660. }
  2661. for (ii = 0; ii < 12; ii++)
  2662. {
  2663. for (jj = 0; jj < 24; jj++)
  2664. if (strcmp(edge_str[ii], edge_cubie_str[jj]) == 0)
  2665. {
  2666. p_cube->edges[ii] = jj;
  2667. break;
  2668. }
  2669. if (jj == 24)
  2670. {
  2671. if (give_err_msg)
  2672. printf("invalid edge cubie: %s\n", edge_str[ii]);
  2673. stat = 1;
  2674. }
  2675. }
  2676. for (ii = 0; ii < 8; ii++)
  2677. {
  2678. for (jj = 0; jj < 24; jj++)
  2679. if (strcmp(corner_str[ii], corner_cubie_str[jj]) == 0)
  2680. {
  2681. p_cube->corners[ii] = jj;
  2682. break;
  2683. }
  2684. if (jj == 24)
  2685. {
  2686. if (give_err_msg)
  2687. printf("invalid corner cubie: %s\n", corner_str[ii]);
  2688. stat = 1;
  2689. }
  2690. }
  2691. if (stat)
  2692. return stat;
  2693. /* fill out the remaining oriented edges and corners */
  2694. for (ii = 12; ii < 24; ii++)
  2695. p_cube->edges[ii] = (12 + p_cube->edges[ii - 12]) % 24;
  2696. for (ii = 8; ii < 24; ii++)
  2697. p_cube->corners[ii] = (8 + p_cube->corners[ii - 8]) % 24;
  2698. /* now check to see that it's a legal cube */
  2699. if (perm_n_check(24, p_cube->edges))
  2700. {
  2701. if (give_err_msg)
  2702. printf("bad edge cubies\n");
  2703. stat = 1;
  2704. }
  2705. if (perm_n_check(24, p_cube->corners))
  2706. {
  2707. if (give_err_msg)
  2708. printf("bad corner cubies\n");
  2709. stat = 1;
  2710. }
  2711. if (stat)
  2712. return stat;
  2713. flip = 0;
  2714. for (ii = 0; ii < 12; ii++)
  2715. flip += (p_cube->edges[ii] / 12);
  2716. if ((flip % 2) != 0)
  2717. {
  2718. if (give_err_msg)
  2719. printf("flip any edge cubie!\n");
  2720. stat = 1;
  2721. }
  2722. twist = 0;
  2723. for (ii = 0; ii < 8; ii++)
  2724. twist += (p_cube->corners[ii] / 8);
  2725. twist %= 3;
  2726. if (twist != 0)
  2727. {
  2728. if (give_err_msg)
  2729. printf("twist any corner cubie %sclockwise!\n",
  2730. (twist == 1) ? "counter" : "");
  2731. stat = 1;
  2732. }
  2733. for (ii = 0; ii < 12; ii++)
  2734. edge_arr[ii] = p_cube->edges[ii] % 12;
  2735. edge_par = perm_n_parity(12, edge_arr);
  2736. for (ii = 0; ii < 8; ii++)
  2737. corner_arr[ii] = p_cube->corners[ii] % 8;
  2738. corner_par = perm_n_parity(8, corner_arr);
  2739. if (edge_par != corner_par)
  2740. {
  2741. if (give_err_msg)
  2742. printf("swap any two edge cubies or any two corner cubies!\n");
  2743. stat = 1;
  2744. }
  2745. return stat;
  2746. }
  2747. /* ========================================================================= */
  2748. int user_enters_cube(Cube *p_cube)
  2749. /* ------------------------------------------------------------------------- */
  2750. {
  2751. char line_str[256];
  2752. printf("\nenter cube (Ctrl-D to exit):\n");
  2753. line_str[0] = '\n';
  2754. while (line_str[0] == '\n') /* ignore blank lines */
  2755. {
  2756. if (fgets(line_str, 256, stdin) == NULL)
  2757. return -1;
  2758. if (line_str[0] == '%') /* echo comments */
  2759. {
  2760. printf("%s", line_str);
  2761. line_str[0] = '\n';
  2762. }
  2763. }
  2764. return string_to_cube(line_str, p_cube, 1);
  2765. }
  2766. /* ========================================================================= */
  2767. void calc_cube_urf(Cube *p_cube)
  2768. /* ------------------------------------------------------------------------- */
  2769. {
  2770. cube_init(p_cube);
  2771. three_cycle(p_cube->edges, EDGE_UF, EDGE_FR, EDGE_RU);
  2772. three_cycle(p_cube->edges, EDGE_UB, EDGE_FL, EDGE_RD);
  2773. three_cycle(p_cube->edges, EDGE_DB, EDGE_BL, EDGE_LD);
  2774. three_cycle(p_cube->edges, EDGE_DF, EDGE_BR, EDGE_LU);
  2775. three_cycle(p_cube->edges, EDGE_FU, EDGE_RF, EDGE_UR);
  2776. three_cycle(p_cube->edges, EDGE_BU, EDGE_LF, EDGE_DR);
  2777. three_cycle(p_cube->edges, EDGE_BD, EDGE_LB, EDGE_DL);
  2778. three_cycle(p_cube->edges, EDGE_FD, EDGE_RB, EDGE_UL);
  2779. three_cycle(p_cube->corners, CORNER_UFR, CORNER_FRU, CORNER_RUF);
  2780. three_cycle(p_cube->corners, CORNER_DLB, CORNER_BDL, CORNER_LBD);
  2781. three_cycle(p_cube->corners, CORNER_URB, CORNER_FUL, CORNER_RFD);
  2782. three_cycle(p_cube->corners, CORNER_UBL, CORNER_FLD, CORNER_RDB);
  2783. three_cycle(p_cube->corners, CORNER_RBU, CORNER_ULF, CORNER_FDR);
  2784. three_cycle(p_cube->corners, CORNER_BLU, CORNER_LDF, CORNER_DBR);
  2785. three_cycle(p_cube->corners, CORNER_BUR, CORNER_LFU, CORNER_DRF);
  2786. three_cycle(p_cube->corners, CORNER_LUB, CORNER_DFL, CORNER_BRD);
  2787. return;
  2788. }
  2789. /* ========================================================================= */
  2790. void cube_to_coset_coord(Cube *p_cube, Coset_coord *p_coset_coord)
  2791. /* ------------------------------------------------------------------------- */
  2792. /* output: *p_coset_coord */
  2793. {
  2794. int corner_arr[8], edge_arr[12];
  2795. int ii, eflip, eloc, sym, corner;
  2796. for (ii = 0; ii < 12; ii++)
  2797. edge_arr[ii] = p_cube->edges[ii] / 12;
  2798. eflip = eflip_pack(edge_arr);
  2799. for (ii = 0; ii < 12; ii++)
  2800. edge_arr[ii] = (p_cube->edges[ii] % 12) / 8;
  2801. eloc = eloc_pack(edge_arr);
  2802. p_coset_coord->edge_state = (int)fulledge_to_edge[eloc * N_EFLIP + eflip];
  2803. p_coset_coord->sym_state = sym = (int)fulledge_to_sym[eloc * N_EFLIP + eflip];
  2804. for (ii = 0; ii < 8; ii++)
  2805. corner_arr[ii] = p_cube->corners[ii] / 8;
  2806. corner = corner_pack(corner_arr);
  2807. p_coset_coord->corner_state =
  2808. (int)sym_on_corner[(int)sym_x_invsym_to_sym[0][sym]][corner];
  2809. return;
  2810. }
  2811. /* ========================================================================= */
  2812. void process_full_cube(Full_cube *p_cube)
  2813. /* ------------------------------------------------------------------------- */
  2814. {
  2815. Cube cube1, cube2, cube_urf;
  2816. int edges_to_ud[12], edges_to_rl[12], edges_to_fb[12];
  2817. int cornerperm_arr[8], sliceedge_arr[12], ii;
  2818. /* p_cube->cubies already filled in */
  2819. /* fill in other fields of p_cube */
  2820. for (ii = 0; ii < 8; ii++)
  2821. cornerperm_arr[ii] = p_cube->cubies.corners[ii] % 8;
  2822. p_cube->cornerperm = cornerperm_pack(cornerperm_arr);
  2823. p_cube->parity = perm_n_parity(8, cornerperm_arr);
  2824. for (ii = 0; ii < 12; ii++)
  2825. edges_to_ud[ii] = edges_to_fb[ii] = edges_to_rl[ii] = 0;
  2826. edges_to_ud[EDGE_FR] = 1;
  2827. edges_to_ud[EDGE_FL] = 2;
  2828. edges_to_ud[EDGE_BR] = 3;
  2829. edges_to_ud[EDGE_BL] = 4;
  2830. edges_to_rl[EDGE_UF] = 1;
  2831. edges_to_rl[EDGE_UB] = 2;
  2832. edges_to_rl[EDGE_DF] = 3;
  2833. edges_to_rl[EDGE_DB] = 4;
  2834. edges_to_fb[EDGE_UR] = 1;
  2835. edges_to_fb[EDGE_UL] = 2;
  2836. edges_to_fb[EDGE_DR] = 3;
  2837. edges_to_fb[EDGE_DL] = 4;
  2838. for (ii = 0; ii < 12; ii++)
  2839. sliceedge_arr[ii] = edges_to_ud[(p_cube->cubies.edges[ii]) % 12];
  2840. p_cube->ud_sliceedge = sliceedge_pack(sliceedge_arr);
  2841. for (ii = 0; ii < 12; ii++)
  2842. sliceedge_arr[ii] = edges_to_fb[(p_cube->cubies.edges[ii]) % 12];
  2843. p_cube->fb_sliceedge = sliceedge_pack(sliceedge_arr);
  2844. for (ii = 0; ii < 12; ii++)
  2845. sliceedge_arr[ii] = edges_to_rl[(p_cube->cubies.edges[ii]) % 12];
  2846. p_cube->rl_sliceedge = sliceedge_pack(sliceedge_arr);
  2847. cube_to_coset_coord(&p_cube->cubies, &p_cube->ud);
  2848. calc_cube_urf(&cube_urf);
  2849. cube_conjugate(&p_cube->cubies, &cube_urf, &cube1);
  2850. cube_to_coset_coord(&cube1, &p_cube->rl);
  2851. cube_conjugate(&cube1, &cube_urf, &cube2);
  2852. cube_to_coset_coord(&cube2, &p_cube->fb);
  2853. return;
  2854. }
  2855. /* ========================================================================= */
  2856. void set_cube_symmetry(Full_cube *p_cube, Cube sym_cubes[N_CUBESYM],
  2857. int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
  2858. /* ------------------------------------------------------------------------- */
  2859. {
  2860. Cube temp_cube;
  2861. int subgroup[N_CUBESYM], sym, count;
  2862. if (p_current_options->use_symmetry)
  2863. {
  2864. count = 0;
  2865. for (sym = 0; sym < N_CUBESYM; sym++)
  2866. {
  2867. cube_conjugate(&p_cube->cubies, &sym_cubes[sym], &temp_cube);
  2868. subgroup[sym] = (cube_compare(&p_cube->cubies, &temp_cube) == 0);
  2869. if (subgroup[sym])
  2870. count++;
  2871. }
  2872. p_cube->sym_subgrp = which_subgroup(subgroup, subgroup_list);
  2873. if (p_cube->sym_subgrp < 0)
  2874. exit_w_error_message("set_cube_symmetry : unknown symmetry group");
  2875. if (count > 1)
  2876. printf("position has %d-fold symmetry (subgroup #%d)\n", count,
  2877. p_cube->sym_subgrp);
  2878. else
  2879. printf("asymmetric position\n");
  2880. }
  2881. else
  2882. p_cube->sym_subgrp = SUBGRP_TRIVIAL;
  2883. return;
  2884. }
  2885. /* ========================================================================= */
  2886. void output_solution(Search_node *node_arr)
  2887. /* ------------------------------------------------------------------------- */
  2888. {
  2889. static char *twist_string[] = {"F ", "F2", "F'", "R ", "R2", "R'",
  2890. "U ", "U2", "U'", "B ", "B2", "B'",
  2891. "L ", "L2", "L'", "D ", "D2", "D'"};
  2892. Search_node *p_node;
  2893. int turn_list[MAX_TWISTS];
  2894. int ii, count, q_length, f_length;
  2895. count = 0;
  2896. for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
  2897. turn_list[count++] = p_node[1].twist;
  2898. q_length = f_length = 0;
  2899. for (ii = 0; ii < count; ii++)
  2900. {
  2901. q_length += metric_q_length(turn_list[ii]);
  2902. f_length += metric_f_length(turn_list[ii]);
  2903. }
  2904. for (ii = 0; ii < count; ii++)
  2905. printf(" %s", twist_string[turn_list[ii]]);
  2906. if (p_current_metric->metric == QUARTER_TURN_METRIC)
  2907. printf(" (%dq*, %df)\n", q_length, f_length);
  2908. else
  2909. printf(" (%df*, %dq)\n", f_length, q_length);
  2910. fflush(stdout);
  2911. sol_found = 1;
  2912. return;
  2913. }
  2914. /* ========================================================================= */
  2915. int test_for_solution(Full_cube *p_cube, Search_node *node_arr)
  2916. /* ------------------------------------------------------------------------- */
  2917. {
  2918. register Search_node *p_node;
  2919. register int cornerperm, sliceedge;
  2920. n_tests++;
  2921. cornerperm = p_cube->cornerperm;
  2922. for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
  2923. cornerperm = (int)twist_on_cornerperm[p_node[1].twist][cornerperm];
  2924. if (cornerperm != CORNERPERM_START)
  2925. return 0; /* not a solution */
  2926. sliceedge = p_cube->ud_sliceedge;
  2927. for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
  2928. sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
  2929. if (sliceedge != UD_SLICEEDGE_START)
  2930. return 0; /* not a solution */
  2931. sliceedge = p_cube->rl_sliceedge;
  2932. for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
  2933. sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
  2934. if (sliceedge != RL_SLICEEDGE_START)
  2935. return 0; /* not a solution */
  2936. sliceedge = p_cube->fb_sliceedge;
  2937. for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
  2938. sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
  2939. if (sliceedge != FB_SLICEEDGE_START)
  2940. return 0; /* not a solution */
  2941. output_solution(node_arr); /* solution ! */
  2942. return 1;
  2943. }
  2944. /* ========================================================================= */
  2945. void search_tree(Full_cube *p_cube, Search_node *node_arr)
  2946. /* ------------------------------------------------------------------------- */
  2947. {
  2948. register Search_node *p_node;
  2949. register int twist, virtual_twist, new_sym_factor;
  2950. p_node = node_arr;
  2951. while (p_node >= node_arr)
  2952. {
  2953. if (p_node->remain_depth == 0)
  2954. {
  2955. if (test_for_solution(p_cube, node_arr) &&
  2956. p_current_options->one_solution_only)
  2957. return;
  2958. p_node--;
  2959. }
  2960. else
  2961. {
  2962. for (twist = p_node[1].twist + 1; twist < N_TWIST; twist++)
  2963. {
  2964. p_node[1].follow_type =
  2965. (int)twist_on_follow[twist][p_node->follow_type];
  2966. if (p_node[1].follow_type == FOLLOW_INVALID)
  2967. continue;
  2968. p_node[1].remain_depth = p_node->remain_depth -
  2969. p_current_metric->twist_length[twist];
  2970. if (p_node[1].remain_depth < 0)
  2971. continue;
  2972. n_nodes++;
  2973. virtual_twist =
  2974. (int)invsym_on_twist_ud[p_node->ud.sym_state][twist];
  2975. new_sym_factor =
  2976. (int)twist_x_edge_to_sym[virtual_twist][p_node->ud.edge_state];
  2977. p_node[1].ud.edge_state =
  2978. (int)twist_on_edge[virtual_twist][p_node->ud.edge_state];
  2979. p_node[1].ud.sym_state =
  2980. (int)sym_x_invsym_to_sym[p_node->ud.sym_state][new_sym_factor];
  2981. p_node[1].ud.corner_state = (int)sym_on_corner[new_sym_factor]
  2982. [(int)twist_on_corner[virtual_twist][p_node->ud.corner_state]];
  2983. if (p_node[1].remain_depth <
  2984. DIST(p_node[1].ud.corner_state, p_node[1].ud.edge_state))
  2985. continue;
  2986. virtual_twist =
  2987. (int)invsym_on_twist_rl[p_node->rl.sym_state][twist];
  2988. new_sym_factor =
  2989. (int)twist_x_edge_to_sym[virtual_twist][p_node->rl.edge_state];
  2990. p_node[1].rl.edge_state =
  2991. (int)twist_on_edge[virtual_twist][p_node->rl.edge_state];
  2992. p_node[1].rl.sym_state =
  2993. (int)sym_x_invsym_to_sym[p_node->rl.sym_state][new_sym_factor];
  2994. p_node[1].rl.corner_state = (int)sym_on_corner[new_sym_factor]
  2995. [(int)twist_on_corner[virtual_twist][p_node->rl.corner_state]];
  2996. if (p_node[1].remain_depth <
  2997. DIST(p_node[1].rl.corner_state, p_node[1].rl.edge_state))
  2998. continue;
  2999. virtual_twist =
  3000. (int)invsym_on_twist_fb[p_node->fb.sym_state][twist];
  3001. new_sym_factor =
  3002. (int)twist_x_edge_to_sym[virtual_twist][p_node->fb.edge_state];
  3003. p_node[1].fb.edge_state =
  3004. (int)twist_on_edge[virtual_twist][p_node->fb.edge_state];
  3005. p_node[1].fb.sym_state =
  3006. (int)sym_x_invsym_to_sym[p_node->fb.sym_state][new_sym_factor];
  3007. p_node[1].fb.corner_state = (int)sym_on_corner[new_sym_factor]
  3008. [(int)twist_on_corner[virtual_twist][p_node->fb.corner_state]];
  3009. if (p_node[1].remain_depth <
  3010. DIST(p_node[1].fb.corner_state, p_node[1].fb.edge_state))
  3011. continue;
  3012. p_node[1].twist = twist;
  3013. break;
  3014. }
  3015. if (twist == N_TWIST)
  3016. p_node--;
  3017. else
  3018. {
  3019. p_node++;
  3020. p_node[1].twist = -1;
  3021. }
  3022. }
  3023. }
  3024. return;
  3025. }
  3026. /* ========================================================================= */
  3027. void calc_sym_cubes(Cube sym_conj[N_CUBESYM])
  3028. /* ------------------------------------------------------------------------- */
  3029. {
  3030. int ii;
  3031. cube_init(&sym_conj[0]);
  3032. cube_init(&sym_conj[1]);
  3033. four_cycle(sym_conj[1].edges, EDGE_UF, EDGE_UL, EDGE_UB, EDGE_UR);
  3034. four_cycle(sym_conj[1].edges, EDGE_DF, EDGE_DL, EDGE_DB, EDGE_DR);
  3035. four_cycle(sym_conj[1].edges, EDGE_FR, EDGE_LF, EDGE_BL, EDGE_RB);
  3036. four_cycle(sym_conj[1].edges, EDGE_FU, EDGE_LU, EDGE_BU, EDGE_RU);
  3037. four_cycle(sym_conj[1].edges, EDGE_FD, EDGE_LD, EDGE_BD, EDGE_RD);
  3038. four_cycle(sym_conj[1].edges, EDGE_RF, EDGE_FL, EDGE_LB, EDGE_BR);
  3039. four_cycle(sym_conj[1].corners, CORNER_UFR, CORNER_ULF, CORNER_UBL, CORNER_URB);
  3040. four_cycle(sym_conj[1].corners, CORNER_DRF, CORNER_DFL, CORNER_DLB, CORNER_DBR);
  3041. four_cycle(sym_conj[1].corners, CORNER_FRU, CORNER_LFU, CORNER_BLU, CORNER_RBU);
  3042. four_cycle(sym_conj[1].corners, CORNER_RFD, CORNER_FLD, CORNER_LBD, CORNER_BRD);
  3043. four_cycle(sym_conj[1].corners, CORNER_RUF, CORNER_FUL, CORNER_LUB, CORNER_BUR);
  3044. four_cycle(sym_conj[1].corners, CORNER_FDR, CORNER_LDF, CORNER_BDL, CORNER_RDB);
  3045. for (ii = 2; ii < 4; ii++)
  3046. cube_compose(&sym_conj[1], &sym_conj[ii - 1], &sym_conj[ii]);
  3047. cube_init(&sym_conj[4]);
  3048. two_cycle(sym_conj[4].edges, EDGE_UF, EDGE_DF);
  3049. two_cycle(sym_conj[4].edges, EDGE_UR, EDGE_DL);
  3050. two_cycle(sym_conj[4].edges, EDGE_UB, EDGE_DB);
  3051. two_cycle(sym_conj[4].edges, EDGE_UL, EDGE_DR);
  3052. two_cycle(sym_conj[4].edges, EDGE_FR, EDGE_FL);
  3053. two_cycle(sym_conj[4].edges, EDGE_BR, EDGE_BL);
  3054. two_cycle(sym_conj[4].edges, EDGE_FU, EDGE_FD);
  3055. two_cycle(sym_conj[4].edges, EDGE_RU, EDGE_LD);
  3056. two_cycle(sym_conj[4].edges, EDGE_BU, EDGE_BD);
  3057. two_cycle(sym_conj[4].edges, EDGE_LU, EDGE_RD);
  3058. two_cycle(sym_conj[4].edges, EDGE_RF, EDGE_LF);
  3059. two_cycle(sym_conj[4].edges, EDGE_RB, EDGE_LB);
  3060. two_cycle(sym_conj[4].corners, CORNER_UFR, CORNER_DFL);
  3061. two_cycle(sym_conj[4].corners, CORNER_ULF, CORNER_DRF);
  3062. two_cycle(sym_conj[4].corners, CORNER_UBL, CORNER_DBR);
  3063. two_cycle(sym_conj[4].corners, CORNER_URB, CORNER_DLB);
  3064. two_cycle(sym_conj[4].corners, CORNER_FRU, CORNER_FLD);
  3065. two_cycle(sym_conj[4].corners, CORNER_LFU, CORNER_RFD);
  3066. two_cycle(sym_conj[4].corners, CORNER_BLU, CORNER_BRD);
  3067. two_cycle(sym_conj[4].corners, CORNER_RBU, CORNER_LBD);
  3068. two_cycle(sym_conj[4].corners, CORNER_RUF, CORNER_LDF);
  3069. two_cycle(sym_conj[4].corners, CORNER_FUL, CORNER_FDR);
  3070. two_cycle(sym_conj[4].corners, CORNER_LUB, CORNER_RDB);
  3071. two_cycle(sym_conj[4].corners, CORNER_BUR, CORNER_BDL);
  3072. for (ii = 5; ii < 8; ii++)
  3073. cube_compose(&sym_conj[4], &sym_conj[ii - 4], &sym_conj[ii]);
  3074. cube_init(&sym_conj[8]);
  3075. two_cycle(sym_conj[8].edges, EDGE_UF, EDGE_DF);
  3076. two_cycle(sym_conj[8].edges, EDGE_UR, EDGE_DR);
  3077. two_cycle(sym_conj[8].edges, EDGE_UB, EDGE_DB);
  3078. two_cycle(sym_conj[8].edges, EDGE_UL, EDGE_DL);
  3079. two_cycle(sym_conj[8].edges, EDGE_FU, EDGE_FD);
  3080. two_cycle(sym_conj[8].edges, EDGE_RU, EDGE_RD);
  3081. two_cycle(sym_conj[8].edges, EDGE_BU, EDGE_BD);
  3082. two_cycle(sym_conj[8].edges, EDGE_LU, EDGE_LD);
  3083. two_cycle(sym_conj[8].corners, CORNER_UFR, CORNER_DRF);
  3084. two_cycle(sym_conj[8].corners, CORNER_ULF, CORNER_DFL);
  3085. two_cycle(sym_conj[8].corners, CORNER_UBL, CORNER_DLB);
  3086. two_cycle(sym_conj[8].corners, CORNER_URB, CORNER_DBR);
  3087. two_cycle(sym_conj[8].corners, CORNER_FRU, CORNER_FDR);
  3088. two_cycle(sym_conj[8].corners, CORNER_LFU, CORNER_LDF);
  3089. two_cycle(sym_conj[8].corners, CORNER_BLU, CORNER_BDL);
  3090. two_cycle(sym_conj[8].corners, CORNER_RBU, CORNER_RDB);
  3091. two_cycle(sym_conj[8].corners, CORNER_RUF, CORNER_RFD);
  3092. two_cycle(sym_conj[8].corners, CORNER_FUL, CORNER_FLD);
  3093. two_cycle(sym_conj[8].corners, CORNER_LUB, CORNER_LBD);
  3094. two_cycle(sym_conj[8].corners, CORNER_BUR, CORNER_BRD);
  3095. for (ii = 9; ii < 16; ii++)
  3096. cube_compose(&sym_conj[8], &sym_conj[ii - 8], &sym_conj[ii]);
  3097. calc_cube_urf(&sym_conj[16]);
  3098. for (ii = 17; ii < 48; ii++)
  3099. cube_compose(&sym_conj[16], &sym_conj[ii - 16], &sym_conj[ii]);
  3100. return;
  3101. }
  3102. /* ========================================================================= */
  3103. void pretty_print_unsigned_int(unsigned int nn)
  3104. /* ------------------------------------------------------------------------- */
  3105. {
  3106. int digits[4], ii, started;
  3107. for (ii = 0; ii < 4; ii++)
  3108. {
  3109. digits[ii] = nn % 1000;
  3110. nn /= 1000;
  3111. }
  3112. started = 0;
  3113. for (ii = 3; ii >= 0; ii--)
  3114. {
  3115. if (started)
  3116. {
  3117. if (digits[ii] >= 100)
  3118. printf("%3d", digits[ii]);
  3119. else if (digits[ii] >= 10)
  3120. printf("0%2d", digits[ii]);
  3121. else
  3122. printf("00%1d", digits[ii]);
  3123. }
  3124. else
  3125. {
  3126. if (digits[ii] >= 100)
  3127. {
  3128. printf("%3d", digits[ii]);
  3129. started = 1;
  3130. }
  3131. else if (digits[ii] >= 10)
  3132. {
  3133. printf(" %2d", digits[ii]);
  3134. started = 1;
  3135. }
  3136. else if ((digits[ii] >= 1) || (ii == 0))
  3137. {
  3138. printf(" %1d", digits[ii]);
  3139. started = 1;
  3140. }
  3141. else
  3142. printf(" ");
  3143. }
  3144. if (ii > 0)
  3145. printf("%c", started ? ',' : ' ');
  3146. }
  3147. return;
  3148. }
  3149. /* ========================================================================= */
  3150. void solve_cube(Cube *p_cube)
  3151. /* ------------------------------------------------------------------------- */
  3152. {
  3153. static Cube sym_cubes[N_CUBESYM];
  3154. static int subgroup_list[N_SYMSUBGRP][N_CUBESYM];
  3155. static int initialized = 0;
  3156. Full_cube full_cube_struct;
  3157. Search_node node_arr[MAX_TWISTS];
  3158. int ii, start_depth, search_limit;
  3159. if (initialized == 0)
  3160. {
  3161. calc_sym_cubes(sym_cubes);
  3162. calc_subgroup_list(subgroup_list);
  3163. initialized = 1;
  3164. }
  3165. print_cube(p_cube);
  3166. if (cube_is_solved(p_cube))
  3167. {
  3168. printf("cube is already solved!\n");
  3169. return;
  3170. }
  3171. cube_conjugate(p_cube, &sym_cubes[0], &full_cube_struct.cubies);
  3172. process_full_cube(&full_cube_struct);
  3173. set_cube_symmetry(&full_cube_struct, sym_cubes, subgroup_list);
  3174. node_arr[0].follow_type = 1 + full_cube_struct.sym_subgrp;
  3175. node_arr[0].ud.corner_state = full_cube_struct.ud.corner_state;
  3176. node_arr[0].ud.edge_state = full_cube_struct.ud.edge_state;
  3177. node_arr[0].ud.sym_state = full_cube_struct.ud.sym_state;
  3178. node_arr[0].rl.corner_state = full_cube_struct.rl.corner_state;
  3179. node_arr[0].rl.edge_state = full_cube_struct.rl.edge_state;
  3180. node_arr[0].rl.sym_state = full_cube_struct.rl.sym_state;
  3181. node_arr[0].fb.corner_state = full_cube_struct.fb.corner_state;
  3182. node_arr[0].fb.edge_state = full_cube_struct.fb.edge_state;
  3183. node_arr[0].fb.sym_state = full_cube_struct.fb.sym_state;
  3184. sol_found = 0;
  3185. if ((p_current_metric->metric == QUARTER_TURN_METRIC) &&
  3186. (full_cube_struct.parity == 0))
  3187. start_depth = 2;
  3188. else
  3189. start_depth = 1;
  3190. search_limit = p_current_options->search_limit;
  3191. if ((search_limit <= 0) || (search_limit >= MAX_TWISTS))
  3192. search_limit = MAX_TWISTS - 1;
  3193. for (ii = start_depth; ii <= search_limit; ii += p_current_metric->increment)
  3194. {
  3195. n_nodes = (long long int)0;
  3196. n_tests = (unsigned int)0;
  3197. node_arr[0].remain_depth = ii;
  3198. node_arr[1].twist = -1;
  3199. search_tree(&full_cube_struct, node_arr);
  3200. if ((p_current_options->one_solution_only == 0) || (sol_found == 0))
  3201. {
  3202. printf("depth %2d%c completed (", ii, p_current_metric->metric_char);
  3203. pretty_print_unsigned_int(n_nodes);
  3204. printf(" nodes, ");
  3205. pretty_print_unsigned_int(n_tests);
  3206. printf(" tests)\n");
  3207. fflush(stdout);
  3208. }
  3209. if (sol_found)
  3210. break;
  3211. }
  3212. return;
  3213. }
  3214. /* ========================================================================= */
  3215. int main(void)
  3216. /* ------------------------------------------------------------------------- */
  3217. {
  3218. Metric_data metric_data;
  3219. Options user_options;
  3220. Cube cube_struct;
  3221. int stat;
  3222. init_options(&metric_data, &user_options);
  3223. init_globals();
  3224. signal(SIGINT, SIG_IGN);
  3225. while (1)
  3226. {
  3227. stat = user_enters_cube(&cube_struct);
  3228. if (stat < 0)
  3229. break;
  3230. if (stat == 0)
  3231. {
  3232. if (sigsetjmp(jump_env, 1) == 0)
  3233. {
  3234. signal(SIGINT, user_interrupt);
  3235. solve_cube(&cube_struct);
  3236. }
  3237. signal(SIGINT, SIG_IGN);
  3238. }
  3239. }
  3240. exit(EXIT_SUCCESS);
  3241. return 0; /* haha */
  3242. }