nissy-classic

Stable branch of nissy
git clone https://git.tronto.net/nissy-classic
Download | Log | Files | Refs | README | LICENSE

coord.c (13242B)


      1 #include "coord.h"
      2 
      3 static uint64_t    index_eofb(Cube cube);
      4 static uint64_t    index_eofbepos(Cube cube);
      5 static uint64_t    index_epud(Cube cube);
      6 static uint64_t    index_coud(Cube cube);
      7 static uint64_t    index_corners(Cube cube);
      8 static uint64_t    index_cp(Cube cube);
      9 static uint64_t    index_cphtr(Cube cube);
     10 static uint64_t    index_cornershtr(Cube cube);
     11 static uint64_t    index_cornershtrfin(Cube cube);
     12 static uint64_t    index_drud(Cube cube);
     13 static uint64_t    index_drud_eofb(Cube cube);
     14 static uint64_t    index_htr_drud(Cube cube);
     15 static uint64_t    index_htrfin(Cube cube);
     16 static uint64_t    index_cpud_separate(Cube cube);
     17 
     18 static uint64_t    move_eofb(Move m, uint64_t ind);
     19 static uint64_t    move_eofbepos(Move m, uint64_t ind);
     20 static uint64_t    move_epud(Move m, uint64_t ind);
     21 static uint64_t    move_coud(Move m, uint64_t ind);
     22 static uint64_t    move_corners(Move m, uint64_t ind);
     23 static uint64_t    move_cp(Move m, uint64_t ind);
     24 static uint64_t    move_cphtr(Move m, uint64_t ind);
     25 static uint64_t    move_cornershtr(Move m, uint64_t ind);
     26 static uint64_t    move_cornershtrfin(Move m, uint64_t ind);
     27 static uint64_t    move_drud(Move m, uint64_t ind);
     28 static uint64_t    move_drud_eofb(Move m, uint64_t ind);
     29 static uint64_t    move_htr_drud(Move m, uint64_t ind);
     30 static uint64_t    move_htrfin(Move m, uint64_t ind);
     31 static uint64_t    move_cpud_separate(Move m, uint64_t ind);
     32 
     33 static void        init_cphtr_cosets(void);
     34 static void        init_cphtr_left_cosets_bfs(int i, int c);
     35 static void        init_cphtr_right_cosets_color(int i, int c);
     36 static void        init_cpud_separate(void);
     37 static void        init_cornershtrfin(void);
     38 static void        init_htr_eposs(void);
     39 static void        init_move_epud(void);
     40 static void        init_move_cphtr(void);
     41 
     42 
     43 /* All sorts of useful costants and tables  **********************************/
     44 
     45 static int              cphtr_left_cosets[FACTORIAL8];
     46 static int              cphtr_right_cosets[FACTORIAL8];
     47 static int              cphtr_right_rep[BINOM8ON4*6];
     48 int                     cpud_separate_ind[FACTORIAL8];
     49 int                     cpud_separate_ant[BINOM8ON4];
     50 static int              cornershtrfin_ind[FACTORIAL8];
     51 int                     cornershtrfin_ant[24*24/6];
     52 static int              htr_eposs_ind[BINOM12ON4];
     53 static int              htr_eposs_ant[BINOM8ON4];
     54 static int              move_cphtr_aux[NMOVES][BINOM8ON4*6];
     55 static int              move_epud_aux[NMOVES][FACTORIAL8];
     56 
     57 /* Coordinates and their implementation **************************************/
     58 
     59 Coordinate
     60 coord_eofb = {
     61 	.index  = index_eofb,
     62 	.max    = POW2TO11,
     63 	.move   = move_eofb,
     64 };
     65 
     66 Coordinate
     67 coord_eofbepos = {
     68 	.index  = index_eofbepos,
     69 	.max    = POW2TO11 * BINOM12ON4,
     70 	.move   = move_eofbepos,
     71 };
     72 
     73 Coordinate
     74 coord_coud = {
     75 	.index  = index_coud,
     76 	.max    = POW3TO7,
     77 	.move   = move_coud,
     78 };
     79 
     80 Coordinate
     81 coord_corners = {
     82 	.index  = index_corners,
     83 	.max    = POW3TO7 * FACTORIAL8,
     84 	.move   = move_corners,
     85 };
     86 
     87 Coordinate
     88 coord_cp = {
     89 	.index  = index_cp,
     90 	.max    = FACTORIAL8,
     91 	.move   = move_cp,
     92 };
     93 
     94 Coordinate
     95 coord_cphtr = {
     96 	.index  = index_cphtr,
     97 	.max    = BINOM8ON4 * 6,
     98 	.move   = move_cphtr,
     99 };
    100 
    101 Coordinate
    102 coord_cornershtr = {
    103 	.index  = index_cornershtr,
    104 	.max    = POW3TO7 * BINOM8ON4 * 6,
    105 	.move   = move_cornershtr,
    106 };
    107 
    108 Coordinate
    109 coord_cornershtrfin = {
    110 	.index  = index_cornershtrfin,
    111 	.max    = 24*24/6,
    112 	.move   = move_cornershtrfin,
    113 };
    114 
    115 Coordinate
    116 coord_epud = {
    117 	.index  = index_epud,
    118 	.max    = FACTORIAL8,
    119 	.move   = move_epud,
    120 };
    121 
    122 Coordinate
    123 coord_drud = {
    124 	.index  = index_drud,
    125 	.max    = POW2TO11 * POW3TO7 * BINOM12ON4,
    126 	.move   = move_drud,
    127 };
    128 
    129 Coordinate
    130 coord_htr_drud = {
    131 	.index  = index_htr_drud,
    132 	.max    = BINOM8ON4 * 6 * BINOM8ON4,
    133 	.move   = move_htr_drud,
    134 };
    135 
    136 Coordinate
    137 coord_htrfin = {
    138 	.index  = index_htrfin,
    139 	.max    = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */
    140 	.move   = move_htrfin,
    141 };
    142 
    143 Coordinate
    144 coord_drud_eofb = {
    145 	.index  = index_drud_eofb,
    146 	.max    = POW3TO7 * BINOM12ON4,
    147 	.move   = move_drud_eofb,
    148 };
    149 
    150 Coordinate
    151 coord_cpud_separate = {
    152 	.index  = index_cpud_separate,
    153 	.max    = BINOM8ON4,
    154 	.move   = move_cpud_separate,
    155 };
    156 
    157 /* Indexers ******************************************************************/
    158 
    159 static uint64_t
    160 index_eofb(Cube cube)
    161 {
    162 	return cube.eofb;
    163 }
    164 
    165 static uint64_t
    166 index_eofbepos(Cube cube)
    167 {
    168 	return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb;
    169 }
    170 
    171 static uint64_t
    172 index_epud(Cube cube)
    173 {
    174 	uint64_t ret;
    175 	CubeArray *arr = new_cubearray(cube, pf_ep);
    176 
    177 	ret = perm_to_index(arr->ep, 8);
    178 	free_cubearray(arr, pf_ep);
    179 
    180 	return ret;
    181 }
    182 
    183 static uint64_t
    184 index_coud(Cube cube)
    185 {
    186 	return cube.coud;
    187 }
    188 
    189 static uint64_t
    190 index_corners(Cube cube)
    191 {
    192 	return cube.coud * FACTORIAL8 + cube.cp;
    193 }
    194 
    195 static uint64_t
    196 index_cp(Cube cube)
    197 {
    198 	return cube.cp;
    199 }
    200 
    201 static uint64_t
    202 index_cphtr(Cube cube)
    203 {
    204 	return cphtr_right_cosets[cube.cp];
    205 }
    206 
    207 static uint64_t
    208 index_cornershtr(Cube cube)
    209 {
    210 	return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube);
    211 }
    212 
    213 static uint64_t
    214 index_cornershtrfin(Cube cube)
    215 {
    216 	return cornershtrfin_ind[cube.cp];
    217 }
    218 
    219 static uint64_t
    220 index_drud(Cube cube)
    221 {
    222 	uint64_t a, b, c;
    223 
    224 	a = cube.eofb;
    225 	b = cube.coud;
    226 	c = cube.epose / FACTORIAL4;
    227 
    228 	b *= POW2TO11;
    229 	c *= POW2TO11 * POW3TO7;
    230 
    231 	return a + b + c;
    232 }
    233 
    234 static uint64_t
    235 index_drud_eofb(Cube cube)
    236 {
    237 	return index_drud(cube) / POW2TO11;
    238 }
    239 
    240 static uint64_t
    241 index_htr_drud(Cube cube)
    242 {
    243 	uint64_t a, b;
    244 
    245 	a = index_cphtr(cube);
    246 	b = htr_eposs_ind[cube.eposs/24];
    247 
    248 	return a * BINOM8ON4 + b;
    249 }
    250 
    251 static uint64_t
    252 index_htrfin(Cube cube)
    253 {
    254 	uint64_t epe, eps, epm, cp, ep;
    255 
    256 	epe = cube.epose % 24;
    257 	eps = cube.eposs % 24;
    258 	epm = cube.eposm % 24;
    259 	ep = (epe * 24 + eps) *24 + epm;
    260 	cp = index_cornershtrfin(cube);
    261 
    262 	return cp * 24 * 24 * 24 + ep;
    263 }
    264 
    265 static uint64_t
    266 index_cpud_separate(Cube cube)
    267 {
    268 	return cpud_separate_ind[cube.cp];
    269 }
    270 
    271 /* Coordinate movers *********************************************************/
    272 
    273 static uint64_t
    274 move_eofb(Move m, uint64_t ind)
    275 {
    276 	return eofb_mtable[m][ind];
    277 }
    278 
    279 static uint64_t
    280 move_eofbepos(Move m, uint64_t ind)
    281 {
    282 	uint64_t a, b;
    283 
    284 	a = epose_mtable[m][(ind / POW2TO11)*24];
    285 	b = eofb_mtable[m][ind % POW2TO11];
    286 
    287 	return (a/24) * POW2TO11 + b;
    288 }
    289 
    290 static uint64_t
    291 move_epud(Move m, uint64_t ind)
    292 {
    293 	static int shortlist[NMOVES] = {
    294 		[U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5,
    295 		[R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9
    296 	};
    297 
    298 	return move_epud_aux[shortlist[m]][ind];
    299 }
    300 
    301 static uint64_t
    302 move_coud(Move m, uint64_t ind)
    303 {
    304 	return coud_mtable[m][ind];
    305 }
    306 
    307 static uint64_t
    308 move_corners(Move m, uint64_t ind)
    309 {
    310 	uint64_t a, b;
    311 
    312 	a = coud_mtable[m][ind / FACTORIAL8];
    313 	b = cp_mtable[m][ind % FACTORIAL8];
    314 
    315 	return a * FACTORIAL8 + b;
    316 }
    317 
    318 static uint64_t
    319 move_cp(Move m, uint64_t ind)
    320 {
    321 	return cp_mtable[m][ind];
    322 }
    323 
    324 static uint64_t
    325 move_cphtr(Move m, uint64_t ind)
    326 {
    327 	return move_cphtr_aux[m][ind];
    328 }
    329 
    330 static uint64_t
    331 move_cornershtr(Move m, uint64_t ind)
    332 {
    333 	uint64_t a, b;
    334 
    335 	a = coud_mtable[m][ind/(BINOM8ON4 * 6)];
    336 	b = move_cphtr(m, ind % (BINOM8ON4 * 6));
    337 
    338 	return a * BINOM8ON4 * 6 + b;
    339 }
    340 
    341 static uint64_t
    342 move_cornershtrfin(Move m, uint64_t ind)
    343 {
    344 	int a;
    345 
    346 	a = cp_mtable[m][cornershtrfin_ant[ind]];
    347 
    348 	return cornershtrfin_ind[a];
    349 }
    350 
    351 static uint64_t
    352 move_drud(Move m, uint64_t ind)
    353 {
    354 	uint64_t a, b, c;
    355 
    356 	a = eofb_mtable[m][ind % POW2TO11];
    357 	b = coud_mtable[m][(ind / POW2TO11) % POW3TO7];
    358 	c = epose_mtable[m][ind / (POW2TO11 * POW3TO7)];
    359 
    360 	return a + (b + c * POW3TO7) * POW2TO11;
    361 }
    362 
    363 static uint64_t
    364 move_drud_eofb(Move m, uint64_t ind)
    365 {
    366 	uint64_t a, b;
    367 
    368 	a = coud_mtable[m][ind % POW3TO7];
    369 	b = epose_mtable[m][(ind / POW3TO7) * 24] / 24;
    370 
    371 	return a + b * POW3TO7;
    372 }
    373 
    374 static uint64_t
    375 move_htr_drud(Move m, uint64_t ind)
    376 {
    377 	uint64_t a, b;
    378 
    379 	a = move_cphtr(m, ind/BINOM8ON4);
    380 	b = eposs_mtable[m][htr_eposs_ant[ind%BINOM8ON4]];
    381 
    382 	return a*BINOM8ON4 + htr_eposs_ind[b/24];
    383 }
    384 
    385 static uint64_t
    386 move_htrfin(Move m, uint64_t ind)
    387 {
    388 	uint64_t a, b, bm, bs, be;
    389 
    390 	a = move_cornershtrfin(m, ind / (24*24*24));
    391 	bm = eposm_mtable[m][ind%24] % 24;
    392 	bs = eposs_mtable[m][(ind/24)%24] % 24;
    393 	be = epose_mtable[m][(ind/(24*24))%24] % 24;
    394 	b = (be * 24 + bs) * 24 + bm;
    395 
    396 	return a * (24*24*24) + b;
    397 }
    398 
    399 static uint64_t
    400 move_cpud_separate(Move m, uint64_t ind)
    401 {
    402 	return cpud_separate_ind[cp_mtable[m][cpud_separate_ant[ind]]];
    403 }
    404 
    405 /* Init functions implementation *********************************************/
    406 
    407 /*
    408  * There is certainly a better way to do this, but for now I just use
    409  * a "graph coloring" algorithm to compute the left cosets, and I compose
    410  * with every possible cp to get the right cosets (it is possible that I am
    411  * mixing up left and right).
    412  * 
    413  * For doing it better "Mathematically", we need 3 things:
    414  *   - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other
    415  *     This is easy and it is done in the commented function cphtr_cp().
    416  *   - Check that there is no ep/cp parity
    417  *   - Check that we are not in the "3c" case; this is the part I don't
    418  *     know how to do.
    419  */
    420 static void
    421 init_cphtr_cosets(void)
    422 {
    423 	unsigned int i; 
    424 	int c = 0, d = 0;
    425 
    426 	for (i = 0; i < FACTORIAL8; i++) {
    427 		cphtr_left_cosets[i]  = -1;
    428 		cphtr_right_cosets[i] = -1;
    429 	}
    430 
    431 	/* First we compute left cosets with a bfs */
    432 	for (i = 0; i < FACTORIAL8; i++)
    433 		if (cphtr_left_cosets[i] == -1)
    434 			init_cphtr_left_cosets_bfs(i, c++);
    435 
    436 	/* Then we compute right cosets using compose() */
    437 	for (i = 0; i < FACTORIAL8; i++)
    438 		if (cphtr_right_cosets[i] == -1)
    439 			init_cphtr_right_cosets_color(i, d++);
    440 }
    441 
    442 static void
    443 init_cphtr_left_cosets_bfs(int i, int c)
    444 {
    445 	int j, jj, next[FACTORIAL8], next2[FACTORIAL8], n, n2;
    446 
    447 	Move k;
    448 
    449 	n = 1;
    450 	next[0] = i;
    451 	cphtr_left_cosets[i] = c;
    452 
    453 	while (n != 0) {
    454 		for (j = 0, n2 = 0; j < n; j++) {
    455 			for (k = U2; k < B3; k++) {
    456 				if (!moveset_htr.allowed(k))
    457 					continue;
    458 				jj = apply_move(k, (Cube){ .cp = next[j] }).cp;
    459 
    460 				if (cphtr_left_cosets[jj] == -1) {
    461 					cphtr_left_cosets[jj] = c;
    462 					next2[n2++] = jj;
    463 				}
    464 			}
    465 		}
    466 
    467 		for (j = 0; j < n2; j++)
    468 			next[j] = next2[j];
    469 		n = n2;
    470 	}
    471 }
    472 
    473 static void
    474 init_cphtr_right_cosets_color(int i, int d)
    475 {
    476 	int cp;
    477 	unsigned int j;
    478 
    479 	cphtr_right_rep[d] = i;
    480 	for (j = 0; j < FACTORIAL8; j++) {
    481 		if (cphtr_left_cosets[j] == 0) {
    482 			cp = compose_filtered(
    483 			    (Cube){.cp = i}, (Cube){.cp = j}, pf_cp).cp;
    484 			cphtr_right_cosets[cp] = d;
    485 		}
    486 	}
    487 }
    488 
    489 static void
    490 init_cpud_separate(void)
    491 {
    492 	unsigned int ui;
    493 	int i, co[8];
    494 
    495 	for (ui = 0; ui < FACTORIAL8; ui++) {
    496 		for (i = 0; i < 8; i++)
    497 			co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ?  1 : 0;
    498 		cpud_separate_ind[ui] = subset_to_index(co, 8, 4);
    499 		cpud_separate_ant[cpud_separate_ind[ui]] = ui;
    500 	}
    501 }
    502 
    503 static void
    504 init_cornershtrfin(void)
    505 {
    506 	unsigned int i, j;
    507 	int n, c;
    508 	Move m;
    509 
    510 	for (i = 0; i < FACTORIAL8; i++)
    511 		cornershtrfin_ind[i] = -1;
    512 	cornershtrfin_ind[0] = 0;
    513 
    514 	/* 10-pass, I think 5 is enough, but just in case */
    515 	n = 1;
    516 	for (i = 0; i < 10; i++) {
    517 		for (j = 0; j < FACTORIAL8; j++) {
    518 			if (cornershtrfin_ind[j] == -1)
    519 				continue;
    520 			for (m = U; m < NMOVES; m++) {
    521 				if (moveset_htr.allowed(m)) {
    522 					c = cp_mtable[m][j];
    523 					if (cornershtrfin_ind[c] == -1) {
    524 						cornershtrfin_ind[c] = n;
    525 						cornershtrfin_ant[n] = c;
    526 						n++;
    527 					}
    528 				}
    529 			}
    530 		}
    531 	}
    532 }
    533 
    534 void
    535 init_htr_eposs(void)
    536 {
    537 	int ep[12], ep2[12];
    538 	int eps_solved[4] = {UL, UR, DL, DR};
    539 	unsigned int i, j;
    540 
    541 	/* NOTE: we loop over all possible positions of S-slice edges,    *
    542 	 * although some of them are not possible (because the E-slice    *
    543 	 * edges are already in the E-slice). Then we discard the invalid *
    544 	 * configurations by checking that the value returned by          *
    545 	 * subset_to_index() is acceptable.                               */
    546 	for (i = 0; i < BINOM12ON4; i++) {
    547 		for (j = 0; j < 12; j++)
    548 			ep[j] = ep2[j] = 0;
    549 		epos_to_partial_ep(i*24, ep, eps_solved);
    550 		for (j = 0; j < 8; j++)
    551 			ep2[j/2 + 4*(j%2)] = ep[j] ? 1 : 0;
    552 		htr_eposs_ind[i] = subset_to_index(ep2, 8, 4);
    553 		if (htr_eposs_ind[i] < (int)BINOM8ON4)
    554 			htr_eposs_ant[htr_eposs_ind[i]] = i*24;
    555 	}
    556 }
    557 
    558 static void
    559 init_move_epud(void)
    560 {
    561 	/* TODO: save to file? */
    562 	static int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 };
    563 	static int shortlist[NMOVES] = {
    564 		[U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5,
    565 		[R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9
    566 	};
    567 	uint64_t ui;
    568 	int j;
    569 	Move mj;
    570 	Cube c;
    571 	CubeArray *arr, *auxarr;
    572 
    573 	auxarr = malloc(sizeof(CubeArray));
    574 	auxarr->ep = a;
    575 	for (ui = 0; ui < coord_epud.max; ui++) {
    576 		index_to_perm(ui, 8, a);
    577 		c = arrays_to_cube(auxarr, pf_ep);
    578 		for (j = 0; moveset_drud.sorted_moves[j] != NULLMOVE;
    579 		    j++) {
    580 			mj = moveset_drud.sorted_moves[j];
    581 			arr = new_cubearray(apply_move(mj, c), pf_ep);
    582 			move_epud_aux[shortlist[mj]][ui] =
    583 			    perm_to_index(arr->ep, 8);
    584 			free_cubearray(arr, pf_ep);
    585 		}
    586 	}
    587 	free(auxarr);
    588 }
    589 
    590 static void
    591 init_move_cphtr(void)
    592 {
    593 	uint64_t ui;
    594 	Move j;
    595 
    596 	for (ui = 0; ui < BINOM8ON4*6; ui++)
    597 		for (j = U; j < NMOVES; j++)
    598 			move_cphtr_aux[j][ui] = cphtr_right_cosets[
    599 			    cp_mtable[j][cphtr_right_rep[ui]]];
    600 }
    601 
    602 
    603 void
    604 init_coord(void)
    605 {
    606 	static bool initialized = false;
    607 	if (initialized)
    608 		return;
    609 	initialized = true;
    610 
    611 	init_trans();
    612 
    613 	init_cphtr_cosets();
    614 	init_cornershtrfin();
    615 	init_htr_eposs();
    616 	init_cpud_separate();
    617 
    618 	init_move_epud();
    619 	init_move_cphtr();
    620 }
    621