gendata.h (6603B)
1 STATIC size_t gendata_coord(const coord_t [static 1], unsigned char *); 2 STATIC long long gendata_coord_dispatch(const char *, unsigned long long, 3 unsigned char *); 4 STATIC tableinfo_t genptable_coord( 5 const coord_t [static 1], const unsigned char *, unsigned char *); 6 STATIC bool switch_to_fromnew(uint64_t, uint64_t, uint64_t); 7 STATIC uint64_t genptable_coord_fillneighbors(const coord_t [static 1], 8 const unsigned char *, uint64_t, uint8_t, unsigned char *); 9 STATIC uint64_t genptable_coord_fillfromnew(const coord_t [static 1], 10 const unsigned char *, uint64_t, uint8_t, unsigned char *); 11 STATIC uint8_t get_coord_pval( 12 const coord_t [static 1], const unsigned char *, uint64_t); 13 STATIC void set_coord_pval( 14 const coord_t [static 1], unsigned char *, uint64_t, uint8_t); 15 16 STATIC long long 17 gendata_coord_dispatch( 18 const char *coordstr, 19 unsigned long long bufsize, 20 unsigned char *buf 21 ) 22 { 23 coord_t *coord; 24 25 parse_coord_and_axis(coordstr, &coord, NULL); 26 27 if (coord == NULL) { 28 LOG("Error: could not parse coordinate '%s'\n", coordstr); 29 return NISSY_ERROR_INVALID_SOLVER; 30 } 31 32 return (int64_t)gendata_coord(coord, buf); 33 } 34 35 STATIC size_t 36 gendata_coord(const coord_t coord[static 1], unsigned char *buf) 37 { 38 uint64_t coord_dsize, tablesize, ninfo; 39 unsigned char *pruningbuf, *coord_data; 40 unsigned char *table; 41 tableinfo_t coord_data_info, pruning_info; 42 43 coord_data = buf == NULL ? NULL : buf + INFOSIZE; 44 coord_dsize = coord->gendata(coord_data); 45 if (coord_dsize == SIZE_MAX) 46 goto gendata_coord_error; 47 48 ninfo = coord_dsize == 0 ? 1 : 2; 49 tablesize = DIV_ROUND_UP(coord->max, 2); 50 51 if (buf == NULL) 52 goto gendata_coord_return_size; 53 54 if (ninfo == 2) { 55 coord_data_info = (tableinfo_t) { 56 .solver = "coord helper table for ", 57 .type = TABLETYPE_SPECIAL, 58 .infosize = INFOSIZE, 59 .fullsize = INFOSIZE + coord_dsize, 60 .hash = 0, /* TODO */ 61 .next = INFOSIZE + coord_dsize, 62 63 /* Unknown / non-applicable values */ 64 .entries = 0, 65 .classes = 0, 66 .bits = 0, 67 .base = 0, 68 .maxvalue = 0, 69 }; 70 71 append_coord_name(coord, coord_data_info.solver); 72 73 writetableinfo(&coord_data_info, INFOSIZE + coord_dsize, buf); 74 75 pruningbuf = buf + INFOSIZE + coord_dsize; 76 } else { 77 pruningbuf = buf; 78 } 79 80 table = pruningbuf + INFOSIZE; 81 pruning_info = genptable_coord(coord, coord_data, table); 82 writetableinfo(&pruning_info, INFOSIZE + tablesize, pruningbuf); 83 84 gendata_coord_return_size: 85 return ninfo * INFOSIZE + coord_dsize + tablesize; 86 87 gendata_coord_error: 88 LOG("Unexpected error generating coordinate data\n"); 89 return 0; 90 } 91 92 STATIC tableinfo_t 93 genptable_coord( 94 const coord_t coord[static 1], 95 const unsigned char *data, 96 unsigned char *table 97 ) 98 { 99 uint64_t tablesize, i, d, tot, t, nm; 100 tableinfo_t info; 101 102 tablesize = DIV_ROUND_UP(coord->max, 2); 103 104 memset(table, 0xFF, tablesize); 105 106 info = (tableinfo_t) { 107 .solver = "coordinate solver for ", 108 .type = TABLETYPE_PRUNING, 109 .infosize = INFOSIZE, 110 .fullsize = INFOSIZE + tablesize, 111 .hash = 0, /* TODO */ 112 .entries = coord->max, 113 .classes = 0, 114 .bits = 4, 115 .base = 0, 116 .maxvalue = 0, 117 .next = 0 118 }; 119 120 memset(info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); 121 append_coord_name(coord, info.solver); 122 123 nm = popcount_u32(coord->moves_mask); 124 i = coord->coord(SOLVED_CUBE, data); 125 set_coord_pval(coord, table, i, 0); 126 info.distribution[0] = 1; 127 for (d = 1, tot = 1; tot < coord->max && d < 20; d++) { 128 t = 0; 129 if (switch_to_fromnew(tot, coord->max, nm)) { 130 for (i = 0; i < coord->max; i++) 131 if (get_coord_pval(coord, table, i) > d) 132 t += genptable_coord_fillfromnew( 133 coord, data, i, d, table); 134 } else { 135 for (i = 0; i < coord->max; i++) 136 if (get_coord_pval(coord, table, i) == d-1) 137 t += genptable_coord_fillneighbors( 138 coord, data, i, d, table); 139 } 140 tot += t; 141 info.distribution[d] = t; 142 LOG("[%s gendata] Depth %" PRIu64 ": found %" PRIu64 " (%" 143 PRIu64 " of %" PRIu64 ")\n", 144 coord->name, d, t, tot, coord->max); 145 } 146 info.maxvalue = d-1; 147 148 return info; 149 } 150 151 STATIC bool 152 switch_to_fromnew(uint64_t done, uint64_t max, uint64_t nm) 153 { 154 /* 155 Heuristic to determine if it is more conveniente to loop over 156 done coordinates and fill the new discovered, or to loop from new 157 coordinates and fill them if they have a done neighbor. 158 */ 159 160 double r = (double)done / (double)max; 161 return 1.0 - intpow(1.0-r, nm) > nm * (1.0-r); 162 } 163 164 STATIC uint64_t 165 genptable_coord_fillneighbors( 166 const coord_t coord[static 1], 167 const unsigned char *data, 168 uint64_t i, 169 uint8_t d, 170 unsigned char *table 171 ) 172 { 173 bool isnasty; 174 uint8_t m; 175 uint64_t ii, j, t, tot; 176 cube_t c, moved; 177 178 c = coord->cube(i, data); 179 tot = 0; 180 for (m = 0; m < NMOVES; m++) { 181 if (!((UINT32_C(1) << (uint32_t)m) & coord->moves_mask)) 182 continue; 183 moved = move(c, m); 184 ii = coord->coord(moved, data); 185 isnasty = coord->isnasty(ii, data); 186 for (t = 0; t < NTRANS && (t == 0 || isnasty); t++) { 187 if (!((UINT64_C(1) << t) & coord->trans_mask)) 188 continue; 189 190 j = coord->coord(transform(moved, t), data); 191 if (get_coord_pval(coord, table, j) > d) { 192 set_coord_pval(coord, table, j, d); 193 tot++; 194 } 195 } 196 } 197 198 return tot; 199 } 200 201 STATIC uint64_t 202 genptable_coord_fillfromnew( 203 const coord_t coord[static 1], 204 const unsigned char *data, 205 uint64_t i, 206 uint8_t d, 207 unsigned char *table 208 ) 209 { 210 bool found; 211 uint8_t m; 212 uint64_t tot, t, ii, j, nsim, sim[NTRANS]; 213 cube_t c; 214 215 tot = 0; 216 c = coord->cube(i, data); 217 218 for (t = 0, nsim = 0; t < NTRANS; t++) { 219 if (!((UINT64_C(1) << t) & coord->trans_mask)) 220 continue; 221 222 ii = coord->coord(transform(c, t), data); 223 for (j = 0, found = false; j < nsim && !found; j++) 224 found = sim[j] == ii; 225 if (!found) 226 sim[nsim++] = ii; 227 } 228 229 for (j = 0, found = false; j < nsim && !found; j++) { 230 c = coord->cube(sim[j], data); 231 for (m = 0; m < NMOVES; m++) { 232 if (!((UINT32_C(1) << (uint32_t)m) & coord->moves_mask)) 233 continue; 234 ii = coord->coord(move(c, m), data); 235 if (get_coord_pval(coord, table, ii) < d) { 236 found = true; 237 break; 238 } 239 } 240 } 241 242 tot = 0; 243 if (found) { 244 for (j = 0; j < nsim; j++) { 245 if (get_coord_pval(coord, table, sim[j]) > d) { 246 set_coord_pval(coord, table, sim[j], d); 247 tot++; 248 } 249 } 250 } 251 252 return tot; 253 } 254 255 STATIC uint8_t 256 get_coord_pval( 257 const coord_t coord[static 1], 258 const unsigned char *table, 259 uint64_t i 260 ) 261 { 262 return (table[COORD_INDEX(i)] & COORD_MASK(i)) >> COORD_SHIFT(i); 263 } 264 265 STATIC void 266 set_coord_pval( 267 const coord_t coord[static 1], 268 unsigned char *table, 269 uint64_t i, 270 uint8_t val 271 ) 272 { 273 table[COORD_INDEX(i)] = (table[COORD_INDEX(i)] & (~COORD_MASK(i))) 274 | (val << COORD_SHIFT(i)); 275 }