diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/_base_arr.c | 30 | ||||
| -rw-r--r-- | src/_base_avx2.c | 28 | ||||
| -rw-r--r-- | src/_constants.c | 4 | ||||
| -rw-r--r-- | src/_move_logic_avx2.c | 7 | ||||
| -rw-r--r-- | src/cube.c | 128 | ||||
| -rw-r--r-- | src/cube.h | 28 |
6 files changed, 123 insertions, 102 deletions
diff --git a/src/_base_arr.c b/src/_base_arr.c deleted file mode 100644 index 2169cd5..0000000 --- a/src/_base_arr.c +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | cube_t solvedcube = { | ||
| 2 | .c = {0, 1, 2, 3, 4, 5, 6, 7}, | ||
| 3 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} | ||
| 4 | }; | ||
| 5 | static cube_t errorcube = { .e = {0}, .c = {0} }; | ||
| 6 | static cube_t zerocube = { .e = {0}, .c = {0} }; | ||
| 7 | |||
| 8 | static uint8_t | ||
| 9 | get_edge(cube_t c, uint8_t i) | ||
| 10 | { | ||
| 11 | return c.e[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | static uint8_t | ||
| 15 | get_corner(cube_t c, uint8_t i) | ||
| 16 | { | ||
| 17 | return c.c[i]; | ||
| 18 | } | ||
| 19 | |||
| 20 | static void | ||
| 21 | set_edge(cube_t *c, uint8_t i, uint8_t p) | ||
| 22 | { | ||
| 23 | c->e[i] = p; | ||
| 24 | } | ||
| 25 | |||
| 26 | static void | ||
| 27 | set_corner(cube_t *c, uint8_t i, uint8_t p) | ||
| 28 | { | ||
| 29 | c->c[i] = p; | ||
| 30 | } | ||
diff --git a/src/_base_avx2.c b/src/_base_avx2.c deleted file mode 100644 index 7af88eb..0000000 --- a/src/_base_avx2.c +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | #define solvedcube _mm256_set_epi8( \ | ||
| 2 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0, /* Corners */ \ | ||
| 3 | 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 /* Edges */ \ | ||
| 4 | ) | ||
| 5 | #define errorcube _mm256_setzero_si256() | ||
| 6 | #define zerocube _mm256_setzero_si256() | ||
| 7 | |||
| 8 | static uint8_t | ||
| 9 | get_edge(cube_t c, uint8_t i) | ||
| 10 | { | ||
| 11 | return 0; | ||
| 12 | } | ||
| 13 | |||
| 14 | static uint8_t | ||
| 15 | get_corner(cube_t c, uint8_t i) | ||
| 16 | { | ||
| 17 | return 0; | ||
| 18 | } | ||
| 19 | |||
| 20 | static void | ||
| 21 | set_edge(cube_t *c, uint8_t i, uint8_t p) | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | static void | ||
| 26 | set_corner(cube_t *c, uint8_t i, uint8_t p) | ||
| 27 | { | ||
| 28 | } | ||
diff --git a/src/_constants.c b/src/_constants.c index 3121e3b..0070990 100644 --- a/src/_constants.c +++ b/src/_constants.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #define _eflip 0x10U | 32 | #define _eflip 0x10U |
| 33 | #define _error 0xFFU | 33 | #define _error 0xFFU |
| 34 | 34 | ||
| 35 | move_t inverse_move[] = { | 35 | static move_t inverse_move_arr[] = { |
| 36 | [U] = U3, | 36 | [U] = U3, |
| 37 | [U2] = U2, | 37 | [U2] = U2, |
| 38 | [U3] = U, | 38 | [U3] = U, |
| @@ -53,7 +53,7 @@ move_t inverse_move[] = { | |||
| 53 | [B3] = B, | 53 | [B3] = B, |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | trans_t inverse_trans[] = { | 56 | static trans_t inverse_trans_arr[] = { |
| 57 | [UFr] = UFr, | 57 | [UFr] = UFr, |
| 58 | [ULr] = URr, | 58 | [ULr] = URr, |
| 59 | [UBr] = UBr, | 59 | [UBr] = UBr, |
diff --git a/src/_move_logic_avx2.c b/src/_move_logic_avx2.c index 7bf881c..29df776 100644 --- a/src/_move_logic_avx2.c +++ b/src/_move_logic_avx2.c | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | static cube_t move_cube[18]; /* TODO */ | 1 | /* TODO: |
| 2 | 2 | static cube_t move_cube[18]; | |
| 3 | return compose(move_cube[m], c); | 3 | return compose(move_cube[m], c); |
| 4 | */ | ||
| 5 | |||
| 6 | goto move_error; | ||
| @@ -14,10 +14,38 @@ | |||
| 14 | 14 | ||
| 15 | #include "_constants.c" | 15 | #include "_constants.c" |
| 16 | 16 | ||
| 17 | cube_arr_t solvedcube_arr = { | ||
| 18 | .c = {0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
| 19 | .e = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0} | ||
| 20 | }; | ||
| 21 | cube_arr_t zerocube_arr = { .e = {0}, .c = {0} }; | ||
| 22 | |||
| 17 | #ifdef CUBE_AVX2 | 23 | #ifdef CUBE_AVX2 |
| 18 | #include "_base_avx2.c" | 24 | |
| 25 | #define setsolved(cube) cube = _mm256_loadu_si256((__m256i_u *)&solvedcube_arr) | ||
| 26 | #define setzero(cube) cube = _mm256_setzero_si256() | ||
| 27 | #define _c _mm256_set_epi64x(0, 0, 0, 0xFF) | ||
| 28 | #define _e _mm256_set_epi64x(0, 0xFF, 0, 0) | ||
| 29 | /* TODO: in the next 4 macros, all 0 should be i, but must be constant! */ | ||
| 30 | #define get_edge(cube, i) _mm256_extract_epi8(cube, 0+16) | ||
| 31 | #define get_corner(cube, i) _mm256_extract_epi8(cube, 0) | ||
| 32 | #define set_edge(cube, i, p) _mm256_or_si256( \ | ||
| 33 | _mm256_andnot_si256(cube, _mm256_slli_si256(_e, 0)), \ | ||
| 34 | _mm256_and_si256(_mm256_set1_epi8(p), _mm256_slli_si256(_e, 0))) | ||
| 35 | #define set_corner(cube, i, p) _mm256_or_si256( \ | ||
| 36 | _mm256_andnot_si256(cube, _mm256_slli_si256(_c, 0)), \ | ||
| 37 | _mm256_and_si256(_mm256_set1_epi8(p), _mm256_slli_si256(_c, 0))) | ||
| 38 | |||
| 19 | #else | 39 | #else |
| 20 | #include "_base_arr.c" | 40 | |
| 41 | #define setsolved(cube) cube = solvedcube_arr | ||
| 42 | #define setzero(cube) cube = zerocube_arr | ||
| 43 | #define _c _mm256_set_epi64x(0, 0, 0, 0xFF) | ||
| 44 | #define get_edge(cube, i) (cube).e[(i)] | ||
| 45 | #define get_corner(cube, i) (cube).c[(i)] | ||
| 46 | #define set_edge(cube, i, p) (cube).e[(i)] = (p) | ||
| 47 | #define set_corner(cube, i, p) (cube).c[(i)] = (p) | ||
| 48 | |||
| 21 | #endif | 49 | #endif |
| 22 | 50 | ||
| 23 | static bool isconsistent(cube_t); | 51 | static bool isconsistent(cube_t); |
| @@ -34,6 +62,22 @@ static int writepiece_SRC(uint8_t, char *); | |||
| 34 | static void writecube_SRC(cube_t, char *); | 62 | static void writecube_SRC(cube_t, char *); |
| 35 | static int permsign(uint8_t *, int); | 63 | static int permsign(uint8_t *, int); |
| 36 | 64 | ||
| 65 | cube_t | ||
| 66 | solvedcube(void) | ||
| 67 | { | ||
| 68 | cube_t solved; | ||
| 69 | setsolved(solved); | ||
| 70 | return solved; | ||
| 71 | } | ||
| 72 | |||
| 73 | cube_t | ||
| 74 | zerocube(void) | ||
| 75 | { | ||
| 76 | cube_t solved; | ||
| 77 | setzero(solved); | ||
| 78 | return solved; | ||
| 79 | } | ||
| 80 | |||
| 37 | static uint8_t | 81 | static uint8_t |
| 38 | readco(char *str) | 82 | readco(char *str) |
| 39 | { | 83 | { |
| @@ -100,30 +144,34 @@ readcube_H48(char *buf) | |||
| 100 | { | 144 | { |
| 101 | int i; | 145 | int i; |
| 102 | uint8_t piece, orient; | 146 | uint8_t piece, orient; |
| 103 | cube_t ret = zerocube; | 147 | cube_t ret, err; |
| 104 | char *b = buf; | 148 | char *b; |
| 149 | |||
| 150 | setzero(ret); | ||
| 151 | setzero(err); | ||
| 152 | b = buf; | ||
| 105 | 153 | ||
| 106 | for (i = 0; i < 12; i++) { | 154 | for (i = 0; i < 12; i++) { |
| 107 | while (*b == ' ' || *b == '\t' || *b == '\n') | 155 | while (*b == ' ' || *b == '\t' || *b == '\n') |
| 108 | b++; | 156 | b++; |
| 109 | if ((piece = readep(b)) == _error) | 157 | if ((piece = readep(b)) == _error) |
| 110 | return errorcube; | 158 | return err; |
| 111 | b += 2; | 159 | b += 2; |
| 112 | if ((orient = readeo(b)) == _error) | 160 | if ((orient = readeo(b)) == _error) |
| 113 | return errorcube; | 161 | return err; |
| 114 | b++; | 162 | b++; |
| 115 | set_edge(&ret, i, piece | orient); | 163 | set_edge(ret, i, piece | orient); |
| 116 | } | 164 | } |
| 117 | for (i = 0; i < 8; i++) { | 165 | for (i = 0; i < 8; i++) { |
| 118 | while (*b == ' ' || *b == '\t' || *b == '\n') | 166 | while (*b == ' ' || *b == '\t' || *b == '\n') |
| 119 | b++; | 167 | b++; |
| 120 | if ((piece = readcp(b)) == _error) | 168 | if ((piece = readcp(b)) == _error) |
| 121 | return errorcube; | 169 | return err; |
| 122 | b += 3; | 170 | b += 3; |
| 123 | if ((orient = readco(b)) == _error) | 171 | if ((orient = readco(b)) == _error) |
| 124 | return errorcube; | 172 | return err; |
| 125 | b++; | 173 | b++; |
| 126 | set_corner(&ret, i, piece | orient); | 174 | set_corner(ret, i, piece | orient); |
| 127 | } | 175 | } |
| 128 | 176 | ||
| 129 | return ret; | 177 | return ret; |
| @@ -142,7 +190,7 @@ readcube(format_t format, char *buf) | |||
| 142 | #ifdef DEBUG | 190 | #ifdef DEBUG |
| 143 | fprintf(stderr, "Cannot read cube in the given format\n"); | 191 | fprintf(stderr, "Cannot read cube in the given format\n"); |
| 144 | #endif | 192 | #endif |
| 145 | ret = errorcube; | 193 | setzero(ret); |
| 146 | } | 194 | } |
| 147 | 195 | ||
| 148 | #ifdef DEBUG | 196 | #ifdef DEBUG |
| @@ -373,6 +421,18 @@ writetrans(trans_t t, char *buf) | |||
| 373 | buf[11] = '\0'; | 421 | buf[11] = '\0'; |
| 374 | } | 422 | } |
| 375 | 423 | ||
| 424 | move_t | ||
| 425 | inverse_move(move_t m) | ||
| 426 | { | ||
| 427 | return inverse_move_arr[m]; | ||
| 428 | } | ||
| 429 | |||
| 430 | trans_t | ||
| 431 | inverse_trans(trans_t t) | ||
| 432 | { | ||
| 433 | return inverse_trans_arr[t]; | ||
| 434 | } | ||
| 435 | |||
| 376 | static int | 436 | static int |
| 377 | permsign(uint8_t *a, int n) | 437 | permsign(uint8_t *a, int n) |
| 378 | { | 438 | { |
| @@ -532,18 +592,24 @@ equal(cube_t cube1, cube_t cube2) | |||
| 532 | bool | 592 | bool |
| 533 | issolved(cube_t cube) | 593 | issolved(cube_t cube) |
| 534 | { | 594 | { |
| 535 | return equal(cube, solvedcube); | 595 | cube_t solved; |
| 596 | setsolved(solved); | ||
| 597 | return equal(cube, solved); | ||
| 536 | } | 598 | } |
| 537 | 599 | ||
| 538 | bool | 600 | bool |
| 539 | iserror(cube_t cube) | 601 | iserror(cube_t cube) |
| 540 | { | 602 | { |
| 541 | return equal(cube, errorcube); | 603 | cube_t err; |
| 604 | setzero(err); | ||
| 605 | return equal(cube, err); | ||
| 542 | } | 606 | } |
| 543 | 607 | ||
| 544 | cube_t | 608 | cube_t |
| 545 | move(cube_t c, move_t m) | 609 | move(cube_t c, move_t m) |
| 546 | { | 610 | { |
| 611 | cube_t err; | ||
| 612 | |||
| 547 | #ifdef DEBUG | 613 | #ifdef DEBUG |
| 548 | if (!isconsistent(c)) { | 614 | if (!isconsistent(c)) { |
| 549 | fprintf(stderr, "move error, inconsistent cube\n"); | 615 | fprintf(stderr, "move error, inconsistent cube\n"); |
| @@ -558,7 +624,8 @@ move(cube_t c, move_t m) | |||
| 558 | #endif | 624 | #endif |
| 559 | 625 | ||
| 560 | move_error: | 626 | move_error: |
| 561 | return errorcube; | 627 | setzero(err); |
| 628 | return err; | ||
| 562 | } | 629 | } |
| 563 | 630 | ||
| 564 | cube_t | 631 | cube_t |
| @@ -566,25 +633,27 @@ inverse(cube_t c) | |||
| 566 | { | 633 | { |
| 567 | /* TODO: optimize for avx2 */ | 634 | /* TODO: optimize for avx2 */ |
| 568 | uint8_t i, piece, orien; | 635 | uint8_t i, piece, orien; |
| 569 | cube_t ret = zerocube; | 636 | cube_t ret; |
| 637 | |||
| 638 | setzero(ret); | ||
| 570 | 639 | ||
| 571 | #ifdef DEBUG | 640 | #ifdef DEBUG |
| 572 | if (!isconsistent(c)) { | 641 | if (!isconsistent(c)) { |
| 573 | fprintf(stderr, "inverse error, inconsistent cube\n"); | 642 | fprintf(stderr, "inverse error, inconsistent cube\n"); |
| 574 | return errorcube; | 643 | return ret; |
| 575 | } | 644 | } |
| 576 | #endif | 645 | #endif |
| 577 | 646 | ||
| 578 | for (i = 0; i < 12; i++) { | 647 | for (i = 0; i < 12; i++) { |
| 579 | piece = get_edge(c, i); | 648 | piece = get_edge(c, i); |
| 580 | orien = piece & _eobit; | 649 | orien = piece & _eobit; |
| 581 | set_edge(&ret, piece & _pbits, i | orien); | 650 | set_edge(ret, piece & _pbits, i | orien); |
| 582 | } | 651 | } |
| 583 | 652 | ||
| 584 | for (i = 0; i < 8; i++) { | 653 | for (i = 0; i < 8; i++) { |
| 585 | piece = get_corner(c, i); | 654 | piece = get_corner(c, i); |
| 586 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | 655 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; |
| 587 | set_corner(&ret, piece & _pbits, i | orien); | 656 | set_corner(ret, piece & _pbits, i | orien); |
| 588 | } | 657 | } |
| 589 | 658 | ||
| 590 | return ret; | 659 | return ret; |
| @@ -595,12 +664,14 @@ compose(cube_t c1, cube_t c2) | |||
| 595 | { | 664 | { |
| 596 | /* TODO: optimize for avx2 */ | 665 | /* TODO: optimize for avx2 */ |
| 597 | uint8_t i, piece1, piece2, p, orien, aux, auy; | 666 | uint8_t i, piece1, piece2, p, orien, aux, auy; |
| 598 | cube_t ret = zerocube; | 667 | cube_t ret; |
| 668 | |||
| 669 | setzero(ret); | ||
| 599 | 670 | ||
| 600 | #ifdef DEBUG | 671 | #ifdef DEBUG |
| 601 | if (!isconsistent(c1) || !isconsistent(c2)) { | 672 | if (!isconsistent(c1) || !isconsistent(c2)) { |
| 602 | fprintf(stderr, "compose error, inconsistent cube\n"); | 673 | fprintf(stderr, "compose error, inconsistent cube\n"); |
| 603 | return errorcube; | 674 | return ret; |
| 604 | } | 675 | } |
| 605 | #endif | 676 | #endif |
| 606 | 677 | ||
| @@ -609,7 +680,7 @@ compose(cube_t c1, cube_t c2) | |||
| 609 | p = piece2 & _pbits; | 680 | p = piece2 & _pbits; |
| 610 | piece1 = get_edge(c1, p); | 681 | piece1 = get_edge(c1, p); |
| 611 | orien = (piece2 ^ piece1) & _eobit; | 682 | orien = (piece2 ^ piece1) & _eobit; |
| 612 | set_edge(&ret, i, (piece1 & _pbits) | orien); | 683 | set_edge(ret, i, (piece1 & _pbits) | orien); |
| 613 | } | 684 | } |
| 614 | 685 | ||
| 615 | for (i = 0; i < 8; i++) { | 686 | for (i = 0; i < 8; i++) { |
| @@ -619,7 +690,7 @@ compose(cube_t c1, cube_t c2) | |||
| 619 | aux = (piece2 & _cobits) + (piece1 & _cobits); | 690 | aux = (piece2 & _cobits) + (piece1 & _cobits); |
| 620 | auy = (aux + _ctwist_cw) >> 2U; | 691 | auy = (aux + _ctwist_cw) >> 2U; |
| 621 | orien = (aux + auy) & _cobits2; | 692 | orien = (aux + auy) & _cobits2; |
| 622 | set_corner(&ret, i, (piece1 & _pbits) | orien); | 693 | set_corner(ret, i, (piece1 & _pbits) | orien); |
| 623 | } | 694 | } |
| 624 | 695 | ||
| 625 | return ret; | 696 | return ret; |
| @@ -637,7 +708,7 @@ flipallcorners(cube_t c) | |||
| 637 | for (i = 0; i < 8; i++) { | 708 | for (i = 0; i < 8; i++) { |
| 638 | piece = get_corner(c, i); | 709 | piece = get_corner(c, i); |
| 639 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | 710 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; |
| 640 | set_corner(&ret, i, (piece & _pbits) | orien); | 711 | set_corner(ret, i, (piece & _pbits) | orien); |
| 641 | } | 712 | } |
| 642 | 713 | ||
| 643 | return ret; | 714 | return ret; |
| @@ -646,16 +717,17 @@ flipallcorners(cube_t c) | |||
| 646 | cube_t | 717 | cube_t |
| 647 | transform(cube_t c, trans_t t) | 718 | transform(cube_t c, trans_t t) |
| 648 | { | 719 | { |
| 649 | cube_t ret; | 720 | cube_t ret, solved; |
| 650 | 721 | ||
| 651 | #ifdef DEBUG | 722 | #ifdef DEBUG |
| 723 | setzero(ret); | ||
| 652 | if (!isconsistent(c)) { | 724 | if (!isconsistent(c)) { |
| 653 | fprintf(stderr, "transform error, inconsistent cube\n"); | 725 | fprintf(stderr, "transform error, inconsistent cube\n"); |
| 654 | return errorcube; | 726 | return ret; |
| 655 | } | 727 | } |
| 656 | if (t >= 48) { | 728 | if (t >= 48) { |
| 657 | fprintf(stderr, "transform error, unknown transformation\n"); | 729 | fprintf(stderr, "transform error, unknown transformation\n"); |
| 658 | return errorcube; | 730 | return ret; |
| 659 | } | 731 | } |
| 660 | #endif | 732 | #endif |
| 661 | 733 | ||
| @@ -665,7 +737,9 @@ transform(cube_t c, trans_t t) | |||
| 665 | #include "_trans_move_arr.c" | 737 | #include "_trans_move_arr.c" |
| 666 | #endif | 738 | #endif |
| 667 | 739 | ||
| 668 | ret = compose(solvedcube, trans_move_cube[t]); | 740 | setsolved(solved); |
| 741 | |||
| 742 | ret = compose(solved, trans_move_cube[t]); | ||
| 669 | ret = compose(ret, c); | 743 | ret = compose(ret, c); |
| 670 | ret = compose(ret, trans_move_cube_inverse[t]); | 744 | ret = compose(ret, trans_move_cube_inverse[t]); |
| 671 | 745 | ||
| @@ -1,43 +1,45 @@ | |||
| 1 | /* Types *********************************************************************/ | 1 | /* Types *********************************************************************/ |
| 2 | 2 | ||
| 3 | /* See doc/CUBE_INTERNAL.md for a description of the cube format */ | 3 | /* See doc/CUBE_INTERNAL.md for a description of the cube format */ |
| 4 | typedef struct { | ||
| 5 | uint8_t c[16]; | ||
| 6 | uint8_t e[16]; | ||
| 7 | } cube_arr_t; | ||
| 4 | #ifdef CUBE_AVX2 | 8 | #ifdef CUBE_AVX2 |
| 5 | typedef __m256i cube_t; | 9 | typedef __m256i cube_t; |
| 6 | #else | 10 | #else |
| 7 | typedef struct { uint8_t c[8]; uint8_t e[12]; } cube_t; | 11 | typedef cube_arr_t cube_t; |
| 8 | #endif | 12 | #endif |
| 9 | 13 | ||
| 10 | typedef uint8_t move_t; | 14 | typedef uint8_t move_t; |
| 11 | typedef uint8_t trans_t; | 15 | typedef uint8_t trans_t; |
| 12 | 16 | ||
| 13 | extern move_t inverse_move[]; | ||
| 14 | extern trans_t inverse_trans[]; | ||
| 15 | extern cube_t solvedcube; | ||
| 16 | |||
| 17 | /* Functions *****************************************************************/ | 17 | /* Functions *****************************************************************/ |
| 18 | 18 | ||
| 19 | int readmoves(char *, move_t *); | ||
| 20 | void writemoves(move_t *, int, char *); | ||
| 21 | trans_t readtrans(char *); | ||
| 22 | void writetrans(trans_t, char *); | ||
| 23 | |||
| 24 | move_t inverse_move(move_t); | ||
| 25 | trans_t inverse_trans(trans_t); | ||
| 26 | |||
| 19 | /* Not all formats are supported for both read and write. */ | 27 | /* Not all formats are supported for both read and write. */ |
| 20 | /* See doc/CUBE_TEXT.md for details. */ | 28 | /* See doc/CUBE_TEXT.md for details. */ |
| 21 | typedef enum {H48, SRC} format_t; | 29 | typedef enum {H48, SRC} format_t; |
| 22 | cube_t readcube(format_t, char *); | 30 | cube_t readcube(format_t, char *); |
| 23 | void writecube(format_t, cube_t, char *); | 31 | void writecube(format_t, cube_t, char *); |
| 24 | 32 | ||
| 33 | cube_t solvedcube(void); | ||
| 34 | cube_t zerocube(void); | ||
| 25 | bool issolvable(cube_t); | 35 | bool issolvable(cube_t); |
| 26 | bool equal(cube_t, cube_t); | 36 | bool equal(cube_t, cube_t); |
| 27 | bool issolved(cube_t); | 37 | bool issolved(cube_t); |
| 28 | bool iserror(cube_t); | 38 | bool iserror(cube_t); |
| 29 | 39 | ||
| 30 | int readmoves(char *, move_t *); | ||
| 31 | void writemoves(move_t *, int, char *); | ||
| 32 | |||
| 33 | trans_t readtrans(char *); | ||
| 34 | void writetrans(trans_t, char *); | ||
| 35 | |||
| 36 | cube_t move(cube_t, move_t); | 40 | cube_t move(cube_t, move_t); |
| 37 | cube_t inverse(cube_t); | 41 | cube_t inverse(cube_t); |
| 38 | cube_t compose(cube_t, cube_t); | 42 | cube_t compose(cube_t, cube_t); |
| 39 | |||
| 40 | /* See doc/TRANSFORMATIONS.md for how transformations are applied */ | ||
| 41 | cube_t transform(cube_t, trans_t); | 43 | cube_t transform(cube_t, trans_t); |
| 42 | 44 | ||
| 43 | /* Constants for moves and transformations ***********************************/ | 45 | /* Constants for moves and transformations ***********************************/ |
