aboutsummaryrefslogtreecommitdiff
path: root/src/cube.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/cube.c1195
1 files changed, 0 insertions, 1195 deletions
diff --git a/src/cube.c b/src/cube.c
deleted file mode 100644
index 4f92ea7..0000000
--- a/src/cube.c
+++ /dev/null
@@ -1,1195 +0,0 @@
1#include <inttypes.h>
2#include <stdbool.h>
3#include <string.h>
4
5#ifdef DEBUG
6#include <stdio.h>
7#endif
8
9#include "cube.h"
10
11#define U 0U
12#define U2 1U
13#define U3 2U
14#define D 3U
15#define D2 4U
16#define D3 5U
17#define R 6U
18#define R2 7U
19#define R3 8U
20#define L 9U
21#define L2 10U
22#define L3 11U
23#define F 12U
24#define F2 13U
25#define F3 14U
26#define B 15U
27#define B2 16U
28#define B3 17U
29
30#define UFr 0
31#define ULr 1
32#define UBr 2
33#define URr 3
34#define DFr 4
35#define DLr 5
36#define DBr 6
37#define DRr 7
38#define RUr 8
39#define RFr 9
40#define RDr 10
41#define RBr 11
42#define LUr 12
43#define LFr 13
44#define LDr 14
45#define LBr 15
46#define FUr 16
47#define FRr 17
48#define FDr 18
49#define FLr 19
50#define BUr 20
51#define BRr 21
52#define BDr 22
53#define BLr 23
54
55#define UFm 24
56#define ULm 25
57#define UBm 26
58#define URm 27
59#define DFm 28
60#define DLm 29
61#define DBm 30
62#define DRm 31
63#define RUm 32
64#define RFm 33
65#define RDm 34
66#define RBm 35
67#define LUm 36
68#define LFm 37
69#define LDm 38
70#define LBm 39
71#define FUm 40
72#define FRm 41
73#define FDm 42
74#define FLm 43
75#define BUm 44
76#define BRm 45
77#define BDm 46
78#define BLm 47
79
80#define errormove 99U
81#define errortrans 99U
82
83#define _c_ufr 0U
84#define _c_ubl 1U
85#define _c_dfl 2U
86#define _c_dbr 3U
87#define _c_ufl 4U
88#define _c_ubr 5U
89#define _c_dfr 6U
90#define _c_dbl 7U
91
92#define _e_uf 0U
93#define _e_ub 1U
94#define _e_db 2U
95#define _e_df 3U
96#define _e_ur 4U
97#define _e_ul 5U
98#define _e_dl 6U
99#define _e_dr 7U
100#define _e_fr 8U
101#define _e_fl 9U
102#define _e_bl 10U
103#define _e_br 11U
104
105#define _eoshift 4U
106#define _coshift 5U
107
108#define _pbits 0xFU
109#define _eobit 0x10U
110#define _cobits 0xF0U
111#define _cobits2 0x60U
112#define _ctwist_cw 0x20U
113#define _ctwist_ccw 0x40U
114#define _eflip 0x10U
115#define _error 0xFFU
116
117#define get_edge(cube, i) (cube).e[(i)]
118#define get_corner(cube, i) (cube).c[(i)]
119#define set_edge(cube, i, p) (cube).e[(i)] = (p)
120#define set_corner(cube, i, p) (cube).c[(i)] = (p)
121
122cube_arr_t solvedcube_arr = {
123 .c = {0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0},
124 .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0}
125};
126cube_arr_t zerocube_arr = { .e = {0}, .c = {0} };
127
128#ifdef CUBE_AVX2
129
130#define _co_avx2 _mm256_set_epi8( \
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
132 0, 0, 0, 0, 0, 0, 0, 0, \
133 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0)
134#define _co2_avx2 _mm256_set_epi8( \
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
136 0, 0, 0, 0, 0, 0, 0, 0, \
137 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60)
138#define _eo_avx2 _mm256_set_epi8( \
139 0, 0, 0, 0, 0x10, 0x10, 0x10, 0x10, \
140 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, \
141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
142#define setsolved(cube) cube = _mm256_loadu_si256((__m256i_u *)&solvedcube_arr)
143#define setzero(cube) cube = _mm256_setzero_si256()
144
145#include "_moves_avx2.c"
146#include "_trans_avx2.c"
147
148static cube_t
149arrtocube(cube_arr_t a)
150{
151 return _mm256_loadu_si256((__m256i_u *)&a);
152}
153
154static void
155cubetoarr(cube_t c, cube_arr_t *a)
156{
157 _mm256_storeu_si256((__m256i_u *)a, c);
158}
159
160#else
161
162#define setsolved(cube) cube = solvedcube_arr
163#define setzero(cube) cube = zerocube_arr
164
165static cube_t
166arrtocube(cube_arr_t a)
167{
168 return a;
169}
170
171static void
172cubetoarr(cube_t c, cube_arr_t *a)
173{
174 memcpy(a, &c, sizeof(cube_t));
175}
176
177#include "_moves_arr.c"
178#include "_trans_arr.c"
179
180#endif
181
182static char *cornerstr[] = {
183 [_c_ufr] = "UFR",
184 [_c_ubl] = "UBL",
185 [_c_dfl] = "DFL",
186 [_c_dbr] = "DBR",
187 [_c_ufl] = "UFL",
188 [_c_ubr] = "UBR",
189 [_c_dfr] = "DFR",
190 [_c_dbl] = "DBL"
191};
192
193static char *cornerstralt[] = {
194 [_c_ufr] = "URF",
195 [_c_ubl] = "ULB",
196 [_c_dfl] = "DLF",
197 [_c_dbr] = "DRB",
198 [_c_ufl] = "ULF",
199 [_c_ubr] = "URB",
200 [_c_dfr] = "DRF",
201 [_c_dbl] = "DLB"
202};
203
204static char *edgestr[] = {
205 [_e_uf] = "UF",
206 [_e_ub] = "UB",
207 [_e_db] = "DB",
208 [_e_df] = "DF",
209 [_e_ur] = "UR",
210 [_e_ul] = "UL",
211 [_e_dl] = "DL",
212 [_e_dr] = "DR",
213 [_e_fr] = "FR",
214 [_e_fl] = "FL",
215 [_e_bl] = "BL",
216 [_e_br] = "BR"
217};
218
219static char *movestr[] = {
220 [U] = "U",
221 [U2] = "U2",
222 [U3] = "U'",
223 [D] = "D",
224 [D2] = "D2",
225 [D3] = "D'",
226 [R] = "R",
227 [R2] = "R2",
228 [R3] = "R'",
229 [L] = "L",
230 [L2] = "L2",
231 [L3] = "L'",
232 [F] = "F",
233 [F2] = "F2",
234 [F3] = "F'",
235 [B] = "B",
236 [B2] = "B2",
237 [B3] = "B'",
238};
239
240static char *transstr[] = {
241 [UFr] = "rotation UF",
242 [UFm] = "mirrored UF",
243 [ULr] = "rotation UL",
244 [ULm] = "mirrored UL",
245 [UBr] = "rotation UB",
246 [UBm] = "mirrored UB",
247 [URr] = "rotation UR",
248 [URm] = "mirrored UR",
249 [DFr] = "rotation DF",
250 [DFm] = "mirrored DF",
251 [DLr] = "rotation DL",
252 [DLm] = "mirrored DL",
253 [DBr] = "rotation DB",
254 [DBm] = "mirrored DB",
255 [DRr] = "rotation DR",
256 [DRm] = "mirrored DR",
257 [RUr] = "rotation RU",
258 [RUm] = "mirrored RU",
259 [RFr] = "rotation RF",
260 [RFm] = "mirrored RF",
261 [RDr] = "rotation RD",
262 [RDm] = "mirrored RD",
263 [RBr] = "rotation RB",
264 [RBm] = "mirrored RB",
265 [LUr] = "rotation LU",
266 [LUm] = "mirrored LU",
267 [LFr] = "rotation LF",
268 [LFm] = "mirrored LF",
269 [LDr] = "rotation LD",
270 [LDm] = "mirrored LD",
271 [LBr] = "rotation LB",
272 [LBm] = "mirrored LB",
273 [FUr] = "rotation FU",
274 [FUm] = "mirrored FU",
275 [FRr] = "rotation FR",
276 [FRm] = "mirrored FR",
277 [FDr] = "rotation FD",
278 [FDm] = "mirrored FD",
279 [FLr] = "rotation FL",
280 [FLm] = "mirrored FL",
281 [BUr] = "rotation BU",
282 [BUm] = "mirrored BU",
283 [BRr] = "rotation BR",
284 [BRm] = "mirrored BR",
285 [BDr] = "rotation BD",
286 [BDm] = "mirrored BD",
287 [BLr] = "rotation BL",
288 [BLm] = "mirrored BL",
289};
290
291static inline cube_t inline_compose(cube_t, cube_t);
292static bool isconsistent(cube_t);
293static cube_t flipallcorners(cube_t);
294static uint8_t readco(char *);
295static uint8_t readcp(char *);
296static uint8_t readeo(char *);
297static uint8_t readep(char *);
298static uint8_t readmove(char);
299static uint8_t readmodifier(char);
300static cube_t readcube_H48(char *);
301static void writecube_AVX(cube_arr_t, char *);
302static void writecube_H48(cube_arr_t, char *);
303static int writepiece_SRC(uint8_t, char *);
304static void writecube_SRC(cube_arr_t, char *);
305static int permsign(uint8_t *, int);
306
307cube_t
308solvedcube(void)
309{
310 cube_t solved;
311 setsolved(solved);
312 return solved;
313}
314
315cube_t
316zerocube(void)
317{
318 cube_t solved;
319 setzero(solved);
320 return solved;
321}
322
323static uint8_t
324readco(char *str)
325{
326 if (*str == '0')
327 return 0;
328 if (*str == '1')
329 return _ctwist_cw;
330 if (*str == '2')
331 return _ctwist_ccw;
332
333#ifdef DEBUG
334 fprintf(stderr, "Error reading CO\n");
335#endif
336 return _error;
337}
338
339static uint8_t
340readcp(char *str)
341{
342 uint8_t c;
343
344 for (c = 0; c < 8; c++)
345 if (!strncmp(str, cornerstr[c], 3) ||
346 !strncmp(str, cornerstralt[c], 3))
347 return c;
348
349#ifdef DEBUG
350 fprintf(stderr, "Error reading CP\n");
351#endif
352 return _error;
353}
354
355static uint8_t
356readeo(char *str)
357{
358 if (*str == '0')
359 return 0;
360 if (*str == '1')
361 return _eflip;
362
363#ifdef DEBUG
364 fprintf(stderr, "Error reading EO\n");
365#endif
366 return _error;
367}
368
369static uint8_t
370readep(char *str)
371{
372 uint8_t e;
373
374 for (e = 0; e < 12; e++)
375 if (!strncmp(str, edgestr[e], 2))
376 return e;
377
378#ifdef DEBUG
379 fprintf(stderr, "Error reading EP\n");
380#endif
381 return _error;
382}
383
384static cube_t
385readcube_H48(char *buf)
386{
387 int i;
388 uint8_t piece, orient;
389 cube_arr_t ret = {0};
390 cube_t err;
391 char *b;
392
393 setzero(err);
394 b = buf;
395
396 for (i = 0; i < 12; i++) {
397 while (*b == ' ' || *b == '\t' || *b == '\n')
398 b++;
399 if ((piece = readep(b)) == _error)
400 return err;
401 b += 2;
402 if ((orient = readeo(b)) == _error)
403 return err;
404 b++;
405 set_edge(ret, i, piece | orient);
406 }
407 for (i = 0; i < 8; i++) {
408 while (*b == ' ' || *b == '\t' || *b == '\n')
409 b++;
410 if ((piece = readcp(b)) == _error)
411 return err;
412 b += 3;
413 if ((orient = readco(b)) == _error)
414 return err;
415 b++;
416 set_corner(ret, i, piece | orient);
417 }
418
419 return arrtocube(ret);
420}
421
422cube_t
423readcube(format_t format, char *buf)
424{
425 cube_t ret;
426
427 switch (format) {
428 case H48:
429 ret = readcube_H48(buf);
430 break;
431 default:
432#ifdef DEBUG
433 fprintf(stderr, "Cannot read cube in the given format\n");
434#endif
435 setzero(ret);
436 }
437
438#ifdef DEBUG
439 if (iserror(ret))
440 fprintf(stderr, "readcube error\n");
441#endif
442 return ret;
443}
444
445static void
446writecube_AVX(cube_arr_t cube, char *buf)
447{
448 int i, ptr;
449 uint8_t piece;
450
451 memcpy(buf, "_mm256_set_epi8(\n\t0, 0, 0, 0, ", 30);
452 ptr = 30;
453
454 for (i = 11; i >= 0; i--) {
455 piece = get_edge(cube, i);
456 ptr += writepiece_SRC(piece, buf + ptr);
457 }
458
459 memcpy(buf+ptr-2, ",\n\t0, 0, 0, 0, 0, 0, 0, 0, ", 27);
460 ptr += 25;
461
462 for (i = 7; i >= 0; i--) {
463 piece = get_corner(cube, i);
464 ptr += writepiece_SRC(piece, buf + ptr);
465 }
466
467 memcpy(buf+ptr-2, "\n)\0", 3);
468}
469
470static void
471writecube_H48(cube_arr_t cube, char *buf)
472{
473 uint8_t piece, perm, orient;
474 int i;
475
476 for (i = 0; i < 12; i++) {
477 piece = get_edge(cube, i);
478 perm = piece & _pbits;
479 orient = (piece & _eobit) >> _eoshift;
480 buf[4*i ] = edgestr[perm][0];
481 buf[4*i + 1] = edgestr[perm][1];
482 buf[4*i + 2] = orient + '0';
483 buf[4*i + 3] = ' ';
484 }
485 for (i = 0; i < 8; i++) {
486 piece = get_corner(cube, i);
487 perm = piece & _pbits;
488 orient = (piece & _cobits) >> _coshift;
489 buf[48 + 5*i ] = cornerstr[perm][0];
490 buf[48 + 5*i + 1] = cornerstr[perm][1];
491 buf[48 + 5*i + 2] = cornerstr[perm][2];
492 buf[48 + 5*i + 3] = orient + '0';
493 buf[48 + 5*i + 4] = ' ';
494 }
495
496 buf[48+39] = '\0';
497}
498
499static int
500writepiece_SRC(uint8_t piece, char *buf)
501{
502 char digits[3];
503 int i, len = 0;
504
505 while (piece != 0) {
506 digits[len++] = (piece % 10) + '0';
507 piece /= 10;
508 }
509
510 if (len == 0)
511 digits[len++] = '0';
512
513 for (i = 0; i < len; i++)
514 buf[i] = digits[len-i-1];
515
516 buf[len] = ',';
517 buf[len+1] = ' ';
518
519 return len+2;
520}
521
522static void
523writecube_SRC(cube_arr_t cube, char *buf)
524{
525 int i, ptr;
526 uint8_t piece;
527
528 memcpy(buf, "{\n\t.c = {", 9);
529 ptr = 9;
530
531 for (i = 0; i < 8; i++) {
532 piece = get_corner(cube, i);
533 ptr += writepiece_SRC(piece, buf + ptr);
534 }
535
536 memcpy(buf+ptr-2, "},\n\t.e = {", 10);
537 ptr += 8;
538
539 for (i = 0; i < 12; i++) {
540 piece = get_edge(cube, i);
541 ptr += writepiece_SRC(piece, buf + ptr);
542 }
543
544 memcpy(buf+ptr-2, "}\n}\0", 4);
545}
546
547void
548writecube(format_t format, cube_t cube, char *buf)
549{
550 cube_arr_t a;
551 char *errormsg;
552 size_t len;
553
554 if (!isconsistent(cube)) {
555 errormsg = "ERROR: cannot write inconsistent cube";
556 goto writecube_error;
557 }
558
559 cubetoarr(cube, &a);
560
561 switch (format) {
562 case AVX:
563 writecube_AVX(a, buf);
564 break;
565 case H48:
566 writecube_H48(a, buf);
567 break;
568 case SRC:
569 writecube_SRC(a, buf);
570 break;
571 default:
572 errormsg = "ERROR: cannot write cube in the given format";
573 goto writecube_error;
574 }
575
576 return;
577
578writecube_error:
579#ifdef DEBUG
580 fprintf(stderr, "writecube error, see stdout for details\n");
581#endif
582 len = strlen(errormsg);
583 memcpy(buf, errormsg, len);
584 buf[len] = '\n';
585 buf[len+1] = '\0';
586}
587
588static uint8_t
589readmove(char c)
590{
591 switch (c) {
592 case 'U':
593 return U;
594 case 'D':
595 return D;
596 case 'R':
597 return R;
598 case 'L':
599 return L;
600 case 'F':
601 return F;
602 case 'B':
603 return B;
604 default:
605 return _error;
606 }
607}
608
609static uint8_t
610readmodifier(char c)
611{
612 switch (c) {
613 case '1': /* Fallthrough */
614 case '2': /* Fallthrough */
615 case '3':
616 return c - '0' - 1;
617 case '\'':
618 return 2;
619 default:
620 return 0;
621 }
622}
623
624int
625readmoves(char *buf, move_t *m)
626{
627 int n;
628 uint64_t r;
629 char *b;
630
631 for (b = buf, n = 0; *b != '\0'; b++) {
632 while (*b == ' ' || *b == '\t' || *b == '\n')
633 b++;
634 if (*b == '\0')
635 return n;
636 if ((r = readmove(*b)) == _error)
637 goto readmoves_error;
638 m[n] = (move_t)r;
639 if ((r = readmodifier(*(b+1))) != 0) {
640 b++;
641 m[n] += r;
642 }
643 n++;
644 }
645
646 return n;
647
648readmoves_error:
649#ifdef DEBUG
650 fprintf(stderr, "readmoves error\n");
651#endif
652 return -1;
653}
654
655trans_t
656readtrans(char *buf)
657{
658 uint8_t t;
659
660 for (t = 0; t < 48; t++)
661 if (!strncmp(buf, transstr[t], 11))
662 return t;
663
664#ifdef DEBUG
665 fprintf(stderr, "readtrans error\n");
666#endif
667 return errortrans;
668}
669
670void
671writemoves(move_t *m, int n, char *buf)
672{
673 int i;
674 size_t len;
675 char *b, *s;
676
677 for (i = 0, b = buf; i < n; i++, b++) {
678 s = movestr[m[i]];
679 len = strlen(s);
680 memcpy(b, s, len);
681 b += len;
682 *b = ' ';
683 }
684 *b = '\0';
685}
686
687void
688writetrans(trans_t t, char *buf)
689{
690 if (t >= 48)
691 memcpy(buf, "error trans", 11);
692 else
693 memcpy(buf, transstr[t], 11);
694 buf[11] = '\0';
695}
696
697static int
698permsign(uint8_t *a, int n)
699{
700 int i, j;
701 uint8_t ret = 0;
702
703 for (i = 0; i < n; i++)
704 for (j = i+1; j < n; j++)
705 ret += a[i] > a[j] ? 1 : 0;
706
707 return ret % 2;
708}
709
710static bool
711isconsistent(cube_t cube)
712{
713 cube_arr_t c;
714 uint8_t i, p, e, piece;
715 bool found[12];
716
717 cubetoarr(cube, &c);
718
719 for (i = 0; i < 12; i++)
720 found[i] = false;
721 for (i = 0; i < 12; i++) {
722 piece = get_edge(c, i);
723 p = piece & _pbits;
724 e = piece & _eobit;
725 if (p >= 12)
726 goto inconsistent_ep;
727 if (e != 0 && e != _eobit)
728 goto inconsistent_eo;
729 found[p] = true;
730 }
731 for (i = 0; i < 12; i++)
732 if (!found[i])
733 goto inconsistent_ep;
734
735 for (i = 0; i < 8; i++)
736 found[i] = false;
737 for (i = 0; i < 8; i++) {
738 piece = get_corner(c, i);
739 p = piece & _pbits;
740 e = piece & _cobits;
741 if (p >= 8)
742 goto inconsistent_cp;
743 if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw)
744 goto inconsistent_co;
745 found[p] = true;
746 }
747 for (i = 0; i < 8; i++)
748 if (!found[i])
749 goto inconsistent_co;
750
751 return true;
752
753inconsistent_ep:
754#ifdef DEBUG
755 fprintf(stderr, "Inconsistent EP\n");
756#endif
757 return false;
758inconsistent_cp:
759#ifdef DEBUG
760 fprintf(stderr, "Inconsistent CP\n");
761#endif
762 return false;
763inconsistent_eo:
764#ifdef DEBUG
765 fprintf(stderr, "Inconsistent EO\n");
766#endif
767 return false;
768inconsistent_co:
769#ifdef DEBUG
770 fprintf(stderr, "Inconsistent CO\n");
771#endif
772 return false;
773}
774
775bool
776issolvable(cube_t cube)
777{
778 cube_arr_t c;
779 uint8_t i, eo, co, piece, edges[12], corners[8];
780
781#ifdef DEBUG
782 if (!isconsistent(cube)) {
783 fprintf(stderr, "issolvable: cube is inconsistent\n");
784 return false;
785 }
786#endif
787
788 cubetoarr(cube, &c);
789
790 for (i = 0; i < 12; i++)
791 edges[i] = get_edge(c, i) & _pbits;
792 for (i = 0; i < 8; i++)
793 corners[i] = get_corner(c, i) & _pbits;
794
795 if (permsign(edges, 12) != permsign(corners, 8))
796 goto issolvable_parity;
797
798 eo = 0;
799 for (i = 0; i < 12; i++) {
800 piece = get_edge(c, i);
801 eo += (piece & _eobit) >> _eoshift;
802 }
803 if (eo % 2 != 0)
804 goto issolvable_eo;
805
806 co = 0;
807 for (i = 0; i < 8; i++) {
808 piece = get_corner(c, i);
809 co += (piece & _cobits) >> _coshift;
810 }
811 if (co % 3 != 0)
812 goto issolvable_co;
813
814 return true;
815
816issolvable_parity:
817#ifdef DEBUG
818 fprintf(stderr, "EP and CP parities are different\n");
819#endif
820 return false;
821issolvable_eo:
822#ifdef DEBUG
823 fprintf(stderr, "Odd number of flipped edges\n");
824#endif
825 return false;
826issolvable_co:
827#ifdef DEBUG
828 fprintf(stderr, "Sum of corner orientation is not multiple of 3\n");
829#endif
830 return false;
831}
832
833bool
834equal(cube_t cube1, cube_t cube2)
835{
836#ifdef CUBE_AVX2
837 uint32_t mask;
838 __m256i cmp;
839
840 cmp = _mm256_cmpeq_epi8(cube1, cube2);
841 mask = _mm256_movemask_epi8(cmp);
842
843 return mask == 0xffffffffU;
844#else
845 uint8_t i;
846
847 for (i = 0; i < 12; i++)
848 if (cube1.e[i] != cube2.e[i])
849 return false;
850
851 for (i = 0; i < 8; i++)
852 if (cube1.c[i] != cube2.c[i])
853 return false;
854
855 return true;
856#endif
857}
858
859bool
860issolved(cube_t cube)
861{
862 cube_t solved;
863 setsolved(solved);
864 return equal(cube, solved);
865}
866
867bool
868iserror(cube_t cube)
869{
870 cube_t err;
871 setzero(err);
872 return equal(cube, err);
873}
874
875cube_t
876move(cube_t c, move_t m)
877{
878 cube_t err;
879
880#ifdef DEBUG
881 if (!isconsistent(c)) {
882 fprintf(stderr, "move error, inconsistent cube\n");
883 goto move_error;
884 }
885#endif
886
887 switch (m) {
888 case U:
889 return inline_move_U(c);
890 case U2:
891 return inline_move_U2(c);
892 case U3:
893 return inline_move_U3(c);
894 case D:
895 return inline_move_D(c);
896 case D2:
897 return inline_move_D2(c);
898 case D3:
899 return inline_move_D3(c);
900 case R:
901 return inline_move_R(c);
902 case R2:
903 return inline_move_R2(c);
904 case R3:
905 return inline_move_R3(c);
906 case L:
907 return inline_move_L(c);
908 case L2:
909 return inline_move_L2(c);
910 case L3:
911 return inline_move_L3(c);
912 case F:
913 return inline_move_F(c);
914 case F2:
915 return inline_move_F2(c);
916 case F3:
917 return inline_move_F3(c);
918 case B:
919 return inline_move_B(c);
920 case B2:
921 return inline_move_B2(c);
922 case B3:
923 return inline_move_B3(c);
924 default:
925#ifdef DEBUG
926 fprintf(stderr, "mover error, unknown move\n");
927#endif
928 goto move_error;
929 }
930
931move_error:
932 setzero(err);
933 return err;
934}
935
936cube_t
937inverse(cube_t c)
938{
939 cube_t ret;
940
941#ifdef DEBUG
942 if (!isconsistent(c)) {
943 fprintf(stderr, "inverse error, inconsistent cube\n");
944 setzero(ret);
945 return ret;
946 }
947#endif
948
949#ifdef CUBE_AVX2
950 /* Method taken from Andrew Skalski's vcube[1]. The addition sequence
951 * was generated using [2].
952 * [1] https://github.com/Voltara/vcube
953 * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html
954 */
955 cube_t v3, vi, vo, vp;
956
957 v3 = _mm256_shuffle_epi8(c, c);
958 v3 = _mm256_shuffle_epi8(v3, c);
959 vi = _mm256_shuffle_epi8(v3, v3);
960 vi = _mm256_shuffle_epi8(vi, vi);
961 vi = _mm256_shuffle_epi8(vi, vi);
962 vi = _mm256_shuffle_epi8(vi, v3);
963 vi = _mm256_shuffle_epi8(vi, vi);
964 vi = _mm256_shuffle_epi8(vi, vi);
965 vi = _mm256_shuffle_epi8(vi, vi);
966 vi = _mm256_shuffle_epi8(vi, vi);
967 vi = _mm256_shuffle_epi8(vi, c);
968 vi = _mm256_shuffle_epi8(vi, vi);
969 vi = _mm256_shuffle_epi8(vi, vi);
970 vi = _mm256_shuffle_epi8(vi, vi);
971 vi = _mm256_shuffle_epi8(vi, vi);
972 vi = _mm256_shuffle_epi8(vi, vi);
973 vi = _mm256_shuffle_epi8(vi, v3);
974 vi = _mm256_shuffle_epi8(vi, vi);
975 vi = _mm256_shuffle_epi8(vi, c);
976
977 vo = _mm256_and_si256(c, _mm256_or_si256(_eo_avx2, _co2_avx2));
978 vo = _mm256_shuffle_epi8(vo, vi);
979 vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi);
980 ret = _mm256_or_si256(vp, vo);
981
982 return flipallcorners(ret);
983#else
984 uint8_t i, piece, orien;
985
986 setzero(ret);
987
988 for (i = 0; i < 12; i++) {
989 piece = get_edge(c, i);
990 orien = piece & _eobit;
991 set_edge(ret, piece & _pbits, i | orien);
992 }
993
994 for (i = 0; i < 8; i++) {
995 piece = get_corner(c, i);
996 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
997 set_corner(ret, piece & _pbits, i | orien);
998 }
999#endif
1000
1001 return ret;
1002}
1003
1004static inline cube_t
1005inline_compose(cube_t c1, cube_t c2)
1006{
1007 cube_t ret;
1008
1009#ifdef DEBUG
1010 if (!isconsistent(c1) || !isconsistent(c2)) {
1011 fprintf(stderr, "compose error, inconsistent cube\n");
1012 setzero(ret);
1013 return ret;
1014 }
1015#endif
1016
1017#ifdef CUBE_AVX2
1018 cube_t s, eo2, ed, co1, co2, aux, auy1, auy2, cw, cwccw, auz1, auz2,
1019 coclean;
1020
1021 eo2 = _mm256_and_si256(c2, _eo_avx2);
1022 s = _mm256_shuffle_epi8(c1, c2);
1023 ed = _mm256_xor_si256(s, eo2);
1024 co1 = _mm256_and_si256(s, _co2_avx2);
1025 co2 = _mm256_and_si256(c2, _co2_avx2);
1026 aux = _mm256_add_epi8(co1, co2);
1027 cw = _mm256_set_epi8(
1028 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1029 0, 0, 0, 0, 0, 0, 0, 0,
1030 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
1031 );
1032 auy1 = _mm256_add_epi8(aux, cw);
1033 auy2 = _mm256_srli_epi32(auy1, 2);
1034 auz1 = _mm256_add_epi8(aux, auy2);
1035 cwccw = _mm256_set_epi8(
1036 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1037 0, 0, 0, 0, 0, 0, 0, 0,
1038 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
1039 );
1040 auz2 = _mm256_and_si256(auz1, cwccw);
1041 coclean = _mm256_andnot_si256(_co2_avx2, ed);
1042 ret = _mm256_or_si256(coclean, auz2);
1043#else
1044 uint8_t i, piece1, piece2, p, orien, aux, auy;
1045
1046 setzero(ret);
1047
1048 for (i = 0; i < 12; i++) {
1049 piece2 = get_edge(c2, i);
1050 p = piece2 & _pbits;
1051 piece1 = get_edge(c1, p);
1052 orien = (piece2 ^ piece1) & _eobit;
1053 set_edge(ret, i, (piece1 & _pbits) | orien);
1054 }
1055
1056 for (i = 0; i < 8; i++) {
1057 piece2 = get_corner(c2, i);
1058 p = piece2 & _pbits;
1059 piece1 = get_corner(c1, p);
1060 aux = (piece2 & _cobits) + (piece1 & _cobits);
1061 auy = (aux + _ctwist_cw) >> 2U;
1062 orien = (aux + auy) & _cobits2;
1063 set_corner(ret, i, (piece1 & _pbits) | orien);
1064 }
1065#endif
1066
1067 return ret;
1068}
1069
1070cube_t
1071compose(cube_t c1, cube_t c2)
1072{
1073 return inline_compose(c1, c2);
1074}
1075
1076cube_t
1077transform(cube_t c, trans_t t)
1078{
1079 cube_t ret;
1080
1081#ifdef DEBUG
1082 if (!isconsistent(c)) {
1083 fprintf(stderr, "transform error, inconsistent cube\n");
1084 goto trans_error;
1085 }
1086#endif
1087
1088 switch (t) {
1089 case UFr:
1090 return inline_trans_UFr(c);
1091 case ULr:
1092 return inline_trans_ULr(c);
1093 case UBr:
1094 return inline_trans_UBr(c);
1095 case URr:
1096 return inline_trans_URr(c);
1097 case DFr:
1098 return inline_trans_DFr(c);
1099 case DLr:
1100 return inline_trans_DLr(c);
1101 case DBr:
1102 return inline_trans_DBr(c);
1103 case DRr:
1104 return inline_trans_DRr(c);
1105 case RUr:
1106 return inline_trans_RUr(c);
1107 case RFr:
1108 return inline_trans_RFr(c);
1109 case RDr:
1110 return inline_trans_RDr(c);
1111 case RBr:
1112 return inline_trans_RBr(c);
1113 case LUr:
1114 return inline_trans_LUr(c);
1115 case LFr:
1116 return inline_trans_LFr(c);
1117 case LDr:
1118 return inline_trans_LDr(c);
1119 case LBr:
1120 return inline_trans_LBr(c);
1121 case FUr:
1122 return inline_trans_FUr(c);
1123 case FRr:
1124 return inline_trans_FRr(c);
1125 case FDr:
1126 return inline_trans_FDr(c);
1127 case FLr:
1128 return inline_trans_FLr(c);
1129 case BUr:
1130 return inline_trans_BUr(c);
1131 case BRr:
1132 return inline_trans_BRr(c);
1133 case BDr:
1134 return inline_trans_BDr(c);
1135 case BLr:
1136 return inline_trans_BLr(c);
1137 case UFm:
1138 return inline_trans_UFm(c);
1139 case ULm:
1140 return inline_trans_ULm(c);
1141 case UBm:
1142 return inline_trans_UBm(c);
1143 case URm:
1144 return inline_trans_URm(c);
1145 case DFm:
1146 return inline_trans_DFm(c);
1147 case DLm:
1148 return inline_trans_DLm(c);
1149 case DBm:
1150 return inline_trans_DBm(c);
1151 case DRm:
1152 return inline_trans_DRm(c);
1153 case RUm:
1154 return inline_trans_RUm(c);
1155 case RFm:
1156 return inline_trans_RFm(c);
1157 case RDm:
1158 return inline_trans_RDm(c);
1159 case RBm:
1160 return inline_trans_RBm(c);
1161 case LUm:
1162 return inline_trans_LUm(c);
1163 case LFm:
1164 return inline_trans_LFm(c);
1165 case LDm:
1166 return inline_trans_LDm(c);
1167 case LBm:
1168 return inline_trans_LBm(c);
1169 case FUm:
1170 return inline_trans_FUm(c);
1171 case FRm:
1172 return inline_trans_FRm(c);
1173 case FDm:
1174 return inline_trans_FDm(c);
1175 case FLm:
1176 return inline_trans_FLm(c);
1177 case BUm:
1178 return inline_trans_BUm(c);
1179 case BRm:
1180 return inline_trans_BRm(c);
1181 case BDm:
1182 return inline_trans_BDm(c);
1183 case BLm:
1184 return inline_trans_BLm(c);
1185 default:
1186#ifdef DEBUG
1187 fprintf(stderr, "transform error, unknown transformation\n");
1188#endif
1189 goto trans_error;
1190 }
1191
1192trans_error:
1193 setzero(ret);
1194 return ret;
1195}

Generated with cgit - Back to sebastiano.tronto.net