static void calc_checksum(char *name) { long64 orig_size; if (!work) work = alloc_work(total_work); data = map_file(name, 0, &size); orig_size = size; if ((size & 0x3f) == 0x10) { size &= ~0x3fULL; memcpy(checksum1, data + size, 16); checksum_found = 1; } else { if (size & 0x3f) { printf("Size of %s is not a multiple of 64.\n", name); exit(1); } checksum_found = 0; } int chunks = (size + CHUNK - 1) / CHUNK; results = (uint64 *)malloc(32 * chunks); fill_work(total_work, chunks, 0, work); run_threaded(checksum_worker, work, 0); CityHashCrc128((char *)results, 32 * chunks, checksum2); unmap_file(data, orig_size); free(results); if (checksum_found) checksum_match = (checksum1[0] == checksum2[0] && checksum1[1] == checksum2[1]); }
void verify_stats(ubyte *table, long64 *tot_stats, struct dtz_map *map) { long64 stats[256]; long64 stats2[256]; int i, j; ubyte (*inv_map)[256] = map->inv_map; for (i = 0; i < 256; i++) stats[i] = stats2[i] = 0; for (i = 0; i < 256 * numthreads; i++) thread_stats[i] = 0; count_stats_table = table; run_threaded(count_stats, work_g, 0); for (i = 0; i < numthreads; i++) for (j = 0; j < 256; j++) stats[j] += thread_data[i].stats[j]; stats2[inv_map[0][0]] = tot_stats[0]; stats2[inv_map[1][0]] = tot_stats[STAT_MATE]; if (map->ply_accurate_win) for (i = 0; i < DRAW_RULE; i++) stats2[inv_map[0][i]] += tot_stats[i + 1]; else for (i = 0; i < DRAW_RULE; i++) stats2[inv_map[0][i / 2]] += tot_stats[i + 1]; if (map->ply_accurate_loss) for (i = 0; i < DRAW_RULE; i++) stats2[inv_map[1][i]] += tot_stats[STAT_MATE - 1 - i]; else for (i = 0; i < DRAW_RULE; i++) stats2[inv_map[1][i / 2]] += tot_stats[STAT_MATE - 1 - i]; for (i = DRAW_RULE + 1; i < MAX_PLY; i++) { stats2[inv_map[2][(i - DRAW_RULE - 1) / 2]] += tot_stats[i]; stats2[inv_map[3][(i - DRAW_RULE - 1) / 2]] += tot_stats[STAT_MATE - i]; } int verify_ok = 1; for (i = 0; i < 256; i++) if (stats[i] != stats2[i] && i != map->max_num) { printf("stats[%d] = %"PRIu64"; stats2[%d] = %"PRIu64"\n", i, stats[i], i, stats2[i]); int j; for (j = 0; j < 4; j++) printf("map[%d][%d]=%d\n", j, i, map->map[j][i]); verify_ok = 0; } if (!verify_ok) { fprintf(stderr, "Verification of reconstructed table failed.\n"); exit(1); } }
long64 find_val(ubyte *table, ubyte v, long64 *work) { found_idx = 0xffffffffffffffffULL; find_val_table = table; find_val_v = v; run_threaded(find_loop, work, 0); if (found_idx == 0xffffffffffffffffULL) fprintf(stderr, "find_val: not found!\n"); return found_idx; }
int main(int argc, const char * argv[]) { // Too few arguments specified. if (argc < 2) { print_usage(); return 0; } // One argument specified, should only be the interactive mode. if (argc == 2) { if (!strcmp("-i", argv[1])) { run_interactive(); return 0; } print_usage(); return 0; } // Two arguments. The first should either be the demonstration or worker flag. // The second is assumed to be a file path; errors with that are handled further down. if (argc == 3) { if (!strcmp("-d", argv[1])) { run_multiprocess(argv); return 0; } if (!strcmp("-w", argv[1])) { run_worker(argv); return 0; } if (!strcmp("-t", argv[1])) { run_threaded(argv[2]); return 0; } print_usage(); return 0; } // Anything more and it was used wrong. print_usage(); return 0; }
void reduce_tables(void) { int i; ubyte v[256]; if (!copybuf) copybuf = malloc(COPYSIZE); collect_stats(0); if (generate_dtz) { save_table(table_w, 'w'); if (!symmetric) save_table(table_b, 'b'); } for (i = 0; i < 256; i++) v[i] = 0; #ifndef SUICIDE v[BROKEN] = BROKEN; v[UNKNOWN] = UNKNOWN; v[CHANGED] = CHANGED; v[CAPT_DRAW] = CAPT_DRAW; v[MATE] = MATE; v[ILLEGAL] = ILLEGAL; v[CAPT_WIN] = CAPT_WIN; if (num_saves == 0) { for (i = 0; i < DRAW_RULE; i++) { v[WIN_IN_ONE + i] = WIN_IN_ONE; v[LOSS_IN_ONE - i] = MATE; } v[CAPT_CWIN] = CAPT_CWIN_RED; for (; i < REDUCE_PLY - 2; i++) { v[WIN_IN_ONE + i + 1] = CAPT_CWIN_RED + 1; v[LOSS_IN_ONE - i] = LOSS_IN_ONE; } v[LOSS_IN_ONE - i] = LOSS_IN_ONE; v[WIN_IN_ONE + REDUCE_PLY - 1] = CAPT_CWIN_RED + 2; v[WIN_IN_ONE + REDUCE_PLY] = CAPT_CWIN_RED + 3; v[WIN_IN_ONE + REDUCE_PLY + 1] = CAPT_CWIN_RED + 4; v[LOSS_IN_ONE - REDUCE_PLY + 1] = LOSS_IN_ONE - 1; } else { v[WIN_IN_ONE] = WIN_IN_ONE; v[LOSS_IN_ONE] = LOSS_IN_ONE; v[CAPT_CWIN_RED] = CAPT_CWIN_RED; v[CAPT_CWIN_RED + 1] = CAPT_CWIN_RED + 1; for (i = 0; i < REDUCE_PLY_RED; i++) { v[CAPT_CWIN_RED + i + 2] = CAPT_CWIN_RED + 1; v[LOSS_IN_ONE - i - 1] = LOSS_IN_ONE; } v[CAPT_CWIN_RED + REDUCE_PLY_RED + 2] = CAPT_CWIN_RED + 2; v[CAPT_CWIN_RED + REDUCE_PLY_RED + 3] = CAPT_CWIN_RED + 3; v[CAPT_CWIN_RED + REDUCE_PLY_RED + 4] = CAPT_CWIN_RED + 4; v[LOSS_IN_ONE - REDUCE_PLY_RED - 1] = LOSS_IN_ONE - 1; } #else v[BROKEN] = BROKEN; v[UNKNOWN] = UNKNOWN; v[CHANGED] = CHANGED; v[CAPT_WIN] = CAPT_WIN; v[CAPT_CWIN] = CAPT_CWIN; v[CAPT_DRAW] = CAPT_DRAW; v[CAPT_CLOSS] = CAPT_CLOSS; v[CAPT_LOSS] = CAPT_LOSS; v[THREAT_WIN] = THREAT_WIN; if (num_saves == 0) { for (i = 3; i <= DRAW_RULE; i++) v[BASE_WIN + i] = BASE_WIN + 3; v[THREAT_CWIN1] = BASE_WIN + 4; v[THREAT_CWIN2] = BASE_WIN + 4; v[BASE_WIN + DRAW_RULE + 1] = BASE_WIN + 5; for (i = DRAW_RULE + 2; i < REDUCE_PLY; i++) v[BASE_WIN + i + 2] = BASE_WIN + 5; for (i = 2; i <= DRAW_RULE; i++) v[BASE_LOSS - i] = BASE_LOSS - 2; for (; i < REDUCE_PLY; i++) v[BASE_LOSS - i] = BASE_LOSS - 3; v[BASE_WIN + REDUCE_PLY + 2] = BASE_WIN + 6; v[BASE_WIN + REDUCE_PLY + 3] = BASE_WIN + 7; v[BASE_LOSS - REDUCE_PLY] = BASE_LOSS - 4; } else { v[BASE_WIN + 3] = BASE_WIN + 3; v[BASE_WIN + 4] = BASE_WIN + 4; v[BASE_WIN + 5] = BASE_WIN + 5; v[BASE_LOSS - 2] = BASE_LOSS - 2; v[BASE_LOSS - 3] = BASE_LOSS - 3; for (i = 0; i < REDUCE_PLY_RED; i++) { v[BASE_WIN + i + 6] = BASE_WIN + 5; v[BASE_LOSS - i - 4] = BASE_LOSS - 3; } v[BASE_WIN + REDUCE_PLY_RED + 6] = BASE_WIN + 6; v[BASE_WIN + REDUCE_PLY_RED + 7] = BASE_WIN + 7; v[BASE_LOSS - REDUCE_PLY_RED - 4] = BASE_LOSS - 4; } #endif transform_v = v; run_threaded(transform, work_g, 1); if (num_saves == 0) reduce_cnt = REDUCE_PLY - DRAW_RULE - 2; else reduce_cnt += REDUCE_PLY_RED; }
void reconstruct_table(ubyte *table, char color, struct dtz_map *map) { int i, k; int num = map->max_num; ubyte (*inv_map)[256] = map->inv_map; ubyte v[256]; for (i = 0; i < 256; i++) v[i] = 0; #ifndef SUICIDE v[ILLEGAL] = num; v[BROKEN] = num; v[UNKNOWN] = num; v[CAPT_DRAW] = num; v[CAPT_CWIN_RED] = num; v[CAPT_WIN] = num; for (i = 0; i <= REDUCE_PLY_RED; i++) { v[CAPT_CWIN_RED + i + 2] = inv_map[2][(reduce_cnt + i) / 2]; v[LOSS_IN_ONE - i - 1] = inv_map[3][(reduce_cnt + i + 1) / 2]; } v[CAPT_CWIN_RED + i + 2] = inv_map[2][(reduce_cnt + i) / 2]; #else v[BROKEN] = num; v[UNKNOWN] = num; v[CAPT_WIN] = v[CAPT_CWIN] = v[CAPT_DRAW] = num; v[CAPT_CLOSS] = v[CAPT_LOSS] = num; v[THREAT_WIN] = v[BASE_WIN + 4] = v[THREAT_DRAW] = num; for (i = 0; i <= REDUCE_PLY_RED; i++) { v[BASE_WIN + i + 6] = inv_map[2][(reduce_cnt + i) / 2]; v[BASE_LOSS - i - 4] = inv_map[3][(reduce_cnt + i) / 2]; } #endif transform_v = v; transform_tbl = table; run_threaded(transform_table, work_g, 0); v[0] = 0; int red_cnt = 0; #ifndef SUICIDE for (k = 0; k < num_saves; k++) { if (k == 0) { v[255] = inv_map[1][0]; if (map->ply_accurate_win) for (i = 0; i < DRAW_RULE; i++) v[i + 1] = inv_map[0][i]; else for (i = 0; i < DRAW_RULE; i++) v[i + 1] = inv_map[0][i / 2]; if (map->ply_accurate_loss) for (i = 0; i < DRAW_RULE; i++) v[254 - i] = inv_map[1][i]; else for (i = 0; i < DRAW_RULE; i++) v[254 - i] = inv_map[1][i / 2]; for (; i <= REDUCE_PLY; i += 2) { v[1 + DRAW_RULE + (i - DRAW_RULE) / 2] = inv_map[2][(i - DRAW_RULE) / 2]; v[254 - DRAW_RULE - (i - DRAW_RULE) / 2] = inv_map[3][(i - DRAW_RULE) / 2]; } red_cnt = REDUCE_PLY - DRAW_RULE - 2; } else { for (i = 0; i <= REDUCE_PLY_RED + 1; i += 2) { v[1 + ((red_cnt & 1) + i) / 2] = inv_map[2][(red_cnt + i) / 2]; v[255 - ((red_cnt & 1) + i + 1) / 2] = inv_map[3][(red_cnt + i + 1) / 2]; } red_cnt += REDUCE_PLY_RED; } reconstruct_table_pass(table, color, k, v); } #else for (k = 0; k < num_saves; k++) { if (k == 0) { if (map->ply_accurate_win) for (i = 3; i <= DRAW_RULE; i++) v[1 + (i - 3)] = inv_map[0][i - 1]; else for (i = 3; i <= DRAW_RULE; i++) v[1 + (i - 3)] = inv_map[0][(i - 1) / 2]; if (map->ply_accurate_loss) for (i = 2; i <= DRAW_RULE; i++) v[255 - (i - 2)] = inv_map[1][i - 1]; else for (i = 2; i <= DRAW_RULE; i++) v[255 - (i - 2)] = inv_map[1][(i - 1) / 2]; for (i = DRAW_RULE + 1; i < REDUCE_PLY; i++) { v[DRAW_RULE - 1 + (i - DRAW_RULE - 1) / 2] = inv_map[2][(i - DRAW_RULE - 1) / 2]; v[254 - (DRAW_RULE - 2) - (i - DRAW_RULE - 1) / 2] = inv_map[3][(i - DRAW_RULE - 1) / 2]; } red_cnt = REDUCE_PLY - 1 - DRAW_RULE; } else { for (i = 0; i < REDUCE_PLY_RED; i += 2) { v[1 + ((red_cnt & 1) + i) / 2] = inv_map[2][(red_cnt + i) / 2]; v[255 - ((red_cnt & 1) + i) / 2] = inv_map[3][(red_cnt + i) / 2]; } red_cnt += REDUCE_PLY_RED; } reconstruct_table_pass(table, color, k, v); } #endif if (color == 'w') { printf("Verifying reconstructed table_w based on collected statistics.\n"); verify_stats(table_w, total_stats_w, map); } else { printf("Verifying reconstructed table_b based on collected statistics.\n"); verify_stats(table_b, total_stats_b, map); } }
void collect_stats_table(long64 *total_stats, ubyte *table, int wtm, int phase, int local, long64 *work) { int i, j; int n; int sval; sval = (local == 0) ? 0 : stats_val[local - 1]; for (i = 0; i < 256 * numthreads; i++) thread_stats[i] = 0; count_stats_table = table; run_threaded(count_stats, work, 0); if (local == 0) n = REDUCE_PLY - 2; else n = REDUCE_PLY_RED; if (phase == 1) n += 2; #ifndef SUICIDE for (i = 0; i < numthreads; i++) { long64 *stats = thread_data[i].stats; if (local == 0) { total_stats[STAT_CAPT_WIN] += stats[CAPT_WIN]; total_stats[STAT_CAPT_CWIN] += stats[CAPT_CWIN]; total_stats[STAT_PAWN_WIN] += stats[PAWN_WIN]; total_stats[STAT_PAWN_CWIN] += stats[PAWN_CWIN]; total_stats[STAT_MATE] += stats[MATE]; for (j = 0; j < DRAW_RULE; j++) { total_stats[1 + j] += stats[WIN_IN_ONE + j]; total_stats[STAT_MATE - 1 - j] += stats[LOSS_IN_ONE - j]; } for (; j < n; j++) { total_stats[1 + j] += stats[WIN_IN_ONE + j + 2]; total_stats[STAT_MATE - 1 - j] += stats[LOSS_IN_ONE - j]; } total_stats[STAT_MATE - 1 - j] += stats[LOSS_IN_ONE - j]; } else { for (j = 0; j < n; j++) { total_stats[1 + sval + j] += stats[CAPT_CWIN_RED + j + 2]; total_stats[STAT_MATE - 1 - sval - j - 1] += stats[LOSS_IN_ONE - j - 1]; } } } #else for (i = 0; i < numthreads; i++) { long64 *stats = thread_data[i].stats; if (local == 0) { total_stats[0] += stats[STALE_WIN]; total_stats[1] += stats[STALE_WIN + 1]; for (j = 2; j <= DRAW_RULE + 1; j++) total_stats[j] += stats[BASE_WIN + j]; for (; j < REDUCE_PLY; j++) total_stats[j] += stats[BASE_WIN + j + 2]; for (j = 0; j < REDUCE_PLY; j++) total_stats[STAT_MATE - j] += stats[BASE_LOSS - j]; total_stats[STAT_CAPT_WIN] += stats[CAPT_WIN]; total_stats[STAT_CAPT_CWIN] += stats[CAPT_CWIN]; total_stats[STAT_CAPT_DRAW] += stats[CAPT_DRAW]; total_stats[STAT_CAPT_LOSS] += stats[CAPT_LOSS]; total_stats[STAT_CAPT_CLOSS] += stats[CAPT_CLOSS]; total_stats[STAT_THREAT_WIN2] += stats[THREAT_WIN2]; total_stats[STAT_THREAT_WIN1] += stats[THREAT_WIN1]; total_stats[STAT_THREAT_CWIN2] += stats[THREAT_CWIN2]; total_stats[STAT_THREAT_CWIN1] += stats[THREAT_CWIN1]; } else { for (j = 0; j < n; j++) { total_stats[sval + j] += stats[BASE_CWIN_RED + 1 + j]; total_stats[STAT_MATE - sval - j] += stats[BASE_CLOSS_RED -1 - j]; } } } #endif if (local == 0) { for (i = DRAW_RULE; i >= 0; i--) if (total_stats[i]) break; if (i >= 0) { #ifndef SUICIDE j = WIN_IN_ONE + i - 1; #else j = (i < 2) ? STALE_WIN + i : BASE_WIN + i; #endif if (wtm) { if (i > lw_ply) { lw_ply = i; lw_clr = 1; lw_idx = find_val(table, j, work); } } else { if (i > lb_ply) { lb_ply = i; lb_clr = 0; lb_idx = find_val(table, j, work); } } } for (i = DRAW_RULE; i >= 0; i--) if (total_stats[STAT_MATE - i]) break; if (i >= 0) { #ifndef SUICIDE j = MATE - i; #else j = BASE_LOSS - i; #endif if (wtm) { if (i > lb_ply) { lb_ply = i; lb_clr = 1; lb_idx = find_val(table, j, work); } } else { if (i > lw_ply) { lw_ply = i; lw_clr = 0; lw_idx = find_val(table, j, work); } } } } for (i = MAX_PLY; i > DRAW_RULE; i--) if (total_stats[i]) break; if (i > DRAW_RULE) { #ifndef SUICIDE if (local == 0) j = WIN_IN_ONE + i + 1; else j = CAPT_CWIN_RED + 1 + i - sval; #else if (local == 0) j = (i == DRAW_RULE + 1) ? BASE_WIN + i : BASE_WIN + i + 2; else j = BASE_CWIN_RED + i + 1 - sval; #endif if (wtm) { if (i > lcw_ply) { lcw_ply = i; lcw_clr = 1; lcw_idx = find_val(table, j, work); } } else { if (i > lcb_ply) { lcb_ply = i; lcb_clr = 0; lcb_idx = find_val(table, j, work); } } } for (i = MAX_PLY; i > DRAW_RULE; i--) if (total_stats[STAT_MATE - i]) break; if (i > DRAW_RULE) { #ifndef SUICIDE j = MATE - i + sval; #else if (local == 0) j = BASE_LOSS - i; else j = BASE_CLOSS_RED - 1 - i + sval; #endif if (wtm) { if (i > lcb_ply) { lcb_ply = i; lcb_clr = 1; lcb_idx = find_val(table, j, work); } } else { if (i > lcw_ply) { lcw_ply = i; lcw_clr = 0; lcw_idx = find_val(table, j, work); } } } #ifndef SUICIDE if (phase == 1) for (i = 0; i < numthreads; i++) { total_stats[STAT_DRAW] += thread_data[i].stats[UNKNOWN]; total_stats[STAT_DRAW] += thread_data[i].stats[PAWN_DRAW]; total_stats[STAT_CAPT_DRAW] += thread_data[i].stats[CAPT_DRAW]; } #else if (phase == 1) for (i = 0; i < numthreads; i++) { total_stats[STAT_DRAW] += thread_data[i].stats[UNKNOWN]; total_stats[STAT_DRAW] += thread_data[i].stats[PAWN_DRAW]; total_stats[STAT_THREAT_DRAW] += thread_data[i].stats[THREAT_DRAW]; } #endif }
void reduce_tables(int local) { int i; ubyte v[256]; long64 *work; long64 save_begin = begin; if (!copybuf) copybuf = malloc(COPYSIZE); if (local == num_saves) { work = work_part; fill_work(total_work, begin + (1ULL << shift[numpawns - 1]), 0, work); begin = 0; reduce_val[local] = ply; work = work_part; } else work = work_p; collect_stats(work, 0, local); if (generate_dtz) { save_table(table_w, 'w', local, begin, work[total_work]); if (!symmetric) save_table(table_b, 'b', local, begin, work[total_work]); } for (i = 0; i < 256; i++) v[i] = 0; #ifndef SUICIDE v[BROKEN] = BROKEN; v[UNKNOWN] = UNKNOWN; v[CHANGED] = CHANGED; v[CAPT_DRAW] = CAPT_DRAW; v[PAWN_DRAW] = PAWN_DRAW; v[MATE] = MATE; v[ILLEGAL] = ILLEGAL; v[CAPT_WIN] = CAPT_WIN; if (local == 0) { v[PAWN_WIN] = WIN_RED; for (i = 0; i < DRAW_RULE; i++) { v[WIN_IN_ONE + i] = WIN_RED; v[LOSS_IN_ONE - i] = MATE; } v[CAPT_CWIN] = CAPT_CWIN_RED; v[PAWN_CWIN] = CAPT_CWIN_RED + 1; for (; i < REDUCE_PLY - 2; i++) { v[WIN_IN_ONE + i + 2] = CAPT_CWIN_RED + 1; v[LOSS_IN_ONE - i] = LOSS_IN_ONE; } v[LOSS_IN_ONE - i] = LOSS_IN_ONE; v[WIN_IN_ONE + REDUCE_PLY] = CAPT_CWIN_RED + 2; v[WIN_IN_ONE + REDUCE_PLY + 1] = CAPT_CWIN_RED + 3; v[WIN_IN_ONE + REDUCE_PLY + 2] = CAPT_CWIN_RED + 4; v[LOSS_IN_ONE - REDUCE_PLY + 1] = LOSS_IN_ONE - 1; } else { v[WIN_RED] = WIN_RED; v[LOSS_IN_ONE] = LOSS_IN_ONE; v[CAPT_CWIN_RED] = CAPT_CWIN_RED; v[CAPT_CWIN_RED + 1] = CAPT_CWIN_RED + 1; for (i = 0; i < REDUCE_PLY_RED; i++) { v[CAPT_CWIN_RED + i + 2] = CAPT_CWIN_RED + 1; v[LOSS_IN_ONE - i - 1] = LOSS_IN_ONE; } v[CAPT_CWIN_RED + REDUCE_PLY_RED + 2] = CAPT_CWIN_RED + 2; v[CAPT_CWIN_RED + REDUCE_PLY_RED + 3] = CAPT_CWIN_RED + 3; v[CAPT_CWIN_RED + REDUCE_PLY_RED + 4] = CAPT_CWIN_RED + 4; v[LOSS_IN_ONE - REDUCE_PLY_RED - 1] = LOSS_IN_ONE - 1; } #else v[BROKEN] = BROKEN; v[UNKNOWN] = UNKNOWN; v[CHANGED] = CHANGED; v[CAPT_WIN] = CAPT_WIN; v[CAPT_CWIN] = CAPT_CWIN; v[CAPT_DRAW] = CAPT_DRAW; v[CAPT_CLOSS] = CAPT_CLOSS; v[CAPT_LOSS] = CAPT_LOSS; v[PAWN_DRAW] = PAWN_DRAW; if (local == 0) { v[THREAT_WIN1] = THREAT_WIN_RED; v[THREAT_WIN2] = THREAT_WIN_RED; v[STALE_WIN] = BASE_WIN_RED; v[STALE_WIN + 1] = BASE_WIN_RED; for (i = 2; i <= DRAW_RULE; i++) v[BASE_WIN + i] = BASE_WIN_RED; v[THREAT_CWIN1] = THREAT_CWIN_RED; v[THREAT_CWIN2] = THREAT_CWIN_RED; v[BASE_WIN + DRAW_RULE + 1] = BASE_CWIN_RED; for (i = DRAW_RULE + 2; i < REDUCE_PLY; i++) v[BASE_WIN + i + 2] = BASE_CWIN_RED; for (i = 0; i <= DRAW_RULE; i++) v[BASE_LOSS - i] = BASE_LOSS_RED; for (; i < REDUCE_PLY; i++) v[BASE_LOSS - i] = BASE_CLOSS_RED; v[BASE_WIN + REDUCE_PLY + 2] = BASE_CWIN_RED + 1; v[BASE_WIN + REDUCE_PLY + 3] = BASE_CWIN_RED + 2; v[BASE_LOSS - REDUCE_PLY] = BASE_CLOSS_RED - 1; } else { v[THREAT_WIN_RED] = THREAT_WIN_RED; v[BASE_WIN_RED] = BASE_WIN_RED; v[THREAT_CWIN_RED] = THREAT_CWIN_RED; v[BASE_CWIN_RED] = BASE_CWIN_RED; v[BASE_LOSS_RED] = BASE_LOSS_RED; v[BASE_CLOSS_RED] = BASE_CLOSS_RED; for (i = 0; i < REDUCE_PLY_RED; i++) { v[BASE_CWIN_RED + i + 1] = BASE_CWIN_RED; v[BASE_CLOSS_RED - i - 1] = BASE_CLOSS_RED; } v[BASE_CWIN_RED + REDUCE_PLY_RED + 1] = BASE_CWIN_RED + 1; v[BASE_CWIN_RED + REDUCE_PLY_RED + 2] = BASE_CWIN_RED + 2; v[BASE_CLOSS_RED - REDUCE_PLY_RED - 1] = BASE_CLOSS_RED - 1; } #endif transform_v = v; run_threaded(transform, work, 0); if (local == num_saves) { if (num_saves == 0) reduce_cnt[0] = ply - DRAW_RULE - 2; else reduce_cnt[num_saves] = reduce_cnt[num_saves - 1] + ply; begin = save_begin; num_saves++; } }
int main(int argc, char **argv) { int i, j; int color; int val, longindex; int pcs[16]; int wdl_only = 0; #ifdef SUICIDE int switched = 0; #endif numthreads = 1; do { // val = getopt_long(argc, argv, "t:lwc", options, &longindex); val = getopt_long(argc, argv, "t:ld", options, &longindex); switch (val) { case 't': numthreads = atoi(optarg); break; case 'l': log = 1; break; case 'w': wdl_only = 1; break; case 'd': use_envdirs = 1; break; } } while (val != EOF); if (optind >= argc) { fprintf(stderr, "No tablebase specified.\n"); exit(1); } tablename = argv[optind]; init_tablebases(); for (i = 0; i < 16; i++) pcs[i] = 0; numpcs = strlen(tablename) - 1; color = 0; j = 0; for (i = 0; i < strlen(tablename); i++) switch (tablename[i]) { case 'P': pcs[PAWN | color]++; pt[j++] = PAWN | color; break; case 'N': pcs[KNIGHT | color]++; pt[j++] = KNIGHT | color; break; case 'B': pcs[BISHOP | color]++; pt[j++] = BISHOP | color; break; case 'R': pcs[ROOK | color]++; pt[j++] = ROOK | color; break; case 'Q': pcs[QUEEN | color]++; pt[j++] = QUEEN | color; break; case 'K': pcs[KING | color]++; pt[j++] = KING | color; break; case 'v': if (color) exit(1); color = 0x08; break; default: exit(1); } if (!color) exit(1); if (pcs[WPAWN] || pcs[BPAWN]) { fprintf(stderr, "Can't handle pawns.\n"); exit(1); } if (numthreads < 1) numthreads = 1; else if (numthreads > MAX_THREADS) numthreads = MAX_THREADS; printf("number of threads = %d\n", numthreads); if (numthreads == 1) total_work = 1; else total_work = 100 + 10 * numthreads; for (i = 0; i < numpcs; i++) { shift[i] = (numpcs - i - 1) * 6; mask[i] = 0x3fULL << shift[i]; } #ifndef SMALL size = 10ULL << (6 * (numpcs-1)); #else size = 462ULL << (6 * (numpcs-2)); mask[0] = 0x1ffULL << shift[1]; #endif work_g = create_work(total_work, size, 0x3f); #ifndef SMALL work_piv = create_work(total_work, 1ULL << shift[0], 0); #else work_piv0 = create_work(total_work, 1ULL << shift[0], 0); work_piv1 = create_work(total_work, 10ULL << shift[1], 0); #endif static int piece_order[16] = { 0, 0, 3, 5, 7, 9, 1, 0, 0, 0, 4, 6, 8, 10, 2, 0 }; #ifdef SUICIDE j = pt[0]; for (i = 1; i < numpcs; i++) if (piece_order[pt[i]] < piece_order[j]) j = pt[i]; if (j & 0x08) { for (i = 0; i < numpcs; i++) pt[i] ^= 0x08; for (i = 0; i < 8; i++) { int tmp = pcs[i]; pcs[i] = pcs[i + 8]; pcs[i + 8] = tmp; } switched = 1; } #endif for (i = 0; i < numpcs; i++) for (j = i + 1; j < numpcs; j++) if (piece_order[pt[i]] > piece_order[pt[j]]) { int tmp = pt[i]; pt[i] = pt[j]; pt[j] = tmp; } for (i = 0, j = 0; i < numpcs; i++) if (!(pt[i] & 0x08)) white_pcs[j++] = i; white_pcs[j] = -1; for (i = 0, j = 0; i < numpcs; i++) if (pt[i] & 0x08) black_pcs[j++] = i; black_pcs[j] = -1; idx_mask1[numpcs - 1] = 0xffffffffffffffc0ULL; idx_mask2[numpcs - 1] = 0; for (i = numpcs - 2; i >= 0; i--) { idx_mask1[i] = idx_mask1[i + 1] << 6; idx_mask2[i] = (idx_mask2[i + 1] << 6) | 0x3f; } #ifndef SUICIDE for (i = 0; i < numpcs; i++) if (pt[i] == WKING) white_king = i; for (i = 0; i < numpcs; i++) if (pt[i] == BKING) black_king = i; #endif table_w = alloc_huge(2 * size); table_b = table_w + size; printf("Verifying %s.\n", tablename); if (log) { L = fopen(LOGFILE, "a"); fprintf(L, "Verifying %s...", tablename); fflush(L); } init_threads(0); init_tables(); gettimeofday(&start_time, NULL); cur_time = start_time; printf("Initialising broken positions.\n"); run_threaded(calc_broken, work_g, 1); printf("Calculating white captures.\n"); calc_captures_w(); printf("Calculating black captures.\n"); calc_captures_b(); #ifndef SUICIDE printf("Calculating mate positions.\n"); run_threaded(calc_mates, work_g, 1); #else init_capt_threat(); printf("Calculating white threats.\n"); iter_table = table_b; iter_table_opp = table_w; iter_pcs_opp = white_pcs; run_threaded(calc_threats, work_g, 1); printf("Calculating black threats.\n"); iter_table = table_w; iter_table_opp = table_b; iter_pcs_opp = black_pcs; run_threaded(calc_threats, work_g, 1); #endif decomp_init_piece(pcs); // open wdl table struct tb_handle *H = open_tb(tablename, 1); decomp_init_table(H); load_entry = (struct TBEntry_piece *)get_entry(H); if (!wdl_only) { // white, wdl printf("Loading wdl, white.\n"); tb_table = decompress_table(H, 0, 0); set_perm(H, 0, 0, tb_perm, pt); load_table = table_w; load_bside = 0; run_threaded(load_wdl, work_g, 1); // black, wdl printf("Loading wdl, black.\n"); tb_table = decompress_table(H, 1, 0); set_perm(H, 1, 0, tb_perm, pt); load_table = table_b; load_bside = 1; run_threaded(load_wdl, work_g, 1); close_tb(H); // open dtz table H = open_tb(tablename, 0); decomp_init_table(H); load_entry = (struct TBEntry_piece *)get_entry(H); ply_accurate_win = get_ply_accurate_win(H, 0); ply_accurate_loss = get_ply_accurate_loss(H, 0); load_map = get_dtz_map(H, 0); int dtz_side = get_dtz_side(H, 0); init_wdl_dtz(); // dtz printf("Loading dtz, %s.\n" , dtz_side == 0 ? "white" : "black"); tb_table = decompress_table(H, 0, 0); set_perm(H, 0, 0, tb_perm, pt); load_table = dtz_side == 0 ? table_w : table_b; load_bside = 0; if (load_map) run_threaded(load_dtz_mapped, work_g, 1); else run_threaded(load_dtz, work_g, 1); close_tb(H); if (dtz_side == 0) { load_table = table_w; load_opp_table = table_b; load_pieces = white_pcs; load_opp_pieces = black_pcs; } else { load_table = table_b; load_opp_table = table_w; load_pieces = black_pcs; load_opp_pieces = white_pcs; } printf("Verifying %s.\n", dtz_side ? "white" : "black"); run_threaded(verify_opp, work_g, 1); printf("Verifying %s.\n", dtz_side ? "black" : "white"); run_threaded(verify_dtz, work_g, 1); } else { // currently broken (and disabled) // white, wdl printf("Loading wdl, white.\n"); tb_table = decompress_table(H, 0, 0); set_perm(H, 0, 0, tb_perm, pt); load_table = table_w; load_bside = 0; run_threaded(wdl_load_wdl, work_g, 1); // black, wdl printf("Loading wdl, black.\n"); tb_table = decompress_table(H, 1, 0); set_perm(H, 1, 0, tb_perm, pt); load_table = table_b; load_bside = 1; run_threaded(wdl_load_wdl, work_g, 1); close_tb(H); ply_accurate_win = get_ply_accurate_win(H, 0); ply_accurate_loss = get_ply_accurate_loss(H, 0); init_wdl(); load_table = table_w; load_opp_table = table_b; load_pieces = white_pcs; printf("Verifying white.\n"); run_threaded(verify_wdl, work_g, 1); ply_accurate_win = get_ply_accurate_loss(H, 0); ply_accurate_loss = get_ply_accurate_win(H, 0); init_wdl(); load_table = table_b; load_opp_table = table_w; load_pieces = black_pcs; printf("Verifying black.\n"); run_threaded(verify_wdl, work_g, 1); } if (num_errors == 0) { printf("No errors.\n"); if (log) fprintf(L, " No errors.\n"); } if (log) fclose(L); return 0; }