diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | TODO.md | 13 | ||||
| -rw-r--r-- | src/cube.c | 126 | ||||
| -rw-r--r-- | src/cube.h | 12 | ||||
| -rw-r--r-- | src/fst.c | 75 | ||||
| -rw-r--r-- | src/fst.h | 1 | ||||
| -rw-r--r-- | src/moves.c | 18 | ||||
| -rw-r--r-- | src/moves.h | 3 | ||||
| -rw-r--r-- | tests/fst_post_init_tests.c | 114 | ||||
| -rw-r--r-- | tests/fst_pre_init_tests.c | 89 | ||||
| -rw-r--r-- | tests/fst_test_util.c | 64 | ||||
| -rw-r--r-- | tests/fst_test_util.h | 7 | ||||
| -rw-r--r-- | tests/inc.h | 1 | ||||
| -rw-r--r-- | tests/nissy_tests.c | 12 | ||||
| -rw-r--r-- | tests/test_all.c | 10 | ||||
| -rw-r--r-- | tests/test_fst.c | 184 |
16 files changed, 489 insertions, 244 deletions
| @@ -21,7 +21,9 @@ nissy: clean | |||
| 21 | ${CC} ${CFLAGS} -o nissy src/*.c | 21 | ${CC} ${CFLAGS} -o nissy src/*.c |
| 22 | 22 | ||
| 23 | test: | 23 | test: |
| 24 | ${CC} ${TESTFLAGS} -o test src/*.c tests/*.c | 24 | ${CC} ${TESTFLAGS} -o nissy-test src/*.c tests/*.c |
| 25 | ./nissy-test | ||
| 26 | rm nissy-test | ||
| 25 | 27 | ||
| 26 | nissy.exe: | 28 | nissy.exe: |
| 27 | x86_64-w64-mingw32-gcc ${CFLAGS} -static -o nissy.exe src/*.c | 29 | x86_64-w64-mingw32-gcc ${CFLAGS} -static -o nissy.exe src/*.c |
| @@ -9,8 +9,8 @@ It's more of a personal reminder than anything else. | |||
| 9 | of the files includes + doing more stuff. A static "initiliazed" | 9 | of the files includes + doing more stuff. A static "initiliazed" |
| 10 | variable is probably needed too. | 10 | variable is probably needed too. |
| 11 | ### testing! | 11 | ### testing! |
| 12 | * test fst: implement fst_consistent | 12 | * generic test util: function taking an array of tests, an array of testnames |
| 13 | * test fst: init_fst is necessary before testing move and inverse | 13 | (or maybe tests should be their own type?) and running them |
| 14 | * separate "commands" for testing different parts (e.g. ./test coord) | 14 | * separate "commands" for testing different parts (e.g. ./test coord) |
| 15 | * test coordinate (needed anyway to test fst) | 15 | * test coordinate (needed anyway to test fst) |
| 16 | * other tests (start from bottom: utils.c) | 16 | * other tests (start from bottom: utils.c) |
| @@ -19,10 +19,15 @@ It's more of a personal reminder than anything else. | |||
| 19 | * add Void * extradata to DfsArg and a custom move function | 19 | * add Void * extradata to DfsArg and a custom move function |
| 20 | * add optional custom pre-process for generating special table (nx) | 20 | * add optional custom pre-process for generating special table (nx) |
| 21 | * copy_dfsdata should copy extra too! | 21 | * copy_dfsdata should copy extra too! |
| 22 | ### Solving simplification / refactor | ||
| 23 | * Split solve in solve_coord, solve_generic, solve_singlethread... | ||
| 24 | * Rework choicesteps: simplify, remove one type of rotation... | ||
| 22 | ### nx.c | 25 | ### nx.c |
| 23 | * implement nxopt with all tables and all tricks | 26 | * implement nxopt with all tables and all tricks |
| 24 | (maybe compile time variable for maximum memory to use?) | 27 | (maybe compile time variable for maximum memory to use?) |
| 25 | * is_valid should also unniss / cleanup the alg | 28 | * is_valid should also unniss / cleanup the alg |
| 29 | ### Other easy refactor | ||
| 30 | * split cubetypes.h into other files | ||
| 26 | 31 | ||
| 27 | ## For version 2.1 | 32 | ## For version 2.1 |
| 28 | ### Changes to Step and Solve | 33 | ### Changes to Step and Solve |
| @@ -47,9 +52,11 @@ It's more of a personal reminder than anything else. | |||
| 47 | check if found enough solutions before checking pruning values) | 52 | check if found enough solutions before checking pruning values) |
| 48 | ### Technical | 53 | ### Technical |
| 49 | * generic option parser | 54 | * generic option parser |
| 55 | * scan system to get best number of threads | ||
| 50 | ### Commands | 56 | ### Commands |
| 51 | * Easy: add option -I (inverse) and -L (linear, like inverse + normal) | 57 | * Easy: add option -I (inverse) and -L (linear, like inverse + normal) |
| 52 | to do only linear NISS | 58 | to do only linear NISS |
| 59 | * message for -N ignored say -n (lowercase) | ||
| 53 | 60 | ||
| 54 | ## Commands | 61 | ## Commands |
| 55 | 62 | ||
| @@ -75,6 +82,8 @@ including e.g. solutions that were not shown because -c) | |||
| 75 | * solve should try up to a small bound without loading the large pruning table | 82 | * solve should try up to a small bound without loading the large pruning table |
| 76 | (maybe this is not necessary if loading the table is fast enough) | 83 | (maybe this is not necessary if loading the table is fast enough) |
| 77 | * silent batch mode without >>> | 84 | * silent batch mode without >>> |
| 85 | * Optimal solver: when asking for only one solution, scan for upper bound in | ||
| 86 | parallel using a two-phase solver. | ||
| 78 | 87 | ||
| 79 | ### New features | 88 | ### New features |
| 80 | * EO analysis (and also DR and HTR analysis): group similar EOs together | 89 | * EO analysis (and also DR and HTR analysis): group similar EOs together |
| @@ -5,27 +5,61 @@ | |||
| 5 | static int where_is_piece(int piece, int *arr, int n); | 5 | static int where_is_piece(int piece, int *arr, int n); |
| 6 | 6 | ||
| 7 | void | 7 | void |
| 8 | compose(Cube *c2, Cube *c1) | 8 | compose_centers(Cube *c2, Cube *c1) |
| 9 | { | 9 | { |
| 10 | apply_permutation(c2->ep, c1->ep, 12); | 10 | apply_permutation(c2->xp, c1->xp, 6); |
| 11 | apply_permutation(c2->ep, c1->eo, 12); | 11 | } |
| 12 | sum_arrays_mod(c2->eo, c1->eo, 12, 2); | ||
| 13 | 12 | ||
| 13 | void | ||
| 14 | compose_corners(Cube *c2, Cube *c1) | ||
| 15 | { | ||
| 14 | apply_permutation(c2->cp, c1->cp, 8); | 16 | apply_permutation(c2->cp, c1->cp, 8); |
| 15 | apply_permutation(c2->cp, c1->co, 8); | 17 | apply_permutation(c2->cp, c1->co, 8); |
| 16 | sum_arrays_mod(c2->co, c1->co, 8, 3); | 18 | sum_arrays_mod(c2->co, c1->co, 8, 3); |
| 19 | } | ||
| 17 | 20 | ||
| 18 | apply_permutation(c2->xp, c1->xp, 6); | 21 | void |
| 22 | compose_edges(Cube *c2, Cube *c1) | ||
| 23 | { | ||
| 24 | apply_permutation(c2->ep, c1->ep, 12); | ||
| 25 | apply_permutation(c2->ep, c1->eo, 12); | ||
| 26 | sum_arrays_mod(c2->eo, c1->eo, 12, 2); | ||
| 19 | } | 27 | } |
| 20 | 28 | ||
| 21 | void | 29 | void |
| 22 | copy_cube(Cube *src, Cube *dst) | 30 | compose(Cube *c2, Cube *c1) |
| 31 | { | ||
| 32 | compose_centers(c2, c1); | ||
| 33 | compose_corners(c2, c1); | ||
| 34 | compose_edges(c2, c1); | ||
| 35 | } | ||
| 36 | |||
| 37 | void | ||
| 38 | copy_cube_centers(Cube *src, Cube *dst) | ||
| 39 | { | ||
| 40 | memcpy(dst->xp, src->xp, 6 * sizeof(int)); | ||
| 41 | } | ||
| 42 | |||
| 43 | void | ||
| 44 | copy_cube_corners(Cube *src, Cube *dst) | ||
| 23 | { | 45 | { |
| 24 | memcpy(dst->ep, src->ep, 12 * sizeof(int)); | ||
| 25 | memcpy(dst->eo, src->eo, 12 * sizeof(int)); | ||
| 26 | memcpy(dst->cp, src->cp, 8 * sizeof(int)); | 46 | memcpy(dst->cp, src->cp, 8 * sizeof(int)); |
| 27 | memcpy(dst->co, src->co, 8 * sizeof(int)); | 47 | memcpy(dst->co, src->co, 8 * sizeof(int)); |
| 28 | memcpy(dst->xp, src->xp, 6 * sizeof(int)); | 48 | } |
| 49 | |||
| 50 | void | ||
| 51 | copy_cube_edges(Cube *src, Cube *dst) | ||
| 52 | { | ||
| 53 | memcpy(dst->ep, src->ep, 12 * sizeof(int)); | ||
| 54 | memcpy(dst->eo, src->eo, 12 * sizeof(int)); | ||
| 55 | } | ||
| 56 | |||
| 57 | void | ||
| 58 | copy_cube(Cube *src, Cube *dst) | ||
| 59 | { | ||
| 60 | copy_cube_centers(src, dst); | ||
| 61 | copy_cube_corners(src, dst); | ||
| 62 | copy_cube_edges(src, dst); | ||
| 29 | } | 63 | } |
| 30 | 64 | ||
| 31 | bool | 65 | bool |
| @@ -49,25 +83,51 @@ equal(Cube *c1, Cube *c2) | |||
| 49 | } | 83 | } |
| 50 | 84 | ||
| 51 | void | 85 | void |
| 52 | invert_cube(Cube *cube) | 86 | invert_cube_centers(Cube *cube) |
| 53 | { | 87 | { |
| 54 | Cube aux; | ||
| 55 | int i; | 88 | int i; |
| 89 | Cube aux; | ||
| 56 | 90 | ||
| 57 | copy_cube(cube, &aux); | 91 | copy_cube_centers(cube, &aux); |
| 58 | 92 | ||
| 59 | for (i = 0; i < 12; i++) { | 93 | for (i = 0; i < 6; i++) |
| 60 | cube->ep[aux.ep[i]] = i; | 94 | cube->xp[aux.xp[i]] = i; |
| 61 | cube->eo[aux.ep[i]] = aux.eo[i]; | 95 | } |
| 62 | } | 96 | |
| 97 | void | ||
| 98 | invert_cube_corners(Cube *cube) | ||
| 99 | { | ||
| 100 | int i; | ||
| 101 | Cube aux; | ||
| 102 | |||
| 103 | copy_cube_corners(cube, &aux); | ||
| 63 | 104 | ||
| 64 | for (i = 0; i < 8; i++) { | 105 | for (i = 0; i < 8; i++) { |
| 65 | cube->cp[aux.cp[i]] = i; | 106 | cube->cp[aux.cp[i]] = i; |
| 66 | cube->co[aux.cp[i]] = (3 - aux.co[i]) % 3; | 107 | cube->co[aux.cp[i]] = (3 - aux.co[i]) % 3; |
| 67 | } | 108 | } |
| 109 | } | ||
| 68 | 110 | ||
| 69 | for (i = 0; i < 6; i++) | 111 | void |
| 70 | cube->xp[aux.xp[i]] = i; | 112 | invert_cube_edges(Cube *cube) |
| 113 | { | ||
| 114 | int i; | ||
| 115 | Cube aux; | ||
| 116 | |||
| 117 | copy_cube_edges(cube, &aux); | ||
| 118 | |||
| 119 | for (i = 0; i < 12; i++) { | ||
| 120 | cube->ep[aux.ep[i]] = i; | ||
| 121 | cube->eo[aux.ep[i]] = aux.eo[i]; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | void | ||
| 126 | invert_cube(Cube *cube) | ||
| 127 | { | ||
| 128 | invert_cube_centers(cube); | ||
| 129 | invert_cube_corners(cube); | ||
| 130 | invert_cube_edges(cube); | ||
| 71 | } | 131 | } |
| 72 | 132 | ||
| 73 | bool | 133 | bool |
| @@ -105,15 +165,37 @@ is_solved(Cube *cube) | |||
| 105 | } | 165 | } |
| 106 | 166 | ||
| 107 | void | 167 | void |
| 108 | make_solved(Cube *cube) | 168 | make_solved_centers(Cube *cube) |
| 169 | { | ||
| 170 | static int sorted[6] = {0, 1, 2, 3, 4, 5}; | ||
| 171 | |||
| 172 | memcpy(cube->xp, sorted, 6 * sizeof(int)); | ||
| 173 | } | ||
| 174 | |||
| 175 | void | ||
| 176 | make_solved_corners(Cube *cube) | ||
| 177 | { | ||
| 178 | static int sorted[8] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 179 | |||
| 180 | memcpy(cube->cp, sorted, 8 * sizeof(int)); | ||
| 181 | memset(cube->co, 0, 8 * sizeof(int)); | ||
| 182 | } | ||
| 183 | |||
| 184 | void | ||
| 185 | make_solved_edges(Cube *cube) | ||
| 109 | { | 186 | { |
| 110 | static int sorted[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; | 187 | static int sorted[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; |
| 111 | 188 | ||
| 112 | memcpy(cube->ep, sorted, 12 * sizeof(int)); | 189 | memcpy(cube->ep, sorted, 12 * sizeof(int)); |
| 113 | memset(cube->eo, 0, 12 * sizeof(int)); | 190 | memset(cube->eo, 0, 12 * sizeof(int)); |
| 114 | memcpy(cube->cp, sorted, 8 * sizeof(int)); | 191 | } |
| 115 | memset(cube->co, 0, 8 * sizeof(int)); | 192 | |
| 116 | memcpy(cube->xp, sorted, 6 * sizeof(int)); | 193 | void |
| 194 | make_solved(Cube *cube) | ||
| 195 | { | ||
| 196 | make_solved_centers(cube); | ||
| 197 | make_solved_corners(cube); | ||
| 198 | make_solved_edges(cube); | ||
| 117 | } | 199 | } |
| 118 | 200 | ||
| 119 | void | 201 | void |
| @@ -8,12 +8,24 @@ | |||
| 8 | #include "utils.h" | 8 | #include "utils.h" |
| 9 | 9 | ||
| 10 | void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */ | 10 | void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */ |
| 11 | void compose_centers(Cube *c2, Cube *c1); | ||
| 12 | void compose_corners(Cube *c2, Cube *c1); | ||
| 13 | void compose_edges(Cube *c2, Cube *c1); | ||
| 11 | void copy_cube(Cube *src, Cube *dst); | 14 | void copy_cube(Cube *src, Cube *dst); |
| 15 | void copy_cube_centers(Cube *src, Cube *dst); | ||
| 16 | void copy_cube_corners(Cube *src, Cube *dst); | ||
| 17 | void copy_cube_edges(Cube *src, Cube *dst); | ||
| 12 | bool equal(Cube *c1, Cube *c2); | 18 | bool equal(Cube *c1, Cube *c2); |
| 13 | void invert_cube(Cube *cube); | 19 | void invert_cube(Cube *cube); |
| 20 | void invert_cube_centers(Cube *cube); | ||
| 21 | void invert_cube_corners(Cube *cube); | ||
| 22 | void invert_cube_edges(Cube *cube); | ||
| 14 | bool is_admissible(Cube *cube); | 23 | bool is_admissible(Cube *cube); |
| 15 | bool is_solved(Cube *cube); | 24 | bool is_solved(Cube *cube); |
| 16 | void make_solved(Cube *cube); | 25 | void make_solved(Cube *cube); |
| 26 | void make_solved_centers(Cube *cube); | ||
| 27 | void make_solved_corners(Cube *cube); | ||
| 28 | void make_solved_edges(Cube *cube); | ||
| 17 | void print_cube(Cube *cube); | 29 | void print_cube(Cube *cube); |
| 18 | int where_is_center(Center x, Cube *c); | 30 | int where_is_center(Center x, Cube *c); |
| 19 | int where_is_corner(Corner k, Cube *c); | 31 | int where_is_corner(Corner k, Cube *c); |
| @@ -3,7 +3,6 @@ | |||
| 3 | #include "fst.h" | 3 | #include "fst.h" |
| 4 | 4 | ||
| 5 | static FstCube ep_to_fst_epos(int *ep); | 5 | static FstCube ep_to_fst_epos(int *ep); |
| 6 | static int fst_where_is_edge(int e, FstCube fst); | ||
| 7 | static void transform_ep_only(Trans t, int *ep, Cube *dst); | 6 | static void transform_ep_only(Trans t, int *ep, Cube *dst); |
| 8 | static void init_fst_corner_invtables(); | 7 | static void init_fst_corner_invtables(); |
| 9 | static void init_fst_eo_invtables(); | 8 | static void init_fst_eo_invtables(); |
| @@ -55,7 +54,10 @@ cube_to_fst(Cube *cube) | |||
| 55 | static FstCube | 54 | static FstCube |
| 56 | ep_to_fst_epos(int *ep) | 55 | ep_to_fst_epos(int *ep) |
| 57 | { | 56 | { |
| 58 | /* TODO: maybe optimize? */ | 57 | /* TODO: maybe optimize */ |
| 58 | |||
| 59 | /* TODO: this version if faster, but broken | ||
| 60 | probably need to fix transform_ep_only() | ||
| 59 | 61 | ||
| 60 | FstCube ret; | 62 | FstCube ret; |
| 61 | Cube c; | 63 | Cube c; |
| @@ -68,6 +70,24 @@ ep_to_fst_epos(int *ep) | |||
| 68 | 70 | ||
| 69 | transform_ep_only(rd, ep, &c); | 71 | transform_ep_only(rd, ep, &c); |
| 70 | ret.rd_eposepe = coord_eposepe.i[0]->index(&c); | 72 | ret.rd_eposepe = coord_eposepe.i[0]->index(&c); |
| 73 | */ | ||
| 74 | |||
| 75 | FstCube ret; | ||
| 76 | Cube c, d; | ||
| 77 | |||
| 78 | make_solved(&c); | ||
| 79 | memcpy(c.ep, ep, 12 * sizeof(int)); | ||
| 80 | |||
| 81 | copy_cube(&c, &d); | ||
| 82 | ret.uf_eposepe = coord_eposepe.i[0]->index(&d); | ||
| 83 | |||
| 84 | copy_cube(&c, &d); | ||
| 85 | apply_trans(fr, &d); | ||
| 86 | ret.fr_eposepe = coord_eposepe.i[0]->index(&d); | ||
| 87 | |||
| 88 | copy_cube(&c, &d); | ||
| 89 | apply_trans(rd, &d); | ||
| 90 | ret.rd_eposepe = coord_eposepe.i[0]->index(&d); | ||
| 71 | 91 | ||
| 72 | return ret; | 92 | return ret; |
| 73 | } | 93 | } |
| @@ -155,7 +175,7 @@ fst_to_cube(FstCube fst, Cube *cube) | |||
| 155 | cube->xp[i] = i; | 175 | cube->xp[i] = i; |
| 156 | } | 176 | } |
| 157 | 177 | ||
| 158 | static int | 178 | int |
| 159 | fst_where_is_edge(int e, FstCube fst) | 179 | fst_where_is_edge(int e, FstCube fst) |
| 160 | { | 180 | { |
| 161 | switch (edge_slice[e]) { | 181 | switch (edge_slice[e]) { |
| @@ -183,6 +203,10 @@ void | |||
| 183 | init_fst() | 203 | init_fst() |
| 184 | { | 204 | { |
| 185 | init_trans(); | 205 | init_trans(); |
| 206 | gen_coord(&coord_eofb); | ||
| 207 | gen_coord(&coord_eposepe); | ||
| 208 | gen_coord(&coord_coud); | ||
| 209 | gen_coord(&coord_cp); | ||
| 186 | 210 | ||
| 187 | init_fst_corner_invtables(); | 211 | init_fst_corner_invtables(); |
| 188 | init_fst_eo_invtables(); | 212 | init_fst_eo_invtables(); |
| @@ -193,32 +217,29 @@ init_fst() | |||
| 193 | static void | 217 | static void |
| 194 | init_fst_corner_invtables() | 218 | init_fst_corner_invtables() |
| 195 | { | 219 | { |
| 196 | /* TODO: this can be optimized by transforming and copying only corners */ | ||
| 197 | /* A factor of about 4 would be saved in the innermost loop */ | ||
| 198 | |||
| 199 | Cube c, d; | 220 | Cube c, d; |
| 200 | uint64_t cp, coud; | 221 | uint64_t cp, coud; |
| 201 | 222 | ||
| 202 | for (cp = 0; cp < FACTORIAL8; cp++) { | 223 | for (cp = 0; cp < FACTORIAL8; cp++) { |
| 203 | make_solved(&c); | 224 | make_solved_corners(&c); |
| 204 | coord_cp.i[0]->to_cube(cp, &c); | 225 | coord_cp.i[0]->to_cube(cp, &c); |
| 205 | 226 | ||
| 206 | copy_cube(&c, &d); | 227 | copy_cube_corners(&c, &d); |
| 207 | invert_cube(&d); | 228 | invert_cube_corners(&d); |
| 208 | inv_cp[cp] = coord_coud.i[0]->index(&d); | 229 | inv_cp[cp] = coord_cp.i[0]->index(&d); |
| 209 | 230 | ||
| 210 | for (coud = 0; coud < POW3TO7; coud++) { | 231 | for (coud = 0; coud < POW3TO7; coud++) { |
| 211 | copy_cube(&c, &d); | 232 | copy_cube_corners(&c, &d); |
| 212 | coord_coud.i[0]->to_cube(coud, &d); | 233 | coord_coud.i[0]->to_cube(coud, &d); |
| 213 | invert_cube(&d); | 234 | invert_cube_corners(&d); |
| 214 | inv_coud[cp][coud] = coord_coud.i[0]->index(&d); | 235 | inv_coud[cp][coud] = coord_coud.i[0]->index(&d); |
| 215 | } | 236 | } |
| 216 | 237 | ||
| 217 | copy_cube(&c, &d); | 238 | copy_cube_corners(&c, &d); |
| 218 | apply_trans(fr, &d); | 239 | apply_trans(fr, &d); |
| 219 | uf_cp_to_fr_cp[cp] = coord_cp.i[0]->index(&d); | 240 | uf_cp_to_fr_cp[cp] = coord_cp.i[0]->index(&d); |
| 220 | 241 | ||
| 221 | copy_cube(&c, &d); | 242 | copy_cube_corners(&c, &d); |
| 222 | apply_trans(rd, &d); | 243 | apply_trans(rd, &d); |
| 223 | uf_cp_to_rd_cp[cp] = coord_cp.i[0]->index(&d); | 244 | uf_cp_to_rd_cp[cp] = coord_cp.i[0]->index(&d); |
| 224 | } | 245 | } |
| @@ -234,13 +255,17 @@ init_fst_eo_invtables() | |||
| 234 | make_solved(&c); | 255 | make_solved(&c); |
| 235 | coord_eposepe.i[0]->to_cube(ep, &c); | 256 | coord_eposepe.i[0]->to_cube(ep, &c); |
| 236 | for (eo = 0; eo < POW2TO11; eo++) { | 257 | for (eo = 0; eo < POW2TO11; eo++) { |
| 237 | coord_eofb.i[0]->to_cube(eo, &c); | 258 | copy_cube_edges(&c, &d); |
| 238 | copy_cube(&c, &d); | 259 | coord_eofb.i[0]->to_cube(eo, &d); |
| 239 | init_fst_eo_update(eo, ep, 0, &d); | 260 | init_fst_eo_update(eo, ep, 0, &d); |
| 261 | |||
| 240 | apply_trans(inverse_trans(fr), &d); | 262 | apply_trans(inverse_trans(fr), &d); |
| 263 | coord_eofb.i[0]->to_cube(eo, &d); | ||
| 241 | init_fst_eo_update(eo, ep, 1, &d); | 264 | init_fst_eo_update(eo, ep, 1, &d); |
| 242 | copy_cube(&c, &d); | 265 | |
| 266 | copy_cube_edges(&c, &d); | ||
| 243 | apply_trans(inverse_trans(rd), &d); | 267 | apply_trans(inverse_trans(rd), &d); |
| 268 | coord_eofb.i[0]->to_cube(eo, &d); | ||
| 244 | init_fst_eo_update(eo, ep, 2, &d); | 269 | init_fst_eo_update(eo, ep, 2, &d); |
| 245 | } | 270 | } |
| 246 | } | 271 | } |
| @@ -251,9 +276,11 @@ init_fst_eo_update(uint64_t eo, uint64_t ep, int s, Cube *d) | |||
| 251 | { | 276 | { |
| 252 | int i; | 277 | int i; |
| 253 | 278 | ||
| 254 | for (i = 0; i < 12; i++) | 279 | for (i = 0; i < 12; i++) { |
| 255 | if (d->eo[i]) | 280 | if (edge_slice[d->ep[i]] == s && d->eo[i] && d->ep[i] != 11) |
| 256 | eo_invtable[s][eo][ep] |= ((uint16_t)1) << d->ep[i]; | 281 | eo_invtable[s][eo][ep] |= |
| 282 | ((uint16_t)1) << ((uint16_t)d->ep[i]); | ||
| 283 | } | ||
| 257 | } | 284 | } |
| 258 | 285 | ||
| 259 | static void | 286 | static void |
| @@ -270,7 +297,7 @@ init_fst_transalg() | |||
| 270 | apply_alg(alg, &c); | 297 | apply_alg(alg, &c); |
| 271 | for (i = 0; i < 12; i++) | 298 | for (i = 0; i < 12; i++) |
| 272 | trans_ep_alg[t][i] = c.ep[i]; | 299 | trans_ep_alg[t][i] = c.ep[i]; |
| 273 | invert_cube(&c); | 300 | invert_cube_edges(&c); |
| 274 | for (i = 0; i < 12; i++) | 301 | for (i = 0; i < 12; i++) |
| 275 | trans_ep_inv[t][i] = c.ep[i]; | 302 | trans_ep_inv[t][i] = c.ep[i]; |
| 276 | } | 303 | } |
| @@ -286,20 +313,20 @@ init_fst_where_is_edge() | |||
| 286 | for (e = 0; e < BINOM12ON4 * FACTORIAL4; e++) { | 313 | for (e = 0; e < BINOM12ON4 * FACTORIAL4; e++) { |
| 287 | coord_eposepe.i[0]->to_cube(e, &c); | 314 | coord_eposepe.i[0]->to_cube(e, &c); |
| 288 | 315 | ||
| 289 | copy_cube(&c, &d); | 316 | copy_cube_edges(&c, &d); |
| 290 | fst_where_is_edge_arr[0][FR][e] = where_is_edge(FR, &d); | 317 | fst_where_is_edge_arr[0][FR][e] = where_is_edge(FR, &d); |
| 291 | fst_where_is_edge_arr[0][FL][e] = where_is_edge(FL, &d); | 318 | fst_where_is_edge_arr[0][FL][e] = where_is_edge(FL, &d); |
| 292 | fst_where_is_edge_arr[0][BL][e] = where_is_edge(BL, &d); | 319 | fst_where_is_edge_arr[0][BL][e] = where_is_edge(BL, &d); |
| 293 | fst_where_is_edge_arr[0][BR][e] = where_is_edge(BR, &d); | 320 | fst_where_is_edge_arr[0][BR][e] = where_is_edge(BR, &d); |
| 294 | 321 | ||
| 295 | copy_cube(&c, &d); | 322 | copy_cube_edges(&c, &d); |
| 296 | apply_trans(inverse_trans(fr), &d); | 323 | apply_trans(inverse_trans(fr), &d); |
| 297 | fst_where_is_edge_arr[1][UL][e] = where_is_edge(UL, &d); | 324 | fst_where_is_edge_arr[1][UL][e] = where_is_edge(UL, &d); |
| 298 | fst_where_is_edge_arr[1][UR][e] = where_is_edge(UR, &d); | 325 | fst_where_is_edge_arr[1][UR][e] = where_is_edge(UR, &d); |
| 299 | fst_where_is_edge_arr[1][DL][e] = where_is_edge(DL, &d); | 326 | fst_where_is_edge_arr[1][DL][e] = where_is_edge(DL, &d); |
| 300 | fst_where_is_edge_arr[1][DR][e] = where_is_edge(DR, &d); | 327 | fst_where_is_edge_arr[1][DR][e] = where_is_edge(DR, &d); |
| 301 | 328 | ||
| 302 | copy_cube(&c, &d); | 329 | copy_cube_edges(&c, &d); |
| 303 | apply_trans(inverse_trans(rd), &d); | 330 | apply_trans(inverse_trans(rd), &d); |
| 304 | fst_where_is_edge_arr[2][UF][e] = where_is_edge(UF, &d); | 331 | fst_where_is_edge_arr[2][UF][e] = where_is_edge(UF, &d); |
| 305 | fst_where_is_edge_arr[2][UB][e] = where_is_edge(UB, &d); | 332 | fst_where_is_edge_arr[2][UB][e] = where_is_edge(UB, &d); |
| @@ -7,6 +7,7 @@ FstCube cube_to_fst(Cube *cube); | |||
| 7 | FstCube fst_inverse(FstCube fst); | 7 | FstCube fst_inverse(FstCube fst); |
| 8 | FstCube fst_move(Move m, FstCube fst); | 8 | FstCube fst_move(Move m, FstCube fst); |
| 9 | void fst_to_cube(FstCube fst, Cube *cube); | 9 | void fst_to_cube(FstCube fst, Cube *cube); |
| 10 | int fst_where_is_edge(int e, FstCube fst); | ||
| 10 | void init_fst(); | 11 | void init_fst(); |
| 11 | 12 | ||
| 12 | #endif | 13 | #endif |
diff --git a/src/moves.c b/src/moves.c index 51012db..a9dfdc0 100644 --- a/src/moves.c +++ b/src/moves.c | |||
| @@ -106,6 +106,24 @@ apply_move(Move m, Cube *cube) | |||
| 106 | compose(&move_array[m], cube); | 106 | compose(&move_array[m], cube); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void | ||
| 110 | apply_move_centers(Move m, Cube *cube) | ||
| 111 | { | ||
| 112 | compose_centers(&move_array[m], cube); | ||
| 113 | } | ||
| 114 | |||
| 115 | void | ||
| 116 | apply_move_corners(Move m, Cube *cube) | ||
| 117 | { | ||
| 118 | compose_corners(&move_array[m], cube); | ||
| 119 | } | ||
| 120 | |||
| 121 | void | ||
| 122 | apply_move_edges(Move m, Cube *cube) | ||
| 123 | { | ||
| 124 | compose_edges(&move_array[m], cube); | ||
| 125 | } | ||
| 126 | |||
| 109 | Alg * | 127 | Alg * |
| 110 | cleanup(Alg *alg) | 128 | cleanup(Alg *alg) |
| 111 | { | 129 | { |
diff --git a/src/moves.h b/src/moves.h index 4afe8fb..4e8be7f 100644 --- a/src/moves.h +++ b/src/moves.h | |||
| @@ -7,6 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | void apply_alg(Alg *alg, Cube *cube); | 8 | void apply_alg(Alg *alg, Cube *cube); |
| 9 | void apply_move(Move m, Cube *cube); | 9 | void apply_move(Move m, Cube *cube); |
| 10 | void apply_move_centers(Move m, Cube *cube); | ||
| 11 | void apply_move_corners(Move m, Cube *cube); | ||
| 12 | void apply_move_edges(Move m, Cube *cube); | ||
| 10 | Alg * cleanup(Alg *alg); | 13 | Alg * cleanup(Alg *alg); |
| 11 | 14 | ||
| 12 | void init_moves(); | 15 | void init_moves(); |
diff --git a/tests/fst_post_init_tests.c b/tests/fst_post_init_tests.c new file mode 100644 index 0000000..653e379 --- /dev/null +++ b/tests/fst_post_init_tests.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | #include "fst_test_util.h" | ||
| 2 | |||
| 3 | static bool fst_move_testcase(Cube *c, Alg *a); | ||
| 4 | static bool fst_inverse_testcase(Cube *c, Alg *a); | ||
| 5 | |||
| 6 | static bool fst_move_test(); | ||
| 7 | static bool fst_where_is_edge_test(); | ||
| 8 | static bool fst_inverse_test(); | ||
| 9 | |||
| 10 | static Tester test[] = { | ||
| 11 | fst_move_test, | ||
| 12 | fst_where_is_edge_test, | ||
| 13 | fst_inverse_test, | ||
| 14 | NULL | ||
| 15 | }; | ||
| 16 | |||
| 17 | static char *name[] = { | ||
| 18 | "FST move", | ||
| 19 | "FST where is edge", | ||
| 20 | "FST inverse", | ||
| 21 | }; | ||
| 22 | |||
| 23 | static bool | ||
| 24 | fst_move_testcase(Cube *c, Alg *a) | ||
| 25 | { | ||
| 26 | int i; | ||
| 27 | Cube d; | ||
| 28 | FstCube fst; | ||
| 29 | |||
| 30 | make_solved(&d); | ||
| 31 | fst = cube_to_fst(&d); | ||
| 32 | |||
| 33 | for (i = 0; i < a->len; i++) { | ||
| 34 | if (a->inv[i] || a->move[i] > B3) { | ||
| 35 | printf("Cannot apply the following alg to FST: "); | ||
| 36 | print_alg(a, false); | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | fst = fst_move(a->move[i], fst); | ||
| 40 | } | ||
| 41 | |||
| 42 | fst_to_cube(fst, &d); | ||
| 43 | |||
| 44 | return equal_and_log(c, &d); | ||
| 45 | } | ||
| 46 | |||
| 47 | static bool | ||
| 48 | fst_inverse_testcase(Cube *c, Alg *a) | ||
| 49 | { | ||
| 50 | Cube d; | ||
| 51 | |||
| 52 | fst_to_cube(fst_inverse(cube_to_fst(c)), &d); | ||
| 53 | invert_cube(c); | ||
| 54 | |||
| 55 | return equal_and_log(c, &d); | ||
| 56 | } | ||
| 57 | |||
| 58 | static bool | ||
| 59 | fst_move_test() | ||
| 60 | { | ||
| 61 | return try_all_str(fst_move_testcase, "FST move incorrect"); | ||
| 62 | } | ||
| 63 | |||
| 64 | static bool | ||
| 65 | fst_where_is_edge_test() | ||
| 66 | { | ||
| 67 | int i; | ||
| 68 | Alg *scr; | ||
| 69 | Cube c, d; | ||
| 70 | FstCube fst; | ||
| 71 | |||
| 72 | /* Testing on a single scramble is fine for now */ | ||
| 73 | scr = new_alg("RUFDL2B2FRD"); | ||
| 74 | make_solved(&c); | ||
| 75 | apply_alg(scr, &c); | ||
| 76 | fst = cube_to_fst(&c); | ||
| 77 | |||
| 78 | for (i = 0; i < 12; i++) { | ||
| 79 | if (fst_where_is_edge(c.ep[i], fst) != i) { | ||
| 80 | fst_to_cube(fst, &d); | ||
| 81 | printf("Alg: "); | ||
| 82 | print_alg(scr, false); | ||
| 83 | printf("Expected:\n"); | ||
| 84 | print_cube(&c); | ||
| 85 | printf("But got:\n"); | ||
| 86 | print_cube(&d); | ||
| 87 | return false; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | return true; | ||
| 92 | } | ||
| 93 | |||
| 94 | static bool | ||
| 95 | fst_inverse_test() | ||
| 96 | { | ||
| 97 | return try_all_str(fst_inverse_testcase, "FST test incorrect"); | ||
| 98 | } | ||
| 99 | |||
| 100 | void fst_post_init_testall() { | ||
| 101 | int i; | ||
| 102 | |||
| 103 | init_fst(); | ||
| 104 | |||
| 105 | for (i = 0; test[i] != NULL; i++) { | ||
| 106 | printf("Test: %s\n", name[i]); | ||
| 107 | if (!test[i]()) { | ||
| 108 | printf("Failed!\n"); | ||
| 109 | exit(1); | ||
| 110 | } | ||
| 111 | printf("Passed.\n\n"); | ||
| 112 | } | ||
| 113 | printf("All FST post-init tests passed.\n\n"); | ||
| 114 | } | ||
diff --git a/tests/fst_pre_init_tests.c b/tests/fst_pre_init_tests.c new file mode 100644 index 0000000..6b7a440 --- /dev/null +++ b/tests/fst_pre_init_tests.c | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | #include "fst_test_util.h" | ||
| 2 | |||
| 3 | static bool cube_to_fst_to_cube_testcase(Cube *c, Alg *a); | ||
| 4 | static bool fst_is_consistent_testcase(Cube *c, Alg *a); | ||
| 5 | |||
| 6 | static bool fst_is_consistent_test(); | ||
| 7 | static bool cube_to_fst_to_cube_test(); | ||
| 8 | |||
| 9 | static Tester test[] = { | ||
| 10 | fst_is_consistent_test, | ||
| 11 | cube_to_fst_to_cube_test, | ||
| 12 | NULL | ||
| 13 | }; | ||
| 14 | |||
| 15 | static char *name[] = { | ||
| 16 | "Consistency of FST (converted from cube)", | ||
| 17 | "Cube to FST to cube", | ||
| 18 | }; | ||
| 19 | |||
| 20 | static bool | ||
| 21 | fst_is_consistent_testcase(Cube *c, Alg *a) | ||
| 22 | { | ||
| 23 | FstCube fst_uf, fst_fr, fst_rd; | ||
| 24 | Cube c_fr, c_rd; | ||
| 25 | bool consistent_fr, consistent_rd; | ||
| 26 | |||
| 27 | copy_cube(c, &c_fr); | ||
| 28 | apply_trans(fr, &c_fr); | ||
| 29 | |||
| 30 | copy_cube(c, &c_rd); | ||
| 31 | apply_trans(rd, &c_rd); | ||
| 32 | |||
| 33 | fst_uf = cube_to_fst(c); | ||
| 34 | fst_fr = cube_to_fst(&c_fr); | ||
| 35 | fst_rd = cube_to_fst(&c_rd); | ||
| 36 | |||
| 37 | consistent_fr = fst_uf.fr_eofb == fst_fr.uf_eofb && | ||
| 38 | fst_uf.fr_eposepe == fst_fr.uf_eposepe && | ||
| 39 | fst_uf.fr_coud == fst_fr.uf_coud; | ||
| 40 | |||
| 41 | consistent_rd = fst_uf.rd_eofb == fst_rd.uf_eofb && | ||
| 42 | fst_uf.rd_eposepe == fst_rd.uf_eposepe && | ||
| 43 | fst_uf.rd_coud == fst_rd.uf_coud; | ||
| 44 | |||
| 45 | return consistent_fr && consistent_rd; | ||
| 46 | } | ||
| 47 | |||
| 48 | static bool | ||
| 49 | cube_to_fst_to_cube_testcase(Cube *c, Alg *a) | ||
| 50 | { | ||
| 51 | Cube d; | ||
| 52 | FstCube fst; | ||
| 53 | |||
| 54 | fst = cube_to_fst(c); | ||
| 55 | fst_to_cube(fst, &d); | ||
| 56 | |||
| 57 | return equal_and_log(c, &d);; | ||
| 58 | } | ||
| 59 | |||
| 60 | static bool | ||
| 61 | cube_to_fst_to_cube_test() | ||
| 62 | { | ||
| 63 | return try_all_str( | ||
| 64 | cube_to_fst_to_cube_testcase, "Cube to FST to cube failed"); | ||
| 65 | } | ||
| 66 | |||
| 67 | static bool | ||
| 68 | fst_is_consistent_test() | ||
| 69 | { | ||
| 70 | return try_all_str( | ||
| 71 | fst_is_consistent_testcase, "FST from cube not consistent"); | ||
| 72 | } | ||
| 73 | |||
| 74 | void fst_pre_init_testall() { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | init_env(); | ||
| 78 | init_trans(); | ||
| 79 | |||
| 80 | for (i = 0; test[i] != NULL; i++) { | ||
| 81 | printf("Test: %s\n", name[i]); | ||
| 82 | if (!test[i]()) { | ||
| 83 | printf("Failed!\n"); | ||
| 84 | exit(1); | ||
| 85 | } | ||
| 86 | printf("Passed.\n\n"); | ||
| 87 | } | ||
| 88 | printf("All FST pre-init tests passed.\n\n"); | ||
| 89 | } | ||
diff --git a/tests/fst_test_util.c b/tests/fst_test_util.c new file mode 100644 index 0000000..35c1e9f --- /dev/null +++ b/tests/fst_test_util.c | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #include "fst_test_util.h" | ||
| 2 | |||
| 3 | char *algs[] = { | ||
| 4 | "", | ||
| 5 | "U", "U2", "U'", "D", "D2", "D'", "R", "R2", "R'", | ||
| 6 | "L", "L2", "L'", "F", "F2", "F'", "B", "B2", "B'", | ||
| 7 | "U2 R2 U2 R2 U2", | ||
| 8 | "U2 F2 R2 B2 U2 D2 F2 L2 B2", | ||
| 9 | "RUR'URU2R'", | ||
| 10 | "L2 D R U2 B2 L", | ||
| 11 | "R'U'F", | ||
| 12 | "F2 U' R2 D' B2 D2 R2 D2 R2 U' F L' U' R B F2 R B' D2", | ||
| 13 | "D L2 F2 R2 D R2 U L2 U' B2 D L' F2 U2 B' L D' U' R' B2 F2", | ||
| 14 | "F' L2 F' D' R F2 L U L' D2 R2 F2 D2 R2 B' L2 B2 U2 F D2 B", | ||
| 15 | NULL, | ||
| 16 | }; | ||
| 17 | |||
| 18 | bool | ||
| 19 | equal_and_log(Cube *c, Cube *d) | ||
| 20 | { | ||
| 21 | bool ret = equal(c, d); | ||
| 22 | |||
| 23 | if (!ret) { | ||
| 24 | printf("These cubes should be equal, but are not:\n\n"); | ||
| 25 | print_cube(c); | ||
| 26 | printf("\n"); | ||
| 27 | print_cube(d); | ||
| 28 | printf("\n"); | ||
| 29 | } | ||
| 30 | |||
| 31 | return ret; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool | ||
| 35 | try_str(CubeTester f, char *algstr, char *msg) | ||
| 36 | { | ||
| 37 | bool b; | ||
| 38 | Alg *a; | ||
| 39 | Cube c; | ||
| 40 | |||
| 41 | a = new_alg(algstr); | ||
| 42 | make_solved(&c); | ||
| 43 | apply_alg(a, &c); | ||
| 44 | |||
| 45 | if (!(b = f(&c, a))) | ||
| 46 | printf("%s with alg %s\n", msg, algstr); | ||
| 47 | |||
| 48 | free_alg(a); | ||
| 49 | |||
| 50 | return b; | ||
| 51 | } | ||
| 52 | |||
| 53 | bool | ||
| 54 | try_all_str(CubeTester f, char *msg) | ||
| 55 | { | ||
| 56 | bool b; | ||
| 57 | int i; | ||
| 58 | |||
| 59 | b = true; | ||
| 60 | for (i = 0; algs[i] != NULL; i++) | ||
| 61 | b = b && try_str(f, algs[i], msg); | ||
| 62 | |||
| 63 | return b; | ||
| 64 | } | ||
diff --git a/tests/fst_test_util.h b/tests/fst_test_util.h new file mode 100644 index 0000000..b67b945 --- /dev/null +++ b/tests/fst_test_util.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #include "../src/fst.h" | ||
| 2 | |||
| 3 | extern char *algs[]; | ||
| 4 | |||
| 5 | bool equal_and_log(Cube *c, Cube *d); | ||
| 6 | bool try_str(CubeTester f, char *algstr, char *msg); | ||
| 7 | bool try_all_str(CubeTester f, char *msg); | ||
diff --git a/tests/inc.h b/tests/inc.h deleted file mode 100644 index 53c5fdf..0000000 --- a/tests/inc.h +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | #include <stdio.h> | ||
diff --git a/tests/nissy_tests.c b/tests/nissy_tests.c new file mode 100644 index 0000000..d959423 --- /dev/null +++ b/tests/nissy_tests.c | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | |||
| 3 | void fst_pre_init_testall(); | ||
| 4 | void fst_post_init_testall(); | ||
| 5 | |||
| 6 | int main() { | ||
| 7 | fst_pre_init_testall(); | ||
| 8 | fst_post_init_testall(); | ||
| 9 | |||
| 10 | printf("All tests passed.\n"); | ||
| 11 | return 0; | ||
| 12 | } | ||
diff --git a/tests/test_all.c b/tests/test_all.c deleted file mode 100644 index 4daeec0..0000000 --- a/tests/test_all.c +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | #include "inc.h" | ||
| 2 | |||
| 3 | void test_fst_all(); | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | test_fst_all(); | ||
| 7 | |||
| 8 | printf("All tests passed.\n"); | ||
| 9 | return 0; | ||
| 10 | } | ||
diff --git a/tests/test_fst.c b/tests/test_fst.c deleted file mode 100644 index ad1caba..0000000 --- a/tests/test_fst.c +++ /dev/null | |||
| @@ -1,184 +0,0 @@ | |||
| 1 | #include "inc.h" | ||
| 2 | #include "../src/fst.h" | ||
| 3 | |||
| 4 | static bool cube_to_fst_to_cube(Cube *c, Alg *a); | ||
| 5 | static bool fst_consistent(Cube *c, Alg *a); | ||
| 6 | static bool fst_move_test(Cube *c, Alg *a); | ||
| 7 | static bool fst_inverse_test(Cube *c, Alg *a); | ||
| 8 | static bool try_str(CubeTester f, char *algstr, char *msg); | ||
| 9 | static bool try_all_str(CubeTester f, char *msg); | ||
| 10 | |||
| 11 | static bool test_fst_consistent_algs(); | ||
| 12 | static bool test_cube_to_fst_to_cube_algs(); | ||
| 13 | static bool test_fst_move_algs(); | ||
| 14 | static bool test_fst_inverse_algs(); | ||
| 15 | |||
| 16 | static Tester test[] = { | ||
| 17 | test_fst_consistent_algs, | ||
| 18 | test_cube_to_fst_to_cube_algs, | ||
| 19 | test_fst_move_algs, | ||
| 20 | test_fst_inverse_algs, | ||
| 21 | NULL | ||
| 22 | }; | ||
| 23 | |||
| 24 | static char *name[] = { | ||
| 25 | "Consistency of FST (converted from cube)", | ||
| 26 | "Cube to FST to cube", | ||
| 27 | "FST move", | ||
| 28 | "FST inverse", | ||
| 29 | }; | ||
| 30 | |||
| 31 | static char *algs[] = { | ||
| 32 | "", | ||
| 33 | "U", "U2", "U'", "D", "D2", "D'", "R", "R2", "R'", | ||
| 34 | "L", "L2", "L'", "F", "F2", "F'", "B", "B2", "B'", | ||
| 35 | "U2 R2 U2 R2 U2", | ||
| 36 | "U2 F2 R2 B2 U2 D2 F2 L2 B2", | ||
| 37 | "RUR'URU2R'", | ||
| 38 | "L2 D R U2 B2 L", | ||
| 39 | "R'U'F", | ||
| 40 | "F2 U' R2 D' B2 D2 R2 D2 R2 U' F L' U' R B F2 R B' D2", | ||
| 41 | "D L2 F2 R2 D R2 U L2 U' B2 D L' F2 U2 B' L D' U' R' B2 F2", | ||
| 42 | "F' L2 F' D' R F2 L U L' D2 R2 F2 D2 R2 B' L2 B2 U2 F D2 B", | ||
| 43 | NULL, | ||
| 44 | }; | ||
| 45 | |||
| 46 | static bool | ||
| 47 | fst_consistent(Cube *c, Alg *a) | ||
| 48 | { | ||
| 49 | FstCube fst; | ||
| 50 | |||
| 51 | fst = cube_to_fst(c); | ||
| 52 | |||
| 53 | /* TODO: check consistency of fr_* and rd_* with uf_* */ | ||
| 54 | |||
| 55 | return true; | ||
| 56 | } | ||
| 57 | |||
| 58 | static bool | ||
| 59 | cube_to_fst_to_cube(Cube *c, Alg *a) | ||
| 60 | { | ||
| 61 | Cube d; | ||
| 62 | FstCube fst; | ||
| 63 | |||
| 64 | fst = cube_to_fst(c); | ||
| 65 | fst_to_cube(fst, &d); | ||
| 66 | |||
| 67 | if (!equal(c, &d)) { | ||
| 68 | printf("Cubes are different:\n\n"); | ||
| 69 | printf("Cube 1:\n"); | ||
| 70 | print_cube(c); | ||
| 71 | printf("\nCube 2:\n"); | ||
| 72 | print_cube(&d); | ||
| 73 | printf("\n"); | ||
| 74 | return false; | ||
| 75 | } | ||
| 76 | |||
| 77 | return true; | ||
| 78 | } | ||
| 79 | |||
| 80 | static bool | ||
| 81 | fst_move_test(Cube *c, Alg *a) | ||
| 82 | { | ||
| 83 | int i; | ||
| 84 | Cube d; | ||
| 85 | FstCube fst; | ||
| 86 | |||
| 87 | fst = cube_to_fst(c); | ||
| 88 | |||
| 89 | for (i = 0; i < a->len; i++) { | ||
| 90 | if (a->inv[i] || a->move[i] > B3) { | ||
| 91 | printf("Cannot apply the following alg to FST: "); | ||
| 92 | print_alg(a, false); | ||
| 93 | return false; | ||
| 94 | } | ||
| 95 | fst = fst_move(a->move[i], fst); | ||
| 96 | } | ||
| 97 | |||
| 98 | fst_to_cube(fst, &d); | ||
| 99 | |||
| 100 | return equal(c, &d); | ||
| 101 | } | ||
| 102 | |||
| 103 | static bool | ||
| 104 | fst_inverse_test(Cube *c, Alg *a) | ||
| 105 | { | ||
| 106 | Cube d; | ||
| 107 | |||
| 108 | fst_to_cube(fst_inverse(cube_to_fst(c)), &d); | ||
| 109 | invert_cube(c); | ||
| 110 | |||
| 111 | return equal(c, &d); | ||
| 112 | } | ||
| 113 | |||
| 114 | static bool | ||
| 115 | try_str(CubeTester f, char *algstr, char *msg) | ||
| 116 | { | ||
| 117 | bool b; | ||
| 118 | Alg *a; | ||
| 119 | Cube c; | ||
| 120 | |||
| 121 | a = new_alg(algstr); | ||
| 122 | make_solved(&c); | ||
| 123 | apply_alg(a, &c); | ||
| 124 | |||
| 125 | if (!(b = f(&c, a))) | ||
| 126 | printf("%s with alg %s\n", msg, algstr); | ||
| 127 | |||
| 128 | free_alg(a); | ||
| 129 | |||
| 130 | return b; | ||
| 131 | } | ||
| 132 | |||
| 133 | static bool | ||
| 134 | try_all_str(CubeTester f, char *msg) | ||
| 135 | { | ||
| 136 | bool b; | ||
| 137 | int i; | ||
| 138 | |||
| 139 | b = true; | ||
| 140 | for (i = 0; algs[i] != NULL; i++) | ||
| 141 | b = b && try_str(f, algs[i], msg); | ||
| 142 | |||
| 143 | return b; | ||
| 144 | } | ||
| 145 | |||
| 146 | static bool | ||
| 147 | test_cube_to_fst_to_cube_algs() | ||
| 148 | { | ||
| 149 | return try_all_str(cube_to_fst_to_cube, "Cube to FST to cube failed"); | ||
| 150 | } | ||
| 151 | |||
| 152 | static bool | ||
| 153 | test_fst_consistent_algs() | ||
| 154 | { | ||
| 155 | return try_all_str(fst_consistent, "FST from cube not consistent"); | ||
| 156 | } | ||
| 157 | |||
| 158 | static bool | ||
| 159 | test_fst_move_algs() | ||
| 160 | { | ||
| 161 | return try_all_str(fst_move_test, "FST move incorrect"); | ||
| 162 | } | ||
| 163 | |||
| 164 | static bool | ||
| 165 | test_fst_inverse_algs() | ||
| 166 | { | ||
| 167 | return try_all_str(fst_inverse_test, "FST test incorrect"); | ||
| 168 | } | ||
| 169 | |||
| 170 | void test_fst_all() { | ||
| 171 | int i; | ||
| 172 | |||
| 173 | init_trans(); | ||
| 174 | |||
| 175 | for (i = 0; test[i] != NULL; i++) { | ||
| 176 | printf("Test: %s\n", name[i]); | ||
| 177 | if (!test[i]()) { | ||
| 178 | printf("Failed!\n"); | ||
| 179 | exit(1); | ||
| 180 | } | ||
| 181 | printf("Passed.\n\n"); | ||
| 182 | } | ||
| 183 | printf("All FST tests passed.\n\n"); | ||
| 184 | } | ||
