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

Generated with cgit - Back to sebastiano.tronto.net