diff -Nru fathom-1.0/debian/changelog fathom-1.0+git.20190120.0439ca/debian/changelog --- fathom-1.0/debian/changelog 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/changelog 2019-01-25 19:39:28.000000000 +0000 @@ -1,3 +1,18 @@ +fathom (1.0+git.20190120.0439ca-1) unstable; urgency=medium + + * debian/control: + - Use debhelper compat version 12. + - Change maintainer's e-mail and upstream homepage. + * debian/copyright: + - Update url source, copyright notices and my e-mail. + * debian/rules: + - Add -I option to find headers. + * debian/watch: + - Change upstream git repo. + Use Jon Dart's fork. It has some bug fixes and enhancements. + + -- Jose G. López Fri, 25 Jan 2019 20:39:28 +0100 + fathom (1.0-1) unstable; urgency=medium * Initial release (Closes: #914595) diff -Nru fathom-1.0/debian/compat fathom-1.0+git.20190120.0439ca/debian/compat --- fathom-1.0/debian/compat 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru fathom-1.0/debian/control fathom-1.0+git.20190120.0439ca/debian/control --- fathom-1.0/debian/control 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/control 2019-01-25 19:39:28.000000000 +0000 @@ -1,10 +1,10 @@ Source: fathom Priority: optional -Maintainer: Jose G. López -Build-Depends: debhelper (>= 11) +Maintainer: Jose G. López +Build-Depends: debhelper-compat (= 12) Standards-Version: 4.3.0 Section: libs -Homepage: https://github.com/basil00/Fathom +Homepage: https://github.com/jdart1/Fathom Vcs-Browser: https://salsa.debian.org/josgalo-guest/fathom Vcs-Git: https://salsa.debian.org/josgalo-guest/fathom.git diff -Nru fathom-1.0/debian/copyright fathom-1.0+git.20190120.0439ca/debian/copyright --- fathom-1.0/debian/copyright 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/copyright 2019-01-25 19:39:28.000000000 +0000 @@ -1,9 +1,10 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: fathom -Source: https://github.com/basil00/Fathom +Source: https://github.com/jdart1/Fathom Files: * -Copyright: 2015 basil +Copyright: 2016-2019 Jon Dart + 2015 basil 2011-2015 Ronald de Man License: MIT Permission is hereby granted, free of charge, to any person @@ -27,7 +28,7 @@ SOFTWARE. Files: debian/* -Copyright: 2018 Jose G. López +Copyright: 2018-2019 Jose G. López License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -Nru fathom-1.0/debian/rules fathom-1.0+git.20190120.0439ca/debian/rules --- fathom-1.0/debian/rules 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/rules 2019-01-25 19:39:28.000000000 +0000 @@ -35,7 +35,7 @@ ar rcs $@ $^ tbprobe.o: src/tbprobe.c src/tbprobe.h - $(CC) $(CFLAGS) -fPIC -c -o $@ $< + $(CC) $(CFLAGS) -fPIC -I src -c -o $@ $< libfathom: tbprobe.o libfathom.so.1 libfathom.so $(CC) $(LDFLAGS) -shared tbprobe.o -Wl,-soname,libfathom.so.1 -o libfathom.so.1.0.0 diff -Nru fathom-1.0/debian/watch fathom-1.0+git.20190120.0439ca/debian/watch --- fathom-1.0/debian/watch 2018-12-31 09:02:17.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/debian/watch 2019-01-25 19:39:28.000000000 +0000 @@ -1,5 +1,5 @@ version=4 # Direct Git -opts="mode=git" https://github.com/basil00/Fathom.git \ +opts="mode=git" https://github.com/jdart1/Fathom.git \ refs/tags/v([\d\.]+) debian uupdate \ No newline at end of file diff -Nru fathom-1.0/LICENSE fathom-1.0+git.20190120.0439ca/LICENSE --- fathom-1.0/LICENSE 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/LICENSE 2019-01-21 00:20:10.000000000 +0000 @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2015 basil00 +Modifications Copyright (c) 2016-2018 by Jon Dart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -Nru fathom-1.0/README.md fathom-1.0+git.20190120.0439ca/README.md --- fathom-1.0/README.md 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/README.md 2019-01-21 00:20:10.000000000 +0000 @@ -78,6 +78,7 @@ (C) 2013-2015 Ronald de Man (original code) (C) 2015 basil (new modifications) +(C) 2016-2019 Jon Dart (additional modifications) Ronald de Man's original code can be "redistributed and/or modified without restrictions". diff -Nru fathom-1.0/src/apps/fathom.c fathom-1.0+git.20190120.0439ca/src/apps/fathom.c --- fathom-1.0/src/apps/fathom.c 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/apps/fathom.c 2019-01-21 00:20:10.000000000 +0000 @@ -1,6 +1,7 @@ /* * fathom.c - * (C) 2015 basil, all rights reserved, + * (C) 2015 basil, all rights reserved. + * (C) 2018-2019 Jon Dart, All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -260,6 +261,31 @@ } /* + * Test if the king is in check. + */ +static bool is_check(const struct pos *pos) +{ + uint64_t occ = pos->white | pos->black; + uint64_t us = (pos->turn? pos->white: pos->black), + them = (pos->turn? pos->black: pos->white); + uint64_t king = pos->kings & us; + unsigned sq = tb_lsb(king); + uint64_t ratt = tb_rook_attacks(sq, occ); + uint64_t batt = tb_bishop_attacks(sq, occ); + if (ratt & (pos->rooks & them)) + return true; + if (batt & (pos->bishops & them)) + return true; + if ((ratt | batt) & (pos->queens & them)) + return true; + if (tb_knight_attacks(sq) & (pos->knights & them)) + return true; + if (tb_pawn_attacks(sq, pos->turn) & (pos->pawns & them)) + return true; + return false; +} + +/* * Convert a move into a string. */ static void move_to_str(const struct pos *pos, unsigned move, char *str) @@ -296,15 +322,14 @@ att = tb_knight_attacks(to) & us & pos->knights; } else + att = tb_pawn_attacks(to, !pos->turn) & us & pos->pawns; + if ((b & pos->pawns) && capture) + *str++ = 'a' + f; + else if (tb_pop_count(att) > 1) { - if (capture) - *str++ = 'a' + f; - } - if (tb_pop_count(att) > 1) - { - if (tb_pop_count(att & (BOARD_FILE_A >> f)) <= 1) + if (tb_pop_count(att & (BOARD_FILE_A >> f)) == 1) *str++ = 'a' + f; - else if (tb_pop_count(att & (BOARD_RANK_1 >> r)) <= 1) + else if (tb_pop_count(att & (BOARD_RANK_1 << (8*r))) == 1) *str++ = '1' + r; else { @@ -383,7 +408,7 @@ ep = from-8; else if (TB_GET_EP(move)) { - unsigned ep_to = (pos->turn? to+8: to-8); + unsigned ep_to = (pos->turn? to-8: to+8); uint64_t ep_mask = ~board(ep_to); white &= ep_mask; black &= ep_mask; @@ -414,7 +439,7 @@ static void print_PV(struct pos *pos) { putchar('\n'); - bool first = true; + bool first = true, check = false; if (!pos->turn) { first = false; @@ -435,6 +460,8 @@ printf("# %s\n", (pos->turn? "0-1": "1-0")); return; } + if (check) + putchar('+'); if (pos->rule50 >= 100 || move == TB_RESULT_STALEMATE) { printf(" 1/2-1/2\n"); @@ -450,6 +477,7 @@ printf("%u. ", pos->move); printf("%s", str); do_move(pos, move); + check = is_check(pos); } } @@ -540,7 +568,7 @@ {"test", 0, 0, OPTION_TEST}, {NULL, 0, 0, 0} }; - const char *path = NULL; + char *path = NULL; bool test = false; while (true) { @@ -551,8 +579,9 @@ switch (opt) { case OPTION_PATH: - path = strdup(optarg); + path = (char*)malloc(sizeof(char)*(strlen(optarg)+1)); assert(path != NULL); + strcpy(path,optarg); break; case OPTION_TEST: test = true; diff -Nru fathom-1.0/src/apps/Makefile fathom-1.0+git.20190120.0439ca/src/apps/Makefile --- fathom-1.0/src/apps/Makefile 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/apps/Makefile 2019-01-21 00:20:10.000000000 +0000 @@ -7,7 +7,7 @@ endif CC=clang STRIP=strip -CFLAGS=-std=gnu99 -O2 -Wall -D TB_NO_THREADS -D TB_NO_HW_POP_COUNT -I.. +CFLAGS=-std=c99 -O2 -Wall -D TB_NO_THREADS -I.. main: $(TARGET) diff -Nru fathom-1.0/src/tbconfig.h fathom-1.0+git.20190120.0439ca/src/tbconfig.h --- fathom-1.0/src/tbconfig.h 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/tbconfig.h 2019-01-21 00:20:10.000000000 +0000 @@ -1,6 +1,7 @@ /* * tbconfig.h * (C) 2015 basil, all rights reserved, + * Modifications Copyright 2016-2017 Jon Dart * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,6 +30,34 @@ /****************************************************************************/ /* + * Define TB_CUSTOM_POP_COUNT to override the internal popcount + * implementation. To do this supply a macro or function definition + * here: + */ +/* #define TB_CUSTOM_POP_COUNT(x) */ + +/* + * Define TB_CUSTOM_LSB to override the internal lsb + * implementation. To do this supply a macro or function definition + * here: + */ +/* #define TB_CUSTOM_LSB(x) */ + +/* + * Define TB_CUSTOM_BSWAP32 to override the internal bswap32 + * implementation. To do this supply a macro or function definition + * here: + */ +/* #define TB_CUSTOM_BSWAP32(x) */ + +/* + * Define TB_CUSTOM_BSWAP64 to override the internal bswap64 + * implementation. To do this supply a macro or function definition + * here: + */ +/* #define TB_CUSTOM_BSWAP64(x) */ + +/* * Define TB_NO_STDINT if you do not want to use or it is not * available. */ @@ -52,9 +81,23 @@ /* * Define TB_NO_HW_POP_COUNT if there is no hardware popcount instruction. + * + * Note: if defined, TB_CUSTOM_POP_COUNT is always used in preference + * to any built-in popcount functions. + * + * If no custom popcount function is defined, and if the following + * define is not set, the code will attempt to use an available hardware + * popcnt (currently supported on x86_64 architecture only) and otherwise + * will fall back to a software implementation. */ /* #define TB_NO_HW_POP_COUNT */ +/** + * Define TB_USE_ATOMIC to use C++ 11 (or higher) feature + * (recommended if using C++ and compiler supports it). + */ +/* #define TB_USE_ATOMIC */ + /***************************************************************************/ /* ENGINE INTEGRATION CONFIG */ /***************************************************************************/ diff -Nru fathom-1.0/src/tbcore.c fathom-1.0+git.20190120.0439ca/src/tbcore.c --- fathom-1.0/src/tbcore.c 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/tbcore.c 2019-01-21 00:20:10.000000000 +0000 @@ -1,24 +1,52 @@ /* - Copyright (c) 2011-2015 Ronald de Man - This file may be redistributed and/or modified without restrictions. - + * Copyright (c) 2011-2015 Ronald de Man + * Copyright (c) 2016-2017 Jon Dart + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/* tbcore.c contains engine-independent routines of the tablebase probing code. This file should not need to much adaptation to add tablebase probing to a particular engine, provided the engine is written in C or C++. */ +#include #include -#include +#ifndef TB_NO_STDINT #include +#endif #include #include #include #include -#ifndef __WIN32__ +#ifndef _WIN32 +#include #include #endif #include "tbcore.h" +#if !defined(DECOMP64) && defined(_LP64) +// use 64-bit decompression if OS is 64-bit +// (appears not to work so commented out for now) +//#define DECOMP64 +#endif + #define TBMAX_PIECE 254 #define TBMAX_PAWN 256 #define HSHMAX 5 @@ -42,6 +70,18 @@ static LOCK_T TB_MUTEX; #endif +#ifdef TB_CUSTOM_BSWAP32 +#define internal_bswap32(x) TB_CUSTOM_BSWAP32(x) +#else +#define internal_bswap32(x) __builtin_bswap32(x) +#endif + +#ifdef TB_CUSTOM_BSWAP64 +#define internal_bswap64(x) TB_CUSTOM_BSWAP64(x) +#else +#define internal_bswap64(x) __builtin_bswap64(x) +#endif + static int initialized = 0; static int num_paths = 0; static char *path_string = NULL; @@ -66,27 +106,36 @@ { int i; FD fd; - char file[256]; + char *file; for (i = 0; i < num_paths; i++) { + file = (char*)malloc(strlen(paths[i]) + strlen(str) + + strlen(suffix) + 2); strcpy(file, paths[i]); - strcat(file, "/"); +#ifdef _WIN32 + strcat(file,"\\"); +#else + strcat(file,"/"); +#endif strcat(file, str); strcat(file, suffix); -#ifndef __WIN32__ +#ifndef _WIN32 fd = open(file, O_RDONLY); #else fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); #endif - if (fd != FD_ERR) return fd; + free(file); + if (fd != FD_ERR) { + return fd; + } } return FD_ERR; } static void close_tb(FD fd) { -#ifndef __WIN32__ +#ifndef _WIN32 close(fd); #else CloseHandle(fd); @@ -98,14 +147,18 @@ FD fd = open_tb(name, suffix); if (fd == FD_ERR) return NULL; -#ifndef __WIN32__ +#ifndef _WIN32 struct stat statbuf; - fstat(fd, &statbuf); + if (fstat(fd, &statbuf)) { + perror("fstat"); + close_tb(fd); + return NULL; + } *mapping = statbuf.st_size; char *data = (char *)mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); if (data == (char *)(-1)) { - printf("Could not mmap() %s.\n", name); + fprintf(stderr,"Could not mmap() %s.\n", name); exit(1); } #else @@ -115,13 +168,13 @@ HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low, NULL); if (map == NULL) { - printf("CreateFileMapping() failed.\n"); + fprintf(stderr,"CreateFileMapping() failed.\n"); exit(1); } *mapping = (uint64)map; char *data = (char *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); if (data == NULL) { - printf("MapViewOfFile() failed, name = %s%s, error = %lu.\n", name, suffix, GetLastError()); + fprintf(stderr,"MapViewOfFile() failed, name = %s%s, error = %lu.\n", name, suffix, GetLastError()); exit(1); } #endif @@ -129,18 +182,24 @@ return data; } -#ifndef __WIN32__ +#ifndef _WIN32 static void unmap_file(char *data, uint64 size) { if (!data) return; - munmap(data, size); + if (!munmap(data, size)) { + perror("munmap"); + } } #else static void unmap_file(char *data, uint64 mapping) { if (!data) return; - UnmapViewOfFile(data); - CloseHandle((HANDLE)mapping); + if (!UnmapViewOfFile(data)) { + fprintf(stderr, "unmap failed, error code %d", GetLastError()); + } + if (!CloseHandle((HANDLE)mapping)) { + fprintf(stderr, "CloseHandle failed, error code %d", GetLastError()); + } } #endif @@ -152,7 +211,7 @@ while (i < HSHMAX && TB_hash[hshidx][i].ptr) i++; if (i == HSHMAX) { - printf("HSHMAX too low!\n"); + fprintf(stderr,"HSHMAX too low!\n"); exit(1); } else { TB_hash[hshidx][i].key = key; @@ -206,13 +265,13 @@ key2 = calc_key_from_pcs(pcs, 1); if (pcs[TB_WPAWN] + pcs[TB_BPAWN] == 0) { if (TBnum_piece == TBMAX_PIECE) { - printf("TBMAX_PIECE limit too low!\n"); + fprintf(stderr,"TBMAX_PIECE limit too low!\n"); exit(1); } entry = (struct TBEntry *)&TB_piece[TBnum_piece++]; } else { if (TBnum_pawn == TBMAX_PAWN) { - printf("TBMAX_PAWN limit too low!\n"); + fprintf(stderr,"TBMAX_PAWN limit too low!\n"); exit(1); } entry = (struct TBEntry *)&TB_pawn[TBnum_pawn++]; @@ -371,7 +430,7 @@ // printf("Found %d tablebases.\n", TBnum_piece + TBnum_pawn); } -static const char offdiag[] = { +static const signed char offdiag[] = { 0,-1,-1,-1,-1,-1,-1,-1, 1, 0,-1,-1,-1,-1,-1,-1, 1, 1, 0,-1,-1,-1,-1,-1, @@ -734,6 +793,7 @@ uint64 idx; int i, j, k, m, l, p; int n = ptr->num; + assert(n>=0 && n<7); if (pos[0] & 0x04) { for (i = 0; i < n; i++) @@ -798,6 +858,8 @@ p = pos[m]; for (l = 0, j = 0; l < i; l++) j += (p > pos[l]); + assert(m-i >= 0 && m-i < 5); + assert(p-j >= 0 && p-j < 64); s += binomial[m - i][p - j]; } idx += ((uint64)s) * ((uint64)factor[i]); @@ -812,6 +874,7 @@ uint64 idx; int i, j, k, m, l, p; int n = ptr->num; + assert(n>=0 && n<7); if (ptr->enc_type < 3) { if (pos[0] & 0x04) { @@ -1024,7 +1087,7 @@ f = 1; for (i = norm[0], k = 0; i < num || k == order; k++) { if (k == order) { - factor[0] = f; + factor[0] = (int)f; #ifndef CONNECTED_KINGS f *= pivfac[enc_type]; #else @@ -1034,7 +1097,7 @@ f *= mfactor[enc_type - 2]; #endif } else { - factor[i] = f; + factor[i] = (int)f; f *= subfactor(norm[i], n); n -= norm[i]; i += norm[i]; @@ -1056,13 +1119,13 @@ f = 1; for (k = 0; i < num || k == order || k == order2; k++) { if (k == order) { - factor[0] = f; + factor[0] = (int)f; f *= pfactor[norm[0] - 1][file]; } else if (k == order2) { - factor[norm[0]] = f; + factor[norm[0]] = (int)f; f *= subfactor(norm[norm[0]], 48 - norm[0]); } else { - factor[i] = f; + factor[i] = (int)f; f *= subfactor(norm[i], n); n -= norm[i]; i += norm[i]; @@ -1228,7 +1291,7 @@ d->min_len = min_len; *next = &data[12 + 2 * h + 3 * num_syms + (num_syms & 1)]; - int num_indices = (tb_size + (1ULL << idxbits) - 1) >> idxbits; + int num_indices = (int)((tb_size + (1ULL << idxbits) - 1) >> idxbits); size[0] = 6ULL * num_indices; size[1] = 2ULL * num_blocks; size[2] = (1ULL << blocksize) * real_num_blocks; @@ -1268,13 +1331,13 @@ // first mmap the table into memory entry->data = map_file(str, WDLSUFFIX, &entry->mapping); if (!entry->data) { - printf("Could not find %s" WDLSUFFIX "\n", str); + fprintf(stderr,"Could not find %s" WDLSUFFIX "\n", str); return 0; } ubyte *data = (ubyte *)entry->data; if (((uint32 *)data)[0] != WDL_MAGIC) { - printf("Corrupted table.\n"); + fprintf(stderr,"Corrupted table.\n"); unmap_file(entry->data, entry->mapping); entry->data = 0; return 0; @@ -1384,7 +1447,7 @@ return 0; if (((uint32 *)data)[0] != DTZ_MAGIC) { - printf("Corrupted table.\n"); + fprintf(stderr,"Corrupted table.\n"); return 0; } @@ -1405,8 +1468,8 @@ if (ptr->flags & 2) { int i; for (i = 0; i < 4; i++) { - ptr->map_idx[i] = (data + 1 - ptr->map); - data += 1 + data[0]; + ptr->map_idx[i] = (ushort)(data + 1 - ptr->map); + data += 1 + data[0]; } data += ((uintptr_t)data) & 0x01; } @@ -1437,11 +1500,11 @@ ptr->map = data; for (f = 0; f < files; f++) { if (ptr->flags[f] & 2) { - int i; - for (i = 0; i < 4; i++) { - ptr->map_idx[f][i] = (data + 1 - ptr->map); - data += 1 + data[0]; - } + int i; + for (i = 0; i < 4; i++) { + ptr->map_idx[f][i] = (ushort)(data + 1 - ptr->map); + data += 1 + data[0]; + } } } data += ((uintptr_t)data) & 0x01; @@ -1471,8 +1534,8 @@ if (!d->idxbits) return d->min_len; - uint32 mainidx = idx >> d->idxbits; - int litidx = (idx & ((1 << d->idxbits) - 1)) - (1 << (d->idxbits - 1)); + uint32 mainidx = (uint32)(idx >> d->idxbits); + int litidx = (int)(idx & (((uint64)1 << d->idxbits) - 1)) - ((uint64)1 << (d->idxbits - 1)); uint32 block = *(uint32 *)(d->indextable + 6 * mainidx); litidx += *(ushort *)(d->indextable + 6 * mainidx + 4); if (litidx < 0) { @@ -1493,7 +1556,7 @@ int sym, bitcnt; #ifdef DECOMP64 - uint64 code = __builtin_bswap64(*((uint64 *)ptr)); + uint64 code = internal_bswap64(*((uint64 *)ptr)); ptr += 2; bitcnt = 0; // number of "empty bits" in code for (;;) { @@ -1506,12 +1569,14 @@ bitcnt += l; if (bitcnt >= 32) { bitcnt -= 32; - code |= ((uint64)(__builtin_bswap32(*ptr++))) << bitcnt; + uint32 data = *ptr++; + code |= ((uint64)(internal_bswap32(data))) << bitcnt; } } #else uint32 next = 0; - uint32 code = __builtin_bswap32(*ptr++); + uint32 data = *ptr++; + uint32 code = internal_bswap32(data); bitcnt = 0; // number of bits in next for (;;) { int l = m; @@ -1525,7 +1590,8 @@ code |= (next >> (32 - l)); l -= bitcnt; } - next = __builtin_bswap32(*ptr++); + data = *ptr++; + next = internal_bswap32(data); bitcnt = 32; } code |= (next >> (32 - l)); @@ -1592,11 +1658,13 @@ static void free_wdl_entry(struct TBEntry *entry) { unmap_file(entry->data, entry->mapping); + entry->data = NULL; entry->mapping = 0; if (!entry->has_pawns) { struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry; free(ptr->precomp[0]); if (ptr->precomp[1]) free(ptr->precomp[1]); + ptr->precomp[0] = ptr->precomp[1] = NULL; } else { struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry; int f; @@ -1604,6 +1672,7 @@ free(ptr->file[f].precomp[0]); if (ptr->file[f].precomp[1]) free(ptr->file[f].precomp[1]); + ptr->file[f].precomp[0] = ptr->file[f].precomp[1] = NULL; } } } @@ -1611,14 +1680,18 @@ static void free_dtz_entry(struct TBEntry *entry) { unmap_file(entry->data, entry->mapping); + entry->data = NULL; entry->mapping = 0; if (!entry->has_pawns) { struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry; free(ptr->precomp); + ptr->precomp = NULL; } else { struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry; int f; - for (f = 0; f < 4; f++) + for (f = 0; f < 4; f++) { free(ptr->file[f].precomp); + ptr->file[f].precomp = NULL; + } } free(entry); } diff -Nru fathom-1.0/src/tbcore.h fathom-1.0+git.20190120.0439ca/src/tbcore.h --- fathom-1.0/src/tbcore.h 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/tbcore.h 2019-01-21 00:20:10.000000000 +0000 @@ -1,11 +1,16 @@ /* Copyright (c) 2011-2015 Ronald de Man + Copyright 2017-2018 Jon Dart */ #ifndef TBCORE_H #define TBCORE_H -#ifndef __WIN32__ +#if defined(__cplusplus) && defined(TB_USE_ATOMIC) +#include +#endif + +#ifndef _WIN32 #include #define SEP_CHAR ':' #define FD int @@ -17,8 +22,17 @@ #define FD_ERR INVALID_HANDLE_VALUE #endif -#ifdef TB_HAVE_THREADS -#ifndef __WIN32__ +#ifndef TB_NO_THREADS +#if defined(__cplusplus) && (__cplusplus >= 201103L) + +#include +#define LOCK_T std::mutex +#define LOCK_INIT(x) +#define LOCK(x) x.lock() +#define UNLOCK(x) x.unlock() + +#else +#ifndef _WIN32 #define LOCK_T pthread_mutex_t #define LOCK_INIT(x) pthread_mutex_init(&(x), NULL) #define LOCK(x) pthread_mutex_lock(&(x)) @@ -29,7 +43,9 @@ #define LOCK(x) WaitForSingleObject(x, INFINITE) #define UNLOCK(x) ReleaseMutex(x) #endif -#else /* !TB_HAVE_THREADS */ + +#endif +#else /* TB_NO_THREADS */ #define LOCK_T int #define LOCK_INIT(x) /* NOP */ #define LOCK(x) /* NOP */ @@ -81,13 +97,22 @@ ubyte num; ubyte symmetric; ubyte has_pawns; -} __attribute__((__may_alias__)); +} +#ifdef __GNUC__ +__attribute__((__may_alias__)); +#else +; +#endif struct TBEntry_piece { char *data; uint64 key; uint64 mapping; +#if defined(__cplusplus) && defined(TB_USE_ATOMIC) + std::atomic ready; +#else ubyte ready; +#endif ubyte num; ubyte symmetric; ubyte has_pawns; @@ -102,7 +127,11 @@ char *data; uint64 key; uint64 mapping; +#if defined(__cplusplus) && defined(TB_USE_ATOMIC) + std::atomic ready; +#else ubyte ready; +#endif ubyte num; ubyte symmetric; ubyte has_pawns; diff -Nru fathom-1.0/src/tbprobe.c fathom-1.0+git.20190120.0439ca/src/tbprobe.c --- fathom-1.0/src/tbprobe.c 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/tbprobe.c 2019-01-21 00:20:10.000000000 +0000 @@ -1,9 +1,8 @@ /* * tbprobe.c - * Copyright (c) 2013-2015 Ronald de Man - * This file may be redistributed and/or modified without restrictions. + * Copyright (c) 2013-2016 Ronald de Man + * Copyright (c) 2016-2017, 2019 Jon Dart * - * (C) 2015 basil, all rights reserved, * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -27,9 +26,11 @@ #include #include -#include "tbprobe.h" +#if defined(_MSC_VER) +#include +#endif -#include +#include "tbprobe.h" #define WHITE_KING (TB_WPAWN + 5) #define WHITE_QUEEN (TB_WPAWN + 4) @@ -44,7 +45,7 @@ #define BLACK_KNIGHT (TB_BPAWN + 1) #define BLACK_PAWN TB_BPAWN -#define PRIME_WHITE_QUEEN 15472061604242789393ull +#define PRIME_WHITE_QUEEN 11811845319353239651ull #define PRIME_WHITE_ROOK 10979190538029446137ull #define PRIME_WHITE_BISHOP 12311744257139811149ull #define PRIME_WHITE_KNIGHT 15202887380319082783ull @@ -66,17 +67,34 @@ #define BEST_NONE 0xFFFF #define SCORE_ILLEGAL 0x7FFF -#ifndef TB_NO_HW_POP_COUNT +#undef TB_SOFTWARE_POP_COUNT + +#if defined(TB_CUSTOM_POP_COUNT) +#define popcount(x) TB_CUSTOM_POP_COUNT(x) +#elif defined(TB_NO_HW_POP_COUNT) +#define TB_SOFTWARE_POP_COUNT +#elif defined (__GNUC__) && defined(__x86_64__) && defined(__SSE4_2__) #include #define popcount(x) _mm_popcnt_u64((x)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && defined(_M_AMD64) +#include +#define popcount(x) _mm_popcnt_u64((x)) #else -static inline unsigned popcount(uint64_t x) +#define TB_SOFTWARE_POP_COUNT +#endif + +#ifdef TB_SOFTWARE_POP_COUNT +// Not a recognized compiler/architecture that has popcount: +// fall back to a software popcount. This one is still reasonably +// fast (faster than GCC's builtin). +static inline unsigned tb_software_popcount(uint64_t x) { x = x - ((x >> 1) & 0x5555555555555555ull); x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull); x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full; return (x * 0x0101010101010101ull) >> 56; } +#define popcount(x) tb_software_popcount(x) #endif #define poplsb(x) ((x) & ((x) - 1)) @@ -118,12 +136,48 @@ #define rank(s) ((s) >> 3) #define file(s) ((s) & 0x07) #define board(s) ((uint64_t)1 << (s)) -static inline unsigned lsb(uint64_t b) -{ - size_t idx; - __asm__("bsfq %1, %0": "=r"(idx): "rm"(b)); - return idx; +#ifdef TB_CUSTOM_LSB +#define lsb(b) TB_CUSTOM_LSB(b) +#else +#if defined(__GNUC__) +static inline unsigned lsb(uint64_t b) { + assert(b != 0); + return __builtin_ffsll(b)-1; +} +#elif defined(_MSC_VER) +static inline unsigned lsb(uint64_t b) { + assert(b != 0); + DWORD index; +#ifdef _WIN64 + _BitScanForward64(&index,b); + return (unsigned)index; +#else + if (b & 0xffffffffULL) { + _BitScanForward(&index,(unsigned long)(b & 0xffffffffULL)); + return (unsigned)index; + } + else { + _BitScanForward(&index,(unsigned long)(b >> 32)); + return 32 + (unsigned)index; + } +#endif +} +#else +/* not a compiler/architecture with recognized builtins */ +static uint32_t get_bit32(uint64_t x) { + return (uint32_t)(((int32_t)(x))&-((int32_t)(x))); +} +static const unsigned MAGIC32 = 0xe89b2be; +static const uint32_t MagicTable32[32] = {31,0,9,1,10,20,13,2,7,11,21,23,17,14,3,25,30,8,19,12,6,22,16,24,29,18,5,15,28,4,27,26}; +static unsigned lsb(uint64_t b) { + if (b & 0xffffffffULL) + return MagicTable32[(get_bit32(b & 0xffffffffULL)*MAGIC32)>>27]; + else + return MagicTable32[(get_bit32(b >> 32)*MAGIC32)>>27]+32; } +#endif +#endif + #define square(r, f) (8 * (r) + (f)) #ifdef TB_KING_ATTACKS @@ -684,7 +738,13 @@ return 0; } // Memory barrier to ensure ptr->ready = 1 is not reordered. +#if !defined(__cplusplus) || !defined(TB_USE_ATOMIC) +#ifdef __GNUC__ __asm__ __volatile__ ("" ::: "memory"); +#elif defined(_MSC_VER) + MemoryBarrier(); +#endif +#endif ptr->ready = 1; } UNLOCK(TB_MUTEX); @@ -799,7 +859,7 @@ } ptr = ptr2[i].ptr; char str[16]; - int mirror = (ptr->key != key); + const bool mirror = (ptr->key != key); prt_str(pos, str, mirror); if (DTZ_table[DTZ_ENTRIES - 1].entry) free_dtz_entry(DTZ_table[DTZ_ENTRIES-1].entry); @@ -1158,13 +1218,14 @@ return false; if (to != pos->ep) return false; - if ((board(from) & us & pos->pawns) != 0) + if ((board(from) & us & pos->pawns) == 0) return false; return true; } /* - * Test if the given position is legal (can the king be captured?) + * Test if the given position is legal. + * (Pawns on backrank? Can the king be captured?) */ static bool is_legal(const struct pos *pos) { @@ -1172,6 +1233,8 @@ uint64_t us = (pos->turn? pos->black: pos->white), them = (pos->turn? pos->white: pos->black); uint64_t king = pos->kings & us; + if (!king) + return false; unsigned sq = lsb(king); if (king_attacks(sq) & (pos->kings & them)) return false; @@ -1277,6 +1340,8 @@ return false; if ((pos->knights & pos->pawns) != 0) return false; + if (pos->pawns & BOARD_FILE_EDGE) + return false; if ((pos->white | pos->black) != (pos->kings | pos->queens | pos->rooks | pos->bishops | pos->knights | pos->pawns)) @@ -1330,7 +1395,7 @@ pos->ep = from-8; else if (to == pos0->ep) { - unsigned ep_to = (pos0->turn? to+8: to-8); + unsigned ep_to = (pos0->turn? to-8: to+8); uint64_t ep_mask = ~board(ep_to); pos->white &= ep_mask; pos->black &= ep_mask; @@ -1409,7 +1474,7 @@ struct pos pos1; if (!do_move(&pos1, pos, *moves)) continue; - int v0 = -probe_ab(pos, -2, 2, success); + int v0 = -probe_ab(&pos1, -2, 2, success); if (*success == 0) return 0; if (v0 > v1) @@ -1467,7 +1532,9 @@ struct pos pos1; if (!do_move(&pos1, pos, *moves)) continue; - int v = -probe_ab(&pos1, -2, -wdl + 1, success); + int v = (pos1.ep == 0? + -probe_ab(&pos1, -2, -wdl + 1, success): + -probe_wdl(&pos1, success)); if (*success == 0) return 0; if (v == wdl) @@ -1586,7 +1653,7 @@ struct pos pos1; if (!do_move(&pos1, pos, *moves)) continue; - int v0 = -probe_ab(pos, -2, 2, success); + int v0 = -probe_ab(&pos1, -2, 2, success); if (*success == 0) return 0; if (v0 > v1) @@ -1707,7 +1774,7 @@ res = TB_SET_TO(res, move_to(moves[i])); res = TB_SET_PROMOTES(res, move_promotes(moves[i])); res = TB_SET_EP(res, is_en_passant(pos, moves[i])); - res = TB_SET_DTZ(res, (dtz < 0? -dtz: dtz)); + res = TB_SET_DTZ(res, (v < 0? -v: v)); results[j++] = res; } } @@ -1776,11 +1843,11 @@ } } -extern bool tb_init(const char *path) +bool tb_init_impl(const char *path) { - if (sizeof(uint64_t) != 8 && // Paranoid check - sizeof(uint32_t) != 4 && - sizeof(uint16_t) != 2 && + if (sizeof(uint64_t) != 8 || // Paranoid check + sizeof(uint32_t) != 4 || + sizeof(uint16_t) != 2 || sizeof(uint8_t) != 1) return false; king_attacks_init(); @@ -1794,7 +1861,7 @@ return true; } -extern unsigned tb_probe_wdl_impl( +unsigned tb_probe_wdl_impl( uint64_t white, uint64_t black, uint64_t kings, @@ -1817,7 +1884,7 @@ knights, pawns, 0, - ep, + (uint8_t)ep, turn }; int success; @@ -1827,7 +1894,7 @@ return (unsigned)(v + 2); } -extern unsigned tb_probe_root_impl( +unsigned tb_probe_root_impl( uint64_t white, uint64_t black, uint64_t kings, @@ -1851,8 +1918,8 @@ bishops, knights, pawns, - rule50, - ep, + (uint8_t)rule50, + (uint8_t)ep, turn }; int dtz; diff -Nru fathom-1.0/src/tbprobe.h fathom-1.0+git.20190120.0439ca/src/tbprobe.h --- fathom-1.0/src/tbprobe.h 2015-12-06 03:12:31.000000000 +0000 +++ fathom-1.0+git.20190120.0439ca/src/tbprobe.h 2019-01-21 00:20:10.000000000 +0000 @@ -24,7 +24,7 @@ #ifndef TBPROBE_H #define TBPROBE_H -#include "tbconfig.h" +#include #ifdef __cplusplus extern "C" @@ -54,6 +54,10 @@ #endif #endif +/* + * Internal definitions. Do not call these functions directly. + */ +extern bool tb_init_impl(const char *_path); extern unsigned tb_probe_wdl_impl( uint64_t _white, uint64_t _black, @@ -168,7 +172,10 @@ * initialized. If no tablebase files are found, then `true' is returned * and TB_LARGEST is set to zero. */ -extern bool tb_init(const char *_path); +static inline bool tb_init(const char *_path) +{ + return tb_init_impl(_path); +} /* * Probe the Win-Draw-Loss (WDL) table. @@ -192,6 +199,7 @@ * * NOTES: * - Engines should use this function during search. + * - This function is thread safe assuming TB_NO_THREADS is disabled. */ static inline unsigned tb_probe_wdl( uint64_t _white, @@ -257,6 +265,8 @@ * - DTZ tablebases can suggest unnatural moves, especially for losing * positions. Engines may prefer to traditional search combined with WDL * move filtering using the alternative results array. + * - This function is NOT thread safe. For engines this function should only + * be called once at the root per search. */ static inline unsigned tb_probe_root( uint64_t _white,