nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

common.h (5093B)


      1 STATIC uint64_t coord_coord_generic(
      2     const coord_t [static 1], cube_t, const unsigned char *);
      3 STATIC cube_t coord_cube_generic(
      4     const coord_t [static 1], uint64_t, const unsigned char *);
      5 STATIC bool coord_isnasty_generic(
      6     const coord_t [static 1], uint64_t, const unsigned char *);
      7 STATIC size_t coord_gendata_generic(const coord_t [static 1], unsigned char *);
      8 
      9 STATIC bool solution_lastqt_cw(const solution_moves_t [static 1]);
     10 STATIC bool coord_can_switch(const coord_t [static 1], const unsigned char *,
     11     size_t, const uint8_t *);
     12 STATIC bool coord_is_solved(
     13     const coord_t [static 1], uint64_t, const unsigned char *);
     14 
     15 STATIC cube_t coordinate_merge_ce(cube_t, cube_t);
     16 STATIC cube_t coordinate_merge_ec(cube_t, cube_t);
     17 
     18 STATIC uint64_t
     19 coord_coord_generic(
     20 	const coord_t coord[static 1],
     21 	cube_t c,
     22 	const unsigned char *data
     23 )
     24 {
     25 	const uint32_t *data32;
     26 	uint32_t d;
     27 	cube_t tr;
     28 
     29 	data32 = (const uint32_t *)(data + INFOSIZE);
     30 	d = data32[coord->sym.coord(c)];
     31 	tr = transform(c, COORD_TTREP(d));
     32 
     33 	return COORD_CLASS(d) * coord->sym.max2 + coord->sym.coord2(tr);
     34 }
     35 
     36 STATIC cube_t
     37 coord_cube_generic(
     38 	const coord_t coord[static 1],
     39 	uint64_t i,
     40 	const unsigned char *data
     41 )
     42 {
     43 	const unsigned char *datanoinfo;
     44 	const uint32_t *rep32;
     45 	cube_t c;
     46 
     47 	datanoinfo = data + INFOSIZE;
     48 	rep32 = (const uint32_t *)(datanoinfo + 4 * (size_t)coord->sym.max);
     49 	c = coord->sym.cube(rep32[i / coord->sym.max2]);
     50 
     51 	return coord->sym.merge(c, coord->sym.cube2(i % coord->sym.max2));
     52 }
     53 
     54 STATIC bool
     55 coord_isnasty_generic(
     56 	const coord_t coord[static 1],
     57 	uint64_t i,
     58 	const unsigned char *data
     59 )
     60 {
     61 	const unsigned char *datanoinfo;
     62 	const uint32_t *classttrep, *rep32;
     63 	uint32_t r;
     64 
     65 	datanoinfo = data + INFOSIZE;
     66 	classttrep = (const uint32_t *)datanoinfo;
     67 	rep32 = (const uint32_t *)(datanoinfo + 4 * (size_t)coord->sym.max);
     68 	r = rep32[i / coord->sym.max2];
     69 
     70 	return COORD_ISNASTY(classttrep[r]);
     71 }
     72 
     73 STATIC size_t
     74 coord_gendata_generic(
     75 	const coord_t coord[static 1],
     76 	unsigned char *data
     77 )
     78 {
     79 	uint64_t i, j, n, t, nasty;
     80 	unsigned char *datanoinfo;
     81 	uint32_t *classttrep, *rep;
     82 	size_t coord_datasize;
     83 	cube_t c;
     84 	tableinfo_t info;
     85 
     86 	coord_datasize = INFOSIZE + 4*(coord->sym.classes + coord->sym.max);
     87 
     88 	if (data == NULL)
     89 		return coord_datasize;
     90 
     91 	datanoinfo = data + INFOSIZE;
     92 	classttrep = (uint32_t *)datanoinfo;
     93 	rep = classttrep + coord->sym.max;
     94 	memset(data, 0xFF, coord_datasize);
     95 
     96 	info = (tableinfo_t) {
     97 		.solver = "coord data for ",
     98 		.type = TABLETYPE_SPECIAL,
     99 		.infosize = INFOSIZE,
    100 		.fullsize = coord_datasize,
    101 		.hash = 0,
    102 		.entries = coord->sym.classes + coord->sym.max,
    103 		.classes = coord->sym.classes,
    104 		.bits = 32,
    105 		.base = 0,
    106 		.maxvalue = 0,
    107 		.next = 0
    108 	};
    109 	append_name(&info, coord->name);
    110 
    111 	for (i = 0, n = 0; i < coord->sym.max; i++) {
    112 		if (classttrep[i] != 0xFFFFFFFF)
    113 			continue;
    114 
    115 		c = coord->sym.cube(i);
    116 		for (t = 1, nasty = 0; t < NTRANS && !nasty; t++) {
    117 			if (!((UINT64_C(1) << t) & coord->trans_mask))
    118 				continue;
    119 
    120 			nasty = i == coord->sym.coord(transform(c, t));
    121 		}
    122 
    123 		for (t = 0; t < NTRANS; t++) {
    124 			if (!((UINT64_C(1) << t) & coord->trans_mask))
    125 				continue;
    126 
    127 			j = coord->sym.coord(transform(c, t));
    128 			classttrep[j] =
    129 			    (n << COORD_CLASS_SHIFT) |
    130 			    (nasty << COORD_ISNASTY_SHIFT) |
    131 			    (inverse_trans(t) << COORD_TTREP_SHIFT);
    132 		}
    133 		rep[n++] = i;
    134 	}
    135 
    136 	writetableinfo(&info, coord_datasize, data);
    137 
    138 	DBG_ASSERT(n == coord->sym.classes,
    139 	    "%s coordinate data: computed %" PRIu64 " classes, "
    140 	    "expected %" PRIu64 "\n", coord->name, n, coord->sym.classes);
    141 
    142 	return coord_datasize;
    143 }
    144 
    145 STATIC bool
    146 solution_lastqt_cw(const solution_moves_t s[static 1])
    147 {
    148 	return are_lastmoves_singlecw(s->nmoves, s->moves) &&
    149 	    are_lastmoves_singlecw(s->npremoves, s->premoves);
    150 }
    151 
    152 STATIC bool
    153 solution_always_valid(const solution_moves_t s[static 1])
    154 {
    155 	return true;
    156 }
    157 
    158 STATIC bool
    159 coord_can_switch(
    160 	const coord_t coord[static 1],
    161 	const unsigned char *data,
    162 	size_t n,
    163 	const uint8_t *moves
    164 )
    165 {
    166 	/*
    167 	This function checks that the last move (or two moves, if parallel)
    168 	have a non-trivial effect on the coordinate of the solved cube. This
    169 	works in general for all coordinates that have been used so far, but
    170 	in more general cases that have not been considered yet it may fail.
    171 	*/
    172 
    173 	uint64_t i;
    174 
    175 	DBG_ASSERT(n > 0, "Error: cannot check if coordinate solver "
    176 	    "can use NISS after 0 moves");
    177 
    178 	if (!coord->allow_niss)
    179 		return false;
    180 
    181 	i = coord->coord(move(SOLVED_CUBE, moves[n-1]), data);
    182 	if (i == 0)
    183 		return false;
    184 
    185 	if (n == 1 || !parallel(moves[n-1], moves[n-2]))
    186 		return true;
    187 
    188 	i = coord->coord(move(SOLVED_CUBE, moves[n-1]), data);
    189 	return i != 0;
    190 }
    191 
    192 STATIC bool
    193 coord_is_solved(
    194 	const coord_t coord[static 1],
    195 	uint64_t i,
    196 	const unsigned char *data
    197 )
    198 {
    199 	return coord->is_solved == NULL ? i == 0 : coord->is_solved(i, data);
    200 }
    201 
    202 STATIC cube_t
    203 coordinate_merge_ce(cube_t corners, cube_t edges)
    204 {
    205 	cube_t merged;
    206 
    207 	merged = corners;
    208 	copy_edges(&merged, edges);
    209 
    210 	return merged;
    211 }
    212 
    213 STATIC cube_t
    214 coordinate_merge_ec(cube_t edges, cube_t corners)
    215 {
    216 	return coordinate_merge_ce(corners, edges);
    217 }