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 (3835B)


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