diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-08-25 10:27:21 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-08-25 10:27:21 +0200 |
| commit | dd44adceed44bec3dc313b77ec6f69123dc59016 (patch) | |
| tree | bef73833770b191e113f90c4aa3d6b1683b35ba2 /src/solvers/h48/gendata_cocsep.h | |
| parent | 9c5bdcb09dc56104f7ea34c71a9418c7908ed227 (diff) | |
| download | nissy-core-dd44adceed44bec3dc313b77ec6f69123dc59016.tar.gz nissy-core-dd44adceed44bec3dc313b77ec6f69123dc59016.zip | |
Started work on k=2 tables; further split h48 gendata
Diffstat (limited to 'src/solvers/h48/gendata_cocsep.h')
| -rw-r--r-- | src/solvers/h48/gendata_cocsep.h | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/solvers/h48/gendata_cocsep.h b/src/solvers/h48/gendata_cocsep.h new file mode 100644 index 0000000..13ce68b --- /dev/null +++ b/src/solvers/h48/gendata_cocsep.h | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | #define COCSEP_CLASSES ((size_t)3393) | ||
| 2 | #define COCSEP_TABLESIZE ((size_t)_3p7 << (size_t)7) | ||
| 3 | #define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + (size_t)7) / (size_t)8) | ||
| 4 | #define COCSEP_FULLSIZE ((size_t)4 * (COCSEP_TABLESIZE + (size_t)12)) | ||
| 5 | |||
| 6 | #define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8)) | ||
| 7 | #define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) | ||
| 8 | |||
| 9 | #define CBOUND_MASK UINT32_C(0xFF) | ||
| 10 | #define CBOUND(x) ((x) & CBOUND_MASK) | ||
| 11 | |||
| 12 | typedef struct { | ||
| 13 | cube_t cube; | ||
| 14 | uint8_t depth; | ||
| 15 | uint8_t maxdepth; | ||
| 16 | uint16_t *n; | ||
| 17 | uint32_t *buf32; | ||
| 18 | uint8_t *visited; | ||
| 19 | uint64_t *selfsim; | ||
| 20 | cube_t *rep; | ||
| 21 | } dfsarg_cocsep_t; | ||
| 22 | |||
| 23 | _static_inline bool get_visited(const uint8_t *, int64_t); | ||
| 24 | _static_inline void set_visited(uint8_t *, int64_t); | ||
| 25 | |||
| 26 | _static size_t gendata_cocsep(void *, uint64_t *, cube_t *); | ||
| 27 | _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); | ||
| 28 | |||
| 29 | _static_inline int8_t get_h48_cdata(cube_t, uint32_t *, uint32_t *); | ||
| 30 | |||
| 31 | /* | ||
| 32 | Each element of the cocsep table is a uint32_t used as follows: | ||
| 33 | - Lowest 8-bit block: pruning value | ||
| 34 | - Second-lowest 8-bit block: "ttrep" (transformation to representative) | ||
| 35 | - Top 16-bit block: symcoord value | ||
| 36 | After the data as described above, more auxiliary information is appended: | ||
| 37 | - A uint32_t representing the number of symmetry classes | ||
| 38 | - A uint32_t representing the highest value of the pruning table | ||
| 39 | - One uint32_t for each "line" of the pruning table, representing the number | ||
| 40 | of positions having that pruning value. | ||
| 41 | */ | ||
| 42 | _static size_t | ||
| 43 | gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) | ||
| 44 | { | ||
| 45 | uint32_t *buf32, *info, cc; | ||
| 46 | uint16_t n; | ||
| 47 | uint8_t i, j, visited[COCSEP_VISITEDSIZE]; | ||
| 48 | dfsarg_cocsep_t arg; | ||
| 49 | |||
| 50 | if (buf == NULL) | ||
| 51 | goto gendata_cocsep_return_size; | ||
| 52 | |||
| 53 | buf32 = (uint32_t *)buf; | ||
| 54 | info = buf32 + COCSEP_TABLESIZE; | ||
| 55 | memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); | ||
| 56 | if (selfsim != NULL) | ||
| 57 | memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); | ||
| 58 | |||
| 59 | arg = (dfsarg_cocsep_t) { | ||
| 60 | .cube = solved, | ||
| 61 | .n = &n, | ||
| 62 | .buf32 = buf32, | ||
| 63 | .visited = visited, | ||
| 64 | .selfsim = selfsim, | ||
| 65 | .rep = rep | ||
| 66 | }; | ||
| 67 | for (i = 0, n = 0, cc = 0; i < 10; i++) { | ||
| 68 | LOG("cocsep: generating depth %" PRIu8 "\n", i); | ||
| 69 | memset(visited, 0, COCSEP_VISITEDSIZE); | ||
| 70 | arg.depth = 0; | ||
| 71 | arg.maxdepth = i; | ||
| 72 | cc = gendata_cocsep_dfs(&arg); | ||
| 73 | info[i+2] = cc; | ||
| 74 | LOG("found %" PRIu32 "\n", cc); | ||
| 75 | } | ||
| 76 | |||
| 77 | info[0] = (uint32_t)n; | ||
| 78 | info[1] = 9; /* Known max pruning value */ | ||
| 79 | DBG_ASSERT(n == COCSEP_CLASSES, 0, | ||
| 80 | "cocsep: computed %" PRIu16 " symmetry classes, " | ||
| 81 | "expected %zu\n", n, COCSEP_CLASSES); | ||
| 82 | |||
| 83 | LOG("cocsep data computed\n"); | ||
| 84 | LOG("Symmetry classes: %" PRIu32 "\n", info[0]); | ||
| 85 | LOG("Maximum pruning value: %" PRIu32 "\n", info[1]); | ||
| 86 | LOG("Pruning value distribution:\n"); | ||
| 87 | for (j = 0; j < 10; j++) | ||
| 88 | LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+2]); | ||
| 89 | |||
| 90 | gendata_cocsep_return_size: | ||
| 91 | return COCSEP_FULLSIZE; | ||
| 92 | } | ||
| 93 | |||
| 94 | _static uint32_t | ||
| 95 | gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | ||
| 96 | { | ||
| 97 | uint8_t m; | ||
| 98 | uint32_t cc, class, ttrep, depth, olddepth, tinv; | ||
| 99 | uint64_t t; | ||
| 100 | int64_t i, j; | ||
| 101 | cube_t d; | ||
| 102 | dfsarg_cocsep_t nextarg; | ||
| 103 | |||
| 104 | i = coord_cocsep(arg->cube); | ||
| 105 | olddepth = (uint8_t)(arg->buf32[i] & 0xFF); | ||
| 106 | if (olddepth < arg->depth || get_visited(arg->visited, i)) | ||
| 107 | return 0; | ||
| 108 | set_visited(arg->visited, i); | ||
| 109 | |||
| 110 | if (arg->depth == arg->maxdepth) { | ||
| 111 | if ((arg->buf32[i] & 0xFF) != 0xFF) | ||
| 112 | return 0; | ||
| 113 | |||
| 114 | if (arg->rep != NULL) | ||
| 115 | arg->rep[*arg->n] = arg->cube; | ||
| 116 | for (t = 0, cc = 0; t < 48; t++) { | ||
| 117 | d = transform_corners(arg->cube, t); | ||
| 118 | j = coord_cocsep(d); | ||
| 119 | if (i == j && arg->selfsim != NULL) | ||
| 120 | arg->selfsim[*arg->n] |= UINT64_C(1) << t; | ||
| 121 | if (COCLASS(arg->buf32[j]) != UINT32_C(0xFFFF)) | ||
| 122 | continue; | ||
| 123 | set_visited(arg->visited, j); | ||
| 124 | tinv = inverse_trans(t); | ||
| 125 | olddepth = arg->buf32[j] & 0xFF; | ||
| 126 | cc += olddepth == 0xFF; | ||
| 127 | |||
| 128 | class = (uint32_t)(*arg->n) << UINT32_C(16); | ||
| 129 | ttrep = (uint32_t)tinv << UINT32_C(8); | ||
| 130 | depth = (uint32_t)arg->depth; | ||
| 131 | arg->buf32[j] = class | ttrep | depth; | ||
| 132 | } | ||
| 133 | (*arg->n)++; | ||
| 134 | |||
| 135 | return cc; | ||
| 136 | } | ||
| 137 | |||
| 138 | memcpy(&nextarg, arg, sizeof(dfsarg_cocsep_t)); | ||
| 139 | nextarg.depth++; | ||
| 140 | for (m = 0, cc = 0; m < 18; m++) { | ||
| 141 | nextarg.cube = move(arg->cube, m); | ||
| 142 | cc += gendata_cocsep_dfs(&nextarg); | ||
| 143 | } | ||
| 144 | |||
| 145 | return cc; | ||
| 146 | } | ||
| 147 | |||
| 148 | _static_inline bool | ||
| 149 | get_visited(const uint8_t *a, int64_t i) | ||
| 150 | { | ||
| 151 | return a[VISITED_IND(i)] & VISITED_MASK(i); | ||
| 152 | } | ||
| 153 | |||
| 154 | _static_inline void | ||
| 155 | set_visited(uint8_t *a, int64_t i) | ||
| 156 | { | ||
| 157 | a[VISITED_IND(i)] |= VISITED_MASK(i); | ||
| 158 | } | ||
| 159 | |||
| 160 | _static_inline int8_t | ||
| 161 | get_h48_cdata(cube_t cube, uint32_t *cocsepdata, uint32_t *cdata) | ||
| 162 | { | ||
| 163 | int64_t coord; | ||
| 164 | |||
| 165 | coord = coord_cocsep(cube); | ||
| 166 | *cdata = cocsepdata[coord]; | ||
| 167 | |||
| 168 | return CBOUND(*cdata); | ||
| 169 | } | ||
