diff options
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | Makefile | 16 | ||||
| -rw-r--r-- | TODO.md | 17 | ||||
| -rw-r--r-- | src/cube.c | 32 | ||||
| -rw-r--r-- | src/cube.h | 3 | ||||
| -rw-r--r-- | src/cubetypes.h | 3 | ||||
| -rw-r--r-- | src/fst.c | 291 | ||||
| -rw-r--r-- | src/fst.h | 1 | ||||
| -rw-r--r-- | src/shell.c | 2 | ||||
| -rw-r--r-- | src/trans.c | 2 | ||||
| -rw-r--r-- | tests/inc.h | 1 | ||||
| -rw-r--r-- | tests/test_all.c | 10 | ||||
| -rw-r--r-- | tests/test_fst.c | 88 |
13 files changed, 429 insertions, 42 deletions
| @@ -1,4 +1,5 @@ | |||
| 1 | nissy | ||
| 2 | nissy-* | ||
| 3 | doc/*.html | 1 | doc/*.html |
| 4 | doc/*.pdf | 2 | doc/*.pdf |
| 3 | nissy | ||
| 4 | nissy-* | ||
| 5 | test | ||
| @@ -5,11 +5,12 @@ VERSION = post-2.0.2 | |||
| 5 | PREFIX = /usr/local | 5 | PREFIX = /usr/local |
| 6 | MANPREFIX = ${PREFIX}/share/man | 6 | MANPREFIX = ${PREFIX}/share/man |
| 7 | 7 | ||
| 8 | CPPFLAGS = -DVERSION=\"${VERSION}\" | 8 | CPPFLAGS = -DVERSION=\"${VERSION}\" |
| 9 | CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \ | 9 | CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \ |
| 10 | -Wno-unused-parameter -O3 ${CPPFLAGS} | 10 | -Wno-unused-parameter -O3 ${CPPFLAGS} |
| 11 | DBGFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \ | 11 | DBGFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \ |
| 12 | -Wno-unused-parameter -g ${CPPFLAGS} | 12 | -Wno-unused-parameter -g ${CPPFLAGS} |
| 13 | TESTFLAGS = ${DBGFLAGS} -DTEST | ||
| 13 | 14 | ||
| 14 | CC = cc | 15 | CC = cc |
| 15 | 16 | ||
| @@ -19,6 +20,9 @@ all: nissy | |||
| 19 | nissy: clean | 20 | nissy: clean |
| 20 | ${CC} ${CFLAGS} -o nissy src/*.c | 21 | ${CC} ${CFLAGS} -o nissy src/*.c |
| 21 | 22 | ||
| 23 | test: | ||
| 24 | ${CC} ${TESTFLAGS} -o test src/*.c tests/*.c | ||
| 25 | |||
| 22 | nissy.exe: | 26 | nissy.exe: |
| 23 | x86_64-w64-mingw32-gcc ${CFLAGS} -static -o nissy.exe src/*.c | 27 | x86_64-w64-mingw32-gcc ${CFLAGS} -static -o nissy.exe src/*.c |
| 24 | 28 | ||
| @@ -63,5 +67,5 @@ uninstall: | |||
| 63 | rm -rf ${DESTDIR}${PREFIX}/bin/nissy ${DESTDIR}${MANPREFIX}/man1/nissy.1 | 67 | rm -rf ${DESTDIR}${PREFIX}/bin/nissy ${DESTDIR}${MANPREFIX}/man1/nissy.1 |
| 64 | for s in ${SCRIPTS}; do rm -rf ${DESTDIR}${PREFIX}/bin/$$s; done | 68 | for s in ${SCRIPTS}; do rm -rf ${DESTDIR}${PREFIX}/bin/$$s; done |
| 65 | 69 | ||
| 66 | .PHONY: all debug clean dist install uninstall upload | 70 | .PHONY: all debug clean dist install test uninstall upload |
| 67 | 71 | ||
| @@ -4,12 +4,13 @@ This is a list of things that I would like to add or change at some point. | |||
| 4 | It's more of a personal reminder than anything else. | 4 | It's more of a personal reminder than anything else. |
| 5 | 5 | ||
| 6 | ## After symcoord | 6 | ## After symcoord |
| 7 | ### fst_cube | 7 | ### generic: |
| 8 | * slightly different from cube in v2.0.2: each "side" coordinate | 8 | * all files should have an init function, calling the ones |
| 9 | is a transformation of the other, not an eorl or similar (changes | 9 | of the files includes + doing more stuff. A static "initiliazed" |
| 10 | the permutation!) | 10 | variable is probably needed too. |
| 11 | * inverse: for edges, just generate ep[12] and convert back | 11 | ### testing! |
| 12 | * corners: big table (150Mb if 16bit integers are used) | 12 | * test fst and other things... |
| 13 | * move test_coord to the testing folder | ||
| 13 | ### Solving standard coordinates | 14 | ### Solving standard coordinates |
| 14 | * add Void * extradata to DfsArg and a custom move function | 15 | * add Void * extradata to DfsArg and a custom move function |
| 15 | * add optional custom pre-process for generating special table (nx) | 16 | * add optional custom pre-process for generating special table (nx) |
| @@ -42,7 +43,6 @@ It's more of a personal reminder than anything else. | |||
| 42 | check if found enough solutions before checking pruning values) | 43 | check if found enough solutions before checking pruning values) |
| 43 | ### Technical | 44 | ### Technical |
| 44 | * generic option parser | 45 | * generic option parser |
| 45 | * testing? Maybe just hardcode some examples generated with old nissy | ||
| 46 | ### Commands | 46 | ### Commands |
| 47 | * Easy: add option -I (inverse) and -L (linear, like inverse + normal) | 47 | * Easy: add option -I (inverse) and -L (linear, like inverse + normal) |
| 48 | to do only linear NISS | 48 | to do only linear NISS |
| @@ -86,9 +86,6 @@ including e.g. solutions that were not shown because -c) | |||
| 86 | 86 | ||
| 87 | ## Technical stuff | 87 | ## Technical stuff |
| 88 | 88 | ||
| 89 | ### Testing | ||
| 90 | * write some proper tests, move test_coord to the testing module(s) | ||
| 91 | |||
| 92 | ### Memory management | 89 | ### Memory management |
| 93 | * free pruning table after solve is done? if I do this I need to deafault to a | 90 | * free pruning table after solve is done? if I do this I need to deafault to a |
| 94 | small table for < 8 moves solutions or smth | 91 | small table for < 8 moves solutions or smth |
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | #include "cube.h" | 3 | #include "cube.h" |
| 4 | 4 | ||
| 5 | static int where_is_piece(int piece, int *arr, int n); | ||
| 6 | |||
| 5 | void | 7 | void |
| 6 | compose(Cube *c2, Cube *c1) | 8 | compose(Cube *c2, Cube *c1) |
| 7 | { | 9 | { |
| @@ -154,3 +156,33 @@ print_cube(Cube *cube) | |||
| 154 | printf(" %s ", center_string[cube->xp[i]]); | 156 | printf(" %s ", center_string[cube->xp[i]]); |
| 155 | printf("\n"); | 157 | printf("\n"); |
| 156 | } | 158 | } |
| 159 | |||
| 160 | int | ||
| 161 | where_is_center(Center x, Cube *c) | ||
| 162 | { | ||
| 163 | return where_is_piece(x, c->xp, 6); | ||
| 164 | } | ||
| 165 | |||
| 166 | int | ||
| 167 | where_is_corner(Corner k, Cube *c) | ||
| 168 | { | ||
| 169 | return where_is_piece(k, c->cp, 8); | ||
| 170 | } | ||
| 171 | |||
| 172 | int | ||
| 173 | where_is_edge(Edge e, Cube *c) | ||
| 174 | { | ||
| 175 | return where_is_piece(e, c->ep, 12); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int | ||
| 179 | where_is_piece(int piece, int *arr, int n) | ||
| 180 | { | ||
| 181 | int i; | ||
| 182 | |||
| 183 | for (i = 0; i < n; i++) | ||
| 184 | if (arr[i] == piece) | ||
| 185 | return i; | ||
| 186 | |||
| 187 | return -1; | ||
| 188 | } | ||
| @@ -15,6 +15,9 @@ bool is_admissible(Cube *cube); | |||
| 15 | bool is_solved(Cube *cube); | 15 | bool is_solved(Cube *cube); |
| 16 | void make_solved(Cube *cube); | 16 | void make_solved(Cube *cube); |
| 17 | void print_cube(Cube *cube); | 17 | void print_cube(Cube *cube); |
| 18 | int where_is_center(Center x, Cube *c); | ||
| 19 | int where_is_corner(Corner k, Cube *c); | ||
| 20 | int where_is_edge(Edge e, Cube *c); | ||
| 18 | 21 | ||
| 19 | #endif | 22 | #endif |
| 20 | 23 | ||
diff --git a/src/cubetypes.h b/src/cubetypes.h index bb1ad10..d4fa241 100644 --- a/src/cubetypes.h +++ b/src/cubetypes.h | |||
| @@ -108,6 +108,7 @@ typedef void (*DfsExtraCopier) (void *, void *); | |||
| 108 | typedef bool (*Validator) (Alg *); | 108 | typedef bool (*Validator) (Alg *); |
| 109 | typedef void (*Exec) (CommandArgs *); | 109 | typedef void (*Exec) (CommandArgs *); |
| 110 | typedef CommandArgs * (*ArgParser) (int, char **); | 110 | typedef CommandArgs * (*ArgParser) (int, char **); |
| 111 | typedef bool (*Tester) (void); | ||
| 111 | typedef int (*TransFinder) (uint64_t, Trans *); | 112 | typedef int (*TransFinder) (uint64_t, Trans *); |
| 112 | 113 | ||
| 113 | 114 | ||
| @@ -239,7 +240,7 @@ fstcube | |||
| 239 | uint16_t rd_eofb; | 240 | uint16_t rd_eofb; |
| 240 | uint16_t rd_eposepe; | 241 | uint16_t rd_eposepe; |
| 241 | uint16_t rd_coud; | 242 | uint16_t rd_coud; |
| 242 | } | 243 | }; |
| 243 | 244 | ||
| 244 | struct | 245 | struct |
| 245 | indexer | 246 | indexer |
| @@ -2,7 +2,30 @@ | |||
| 2 | 2 | ||
| 3 | #include "fst.h" | 3 | #include "fst.h" |
| 4 | 4 | ||
| 5 | static void fst_to_ep(FstCube fst, 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); | ||
| 8 | static void init_fst_corner_invtables(); | ||
| 9 | static void init_fst_eo_invtables(); | ||
| 10 | static void init_fst_eo_update(uint64_t, uint64_t, int, Cube *); | ||
| 11 | static void init_fst_transalg(); | ||
| 12 | static void init_fst_where_is_edge(); | ||
| 13 | |||
| 14 | static int edge_slice[12] = {[FR] = 0, [FL] = 0, [BL] = 0, [BR] = 0, | ||
| 15 | [UL] = 1, [UR] = 1, [DR] = 1, [DL] = 1, | ||
| 16 | [UF] = 2, [UB] = 2, [DF] = 2, [DB] = 2}; | ||
| 17 | |||
| 18 | static uint16_t inv_coud[FACTORIAL8][POW3TO7]; | ||
| 19 | static uint16_t inv_cp[FACTORIAL8]; | ||
| 20 | static uint16_t uf_cp_to_fr_cp[FACTORIAL8]; | ||
| 21 | static uint16_t uf_cp_to_rd_cp[FACTORIAL8]; | ||
| 22 | |||
| 23 | static int16_t eo_invtable[3][POW2TO11][BINOM12ON4*FACTORIAL4]; | ||
| 24 | |||
| 25 | static int trans_ep_alg[NROTATIONS][12]; | ||
| 26 | static int trans_ep_inv[NROTATIONS][12]; | ||
| 27 | |||
| 28 | static uint16_t fst_where_is_edge_arr[3][12][BINOM12ON4*FACTORIAL4]; | ||
| 6 | 29 | ||
| 7 | FstCube | 30 | FstCube |
| 8 | cube_to_fst(Cube *cube) | 31 | cube_to_fst(Cube *cube) |
| @@ -11,19 +34,39 @@ cube_to_fst(Cube *cube) | |||
| 11 | FstCube ret; | 34 | FstCube ret; |
| 12 | 35 | ||
| 13 | copy_cube(cube, &c); | 36 | copy_cube(cube, &c); |
| 14 | ret.uf_eofb = index_eofb(&c); | 37 | ret.uf_eofb = coord_eofb.i[0]->index(&c); |
| 15 | ret.uf_eposepe = index_eposepe(&c); | 38 | ret.uf_eposepe = coord_eposepe.i[0]->index(&c); |
| 16 | ret.uf_coud = index_coud(&c); | 39 | ret.uf_coud = coord_coud.i[0]->index(&c); |
| 17 | ret.uf_cp = index_cp(&c); | 40 | ret.uf_cp = coord_cp.i[0]->index(&c); |
| 18 | copy_cube(cube, &c); | 41 | copy_cube(cube, &c); |
| 19 | transform_cube(fr, &c); | 42 | apply_trans(fr, &c); |
| 20 | ret.fr_eofb = index_eofb(&c); | 43 | ret.fr_eofb = coord_eofb.i[0]->index(&c); |
| 21 | ret.fr_eposepe = index_eposepe(&c); | 44 | ret.fr_eposepe = coord_eposepe.i[0]->index(&c); |
| 22 | ret.fr_coud = index_coud(&c); | 45 | ret.fr_coud = coord_coud.i[0]->index(&c); |
| 23 | transform_cube(rd, &c); | 46 | apply_trans(rd, &c); |
| 24 | ret.rd_eofb = index_eofb(&c); | 47 | ret.rd_eofb = coord_eofb.i[0]->index(&c); |
| 25 | ret.rd_eposepe = index_eposepe(&c); | 48 | ret.rd_eposepe = coord_eposepe.i[0]->index(&c); |
| 26 | ret.rd_coud = index_coud(&c); | 49 | ret.rd_coud = coord_coud.i[0]->index(&c); |
| 50 | |||
| 51 | return ret; | ||
| 52 | } | ||
| 53 | |||
| 54 | static FstCube | ||
| 55 | ep_to_fst_epos(int *ep) | ||
| 56 | { | ||
| 57 | /* TODO: maybe optimize? */ | ||
| 58 | |||
| 59 | FstCube ret; | ||
| 60 | Cube c; | ||
| 61 | |||
| 62 | memcpy(c.ep, ep, 12 * sizeof(int)); | ||
| 63 | ret.uf_eposepe = coord_eposepe.i[0]->index(&c); | ||
| 64 | |||
| 65 | transform_ep_only(fr, ep, &c); | ||
| 66 | ret.fr_eposepe = coord_eposepe.i[0]->index(&c); | ||
| 67 | |||
| 68 | transform_ep_only(rd, ep, &c); | ||
| 69 | ret.rd_eposepe = coord_eposepe.i[0]->index(&c); | ||
| 27 | 70 | ||
| 28 | return ret; | 71 | return ret; |
| 29 | } | 72 | } |
| @@ -31,28 +74,232 @@ cube_to_fst(Cube *cube) | |||
| 31 | FstCube | 74 | FstCube |
| 32 | fst_inverse(FstCube fst) | 75 | fst_inverse(FstCube fst) |
| 33 | { | 76 | { |
| 34 | /* TODO */ | 77 | FstCube ret; |
| 78 | int i, ep_inv[12]; | ||
| 79 | |||
| 80 | for (i = 0; i < 12; i++) | ||
| 81 | ep_inv[i] = fst_where_is_edge(i, fst); | ||
| 82 | ret = ep_to_fst_epos(ep_inv); | ||
| 83 | |||
| 84 | ret.uf_eofb = ((uint16_t)eo_invtable[0][fst.uf_eofb][fst.uf_eposepe]) | | ||
| 85 | ((uint16_t)eo_invtable[1][fst.uf_eofb][fst.fr_eposepe]) | | ||
| 86 | ((uint16_t)eo_invtable[2][fst.uf_eofb][fst.rd_eposepe]); | ||
| 87 | ret.fr_eofb = ((uint16_t)eo_invtable[0][fst.fr_eofb][fst.uf_eposepe]) | | ||
| 88 | ((uint16_t)eo_invtable[1][fst.fr_eofb][fst.fr_eposepe]) | | ||
| 89 | ((uint16_t)eo_invtable[2][fst.fr_eofb][fst.rd_eposepe]); | ||
| 90 | ret.rd_eofb = ((uint16_t)eo_invtable[0][fst.rd_eofb][fst.uf_eposepe]) | | ||
| 91 | ((uint16_t)eo_invtable[1][fst.rd_eofb][fst.fr_eposepe]) | | ||
| 92 | ((uint16_t)eo_invtable[2][fst.rd_eofb][fst.rd_eposepe]); | ||
| 93 | |||
| 94 | ret.uf_cp = inv_cp[fst.uf_cp]; | ||
| 95 | |||
| 96 | ret.uf_coud = inv_coud[fst.uf_cp][fst.uf_coud]; | ||
| 97 | ret.fr_coud = inv_coud[uf_cp_to_fr_cp[fst.uf_cp]][fst.fr_coud]; | ||
| 98 | ret.rd_coud = inv_coud[uf_cp_to_rd_cp[fst.uf_cp]][fst.rd_coud]; | ||
| 99 | |||
| 100 | return ret; | ||
| 35 | } | 101 | } |
| 36 | 102 | ||
| 37 | FstCube | 103 | FstCube |
| 38 | fst_move(Move m, FstCube fst) | 104 | fst_move(Move m, FstCube fst) |
| 39 | { | 105 | { |
| 40 | /* TODO */ | 106 | FstCube ret; |
| 107 | Move m_fr, m_rd; | ||
| 108 | |||
| 109 | m_fr = transform_move(fr, m); | ||
| 110 | m_rd = transform_move(rd, m); | ||
| 111 | |||
| 112 | ret.uf_eofb = coord_eofb.mtable[m][fst.uf_eofb]; | ||
| 113 | ret.uf_eposepe = coord_eposepe.mtable[m][fst.uf_eposepe]; | ||
| 114 | ret.uf_coud = coord_coud.mtable[m][fst.uf_coud]; | ||
| 115 | ret.uf_cp = coord_cp.mtable[m][fst.uf_cp]; | ||
| 116 | |||
| 117 | ret.fr_eofb = coord_eofb.mtable[m_fr][fst.fr_eofb]; | ||
| 118 | ret.fr_eposepe = coord_eposepe.mtable[m_fr][fst.fr_eposepe]; | ||
| 119 | ret.fr_coud = coord_coud.mtable[m_fr][fst.fr_coud]; | ||
| 120 | |||
| 121 | ret.rd_eofb = coord_eofb.mtable[m_rd][fst.rd_eofb]; | ||
| 122 | ret.rd_eposepe = coord_eposepe.mtable[m_rd][fst.rd_eposepe]; | ||
| 123 | ret.rd_coud = coord_coud.mtable[m_rd][fst.rd_coud]; | ||
| 124 | |||
| 125 | return ret; | ||
| 41 | } | 126 | } |
| 42 | 127 | ||
| 43 | void | 128 | void |
| 44 | fst_to_cube(FstCube fst, Cube *cube) | 129 | fst_to_cube(FstCube fst, Cube *cube) |
| 45 | { | 130 | { |
| 46 | invindex_eofb((uint64_t)fst.uf_eofb, cube); | 131 | Cube e, s, m; |
| 47 | fst_to_ep(fst, cube->ep); | 132 | int i; |
| 48 | invindex_coud((uint64_t)fst.uf_coud, cube); | 133 | |
| 49 | invindex_cp((uint64_t)fst.uf_cp, cube); | 134 | coord_eposepe.i[0]->to_cube(fst.uf_eposepe, &e); |
| 135 | coord_eposepe.i[0]->to_cube(fst.fr_eposepe, &s); | ||
| 136 | apply_trans(inverse_trans(fr), &s); | ||
| 137 | coord_eposepe.i[0]->to_cube(fst.rd_eposepe, &m); | ||
| 138 | apply_trans(inverse_trans(rd), &m); | ||
| 139 | |||
| 140 | for (i = 0; i < 12; i++) { | ||
| 141 | if (edge_slice[e.ep[i]] == 0) | ||
| 142 | cube->ep[i] = e.ep[i]; | ||
| 143 | if (edge_slice[s.ep[i]] == 1) | ||
| 144 | cube->ep[i] = s.ep[i]; | ||
| 145 | if (edge_slice[m.ep[i]] == 2) | ||
| 146 | cube->ep[i] = m.ep[i]; | ||
| 147 | } | ||
| 148 | |||
| 149 | coord_eofb.i[0]->to_cube((uint64_t)fst.uf_eofb, cube); | ||
| 150 | coord_coud.i[0]->to_cube((uint64_t)fst.uf_coud, cube); | ||
| 151 | coord_cp.i[0]->to_cube((uint64_t)fst.uf_cp, cube); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int | ||
| 155 | fst_where_is_edge(int e, FstCube fst) | ||
| 156 | { | ||
| 157 | switch (edge_slice[e]) { | ||
| 158 | case 0: | ||
| 159 | return fst_where_is_edge_arr[0][e][fst.uf_eposepe]; | ||
| 160 | case 1: | ||
| 161 | return fst_where_is_edge_arr[1][e][fst.fr_eposepe]; | ||
| 162 | default: | ||
| 163 | return fst_where_is_edge_arr[2][e][fst.rd_eposepe]; | ||
| 164 | } | ||
| 165 | |||
| 166 | return -1; | ||
| 167 | } | ||
| 168 | |||
| 169 | static void | ||
| 170 | transform_ep_only(Trans t, int *ep, Cube *dst) | ||
| 171 | { | ||
| 172 | int i; | ||
| 173 | |||
| 174 | for (i = 0; i < 12; i++) | ||
| 175 | dst->ep[i] = trans_ep_alg[t][ep[trans_ep_inv[t][i]]]; | ||
| 176 | } | ||
| 177 | |||
| 178 | void | ||
| 179 | init_fst() | ||
| 180 | { | ||
| 181 | init_fst_corner_invtables(); | ||
| 182 | init_fst_eo_invtables(); | ||
| 183 | init_fst_transalg(); | ||
| 184 | init_fst_where_is_edge(); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void | ||
| 188 | init_fst_corner_invtables() | ||
| 189 | { | ||
| 190 | /* TODO: this can be optimized by transforming and copying only corners */ | ||
| 191 | /* A factor of about 4 would be saved in the innermost loop */ | ||
| 192 | |||
| 193 | Cube c, d; | ||
| 194 | uint64_t cp, coud; | ||
| 195 | |||
| 196 | for (cp = 0; cp < FACTORIAL8; cp++) { | ||
| 197 | make_solved(&c); | ||
| 198 | coord_cp.i[0]->to_cube(cp, &c); | ||
| 199 | |||
| 200 | copy_cube(&c, &d); | ||
| 201 | invert_cube(&d); | ||
| 202 | inv_cp[cp] = coord_coud.i[0]->index(&d); | ||
| 203 | |||
| 204 | for (coud = 0; coud < POW3TO7; coud++) { | ||
| 205 | copy_cube(&c, &d); | ||
| 206 | coord_coud.i[0]->to_cube(coud, &d); | ||
| 207 | invert_cube(&d); | ||
| 208 | inv_coud[cp][coud] = coord_coud.i[0]->index(&d); | ||
| 209 | } | ||
| 210 | |||
| 211 | copy_cube(&c, &d); | ||
| 212 | apply_trans(fr, &d); | ||
| 213 | uf_cp_to_fr_cp[cp] = coord_cp.i[0]->index(&d); | ||
| 214 | |||
| 215 | copy_cube(&c, &d); | ||
| 216 | apply_trans(rd, &d); | ||
| 217 | uf_cp_to_rd_cp[cp] = coord_cp.i[0]->index(&d); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | static void | ||
| 222 | init_fst_eo_invtables() | ||
| 223 | { | ||
| 224 | uint64_t ep, eo; | ||
| 225 | Cube c, d; | ||
| 226 | |||
| 227 | for (ep = 0; ep < BINOM12ON4 * FACTORIAL4; ep++) { | ||
| 228 | make_solved(&c); | ||
| 229 | coord_eposepe.i[0]->to_cube(ep, &c); | ||
| 230 | for (eo = 0; eo < POW2TO11; eo++) { | ||
| 231 | coord_eofb.i[0]->to_cube(eo, &c); | ||
| 232 | copy_cube(&c, &d); | ||
| 233 | init_fst_eo_update(eo, ep, 0, &d); | ||
| 234 | apply_trans(inverse_trans(fr), &d); | ||
| 235 | init_fst_eo_update(eo, ep, 1, &d); | ||
| 236 | copy_cube(&c, &d); | ||
| 237 | apply_trans(inverse_trans(rd), &d); | ||
| 238 | init_fst_eo_update(eo, ep, 2, &d); | ||
| 239 | } | ||
| 240 | } | ||
| 50 | } | 241 | } |
| 51 | 242 | ||
| 52 | static void | 243 | static void |
| 53 | fst_to_ep(FstCube fst, int *ep) | 244 | init_fst_eo_update(uint64_t eo, uint64_t ep, int s, Cube *d) |
| 54 | { | 245 | { |
| 55 | /* TODO */ | 246 | int i; |
| 247 | |||
| 248 | for (i = 0; i < 12; i++) | ||
| 249 | if (d->eo[i]) | ||
| 250 | eo_invtable[s][eo][ep] |= ((uint16_t)1) << d->ep[i]; | ||
| 56 | } | 251 | } |
| 57 | 252 | ||
| 58 | #endif | 253 | static void |
| 254 | init_fst_transalg() | ||
| 255 | { | ||
| 256 | Trans t; | ||
| 257 | Alg *alg; | ||
| 258 | Cube c; | ||
| 259 | int i; | ||
| 260 | |||
| 261 | for (t = uf; t < NROTATIONS; t++) { | ||
| 262 | make_solved(&c); | ||
| 263 | alg = rotation_alg(t); | ||
| 264 | apply_alg(alg, &c); | ||
| 265 | for (i = 0; i < 12; i++) | ||
| 266 | trans_ep_alg[t][i] = c.ep[i]; | ||
| 267 | invert_cube(&c); | ||
| 268 | for (i = 0; i < 12; i++) | ||
| 269 | trans_ep_inv[t][i] = c.ep[i]; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | static void | ||
| 274 | init_fst_where_is_edge() | ||
| 275 | { | ||
| 276 | Cube c, d; | ||
| 277 | uint64_t e; | ||
| 278 | |||
| 279 | init_trans(); | ||
| 280 | |||
| 281 | make_solved(&c); | ||
| 282 | for (e = 0; e < BINOM12ON4 * FACTORIAL4; e++) { | ||
| 283 | coord_eposepe.i[0]->to_cube(e, &c); | ||
| 284 | |||
| 285 | copy_cube(&c, &d); | ||
| 286 | fst_where_is_edge_arr[0][FR][e] = where_is_edge(FR, &d); | ||
| 287 | fst_where_is_edge_arr[0][FL][e] = where_is_edge(FL, &d); | ||
| 288 | fst_where_is_edge_arr[0][BL][e] = where_is_edge(BL, &d); | ||
| 289 | fst_where_is_edge_arr[0][BR][e] = where_is_edge(BR, &d); | ||
| 290 | |||
| 291 | copy_cube(&c, &d); | ||
| 292 | apply_trans(inverse_trans(fr), &d); | ||
| 293 | fst_where_is_edge_arr[1][UL][e] = where_is_edge(UL, &d); | ||
| 294 | fst_where_is_edge_arr[1][UR][e] = where_is_edge(UR, &d); | ||
| 295 | fst_where_is_edge_arr[1][DL][e] = where_is_edge(DL, &d); | ||
| 296 | fst_where_is_edge_arr[1][DR][e] = where_is_edge(DR, &d); | ||
| 297 | |||
| 298 | copy_cube(&c, &d); | ||
| 299 | apply_trans(inverse_trans(rd), &d); | ||
| 300 | fst_where_is_edge_arr[2][UF][e] = where_is_edge(UF, &d); | ||
| 301 | fst_where_is_edge_arr[2][UB][e] = where_is_edge(UB, &d); | ||
| 302 | fst_where_is_edge_arr[2][DF][e] = where_is_edge(DF, &d); | ||
| 303 | fst_where_is_edge_arr[2][DB][e] = where_is_edge(DB, &d); | ||
| 304 | } | ||
| 305 | } | ||
| @@ -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 | void init_fst(); | ||
| 10 | 11 | ||
| 11 | #endif | 12 | #endif |
| 12 | 13 | ||
diff --git a/src/shell.c b/src/shell.c index 44665a8..c25b399 100644 --- a/src/shell.c +++ b/src/shell.c | |||
| @@ -142,6 +142,7 @@ launch(bool batchmode) | |||
| 142 | free(shell_argv); | 142 | free(shell_argv); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | #ifndef TEST | ||
| 145 | int | 146 | int |
| 146 | main(int argc, char *argv[]) | 147 | main(int argc, char *argv[]) |
| 147 | { | 148 | { |
| @@ -187,3 +188,4 @@ main(int argc, char *argv[]) | |||
| 187 | 188 | ||
| 188 | return 0; | 189 | return 0; |
| 189 | } | 190 | } |
| 191 | #endif | ||
diff --git a/src/trans.c b/src/trans.c index da2dca3..898c2be 100644 --- a/src/trans.c +++ b/src/trans.c | |||
| @@ -26,7 +26,7 @@ static char rotation_alg_string[100][NROTATIONS] = { | |||
| 26 | [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", | 26 | [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | static Alg *rotation_alg_arr[NROTATIONS]; | 29 | Alg *rotation_alg_arr[NROTATIONS]; |
| 30 | Move moves_ttable[NTRANS][NMOVES]; | 30 | Move moves_ttable[NTRANS][NMOVES]; |
| 31 | Trans trans_ttable[NTRANS][NTRANS]; | 31 | Trans trans_ttable[NTRANS][NTRANS]; |
| 32 | Trans trans_itable[NTRANS]; | 32 | Trans trans_itable[NTRANS]; |
diff --git a/tests/inc.h b/tests/inc.h new file mode 100644 index 0000000..53c5fdf --- /dev/null +++ b/tests/inc.h | |||
| @@ -0,0 +1 @@ | |||
| #include <stdio.h> | |||
diff --git a/tests/test_all.c b/tests/test_all.c new file mode 100644 index 0000000..4daeec0 --- /dev/null +++ b/tests/test_all.c | |||
| @@ -0,0 +1,10 @@ | |||
| 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 new file mode 100644 index 0000000..fc1185c --- /dev/null +++ b/tests/test_fst.c | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | #include "inc.h" | ||
| 2 | #include "../src/fst.h" | ||
| 3 | |||
| 4 | static bool test_cube_to_fst_to_cube(Cube *c); | ||
| 5 | |||
| 6 | static bool test_cube_to_fst_to_cube_solved(); | ||
| 7 | static bool test_cube_to_fst_to_cube_unsolved(); | ||
| 8 | |||
| 9 | static Tester test[] = { | ||
| 10 | test_cube_to_fst_to_cube_solved, | ||
| 11 | test_cube_to_fst_to_cube_unsolved, | ||
| 12 | NULL | ||
| 13 | }; | ||
| 14 | |||
| 15 | static char *name[] = { | ||
| 16 | "Cube to FST to cube (solved)", | ||
| 17 | "Cube to FST to cube (unsolved)", | ||
| 18 | }; | ||
| 19 | |||
| 20 | static bool | ||
| 21 | test_cube_to_fst_to_cube(Cube *c) | ||
| 22 | { | ||
| 23 | Cube d; | ||
| 24 | FstCube fst; | ||
| 25 | |||
| 26 | fst = cube_to_fst(c); | ||
| 27 | fst_to_cube(fst, &d); | ||
| 28 | |||
| 29 | return equal(c, &d); | ||
| 30 | } | ||
| 31 | |||
| 32 | static bool | ||
| 33 | test_cube_to_fst_to_cube_solved() | ||
| 34 | { | ||
| 35 | Cube c; | ||
| 36 | |||
| 37 | make_solved(&c); | ||
| 38 | return test_cube_to_fst_to_cube(&c); | ||
| 39 | } | ||
| 40 | |||
| 41 | static bool | ||
| 42 | test_cube_to_fst_to_cube_unsolved() | ||
| 43 | { | ||
| 44 | bool b; | ||
| 45 | int i; | ||
| 46 | Alg *a; | ||
| 47 | Cube c; | ||
| 48 | char *algs[] = { | ||
| 49 | "U2 R2 U2 R2 U2", | ||
| 50 | "U2 F2 R2 B2 U2 D2 F2 L2 B2", | ||
| 51 | "RUR'URU2R'", | ||
| 52 | "L2 D R U2 B2 L", | ||
| 53 | "R'U'F", | ||
| 54 | "F2 U' R2 D' B2 D2 R2 D2 R2 U' F L' U' R B F2 R B' D2", | ||
| 55 | "D L2 F2 R2 D R2 U L2 U' B2 D L' F2 U2 B' L D' U' R' B2 F2", | ||
| 56 | "F' L2 F' D' R F2 L U L' D2 R2 F2 D2 R2 B' L2 B2 U2 F D2 B", | ||
| 57 | NULL, | ||
| 58 | }; | ||
| 59 | |||
| 60 | for (i = 0; algs[i] != NULL; i++) { | ||
| 61 | make_solved(&c); | ||
| 62 | a = new_alg(algs[i]); | ||
| 63 | apply_alg(a, &c); | ||
| 64 | b = test_cube_to_fst_to_cube(&c); | ||
| 65 | free_alg(a); | ||
| 66 | if (!b) { | ||
| 67 | printf("Failed with alg %s\n", algs[i]); | ||
| 68 | return false; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | return true; | ||
| 72 | } | ||
| 73 | |||
| 74 | void test_fst_all() { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | init_fst(); | ||
| 78 | |||
| 79 | for (i = 0; test[i] != NULL; i++) { | ||
| 80 | printf("Test: %s\n", name[i]); | ||
| 81 | if (!test[i]()) { | ||
| 82 | printf("Failed!\n"); | ||
| 83 | exit(1); | ||
| 84 | } | ||
| 85 | printf("Passed.\n"); | ||
| 86 | } | ||
| 87 | printf("All FST tests passed.\n\n"); | ||
| 88 | } | ||
