aboutsummaryrefslogtreecommitdiff
path: root/src/coord.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/coord.c959
1 files changed, 458 insertions, 501 deletions
diff --git a/src/coord.c b/src/coord.c
index 673434f..a9df9fd 100644
--- a/src/coord.c
+++ b/src/coord.c
@@ -1,654 +1,611 @@
1#define COORD_C
2
3#include "coord.h" 1#include "coord.h"
4 2
5static void gen_coord_comp(Coordinate *coord); 3static uint64_t index_eofb(Cube cube);
6static void gen_coord_sym(Coordinate *coord); 4static uint64_t index_eofbepos(Cube cube);
7static bool read_coord_mtable(Coordinate *coord); 5static uint64_t index_epud(Cube cube);
8static bool read_coord_sd(Coordinate *coord); 6static uint64_t index_coud(Cube cube);
9static bool read_coord_ttable(Coordinate *coord); 7static uint64_t index_corners(Cube cube);
10static bool write_coord_mtable(Coordinate *coord); 8static uint64_t index_cp(Cube cube);
11static bool write_coord_sd(Coordinate *coord); 9static uint64_t index_cphtr(Cube cube);
12static bool write_coord_ttable(Coordinate *coord); 10static uint64_t index_cornershtr(Cube cube);
11static uint64_t index_cornershtrfin(Cube cube);
12static uint64_t index_drud(Cube cube);
13static uint64_t index_drud_eofb(Cube cube);
14static uint64_t index_htr_drud(Cube cube);
15static uint64_t index_htrfin(Cube cube);
16static uint64_t index_cpud_separate(Cube cube);
13 17
14/* Indexers ******************************************************************/ 18static uint64_t move_eofb(Move m, uint64_t ind);
19static uint64_t move_eofbepos(Move m, uint64_t ind);
20static uint64_t move_epud(Move m, uint64_t ind);
21static uint64_t move_coud(Move m, uint64_t ind);
22static uint64_t move_corners(Move m, uint64_t ind);
23static uint64_t move_cp(Move m, uint64_t ind);
24static uint64_t move_cphtr(Move m, uint64_t ind);
25static uint64_t move_cornershtr(Move m, uint64_t ind);
26static uint64_t move_cornershtrfin(Move m, uint64_t ind);
27static uint64_t move_drud(Move m, uint64_t ind);
28static uint64_t move_drud_eofb(Move m, uint64_t ind);
29static uint64_t move_htr_drud(Move m, uint64_t ind);
30static uint64_t move_htrfin(Move m, uint64_t ind);
31static uint64_t move_cpud_separate(Move m, uint64_t ind);
15 32
16uint64_t 33static void init_cphtr_cosets();
17index_eofb(Cube *cube) 34static void init_cphtr_left_cosets_bfs(int i, int c);
18{ 35static void init_cphtr_right_cosets_color(int i, int c);
19 return (uint64_t)digit_array_to_int(cube->eo, 11, 2); 36static void init_cpud_separate();
20} 37static void init_cornershtrfin();
38static void init_htr_eposs();
21 39
22uint64_t
23index_coud(Cube *cube)
24{
25 return (uint64_t)digit_array_to_int(cube->co, 7, 3);
26}
27 40
28uint64_t 41/* All sorts of useful costants and tables **********************************/
29index_cp(Cube *cube)
30{
31 return (uint64_t)perm_to_index(cube->cp, 8);
32}
33 42
34uint64_t 43static int cphtr_left_cosets[FACTORIAL8];
35index_cpudsep(Cube *cube) 44static int cphtr_right_cosets[FACTORIAL8];
36{ 45static int cphtr_right_rep[BINOM8ON4*6];
37 int i, c[8]; 46int cpud_separate_ind[FACTORIAL8];
47int cpud_separate_ant[BINOM8ON4];
48static int cornershtrfin_ind[FACTORIAL8];
49int cornershtrfin_ant[24*24/6];
50static int htr_eposs_ind[BINOM12ON4];
51static int htr_eposs_ant[BINOM8ON4];
38 52
39 for (i = 0; i < 8; i++) 53/* Coordinates and their implementation **************************************/
40 c[i] = cube->cp[i] < 4 ? 0 : 1;
41 54
42 return (uint64_t)subset_to_index(c, 8, 4); 55Coordinate
43} 56coord_eofb = {
57 .index = index_eofb,
58 .max = POW2TO11,
59 .move = move_eofb,
60};
44 61
45uint64_t 62Coordinate
46index_epe(Cube *cube) 63coord_eofbepos = {
47{ 64 .index = index_eofbepos,
48 int i, e[4]; 65 .max = POW2TO11 * BINOM12ON4,
66 .move = move_eofbepos,
67};
49 68
50 for (i = 0; i < 4; i++) 69Coordinate
51 e[i] = cube->ep[i+8] - 8; 70coord_coud = {
71 .index = index_coud,
72 .max = POW3TO7,
73 .move = move_coud,
74};
52 75
53 return (uint64_t)perm_to_index(e, 4); 76Coordinate
54} 77coord_corners = {
78 .index = index_corners,
79 .max = POW3TO7 * FACTORIAL8,
80 .move = move_corners,
81};
55 82
56uint64_t 83Coordinate
57index_epud(Cube *cube) 84coord_cp = {
58{ 85 .index = index_cp,
59 return (uint64_t)perm_to_index(cube->ep, 8); 86 .max = FACTORIAL8,
60} 87 .move = move_cp,
88};
61 89
62uint64_t 90Coordinate
63index_epos(Cube *cube) 91coord_cphtr = {
64{ 92 .index = index_cphtr,
65 int i, a[12]; 93 .max = BINOM8ON4 * 6,
94 .move = move_cphtr,
95};
66 96
67 for (i = 0; i < 12; i++) 97Coordinate
68 a[i] = (cube->ep[i] < 8) ? 0 : 1; 98coord_cornershtr = {
99 .index = index_cornershtr,
100 .max = POW3TO7 * BINOM8ON4 * 6,
101 .move = move_cornershtr,
102};
69 103
70 return (uint64_t)subset_to_index(a, 12, 4); 104Coordinate
71} 105coord_cornershtrfin = {
106 .index = index_cornershtrfin,
107 .max = 24*24/6,
108 .move = move_cornershtrfin,
109};
72 110
73uint64_t 111Coordinate
74index_eposepe(Cube *cube) 112coord_epud = {
75{ 113 .index = index_epud,
76 int i, j, e[4]; 114 .max = FACTORIAL8,
77 uint64_t epos, epe; 115 .move = move_epud,
116};
78 117
79 epos = (uint64_t)index_epos(cube); 118Coordinate
80 for (i = 0, j = 0; i < 12; i++) 119coord_drud = {
81 if (cube->ep[i] >= 8) 120 .index = index_drud,
82 e[j++] = cube->ep[i] - 8; 121 .max = POW2TO11 * POW3TO7 * BINOM12ON4,
83 epe = (uint64_t)perm_to_index(e, 4); 122 .move = move_drud,
123};
84 124
85 return epos * FACTORIAL4 + epe; 125Coordinate
86} 126coord_htr_drud = {
127 .index = index_htr_drud,
128 .max = BINOM8ON4 * 6 * BINOM8ON4,
129 .move = move_htr_drud,
130};
87 131
88/* Inverse indexers **********************************************************/ 132Coordinate
133coord_htrfin = {
134 .index = index_htrfin,
135 .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */
136 .move = move_htrfin,
137};
89 138
90void 139Coordinate
91invindex_eofb(uint64_t ind, Cube *cube) 140coord_drud_eofb = {
92{ 141 .index = index_drud_eofb,
93 int_to_sum_zero_array(ind, 2, 12, cube->eo); 142 .max = POW3TO7 * BINOM12ON4,
94} 143 .move = move_drud_eofb,
144};
95 145
96void 146Coordinate
97invindex_coud(uint64_t ind, Cube *cube) 147coord_cpud_separate = {
148 .index = index_cpud_separate,
149 .max = BINOM8ON4,
150 .move = move_cpud_separate,
151};
152
153/* Indexers ******************************************************************/
154
155static uint64_t
156index_eofb(Cube cube)
98{ 157{
99 int_to_sum_zero_array(ind, 3, 8, cube->co); 158 return cube.eofb;
100} 159}
101 160
102void 161static uint64_t
103invindex_cp(uint64_t ind, Cube *cube) 162index_eofbepos(Cube cube)
104{ 163{
105 index_to_perm(ind, 8, cube->cp); 164 return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb;
106} 165}
107 166
108void 167static uint64_t
109invindex_cpudsep(uint64_t ind, Cube *cube) 168index_epud(Cube cube)
110{ 169{
111 int i, j, k, c[8]; 170 uint64_t ret;
171 CubeArray *arr = new_cubearray(cube, pf_ep);
112 172
113 index_to_subset(ind, 8, 4, c); 173 ret = perm_to_index(arr->ep, 8);
114 for (i = 0, j = 0, k = 4; i < 8; i++) 174 free_cubearray(arr, pf_ep);
115 cube->cp[i] = c[i] == 0 ? j++ : k++; 175
176 return ret;
116} 177}
117 178
179static uint64_t
180index_coud(Cube cube)
181{
182 return cube.coud;
183}
118 184
119void 185static uint64_t
120invindex_epe(uint64_t ind, Cube *cube) 186index_corners(Cube cube)
121{ 187{
122 int i; 188 return cube.coud * FACTORIAL8 + cube.cp;
189}
123 190
124 index_to_perm(ind, 4, &cube->ep[8]); 191static uint64_t
125 for (i = 0; i < 4; i++) 192index_cp(Cube cube)
126 cube->ep[i+8] += 8; 193{
194 return cube.cp;
127} 195}
128 196
129void 197static uint64_t
130invindex_epud(uint64_t ind, Cube *cube) 198index_cphtr(Cube cube)
131{ 199{
132 index_to_perm(ind, 8, cube->ep); 200 return cphtr_right_cosets[cube.cp];
133} 201}
134 202
135void 203static uint64_t
136invindex_epos(uint64_t ind, Cube *cube) 204index_cornershtr(Cube cube)
137{ 205{
138 int i, j, k; 206 return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube);
207}
139 208
140 index_to_subset(ind, 12, 4, cube->ep); 209static uint64_t
141 for (i = 0, j = 0, k = 8; i < 12; i++) 210index_cornershtrfin(Cube cube)
142 if (cube->ep[i] == 0) 211{
143 cube->ep[i] = j++; 212 return cornershtrfin_ind[cube.cp];
144 else
145 cube->ep[i] = k++;
146} 213}
147 214
148void 215static uint64_t
149invindex_eposepe(uint64_t ind, Cube *cube) 216index_drud(Cube cube)
150{ 217{
151 int i, j, k, e[4]; 218 uint64_t a, b, c;
152 uint64_t epos, epe;
153 219
154 epos = ind / FACTORIAL4; 220 a = cube.eofb;
155 epe = ind % FACTORIAL4; 221 b = cube.coud;
222 c = cube.epose / FACTORIAL4;
156 223
157 index_to_subset(epos, 12, 4, cube->ep); 224 b *= POW2TO11;
158 index_to_perm(epe, 4, e); 225 c *= POW2TO11 * POW3TO7;
159 226
160 for (i = 0, j = 0, k = 0; i < 12; i++) 227 return a + b + c;
161 if (cube->ep[i] == 0)
162 cube->ep[i] = j++;
163 else
164 cube->ep[i] = e[k++] + 8;
165} 228}
166 229
167/* Other local functions *****************************************************/ 230static uint64_t
168 231index_drud_eofb(Cube cube)
169uint64_t
170indexers_getmax(Indexer **is)
171{ 232{
172 int i; 233 return index_drud(cube) / POW2TO11;
173 uint64_t max = 1;
174
175 for (i = 0; is[i] != NULL; i++)
176 max *= is[i]->n;
177
178 return max;
179} 234}
180 235
181uint64_t 236static uint64_t
182indexers_getind(Indexer **is, Cube *c) 237index_htr_drud(Cube cube)
183{ 238{
184 int i; 239 uint64_t a, b;
185 uint64_t max = 0;
186 240
187 for (i = 0; is[i] != NULL; i++) { 241 a = index_cphtr(cube);
188 max *= is[i]->n; 242 b = htr_eposs_ind[cube.eposs/24];
189 max += is[i]->index(c);
190 }
191 243
192 return max; 244 return a * BINOM8ON4 + b;
193} 245}
194 246
195void 247static uint64_t
196indexers_makecube(Indexer **is, uint64_t ind, Cube *c) 248index_htrfin(Cube cube)
197{ 249{
198 /* Warning: anti-indexers are applied in the same order as indexers. */ 250 uint64_t epe, eps, epm, cp, ep;
199 /* We assume order does not matter, but it would make more sense to */
200 /* apply them in reverse. */
201 251
202 int i; 252 epe = cube.epose % 24;
203 uint64_t m; 253 eps = cube.eposs % 24;
254 epm = cube.eposm % 24;
255 ep = (epe * 24 + eps) *24 + epm;
256 cp = index_cornershtrfin(cube);
204 257
205 make_solved(c); 258 return cp * 24 * 24 * 24 + ep;
206 m = indexers_getmax(is);
207 for (i = 0; is[i] != NULL; i++) {
208 m /= is[i]->n;
209 is[i]->to_cube(ind / m, c);
210 ind %= m;
211 }
212} 259}
213 260
214static void 261static uint64_t
215gen_coord_comp(Coordinate *coord) 262index_cpud_separate(Cube cube)
216{ 263{
217 uint64_t ui; 264 return cpud_separate_ind[cube.cp];
218 Cube c, mvd; 265}
219 Move m;
220 Trans t;
221
222 coord->max = indexers_getmax(coord->i);
223
224 for (m = 0; m < NMOVES; m++)
225 coord->mtable[m] = malloc(coord->max * sizeof(uint64_t));
226 266
227 for (t = 0; t < NTRANS; t++) 267/* Coordinate movers *********************************************************/
228 coord->ttable[t] = malloc(coord->max * sizeof(uint64_t));
229 268
230 if (!read_coord_mtable(coord)) { 269static uint64_t
231 fprintf(stderr, "%s: generating mtable\n", coord->name); 270move_eofb(Move m, uint64_t ind)
271{
272 return eofb_mtable[m][ind];
273}
232 274
233 for (ui = 0; ui < coord->max; ui++) { 275static uint64_t
234 indexers_makecube(coord->i, ui, &c); 276move_eofbepos(Move m, uint64_t ind)
235 for (m = 0; m < NMOVES; m++) { 277{
236 copy_cube(&c, &mvd); 278 uint64_t a, b;
237 apply_move(m, &mvd);
238 coord->mtable[m][ui] =
239 indexers_getind(coord->i, &mvd);
240 }
241 }
242 if (!write_coord_mtable(coord))
243 fprintf(stderr, "%s: error writing mtable\n",
244 coord->name);
245
246 fprintf(stderr, "%s: mtable generated\n", coord->name);
247 }
248 279
249 if (!read_coord_ttable(coord)) { 280 a = epose_mtable[m][(ind / POW2TO11)*24];
250 fprintf(stderr, "%s: generating ttable\n", coord->name); 281 b = eofb_mtable[m][ind % POW2TO11];
251 282
252 for (ui = 0; ui < coord->max; ui++) { 283 return (a/24) * POW2TO11 + b;
253 indexers_makecube(coord->i, ui, &c);
254 for (t = 0; t < NTRANS; t++) {
255 copy_cube(&c, &mvd);
256 apply_trans(t, &mvd);
257 coord->ttable[t][ui] =
258 indexers_getind(coord->i, &mvd);
259 }
260 }
261 if (!write_coord_ttable(coord))
262 fprintf(stderr, "%s: error writing ttable\n",
263 coord->name);
264 }
265} 284}
266 285
267static void 286static uint64_t
268gen_coord_sym(Coordinate *coord) 287move_epud(Move m, uint64_t ind)
269{ 288{
270 uint64_t i, in, ui, uj, uu, M, nr; 289 /* TODO: save to file? */
290 static bool initialized = false;
291 static int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 };
292 static int shortlist[NMOVES] = {
293 [U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5,
294 [R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9
295 };
296 static uint64_t aux[10][FACTORIAL8];
297 uint64_t ui;
271 int j; 298 int j;
272 Move m; 299 Move mj;
273 Trans t; 300 Cube c;
274 301 CubeArray *arr, *auxarr;
275 M = coord->base[0]->max;
276 coord->selfsim = malloc(M * sizeof(uint64_t));
277 coord->symclass = malloc(M * sizeof(uint64_t));
278 coord->symrep = malloc(M * sizeof(uint64_t));
279 coord->transtorep = malloc(M * sizeof(Trans));
280
281 if (!read_coord_sd(coord)) {
282 fprintf(stderr, "%s: generating syms\n", coord->name);
283
284 for (i = 0; i < M; i++)
285 coord->symclass[i] = M+1;
286 302
287 for (i = 0, nr = 0; i < M; i++) { 303 if (!moveset_drud.allowed(m)) {
288 if (coord->symclass[i] != M+1) 304 fprintf(stderr, "Move not allowed for epud\n"
289 continue; 305 "This is a bug, please report\n");
306 return coord_epud.max;
307 }
290 308
291 coord->symrep[nr] = i; 309 if (!initialized) {
292 coord->transtorep[i] = uf; 310 auxarr = malloc(sizeof(CubeArray));
293 coord->selfsim[nr] = (uint64_t)0; 311 auxarr->ep = a;
294 for (j = 0; j < coord->tgrp->n; j++) { 312 for (ui = 0; ui < coord_epud.max; ui++) {
295 t = coord->tgrp->t[j]; 313 index_to_perm(ui, 8, a);
296 in = trans_coord(coord->base[0], t, i); 314 c = arrays_to_cube(auxarr, pf_ep);
297 coord->symclass[in] = nr; 315 for (j = 0; moveset_drud.sorted_moves[j] != NULLMOVE;
298 if (in == i) 316 j++) {
299 coord->selfsim[nr] |= ((uint64_t)1<<t); 317 mj = moveset_drud.sorted_moves[j];
300 else 318 arr = new_cubearray(apply_move(mj, c), pf_ep);
301 coord->transtorep[in] = 319 aux[shortlist[mj]][ui] =
302 inverse_trans(t); 320 perm_to_index(arr->ep, 8);
321 free_cubearray(arr, pf_ep);
303 } 322 }
304 nr++;
305 } 323 }
324 free(auxarr);
306 325
307 coord->max = nr; 326 initialized = true;
308
309 fprintf(stderr, "%s: found %" PRIu64 " classes\n",
310 coord->name, nr);
311 if (!write_coord_sd(coord))
312 fprintf(stderr, "%s: error writing symdata\n",
313 coord->name);
314 }
315
316 coord->symrep = realloc(coord->symrep, coord->max*sizeof(uint64_t));
317 coord->selfsim = realloc(coord->selfsim, coord->max*sizeof(uint64_t));
318
319 for (m = 0; m < NMOVES; m++) {
320 coord->mtable[m] = malloc(coord->max*sizeof(uint64_t));
321 coord->ttrep_move[m] = malloc(coord->max*sizeof(Trans));
322 } 327 }
323 328
324 if (!read_coord_mtable(coord)) { 329 return aux[shortlist[m]][ind];
325 for (ui = 0; ui < coord->max; ui++) {
326 uu = coord->symrep[ui];
327 for (m = 0; m < NMOVES; m++) {
328 uj = move_coord(coord->base[0], m, uu, NULL);
329 coord->mtable[m][ui] = coord->symclass[uj];
330 coord->ttrep_move[m][ui] =
331 coord->transtorep[uj];
332 }
333 }
334 if (!write_coord_mtable(coord))
335 fprintf(stderr, "%s: error writing mtable\n",
336 coord->name);
337 }
338} 330}
339 331
340static bool 332static uint64_t
341read_coord_mtable(Coordinate *coord) 333move_coud(Move m, uint64_t ind)
342{ 334{
343 FILE *f; 335 return coud_mtable[m][ind];
344 char fname[strlen(tabledir)+256]; 336}
345 Move m;
346 uint64_t M;
347 bool r;
348
349 strcpy(fname, tabledir);
350 strcat(fname, "/mt_");
351 strcat(fname, coord->name);
352
353 if ((f = fopen(fname, "rb")) == NULL)
354 return false;
355 337
356 M = coord->max; 338static uint64_t
357 r = true; 339move_corners(Move m, uint64_t ind)
358 for (m = 0; m < NMOVES; m++) 340{
359 r = r && fread(coord->mtable[m], sizeof(uint64_t), M, f) == M; 341 uint64_t a, b;
360 342
361 if (coord->type == SYM_COORD) 343 a = coud_mtable[m][ind / FACTORIAL8];
362 for (m = 0; m < NMOVES; m++) 344 b = cp_mtable[m][ind % FACTORIAL8];
363 r = r && fread(coord->ttrep_move[m],
364 sizeof(Trans), M, f) == M;
365 345
366 fclose(f); 346 return a * FACTORIAL8 + b;
367 return r;
368} 347}
369 348
370static bool 349static uint64_t
371read_coord_sd(Coordinate *coord) 350move_cp(Move m, uint64_t ind)
372{ 351{
373 FILE *f; 352 return cp_mtable[m][ind];
374 char fname[strlen(tabledir)+256]; 353}
375 uint64_t M, N;
376 bool r;
377 354
378 strcpy(fname, tabledir); 355static uint64_t
379 strcat(fname, "/sd_"); 356move_cphtr(Move m, uint64_t ind)
380 strcat(fname, coord->name); 357{
358 static bool initialized = false;
359 static uint64_t aux[NMOVES][BINOM8ON4*6];
360 uint64_t ui;
361 Move j;
381 362
382 if ((f = fopen(fname, "rb")) == NULL) 363 if (!initialized) {
383 return false; 364 for (ui = 0; ui < BINOM8ON4*6; ui++)
365 for (j = U; j < NMOVES; j++)
366 aux[j][ui] = cphtr_right_cosets[
367 cp_mtable[j][cphtr_right_rep[ui]]];
384 368
385 r = true; 369 initialized = true;
386 r = r && fread(&coord->max, sizeof(uint64_t), 1, f) == 1; 370 }
387 M = coord->max;
388 N = coord->base[0]->max;
389 r = r && fread(coord->symrep, sizeof(uint64_t), M, f) == M;
390 r = r && fread(coord->selfsim, sizeof(uint64_t), M, f) == M;
391 r = r && fread(coord->symclass, sizeof(uint64_t), N, f) == N;
392 r = r && fread(coord->transtorep, sizeof(Trans), N, f) == N;
393 371
394 fclose(f); 372 return aux[m][ind];
395 return r;
396} 373}
397 374
398static bool 375static uint64_t
399read_coord_ttable(Coordinate *coord) 376move_cornershtr(Move m, uint64_t ind)
400{ 377{
401 FILE *f; 378 uint64_t a, b;
402 char fname[strlen(tabledir)+256];
403 Trans t;
404 uint64_t M;
405 bool r;
406
407 strcpy(fname, tabledir);
408 strcat(fname, "/tt_");
409 strcat(fname, coord->name);
410
411 if ((f = fopen(fname, "rb")) == NULL)
412 return false;
413 379
414 M = coord->max; 380 a = coud_mtable[m][ind/(BINOM8ON4 * 6)];
415 r = true; 381 b = move_cphtr(m, ind % (BINOM8ON4 * 6));
416 for (t = 0; t < NTRANS; t++)
417 r = r && fread(coord->ttable[t], sizeof(uint64_t), M, f) == M;
418 382
419 fclose(f); 383 return a * BINOM8ON4 * 6 + b;
420 return r;
421} 384}
422 385
423static bool 386static uint64_t
424write_coord_mtable(Coordinate *coord) 387move_cornershtrfin(Move m, uint64_t ind)
425{ 388{
426 FILE *f; 389 int a;
427 char fname[strlen(tabledir)+256];
428 Move m;
429 uint64_t M;
430 bool r;
431 390
432 strcpy(fname, tabledir); 391 a = cp_mtable[m][cornershtrfin_ant[ind]];
433 strcat(fname, "/mt_");
434 strcat(fname, coord->name);
435 392
436 if ((f = fopen(fname, "wb")) == NULL) 393 return cornershtrfin_ind[a];
437 return false; 394}
438 395
439 M = coord->max; 396static uint64_t
440 r = true; 397move_drud(Move m, uint64_t ind)
441 for (m = 0; m < NMOVES; m++) 398{
442 r = r && fwrite(coord->mtable[m], sizeof(uint64_t), M, f) == M; 399 uint64_t a, b, c;
443 400
444 if (coord->type == SYM_COORD) 401 a = eofb_mtable[m][ind % POW2TO11];
445 for (m = 0; m < NMOVES; m++) 402 b = coud_mtable[m][(ind / POW2TO11) % POW3TO7];
446 r = r && fwrite(coord->ttrep_move[m], 403 c = epose_mtable[m][ind / (POW2TO11 * POW3TO7)];
447 sizeof(Trans), M, f) == M;
448 404
449 fclose(f); 405 return a + (b + c * POW3TO7) * POW2TO11;
450 return r;
451} 406}
452 407
453static bool 408static uint64_t
454write_coord_sd(Coordinate *coord) 409move_drud_eofb(Move m, uint64_t ind)
455{ 410{
456 FILE *f; 411 uint64_t a, b;
457 char fname[strlen(tabledir)+256];
458 uint64_t M, N;
459 bool r;
460
461 strcpy(fname, tabledir);
462 strcat(fname, "/sd_");
463 strcat(fname, coord->name);
464 412
465 if ((f = fopen(fname, "wb")) == NULL) 413 a = coud_mtable[m][ind % POW3TO7];
466 return false; 414 b = epose_mtable[m][(ind / POW3TO7) * 24] / 24;
467 415
468 r = true; 416 return a + b * POW3TO7;
469 M = coord->max;
470 N = coord->base[0]->max;
471 r = r && fwrite(&coord->max, sizeof(uint64_t), 1, f) == 1;
472 r = r && fwrite(coord->symrep, sizeof(uint64_t), M, f) == M;
473 r = r && fwrite(coord->selfsim, sizeof(uint64_t), M, f) == M;
474 r = r && fwrite(coord->symclass, sizeof(uint64_t), N, f) == N;
475 r = r && fwrite(coord->transtorep, sizeof(Trans), N, f) == N;
476
477 fclose(f);
478 return r;
479} 417}
480 418
481static bool 419static uint64_t
482write_coord_ttable(Coordinate *coord) 420move_htr_drud(Move m, uint64_t ind)
483{ 421{
484 FILE *f; 422 uint64_t a, b;
485 char fname[strlen(tabledir)+256];
486 Trans t;
487 uint64_t M;
488 bool r;
489 423
490 strcpy(fname, tabledir); 424 a = move_cphtr(m, ind/BINOM8ON4);
491 strcat(fname, "/tt_"); 425 b = eposs_mtable[m][htr_eposs_ant[ind%BINOM8ON4]];
492 strcat(fname, coord->name);
493 426
494 if ((f = fopen(fname, "wb")) == NULL) 427 return a*BINOM8ON4 + htr_eposs_ind[b/24];
495 return false; 428}
496 429
497 M = coord->max; 430static uint64_t
498 r = true; 431move_htrfin(Move m, uint64_t ind)
499 for (t = 0; t < NTRANS; t++) 432{
500 r = r && fwrite(coord->ttable[t], sizeof(uint64_t), M, f) == M; 433 uint64_t a, b, bm, bs, be;
501 434
502 fclose(f); 435 a = move_cornershtrfin(m, ind / (24*24*24));
503 return r; 436 bm = eposm_mtable[m][ind%24] % 24;
504} 437 bs = eposs_mtable[m][(ind/24)%24] % 24;
438 be = epose_mtable[m][(ind/(24*24))%24] % 24;
439 b = (be * 24 + bs) * 24 + bm;
505 440
506/* Public functions **********************************************************/ 441 return a * (24*24*24) + b;
442}
507 443
508void 444static uint64_t
509gen_coord(Coordinate *coord) 445move_cpud_separate(Move m, uint64_t ind)
510{ 446{
511 int i; 447 return cpud_separate_ind[cp_mtable[m][cpud_separate_ant[ind]]];
448}
512 449
513 if (coord == NULL || coord->generated) 450/* Init functions implementation *********************************************/
514 return;
515 451
516 for (i = 0; i < 2; i++) 452/*
517 gen_coord(coord->base[i]); 453 * There is certainly a better way to do this, but for now I just use
454 * a "graph coloring" algorithm to compute the left cosets, and I compose
455 * with every possible cp to get the right cosets (it is possible that I am
456 * mixing up left and right).
457 *
458 * For doing it better "Mathematically", we need 3 things:
459 * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other
460 * This is easy and it is done in the commented function cphtr_cp().
461 * - Check that there is no ep/cp parity
462 * - Check that we are not in the "3c" case; this is the part I don't
463 * know how to do.
464 */
465static void
466init_cphtr_cosets()
467{
468 unsigned int i;
469 int c = 0, d = 0;
518 470
519 switch (coord->type) { 471 for (i = 0; i < FACTORIAL8; i++) {
520 case COMP_COORD: 472 cphtr_left_cosets[i] = -1;
521 if (coord->i[0] == NULL) 473 cphtr_right_cosets[i] = -1;
522 goto error_gc;
523 gen_coord_comp(coord);
524 break;
525 case SYM_COORD:
526 if (coord->base[0] == NULL || coord->tgrp == NULL)
527 goto error_gc;
528 gen_coord_sym(coord);
529 break;
530 case SYMCOMP_COORD:
531 if (coord->base[0] == NULL || coord->base[1] == NULL)
532 goto error_gc;
533 coord->max = coord->base[0]->max * coord->base[1]->max;
534 break;
535 default:
536 break;
537 } 474 }
538 475
539 coord->generated = true; 476 /* First we compute left cosets with a bfs */
540 return; 477 for (i = 0; i < FACTORIAL8; i++)
478 if (cphtr_left_cosets[i] == -1)
479 init_cphtr_left_cosets_bfs(i, c++);
541 480
542error_gc: 481 /* Then we compute right cosets using compose() */
543 fprintf(stderr, "Error generating coordinates.\n" 482 for (i = 0; i < FACTORIAL8; i++)
544 "This is a bug, pleae report.\n"); 483 if (cphtr_right_cosets[i] == -1)
545 exit(1); 484 init_cphtr_right_cosets_color(i, d++);
546} 485}
547 486
548uint64_t 487static void
549index_coord(Coordinate *coord, Cube *cube, Trans *offtrans) 488init_cphtr_left_cosets_bfs(int i, int c)
550{ 489{
551 uint64_t c[2], cnosym; 490 int j, jj, next[FACTORIAL8], next2[FACTORIAL8], n, n2;
552 Trans ttr;
553
554 switch (coord->type) {
555 case COMP_COORD:
556 if (offtrans != NULL)
557 *offtrans = uf;
558 491
559 return indexers_getind(coord->i, cube); 492 Move k;
560 case SYM_COORD:
561 cnosym = index_coord(coord->base[0], cube, NULL);
562 ttr = coord->transtorep[cnosym];
563 493
564 if (offtrans != NULL) 494 n = 1;
565 *offtrans = ttr; 495 next[0] = i;
496 cphtr_left_cosets[i] = c;
566 497
567 return coord->symclass[cnosym]; 498 while (n != 0) {
568 case SYMCOMP_COORD: 499 for (j = 0, n2 = 0; j < n; j++) {
569 c[0] = index_coord(coord->base[0], cube, NULL); 500 for (k = U2; k < B3; k++) {
570 cnosym = index_coord(coord->base[0]->base[0], cube, NULL); 501 if (!moveset_htr.allowed(k))
571 ttr = coord->base[0]->transtorep[cnosym]; 502 continue;
572 c[1] = index_coord(coord->base[1], cube, NULL); 503 jj = apply_move(k, (Cube){ .cp = next[j] }).cp;
573 c[1] = trans_coord(coord->base[1], ttr, c[1]);
574 504
575 if (offtrans != NULL) 505 if (cphtr_left_cosets[jj] == -1) {
576 *offtrans = ttr; 506 cphtr_left_cosets[jj] = c;
507 next2[n2++] = jj;
508 }
509 }
510 }
577 511
578 return c[0] * coord->base[1]->max + c[1]; 512 for (j = 0; j < n2; j++)
579 default: 513 next[j] = next2[j];
580 break; 514 n = n2;
581 } 515 }
582
583 return coord->max; /* Only reached in case of error */
584} 516}
585 517
586uint64_t 518static void
587move_coord(Coordinate *coord, Move m, uint64_t ind, Trans *offtrans) 519init_cphtr_right_cosets_color(int i, int d)
588{ 520{
589 uint64_t i[2], M; 521 int cp;
590 Trans ttr; 522 unsigned int j;
591 523
592 /* Some safety checks should be done here, but for performance * 524 cphtr_right_rep[d] = i;
593 * reasons we'd rather do them before calling this function. * 525 for (j = 0; j < FACTORIAL8; j++) {
594 * We should check if coord is generated. */ 526 if (cphtr_left_cosets[j] == 0) {
595 527 cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp;
596 switch (coord->type) { 528 cphtr_right_cosets[cp] = d;
597 case COMP_COORD: 529 }
598 if (offtrans != NULL) 530 }
599 *offtrans = uf; 531}
600 532
601 return coord->mtable[m][ind]; 533static void
602 case SYM_COORD: 534init_cpud_separate()
603 ttr = coord->ttrep_move[m][ind]; 535{
536 unsigned int ui;
537 int i, co[8];
604 538
605 if (offtrans != NULL) 539 for (ui = 0; ui < FACTORIAL8; ui++) {
606 *offtrans = ttr; 540 for (i = 0; i < 8; i++)
541 co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ? 1 : 0;
542 cpud_separate_ind[ui] = subset_to_index(co, 8, 4);
543 cpud_separate_ant[cpud_separate_ind[ui]] = ui;
544 }
545}
607 546
608 return coord->mtable[m][ind]; 547static void
609 case SYMCOMP_COORD: 548init_cornershtrfin()
610 M = coord->base[1]->max; 549{
611 i[0] = ind / M; 550 unsigned int i, j;
612 i[1] = ind % M; 551 int n, c;
613 ttr = coord->base[0]->ttrep_move[m][i[0]]; 552 Move m;
614 i[0] = coord->base[0]->mtable[m][i[0]];
615 i[1] = coord->base[1]->mtable[m][i[1]];
616 i[1] = coord->base[1]->ttable[ttr][i[1]];
617 553
618 if (offtrans != NULL) 554 for (i = 0; i < FACTORIAL8; i++)
619 *offtrans = ttr; 555 cornershtrfin_ind[i] = -1;
556 cornershtrfin_ind[0] = 0;
620 557
621 return i[0] * M + i[1]; 558 /* 10-pass, I think 5 is enough, but just in case */
622 default: 559 n = 1;
623 break; 560 for (i = 0; i < 10; i++) {
561 for (j = 0; j < FACTORIAL8; j++) {
562 if (cornershtrfin_ind[j] == -1)
563 continue;
564 for (m = U; m < NMOVES; m++) {
565 if (moveset_htr.allowed(m)) {
566 c = cp_mtable[m][j];
567 if (cornershtrfin_ind[c] == -1) {
568 cornershtrfin_ind[c] = n;
569 cornershtrfin_ant[n] = c;
570 n++;
571 }
572 }
573 }
574 }
624 } 575 }
625
626 return coord->max; /* Only reached in case of error */
627} 576}
628 577
629uint64_t 578void
630trans_coord(Coordinate *coord, Trans t, uint64_t ind) 579init_htr_eposs()
631{ 580{
632 uint64_t i[2], M; 581 int ep[12], ep2[12];
582 int eps_solved[4] = {UL, UR, DL, DR};
583 unsigned int i, j;
633 584
634 /* Some safety checks should be done here, but for performance * 585 for (i = 0; i < BINOM12ON4; i++) {
635 * reasons we'd rather do them before calling this function. * 586 for (j = 0; j < 12; j++)
636 * We should check if coord is generated. */ 587 ep[j] = ep2[j] = 0;
637 588 epos_to_partial_ep(i*24, ep, eps_solved);
638 switch (coord->type) { 589 for (j = 0; j < 8; j++)
639 case COMP_COORD: 590 ep2[j/2 + 4*(j%2)] = ep[j] ? 1 : 0;
640 return coord->ttable[t][ind]; 591 htr_eposs_ind[i] = subset_to_index(ep2, 8, 4);
641 case SYM_COORD: 592 htr_eposs_ant[htr_eposs_ind[i]] = i*24;
642 return ind;
643 case SYMCOMP_COORD:
644 M = coord->base[1]->max;
645 i[0] = ind / M; /* Always fixed */
646 i[1] = ind % M;
647 i[1] = coord->base[1]->ttable[t][i[1]];
648 return i[0] * M + i[1];
649 default:
650 break;
651 } 593 }
594}
595
596void
597init_coord()
598{
599 static bool initialized = false;
600 if (initialized)
601 return;
602 initialized = true;
652 603
653 return coord->max; /* Only reached in case of error */ 604 init_trans();
605
606 init_cphtr_cosets();
607 init_cornershtrfin();
608 init_htr_eposs();
609 init_cpud_separate();
654} 610}
611

Generated with cgit - Back to sebastiano.tronto.net