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

gendata_cocsep.h (4188B)


      1 STATIC size_t gendata_cocsep(unsigned char *, uint64_t *, cube_t *);
      2 STATIC uint32_t gendata_cocsep_dfs(cocsep_dfs_arg_t [static 1]);
      3 STATIC void getdistribution_cocsep(
      4     const uint32_t [static COCSEP_TABLESIZE], uint64_t [static 21]);
      5 
      6 STATIC_INLINE bool gendata_cocsep_get_visited(
      7     const uint8_t [static COCSEP_VISITEDSIZE], int64_t);
      8 STATIC_INLINE void gendata_cocsep_set_visited(
      9     uint8_t [static COCSEP_VISITEDSIZE], int64_t);
     10 
     11 STATIC_INLINE int8_t get_h48_cdata(
     12     cube_t, const uint32_t [static COCSEP_TABLESIZE], uint32_t *);
     13 
     14 STATIC size_t
     15 gendata_cocsep(
     16 	unsigned char *buf,
     17 	uint64_t *selfsim,
     18 	cube_t *rep
     19 )
     20 {
     21 	uint32_t *buf32, cc;
     22 	uint16_t n;
     23 	uint8_t i, visited[COCSEP_VISITEDSIZE];
     24 	tableinfo_t info;
     25 	cocsep_dfs_arg_t arg;
     26 
     27 	if (buf == NULL)
     28 		goto gendata_cocsep_return_size;
     29 
     30 	memset(buf, 0xFF, COCSEP_FULLSIZE);
     31 	buf32 = (uint32_t *)(buf + INFOSIZE);
     32 	if (selfsim != NULL)
     33 		memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES);
     34 
     35 	info = (tableinfo_t) {
     36 		.solver = "cocsep data for h48",
     37 		.type = TABLETYPE_SPECIAL,
     38 		.infosize = INFOSIZE,
     39 		.fullsize = COCSEP_FULLSIZE,
     40 		.hash = 0, /* TODO */
     41 		.entries = COCSEP_TABLESIZE,
     42 		.classes = COCSEP_CLASSES,
     43 		.bits = 32,
     44 		.base = 0,
     45 		.maxvalue = 9,
     46 		.next = 0
     47 	};
     48 	arg = (cocsep_dfs_arg_t) {
     49 		.cube = SOLVED_CUBE,
     50 		.n = &n,
     51 		.buf32 = buf32,
     52 		.visited = visited,
     53 		.selfsim = selfsim,
     54 		.rep = rep
     55 	};
     56 	for (i = 0, n = 0, cc = 0; i < 10; i++) {
     57 		memset(visited, 0, COCSEP_VISITEDSIZE);
     58 		arg.depth = 0;
     59 		arg.maxdepth = i;
     60 		cc = gendata_cocsep_dfs(&arg);
     61 		info.distribution[i] = cc;
     62 	}
     63 
     64 	writetableinfo(&info, COCSEP_FULLSIZE, buf);
     65 
     66 	DBG_ASSERT(n == COCSEP_CLASSES, 0,
     67 	    "cocsep: computed %" PRIu16 " symmetry classes, "
     68 	    "expected %zu\n", n, COCSEP_CLASSES);
     69 
     70 	LOG("[H48 gendata] cocsep data computed\n");
     71 
     72 	/* The following output is just noise
     73 
     74 	LOG("Symmetry classes: %" PRIu32 "\n", COCSEP_CLASSES);
     75 	LOG("Pruning value distribution:\n");
     76 	for (j = 0; j < 10; j++)
     77 		LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info.distribution[j]);
     78 	*/
     79 
     80 gendata_cocsep_return_size:
     81 	return COCSEP_FULLSIZE;
     82 }
     83 
     84 STATIC uint32_t
     85 gendata_cocsep_dfs(cocsep_dfs_arg_t arg[static 1])
     86 {
     87 	uint8_t m;
     88 	uint32_t cc, class, ttrep, depth, olddepth, tinv;
     89 	uint64_t t;
     90 	int64_t i, j;
     91 	cube_t d;
     92 	cocsep_dfs_arg_t nextarg;
     93 
     94 	i = coord_cocsep(arg->cube);
     95 	olddepth = (uint8_t)(arg->buf32[i] & 0xFF);
     96 	if (olddepth < arg->depth ||
     97 	    gendata_cocsep_get_visited(arg->visited, i))
     98 		return 0;
     99 	gendata_cocsep_set_visited(arg->visited, i);
    100 
    101 	if (arg->depth == arg->maxdepth) {
    102 		if ((arg->buf32[i] & 0xFF) != 0xFF)
    103 			return 0;
    104 
    105 		if (arg->rep != NULL)
    106 			arg->rep[*arg->n] = arg->cube;
    107 		for (t = 0, cc = 0; t < NTRANS; t++) {
    108 			d = transform_corners(arg->cube, t);
    109 			j = coord_cocsep(d);
    110 			if (i == j && arg->selfsim != NULL)
    111 				arg->selfsim[*arg->n] |= UINT64_C(1) << t;
    112 			if (COCLASS(arg->buf32[j]) != UINT32_C(0xFFFF))
    113 				continue;
    114 			gendata_cocsep_set_visited(arg->visited, j);
    115 			tinv = inverse_trans(t);
    116 			olddepth = arg->buf32[j] & 0xFF;
    117 			cc += olddepth == 0xFF;
    118 
    119 			class = (uint32_t)(*arg->n) << UINT32_C(16);
    120 			ttrep = (uint32_t)tinv << UINT32_C(8);
    121 			depth = (uint32_t)arg->depth;
    122 			arg->buf32[j] = class | ttrep | depth;
    123 		}
    124 		(*arg->n)++;
    125 
    126 		return cc;
    127 	}
    128 
    129 	nextarg = *arg;
    130 	nextarg.depth++;
    131 	for (m = 0, cc = 0; m < 18; m++) {
    132 		nextarg.cube = move(arg->cube, m);
    133 		cc += gendata_cocsep_dfs(&nextarg);
    134 	}
    135 
    136 	return cc;
    137 }
    138 
    139 STATIC void
    140 getdistribution_cocsep(
    141     const uint32_t table[static COCSEP_TABLESIZE],
    142     uint64_t distr[static 21]
    143 )
    144 {
    145 	size_t i;
    146 
    147 	memset(distr, 0, 21 * sizeof(uint64_t));
    148 
    149 	for (i = 0; i < COCSEP_TABLESIZE; i++)
    150 		distr[CBOUND(table[i])]++;
    151 }
    152 
    153 STATIC_INLINE bool
    154 gendata_cocsep_get_visited(
    155 	const uint8_t a[static COCSEP_VISITEDSIZE],
    156 	int64_t i
    157 )
    158 {
    159 	return a[VISITED_IND(i)] & VISITED_MASK(i);
    160 }
    161 
    162 STATIC_INLINE void
    163 gendata_cocsep_set_visited(
    164 	uint8_t a[static COCSEP_VISITEDSIZE],
    165 	int64_t i
    166 )
    167 {
    168 	a[VISITED_IND(i)] |= VISITED_MASK(i);
    169 }
    170 
    171 STATIC_INLINE int8_t
    172 get_h48_cdata(
    173 	cube_t cube,
    174 	const uint32_t cocsepdata[static COCSEP_TABLESIZE],
    175 	uint32_t *cdata
    176 )
    177 {
    178 	int64_t coord;
    179 
    180 	coord = coord_cocsep(cube);
    181 	*cdata = cocsepdata[coord];
    182 
    183 	return CBOUND(*cdata);
    184 }