h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit 70d3a3de3a2fdef7e47b2bd510261d69390a3a9c
parent 1f4900a3cc6ca74f94b73e224d14a09d52c4549c
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Tue, 10 Sep 2024 19:43:05 +0200

New tableinfo for gendata_h48, still work to do

Diffstat:
Msrc/solvers/h48/gendata_cocsep.h | 36++++++++++++++++++++++++------------
Msrc/solvers/h48/gendata_h48.h | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/solvers/tables.h | 16+++++++++++-----
Mtest/090_tables_readwrite/00_table.in | 1+
Mtest/090_tables_readwrite/00_table.out | 1+
Mtest/090_tables_readwrite/tables_readwrite_tests.c | 5++++-
Mtest/100_gendata_cocsep/00_all.out | 2+-
Mtest/100_gendata_cocsep/gendata_cocsep_tests.c | 35++++++++++++++++++++++++++++++-----
Mtest/101_cocsep_transform_invariant/cocsep_transform_invariant.c | 9++++++---
Mtest/102_cocsep_selfsim/cocsep_selfsim_tests.c | 7+++++--
Mtest/103_cocsep_selfsim_distribution/cocsep_selfsim_distribution_tests.c | 2+-
Mtest/104_cocsep_ttrep/cocsep_ttrep_tests.c | 10+++++++---
Mtest/110_coord_invcoord_h48/coord_invcoord_h48_tests.c | 7+++++--
Dtest/112_gen_h48short/gen_h48short.c | 87-------------------------------------------------------------------------------
Atest/112_gen_h48short/gen_h48short_tests.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/120_gendata_h48h0k4/00_h_0.out | 2+-
Mtest/120_gendata_h48h0k4/gendata_h48h0k4_tests.c | 60++++++++++++++++++++++++++++++++++++++++++++++++------------
17 files changed, 325 insertions(+), 174 deletions(-)

diff --git a/src/solvers/h48/gendata_cocsep.h b/src/solvers/h48/gendata_cocsep.h @@ -1,7 +1,7 @@ #define COCSEP_CLASSES ((size_t)3393) #define COCSEP_TABLESIZE ((size_t)POW_3_7 << (size_t)7) -#define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + (size_t)7) / (size_t)8) -#define COCSEP_FULLSIZE ((size_t)4 * (COCSEP_TABLESIZE + (size_t)12)) +#define COCSEP_VISITEDSIZE DIV_ROUND_UP(COCSEP_TABLESIZE, (size_t)8) +#define COCSEP_FULLSIZE (INFOSIZE + (size_t)4 * COCSEP_TABLESIZE) #define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8)) #define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) @@ -42,20 +42,33 @@ After the data as described above, more auxiliary information is appended: STATIC size_t gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) { - uint32_t *buf32, *info, cc; + uint32_t *buf32, cc; uint16_t n; uint8_t i, j, visited[COCSEP_VISITEDSIZE]; + tableinfo_t info; cocsep_dfs_arg_t arg; if (buf == NULL) goto gendata_cocsep_return_size; - buf32 = (uint32_t *)buf; - info = buf32 + COCSEP_TABLESIZE; - memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); + memset(buf, 0xFF, COCSEP_FULLSIZE); + buf32 = (uint32_t *)((char *)buf + INFOSIZE); if (selfsim != NULL) memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); + info = (tableinfo_t) { + .solver = "cocsep data for h48", + .type = TABLETYPE_SPECIAL, + .infosize = INFOSIZE, + .fullsize = COCSEP_FULLSIZE, + .hash = 0, /* TODO */ + .entries = COCSEP_TABLESIZE, + .classes = COCSEP_CLASSES, + .bits = 32, + .base = 0, + .maxvalue = 9, + .next = 0 + }; arg = (cocsep_dfs_arg_t) { .cube = SOLVED_CUBE, .n = &n, @@ -70,22 +83,21 @@ gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) arg.depth = 0; arg.maxdepth = i; cc = gendata_cocsep_dfs(&arg); - info[i+2] = cc; + info.distribution[i] = cc; LOG("found %" PRIu32 "\n", cc); } - info[0] = (uint32_t)n; - info[1] = 9; /* Known max pruning value */ + writetableinfo(&info, buf); + DBG_ASSERT(n == COCSEP_CLASSES, 0, "cocsep: computed %" PRIu16 " symmetry classes, " "expected %zu\n", n, COCSEP_CLASSES); LOG("cocsep data computed\n"); - LOG("Symmetry classes: %" PRIu32 "\n", info[0]); - LOG("Maximum pruning value: %" PRIu32 "\n", info[1]); + LOG("Symmetry classes: %" PRIu32 "\n", COCSEP_CLASSES); LOG("Pruning value distribution:\n"); for (j = 0; j < 10; j++) - LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+2]); + LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info.distribution[j]); gendata_cocsep_return_size: return COCSEP_FULLSIZE; diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -1,5 +1,5 @@ #define H48_COORDMAX_NOEO ((int64_t)(COCSEP_CLASSES * COMB_12_4 * COMB_8_4)) -#define H48_COORDMAX(h) ((int64_t)(H48_COORDMAX_NOEO << (int64_t)(h))) +#define H48_COORDMAX(h) (H48_COORDMAX_NOEO << (int64_t)(h)) #define H48_DIV(k) ((size_t)8 / (size_t)(k)) #define H48_TABLESIZE(h, k) DIV_ROUND_UP((size_t)H48_COORDMAX((h)), H48_DIV(k)) @@ -33,10 +33,10 @@ typedef struct { uint8_t h; uint8_t k; uint8_t maxdepth; + tableinfo_t info; void *buf; - uint32_t *info; + void *h48buf; uint32_t *cocsepdata; - uint32_t *h48data; uint64_t selfsim[COCSEP_CLASSES]; cube_t crep[COCSEP_CLASSES]; } gendata_h48_arg_t; @@ -65,7 +65,7 @@ typedef struct { uint8_t base; uint8_t shortdepth; uint32_t *cocsepdata; - uint32_t *h48data; + uint32_t *buf32; uint64_t *selfsim; cube_t *crep; h48map_t *shortcubes; @@ -130,32 +130,45 @@ gen_h48short(gendata_h48short_arg_t *arg) STATIC size_t gendata_h48(gendata_h48_arg_t *arg) { - static const size_t infosize = 88; /* TODO: change to e.g. 1024 */ - + void *cocsepdata_offset; size_t cocsepsize, h48size; + tableinfo_t cocsepinfo; - /* TODO: move info at the start */ - arg->cocsepdata = (uint32_t *)arg->buf; - cocsepsize = gendata_cocsep( - (void *)arg->cocsepdata, arg->selfsim, arg->crep); - arg->h48data = arg->cocsepdata + (cocsepsize / sizeof(uint32_t)); - arg->info = arg->h48data + 1 + - (H48_TABLESIZE(arg->h, arg->k) / sizeof(uint32_t)); + cocsepsize = gendata_cocsep(arg->buf, arg->selfsim, arg->crep); - if (arg->buf != NULL) - memset(arg->h48data, 0xFF, H48_TABLESIZE(arg->h, arg->k)); + cocsepdata_offset = (char *)arg->buf + INFOSIZE; + arg->cocsepdata = (uint32_t *)cocsepdata_offset; + arg->h48buf = (char *)arg->buf + cocsepsize; if (arg->h == 0 && arg->k == 4) { h48size = gendata_h48h0k4(arg); } else if (arg->k == 2) { h48size = gendata_h48k2(arg); } else { - h48size = 0; LOG("Cannot generate data for h = %" PRIu8 " and k = %" PRIu8 " (not implemented yet)\n", arg->h, arg->k); + goto gendata_h48_error; } - return infosize + cocsepsize + h48size; + if (arg->buf == 0) + goto gendata_h48_return_size; + + if (!readtableinfo(arg->buf, &cocsepinfo)) { + LOG("gendata_h48: could not read info for cocsep table\n"); + goto gendata_h48_error; + } + cocsepinfo.next = cocsepsize; + if (!writetableinfo(&cocsepinfo, arg->buf)) { + LOG("gendata_h48: could not write info for cocsep table" + " with updated 'next' value\n"); + goto gendata_h48_error; + } + +gendata_h48_return_size: + return cocsepsize + h48size; + +gendata_h48_error: + return 0; } /* @@ -165,20 +178,36 @@ generating fixed table with h=0, k=4 STATIC size_t gendata_h48h0k4(gendata_h48_arg_t *arg) { - uint32_t j; + uint32_t j, *buf32; h48h0k4_bfs_arg_t bfsarg; int64_t sc, cc, esep_max; if (arg->buf == NULL) goto gendata_h48h0k4_return_size; + arg->info = (tableinfo_t) { + .solver = "h48 solver h = 0, k = 4", + .type = TABLETYPE_PRUNING, + .infosize = INFOSIZE, + .fullsize = H48_TABLESIZE(0, 4) + INFOSIZE, + .hash = 0, /* TODO */ + .entries = H48_COORDMAX(0), + .classes = 0, + .bits = 4, + .base = 0, + .next = 0, + }; + + buf32 = (uint32_t *)((char *)arg->h48buf + INFOSIZE); + memset(buf32, 0xFF, H48_TABLESIZE(0, 4)); + esep_max = (int64_t)H48_COORDMAX(0); sc = coord_h48(SOLVED_CUBE, arg->cocsepdata, 0); - set_esep_pval(arg->h48data, sc, 4, 0); - arg->info[1] = 1; + set_esep_pval(buf32, sc, 4, 0); + arg->info.distribution[0] = 1; bfsarg = (h48h0k4_bfs_arg_t) { .cocsepdata = arg->cocsepdata, - .buf32 = arg->h48data, + .buf32 = buf32, .selfsim = arg->selfsim, .crep = arg->crep }; @@ -190,20 +219,22 @@ gendata_h48h0k4(gendata_h48_arg_t *arg) LOG("esep: generating depth %" PRIu8 "\n", bfsarg.depth); cc = gendata_h48h0k4_bfs(&bfsarg); bfsarg.done += cc; - arg->info[bfsarg.depth+1] = cc; + arg->info.distribution[bfsarg.depth] = cc; LOG("found %" PRId64 "\n", cc); } - arg->info[0] = bfsarg.depth-1; + arg->info.maxvalue = bfsarg.depth-1; LOG("h48 pruning table computed\n"); - LOG("Maximum pruning value: %" PRIu32 "\n", arg->info[0]); + LOG("Maximum pruning value: %" PRIu32 "\n", arg->info.maxvalue); LOG("Pruning value distribution:\n"); - for (j = 0; j <= arg->info[0]; j++) - LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, arg->info[j+1]); + for (j = 0; j <= arg->info.maxvalue; j++) + LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, arg->info.distribution[j]); + + writetableinfo(&arg->info, arg->h48buf); gendata_h48h0k4_return_size: - return H48_TABLESIZE(0, 4); + return H48_TABLESIZE(0, 4) + INFOSIZE; } STATIC int64_t @@ -226,6 +257,7 @@ gendata_h48h0k4_bfs_fromdone(h48h0k4_bfs_arg_t *arg) cube_t cube, moved; for (i = 0, cc = 0; i < (int64_t)H48_COORDMAX(0); i++) { +//LOG("getting esep val for %" PRId64 "\n", i); c = get_esep_pval(arg->buf32, i, 4); if (c != arg->depth - 1) continue; @@ -300,7 +332,8 @@ gendata_h48k2(gendata_h48_arg_t *arg) [11] = 10 }; - uint8_t t; + uint8_t t, selectedbase; + uint32_t *buf32; int64_t j; uint64_t nshort, i, ii; h48map_t shortcubes; @@ -311,6 +344,10 @@ gendata_h48k2(gendata_h48_arg_t *arg) if (arg->buf == NULL) goto gendata_h48k2_return_size; + buf32 = (uint32_t *)((char *)arg->h48buf + INFOSIZE); + if (arg->buf != NULL) + memset(buf32, 0xFF, H48_TABLESIZE(arg->h, arg->k)); + LOG("Computing depth <=%" PRIu8 "\n", shortdepth) h48map_create(&shortcubes, capacity, randomizer); shortarg = (gendata_h48short_arg_t) { @@ -323,13 +360,29 @@ gendata_h48k2(gendata_h48_arg_t *arg) nshort = gen_h48short(&shortarg); LOG("Cubes in <= %" PRIu8 " moves: %" PRIu64 "\n", shortdepth, nshort); + selectedbase = base[arg->h]; + arg->info = (tableinfo_t) { + .solver = "h48 solver h = , k = 4", + .type = TABLETYPE_PRUNING, + .infosize = INFOSIZE, + .fullsize = H48_TABLESIZE(arg->h, 2) + INFOSIZE, + .hash = 0, /* TODO */ + .entries = H48_COORDMAX(arg->h), + .bits = 2, + .base = selectedbase, + .next = 0, + }; + arg->info.solver[15] = (arg->h % 10) + '0'; + if (arg->h >= 10) + arg->info.solver[14] = (arg->h / 10) + '0'; + dfsarg = (h48k2_dfs_arg_t){ .h = arg->h, .k = arg->k, - .base = base[arg->h], + .base = selectedbase, .shortdepth = shortdepth, .cocsepdata = arg->cocsepdata, - .h48data = arg->h48data, + .buf32 = buf32, .selfsim = arg->selfsim, .crep = arg->crep, .shortcubes = &shortcubes @@ -348,15 +401,16 @@ gendata_h48k2(gendata_h48_arg_t *arg) h48map_destroy(&shortcubes); - memset(arg->info, 0, 5 * sizeof(arg->info[0])); - arg->info[0] = base[arg->k]; + arg->info.base = selectedbase; for (j = 0; j < H48_COORDMAX(arg->h); j++) { - t = get_esep_pval(arg->h48data, j, 2); - arg->info[1 + t]++; + t = get_esep_pval(buf32, j, 2); + arg->info.distribution[t]++; } + writetableinfo(&arg->info, arg->h48buf); + gendata_h48k2_return_size: - return H48_TABLESIZE(arg->h, 2); + return H48_TABLESIZE(arg->h, 2) + INFOSIZE; } STATIC void @@ -427,10 +481,9 @@ gendata_h48k2_mark(cube_t cube, int8_t depth, h48k2_dfs_arg_t *arg) FOREACH_H48SIM(cube, arg->cocsepdata, arg->selfsim, fullcoord = coord_h48(cube, arg->cocsepdata, 11); coord = fullcoord >> (int64_t)(11 - arg->h); - oldval = get_esep_pval(arg->h48data, coord, arg->k); + oldval = get_esep_pval(arg->buf32, coord, arg->k); newval = (uint8_t)MAX(depth, 0); - set_esep_pval( - arg->h48data, coord, arg->k, MIN(oldval, newval)); + set_esep_pval(arg->buf32, coord, arg->k, MIN(oldval, newval)); ) } @@ -445,7 +498,7 @@ gendata_h48k2_dfs_stop(cube_t cube, uint8_t depth, h48k2_dfs_arg_t *arg) /* We are in the "real coordinate" case, we can stop if this coordinate has already been visited */ coord = coord_h48(cube, arg->cocsepdata, arg->h); - oldval = get_esep_pval(arg->h48data, coord, arg->k); + oldval = get_esep_pval(arg->buf32, coord, arg->k); return oldval <= depth; } else { /* With 0 < k < 11 we do not have a "real coordinate". diff --git a/src/solvers/tables.h b/src/solvers/tables.h @@ -1,18 +1,21 @@ #define OFFSET(B, K) (((uint8_t *)B) + K) + #define INFOSIZE 512 +#define INFO_SOLVER_STRLEN 100 +#define INFO_DISTRIBUTION_LEN 21 + #define INFO_OFFSET_SOLVER 0 -#define INFO_SOLVER_STRLEN 20 #define INFO_OFFSET_TYPE INFO_SOLVER_STRLEN #define INFO_OFFSET_INFOSIZE (INFO_OFFSET_TYPE + sizeof(uint64_t)) #define INFO_OFFSET_FULLSIZE (INFO_OFFSET_INFOSIZE + sizeof(uint64_t)) #define INFO_OFFSET_HASH (INFO_OFFSET_FULLSIZE + sizeof(uint64_t)) #define INFO_OFFSET_ENTRIES (INFO_OFFSET_HASH + sizeof(uint64_t)) -#define INFO_OFFSET_BITS (INFO_OFFSET_ENTRIES + sizeof(uint64_t)) +#define INFO_OFFSET_CLASSES (INFO_OFFSET_ENTRIES + sizeof(uint64_t)) +#define INFO_OFFSET_BITS (INFO_OFFSET_CLASSES + sizeof(uint64_t)) #define INFO_OFFSET_BASE (INFO_OFFSET_BITS + sizeof(uint8_t)) #define INFO_OFFSET_MAXVALUE (INFO_OFFSET_BASE + sizeof(uint8_t)) #define INFO_OFFSET_NEXT (INFO_OFFSET_MAXVALUE + sizeof(uint8_t)) #define INFO_OFFSET_DISTRIBUTION (INFO_OFFSET_NEXT + sizeof(uint64_t)) -#define INFO_DISTRIBUTION_LEN 21 const uint64_t TABLETYPE_PRUNING = 0; const uint64_t TABLETYPE_SPECIAL = 1; @@ -24,6 +27,7 @@ typedef struct { uint64_t fullsize; uint64_t hash; uint64_t entries; + uint64_t classes; /* Used only by cocsepdata, for now */ uint8_t bits; uint8_t base; uint8_t maxvalue; @@ -38,7 +42,7 @@ STATIC bool readtableinfo(const void *buf, tableinfo_t *info) { if (buf == NULL) { - LOG("Error reading table: buffer in NULL\n"); + LOG("Error reading table: buffer is NULL\n"); return false; } @@ -54,6 +58,7 @@ readtableinfo(const void *buf, tableinfo_t *info) info->fullsize = *(const uint64_t *)OFFSET(buf, INFO_OFFSET_FULLSIZE); info->hash = *(const uint64_t *)OFFSET(buf, INFO_OFFSET_HASH); info->entries = *(const uint64_t *)OFFSET(buf, INFO_OFFSET_ENTRIES); + info->classes = *(const uint64_t *)OFFSET(buf, INFO_OFFSET_CLASSES); info->bits = *OFFSET(buf, INFO_OFFSET_BITS); info->base = *OFFSET(buf, INFO_OFFSET_BASE); info->maxvalue = *OFFSET(buf, INFO_OFFSET_MAXVALUE); @@ -70,7 +75,7 @@ writetableinfo(const tableinfo_t *info, void *buf) int i; if (buf == NULL) { - LOG("Error reading table: buffer in NULL\n"); + LOG("Error writing table: buffer is NULL\n"); return false; } @@ -92,6 +97,7 @@ writetableinfo(const tableinfo_t *info, void *buf) *(uint64_t *)OFFSET(buf, INFO_OFFSET_FULLSIZE) = info->fullsize; *(uint64_t *)OFFSET(buf, INFO_OFFSET_HASH) = info->hash; *(uint64_t *)OFFSET(buf, INFO_OFFSET_ENTRIES) = info->entries; + *(uint64_t *)OFFSET(buf, INFO_OFFSET_CLASSES) = info->classes; *OFFSET(buf, INFO_OFFSET_BITS) = info->bits; *OFFSET(buf, INFO_OFFSET_BASE) = info->base; *OFFSET(buf, INFO_OFFSET_MAXVALUE) = info->maxvalue; diff --git a/test/090_tables_readwrite/00_table.in b/test/090_tables_readwrite/00_table.in @@ -5,6 +5,7 @@ Test solver 100000000000 12345678912345 399999999998 +3393 2 0 20 diff --git a/test/090_tables_readwrite/00_table.out b/test/090_tables_readwrite/00_table.out @@ -5,6 +5,7 @@ Test solver 100000000000 12345678912345 399999999998 +3393 2 0 20 diff --git a/test/090_tables_readwrite/tables_readwrite_tests.c b/test/090_tables_readwrite/tables_readwrite_tests.c @@ -1,7 +1,7 @@ #include "../test.h" #define INFOSIZE 512 -#define INFO_SOLVER_STRLEN 20 +#define INFO_SOLVER_STRLEN 100 #define INFO_DISTRIBUTION_LEN 21 typedef struct { @@ -11,6 +11,7 @@ typedef struct { uint64_t fullsize; uint64_t hash; uint64_t entries; + uint64_t classes; uint8_t bits; uint8_t base; uint8_t maxvalue; @@ -45,6 +46,7 @@ tableinfo_t test_readinfo(void) { ret.fullsize = readn(); ret.hash = readn(); ret.entries = readn(); + ret.classes = readn(); ret.bits = (uint8_t)readn(); ret.base = (uint8_t)readn(); ret.maxvalue = (uint8_t)readn(); @@ -69,6 +71,7 @@ void test_writeinfo(tableinfo_t info) { printf("%" PRIu64 "\n", info.fullsize); printf("%" PRIu64 "\n", info.hash); printf("%" PRIu64 "\n", info.entries); + printf("%" PRIu64 "\n", info.classes); printf("%" PRIu8 "\n", info.bits); printf("%" PRIu8 "\n", info.base); printf("%" PRIu8 "\n", info.maxvalue); diff --git a/test/100_gendata_cocsep/00_all.out b/test/100_gendata_cocsep/00_all.out @@ -1,4 +1,4 @@ -1119792 +1120256 Classes: 3393 Max value: 9 0: 1 diff --git a/test/100_gendata_cocsep/gendata_cocsep_tests.c b/test/100_gendata_cocsep/gendata_cocsep_tests.c @@ -1,20 +1,45 @@ #include "../test.h" -#define COCSEP_CLASSES 3393 +#define INFOSIZE 512 +#define INFO_SOLVER_STRLEN 100 +#define INFO_DISTRIBUTION_LEN 21 +#define COCSEP_CLASSES 3393 + +typedef struct { + char solver[INFO_SOLVER_STRLEN]; + uint64_t type; + uint64_t infosize; + uint64_t fullsize; + uint64_t hash; + uint64_t entries; + uint64_t classes; /* Used only by cocsepdata, for now */ + uint8_t bits; + uint8_t base; + uint8_t maxvalue; + uint64_t next; + uint64_t distribution[INFO_DISTRIBUTION_LEN]; +} tableinfo_t; size_t gendata_cocsep(void *, uint64_t *, cube_t *); +bool readtableinfo(const void *, tableinfo_t *); void run(void) { - uint32_t buf[300000], i; + char buf[2000000]; + uint32_t i; uint64_t selfsim[COCSEP_CLASSES]; cube_t rep[COCSEP_CLASSES]; size_t result; + tableinfo_t info; result = gendata_cocsep(buf, selfsim, rep); + if (!readtableinfo(buf, &info)) { + printf("Error reading info from table\n"); + return; + } printf("%zu\n", result); - printf("Classes: %" PRIu32 "\n", buf[result/4-12]); - printf("Max value: %" PRIu32 "\n", buf[result/4-11]); + printf("Classes: %" PRIu64 "\n", info.classes); + printf("Max value: %" PRIu8 "\n", info.maxvalue); for (i = 0; i < 10; i++) - printf("%" PRIu32 ": %" PRIu32 "\n", i, buf[result/4-10+i]); + printf("%" PRIu32 ": %" PRIu64 "\n", i, info.distribution[i]); } diff --git a/test/101_cocsep_transform_invariant/cocsep_transform_invariant.c b/test/101_cocsep_transform_invariant/cocsep_transform_invariant.c @@ -3,6 +3,7 @@ #define COCLASS_MASK (UINT32_C(0xFFFF) << UINT32_C(16)) #define COCLASS(x) (((x) & COCLASS_MASK) >> UINT32_C(16)) +#define INFOSIZE 512 #define COCSEP_CLASSES 3393 size_t gendata_cocsep(void *, uint64_t *, cube_t *); @@ -11,7 +12,8 @@ int64_t coord_cocsep(cube_t); void run(void) { uint8_t t; - uint32_t buf[300000]; + char buf[2000000]; + uint32_t *cocsepdata; uint64_t selfsim[COCSEP_CLASSES]; int64_t coord, tcoord; char str[STRLENMAX]; @@ -21,11 +23,12 @@ void run(void) { cube = readcube("H48", str); gendata_cocsep(buf, selfsim, rep); + cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); - coord = (int64_t)COCLASS(buf[coord_cocsep(cube)]); + coord = (int64_t)COCLASS(cocsepdata[coord_cocsep(cube)]); for (t = 0; t < 48; t++) { transd = transform(cube, t); - tcoord = (int64_t)COCLASS(buf[coord_cocsep(transd)]); + tcoord = (int64_t)COCLASS(cocsepdata[coord_cocsep(transd)]); if (coord != tcoord) printf("Error: expected %" PRId64 " but got %" PRId64 "\n", coord, tcoord); diff --git a/test/102_cocsep_selfsim/cocsep_selfsim_tests.c b/test/102_cocsep_selfsim/cocsep_selfsim_tests.c @@ -8,25 +8,28 @@ #include "../test.h" #define COCSEP_CLASSES 3393 +#define INFOSIZE 512 size_t gendata_cocsep(void *, uint64_t *, cube_t *); int64_t coord_cocsep(cube_t); void run(void) { char str[STRLENMAX]; - uint32_t buf[300000], data; + char buf[2000000]; + uint32_t *cocsepdata, data; int64_t coord, coclass; uint64_t selfsim[COCSEP_CLASSES], sim, t; cube_t cube, rep[COCSEP_CLASSES]; gendata_cocsep(buf, selfsim, rep); + cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); /* All cases in the same test so we do not generate data many times */ while (fgets(str, STRLENMAX, stdin) != NULL) { cube = readcube("H48", str); coord = coord_cocsep(cube); - data = buf[coord]; + data = cocsepdata[coord]; coclass = (data & (0xFFFU << 16)) >> 16; sim = selfsim[coclass]; for (t = 0; t < 48 && sim; t++, sim >>= 1) { diff --git a/test/103_cocsep_selfsim_distribution/cocsep_selfsim_distribution_tests.c b/test/103_cocsep_selfsim_distribution/cocsep_selfsim_distribution_tests.c @@ -17,7 +17,7 @@ int bcount(uint64_t x) { } void run(void) { - uint32_t buf[300000]; + char buf[2000000]; int size[65], tot, j; int64_t i; uint64_t selfsim[COCSEP_CLASSES], sim; diff --git a/test/104_cocsep_ttrep/cocsep_ttrep_tests.c b/test/104_cocsep_ttrep/cocsep_ttrep_tests.c @@ -1,9 +1,11 @@ #include "../test.h" -#define COCSEP_CLASSES 3393 #define TTREP_MASK (UINT32_C(0xFF) << UINT32_C(8)) #define TTREP(x) (((x) & TTREP_MASK) >> UINT32_C(8)) +#define COCSEP_CLASSES 3393 +#define INFOSIZE 512 + uint8_t inverse_trans(uint8_t); cube_t transform_corners(cube_t, uint8_t); int64_t coord_cocsep(cube_t); @@ -11,19 +13,21 @@ size_t gendata_cocsep(void *, uint64_t *, cube_t *); void run(void) { uint8_t t; - uint32_t buf[300000], tt; + char buf[2000000]; + uint32_t *cocsepdata, tt; uint64_t selfsim[COCSEP_CLASSES]; int64_t i, j, k, l; cube_t rep[COCSEP_CLASSES], c, d; gendata_cocsep(buf, selfsim, rep); + cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); for (i = 0; i < COCSEP_CLASSES; i++) { c = rep[i]; for (t = 0; t < 48; t++) { d = transform_corners(c, t); j = coord_cocsep(d); - tt = TTREP(buf[j]); + tt = TTREP(cocsepdata[j]); d = transform_corners(d, tt); k = coord_cocsep(d); l = coord_cocsep(c); diff --git a/test/110_coord_invcoord_h48/coord_invcoord_h48_tests.c b/test/110_coord_invcoord_h48/coord_invcoord_h48_tests.c @@ -1,6 +1,7 @@ #include "../test.h" #define COCSEP_CLASSES 3393 +#define INFOSIZE 512 size_t gendata_cocsep(void *, uint64_t *, cube_t *); int64_t coord_h48(cube_t, const uint32_t *, uint8_t); @@ -12,12 +13,14 @@ void run(void) { int i; bool found; uint8_t h, t; - uint32_t cocsepdata[300000]; + char buf[2000000]; + uint32_t *cocsepdata; uint64_t selfsim[COCSEP_CLASSES]; int64_t c, cc; cube_t cube, invc, rep[COCSEP_CLASSES]; - gendata_cocsep(cocsepdata, selfsim, rep); + gendata_cocsep(buf, selfsim, rep); + cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); i = 1; h = 11; diff --git a/test/112_gen_h48short/gen_h48short.c b/test/112_gen_h48short/gen_h48short.c @@ -1,87 +0,0 @@ -#include "../test.h" - -#define COCSEP_CLASSES 3393 -#define MAXPOS 200 - -typedef struct { - uint64_t n; - uint64_t capacity; - uint64_t randomizer; - uint64_t *table; - uint32_t *info; - uint32_t *cocsepdata; - uint32_t *h48data; - uint64_t selfsim[COCSEP_CLASSES]; - cube_t crep[COCSEP_CLASSES]; -} h48map_t; - -typedef struct { - uint64_t key; - uint64_t val; -} kvpair_t; - -typedef struct { - uint8_t maxdepth; - const uint32_t *cocsepdata; - const cube_t *crep; - const uint64_t *selfsim; - h48map_t *map; -} gendata_h48short_arg_t; - -void h48map_create(h48map_t *, uint64_t, uint64_t); -void h48map_destroy(h48map_t *); -kvpair_t h48map_nextkvpair(h48map_t *, uint64_t *); -size_t gendata_cocsep(void *, uint64_t *, cube_t *); -uint64_t gen_h48short(gendata_h48short_arg_t *); - -char str[STRLENMAX]; - -int compare(const void *x, const void *y) { - uint64_t a = ((kvpair_t *)x)->key; - uint64_t b = ((kvpair_t *)y)->key; - - if (a > b) return 1; - if (a == b) return 0; - return -1; -} - -uint64_t readl(void) { - fgets(str, STRLENMAX, stdin); - return atoll(str); -} - -void run(void) { - uint32_t cocsepdata[300000]; - h48map_t map; - uint64_t i, j, capacity, randomizer, selfsim[COCSEP_CLASSES]; - kvpair_t kv, b[MAXPOS]; - gendata_h48short_arg_t arg; - cube_t crep[COCSEP_CLASSES]; - - capacity = readl(); - randomizer = readl(); - arg.maxdepth = readl(); - arg.cocsepdata = cocsepdata; - arg.crep = crep; - arg.selfsim = selfsim; - arg.map = &map; - - h48map_create(&map, capacity, randomizer); - gendata_cocsep(cocsepdata, selfsim, crep); - gen_h48short(&arg); - - i = 0; - for (kv = h48map_nextkvpair(&map, &i), j = 0; - i != map.capacity && j < MAXPOS; - kv = h48map_nextkvpair(&map, &i) - ) { - b[j++] = kv; - } - qsort(b, j, sizeof(kvpair_t), compare); - - printf("%" PRIu64 "\n", map.n); - for (i = 0; i < j; i++) - printf("%" PRIu64 " %" PRIu64 "\n", b[i].key, b[i].val); - - h48map_destroy(&map); -} diff --git a/test/112_gen_h48short/gen_h48short_tests.c b/test/112_gen_h48short/gen_h48short_tests.c @@ -0,0 +1,88 @@ +#include "../test.h" + +#define COCSEP_CLASSES 3393 +#define INFOSIZE 512 +#define MAXPOS 200 + +typedef struct { + uint64_t n; + uint64_t capacity; + uint64_t randomizer; + uint64_t *table; + uint32_t *info; + uint32_t *cocsepdata; + uint32_t *h48data; + uint64_t selfsim[COCSEP_CLASSES]; + cube_t crep[COCSEP_CLASSES]; +} h48map_t; + +typedef struct { + uint64_t key; + uint64_t val; +} kvpair_t; + +typedef struct { + uint8_t maxdepth; + const uint32_t *cocsepdata; + const cube_t *crep; + const uint64_t *selfsim; + h48map_t *map; +} gendata_h48short_arg_t; + +void h48map_create(h48map_t *, uint64_t, uint64_t); +void h48map_destroy(h48map_t *); +kvpair_t h48map_nextkvpair(h48map_t *, uint64_t *); +size_t gendata_cocsep(void *, uint64_t *, cube_t *); +uint64_t gen_h48short(gendata_h48short_arg_t *); + +char str[STRLENMAX]; + +int compare(const void *x, const void *y) { + uint64_t a = ((kvpair_t *)x)->key; + uint64_t b = ((kvpair_t *)y)->key; + + if (a > b) return 1; + if (a == b) return 0; + return -1; +} + +uint64_t readl(void) { + fgets(str, STRLENMAX, stdin); + return atoll(str); +} + +void run(void) { + char buf[2000000]; + h48map_t map; + uint64_t i, j, capacity, randomizer, selfsim[COCSEP_CLASSES]; + kvpair_t kv, b[MAXPOS]; + gendata_h48short_arg_t arg; + cube_t crep[COCSEP_CLASSES]; + + capacity = readl(); + randomizer = readl(); + arg.maxdepth = readl(); + arg.crep = crep; + arg.selfsim = selfsim; + arg.map = &map; + + h48map_create(&map, capacity, randomizer); + gendata_cocsep(buf, selfsim, crep); + arg.cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); + gen_h48short(&arg); + + i = 0; + for (kv = h48map_nextkvpair(&map, &i), j = 0; + i != map.capacity && j < MAXPOS; + kv = h48map_nextkvpair(&map, &i) + ) { + b[j++] = kv; + } + qsort(b, j, sizeof(kvpair_t), compare); + + printf("%" PRIu64 "\n", map.n); + for (i = 0; i < j; i++) + printf("%" PRIu64 " %" PRIu64 "\n", b[i].key, b[i].val); + + h48map_destroy(&map); +} diff --git a/test/120_gendata_h48h0k4/00_h_0.out b/test/120_gendata_h48h0k4/00_h_0.out @@ -1,4 +1,4 @@ -59903605 +59904493 cocsepdata: Classes: 3393 diff --git a/test/120_gendata_h48h0k4/gendata_h48h0k4_tests.c b/test/120_gendata_h48h0k4/gendata_h48h0k4_tests.c @@ -1,27 +1,47 @@ #include "../test.h" -#define COCSEP_CLASSES 3393 -#define COCSEPSIZE 1119792 +#define COCSEP_CLASSES 3393 +#define INFOSIZE 512 +#define INFO_SOLVER_STRLEN 100 +#define INFO_DISTRIBUTION_LEN 21 + +typedef struct { + char solver[INFO_SOLVER_STRLEN]; + uint64_t type; + uint64_t infosize; + uint64_t fullsize; + uint64_t hash; + uint64_t entries; + uint64_t classes; /* Used only by cocsepdata, for now */ + uint8_t bits; + uint8_t base; + uint8_t maxvalue; + uint64_t next; + uint64_t distribution[INFO_DISTRIBUTION_LEN]; +} tableinfo_t; typedef struct { uint8_t h; uint8_t k; uint8_t maxdepth; + tableinfo_t info; void *buf; - uint32_t *info; + void *h48buf; uint32_t *cocsepdata; - uint32_t *h48data; uint64_t selfsim[COCSEP_CLASSES]; cube_t crep[COCSEP_CLASSES]; } gendata_h48_arg_t; int64_t gendata_h48(gendata_h48_arg_t *); +bool readtableinfo(const void *, tableinfo_t *); void run(void) { char str[STRLENMAX]; uint8_t i; gendata_h48_arg_t arg; size_t result, sz; + tableinfo_t cinfo, hinfo; + void *h48buf; fgets(str, STRLENMAX, stdin); arg.maxdepth = atoi(str); @@ -30,21 +50,37 @@ void run(void) { arg.k = 4; sz = gendata_h48(&arg); /* With buf = NULL returns data size */ - arg.buf = malloc(sz); + arg.buf = malloc(sz+23); +/* +TODO: the +23 is a workaround for a bug that I don't understand and seems +to happen only with gcc. Hopefully this gets fixed when switching to 8-bit. +*/ + result = gendata_h48(&arg); + if (!readtableinfo(arg.buf, &cinfo)) { + printf("Error reading cocsep info\n"); + goto end; + } + + h48buf = (char *)arg.buf + cinfo.next; + if (!readtableinfo(h48buf, &hinfo)) { + printf("Error reading h48 info\n"); + goto end; + } + printf("%zu\n\n", result); printf("cocsepdata:\n"); - printf("Classes: %" PRIu32 "\n", arg.cocsepdata[COCSEPSIZE/4-12]); - printf("Max value: %" PRIu32 "\n", arg.cocsepdata[COCSEPSIZE/4-11]); - for (i = 0; i < 10; i++) - printf("%" PRIu32 ": %" PRIu32 "\n", - i, arg.cocsepdata[COCSEPSIZE/4-10+i]); + printf("Classes: %" PRIu64 "\n", cinfo.classes); + printf("Max value: %" PRIu8 "\n", cinfo.maxvalue); + for (i = 0; i <= cinfo.maxvalue; i++) + printf("%" PRIu32 ": %" PRIu64 "\n", i, cinfo.distribution[i]); printf("\nh48:\n"); - for (i = 0; i < arg.maxdepth+1; i++) - printf("%" PRIu32 ": %" PRIu32 "\n", i, arg.info[i+1]); + for (i = 0; i <= hinfo.maxvalue; i++) + printf("%" PRIu32 ": %" PRIu64 "\n", i, hinfo.distribution[i]); +end: free(arg.buf); }