172 lines
6.0 KiB
C
172 lines
6.0 KiB
C
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
||
|
* This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
|
||
|
* http://www.gnu.org/software/gnugo/ for more information. *
|
||
|
* *
|
||
|
* Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||
|
* 2008 and 2009 by the Free Software Foundation. *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or *
|
||
|
* modify it under the terms of the GNU General Public License as *
|
||
|
* published by the Free Software Foundation - version 3 or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
* This program is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
|
* GNU General Public License in file COPYING for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public *
|
||
|
* License along with this program; if not, write to the Free *
|
||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||
|
* Boston, MA 02111, USA. *
|
||
|
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
|
||
|
#ifndef _HASH_H_
|
||
|
#define _HASH_H_
|
||
|
|
||
|
#include "config.h"
|
||
|
#include <limits.h>
|
||
|
|
||
|
/*
|
||
|
* This file, together with engine/hash.c implements hashing of go positions
|
||
|
* using a method known as Zobrist hashing. See the Texinfo documentation
|
||
|
* (Reading/Hashing) for more information.
|
||
|
*/
|
||
|
|
||
|
/* Hash values and the compact board representation should use the
|
||
|
* longest integer type that the platform can handle efficiently.
|
||
|
* Typically this would be a 32 bit integer on a 32 bit platform and a
|
||
|
* 64 bit integer on a 64 bit platform.
|
||
|
*
|
||
|
* Our current assumption is that unsigned long has this
|
||
|
* characteristic. Should it turn out to be false for some platform
|
||
|
* we'll add conditional code to choose some other type.
|
||
|
*
|
||
|
* At the few places in the code where the actual size of these types
|
||
|
* matter, the code should use sizeof(type) to test for this. Notice
|
||
|
* that ISO C guarantees a long to be at least 32 bits.
|
||
|
*
|
||
|
* On (future) platforms with word length 128 bits or more, it might
|
||
|
* be a waste to use more than 64 bit hashvalues, since the decreased
|
||
|
* risk for hash collisions probably isn't worth the increased storage
|
||
|
* cost.
|
||
|
*/
|
||
|
typedef unsigned long Hashvalue;
|
||
|
#define SIZEOF_HASHVALUE SIZEOF_LONG
|
||
|
#define HASHVALUE_PRINT_FORMAT "%0*lx"
|
||
|
|
||
|
/* for testing: Enables a lot of checks. */
|
||
|
#define CHECK_HASHING 0
|
||
|
|
||
|
/* Dump (almost) all read results. */
|
||
|
#define TRACE_READ_RESULTS 0
|
||
|
|
||
|
/* How many bits should be used at least for hashing? Set this to 32 for
|
||
|
* some memory save and speedup, at the cost of occasional irreproducable
|
||
|
* mistakes (and possibly assertion failures).
|
||
|
* With 64 bits, there should be less than one such mistake in 10^9 games.
|
||
|
* Set this to 96 if this is not safe enough for you.
|
||
|
*/
|
||
|
#define MIN_HASHBITS 64
|
||
|
|
||
|
#define NUM_HASHVALUES (1 + (MIN_HASHBITS - 1) / (CHAR_BIT * SIZEOF_HASHVALUE))
|
||
|
|
||
|
/* This struct is maintained by the machinery that updates the board
|
||
|
* to provide incremental hashing. Examples: trymove(), play_move(), ...
|
||
|
*/
|
||
|
|
||
|
typedef struct {
|
||
|
Hashvalue hashval[NUM_HASHVALUES];
|
||
|
} Hash_data;
|
||
|
|
||
|
extern Hash_data board_hash;
|
||
|
|
||
|
Hash_data goal_to_hashvalue(const signed char *goal);
|
||
|
|
||
|
void hash_init_zobrist_array(Hash_data *array, int size);
|
||
|
void hash_init(void);
|
||
|
#define INIT_ZOBRIST_ARRAY(a) \
|
||
|
hash_init_zobrist_array(a, (int) (sizeof(a) / sizeof(a[0])))
|
||
|
|
||
|
void hashdata_clear(Hash_data *hd);
|
||
|
void hashdata_recalc(Hash_data *hd, Intersection *board, int ko_pos);
|
||
|
void hashdata_invert_ko(Hash_data *hd, int pos);
|
||
|
void hashdata_invert_stone(Hash_data *hd, int pos, int color);
|
||
|
void hashdata_invert_komaster(Hash_data *hd, int komaster);
|
||
|
void hashdata_invert_kom_pos(Hash_data *hd, int kom_pos);
|
||
|
void hashdata_calc_orientation_invariant(Hash_data *hd, Intersection *board,
|
||
|
int ko_pos);
|
||
|
|
||
|
char *hashdata_to_string(Hash_data *hashdata);
|
||
|
|
||
|
|
||
|
|
||
|
/* ---------------------------------------------------------------- */
|
||
|
|
||
|
/* There is no need to involve all bits in the remainder computation
|
||
|
* as long as we only use it to compute a key into a hash table. 32
|
||
|
* random bits are sufficient to get an even distribution within any
|
||
|
* hashtable of reasonable size. By never using more than 32 bits we
|
||
|
* also reduce the platform dependency of the GNU Go engine.
|
||
|
*/
|
||
|
#define hashdata_remainder(hd, num) \
|
||
|
(((hd).hashval[0] & 0xffffffffU) % (num))
|
||
|
|
||
|
#if NUM_HASHVALUES == 1
|
||
|
|
||
|
#define hashdata_is_equal(hd1, hd2) \
|
||
|
((hd1).hashval[0] == (hd2).hashval[0])
|
||
|
|
||
|
#define hashdata_is_smaller(hd1, hd2) \
|
||
|
((hd1).hashval[0] < (hd2).hashval[0])
|
||
|
|
||
|
#define hashdata_xor(hd1, hd2) \
|
||
|
(hd1).hashval[0] ^= (hd2).hashval[0]
|
||
|
|
||
|
#elif NUM_HASHVALUES == 2
|
||
|
|
||
|
#define hashdata_is_equal(hd1, hd2) \
|
||
|
((hd1).hashval[0] == (hd2).hashval[0] \
|
||
|
&& (hd1).hashval[1] == (hd2).hashval[1])
|
||
|
|
||
|
#define hashdata_is_smaller(hd1, hd2) \
|
||
|
((hd1).hashval[0] < (hd2).hashval[0] \
|
||
|
|| ((hd1).hashval[0] == (hd2).hashval[0] \
|
||
|
&& (hd1).hashval[1] < (hd2).hashval[1]))
|
||
|
|
||
|
#define hashdata_xor(hd1, hd2) \
|
||
|
do { \
|
||
|
(hd1).hashval[0] ^= (hd2).hashval[0]; \
|
||
|
(hd1).hashval[1] ^= (hd2).hashval[1]; \
|
||
|
} while (0)
|
||
|
|
||
|
#else
|
||
|
|
||
|
int hashdata_is_equal_func(Hash_data *hd1, Hash_data *hd2);
|
||
|
int hashdata_is_smaller_func(Hash_data *hd1, Hash_data *hd2);
|
||
|
|
||
|
#define hashdata_is_equal(hd1, hd2) \
|
||
|
hashdata_is_equal_func(&(hd1), &(hd2))
|
||
|
|
||
|
#define hashdata_is_smaller(hd1, hd2) \
|
||
|
hashdata_is_smaller_func(&(hd1), &(hd2))
|
||
|
|
||
|
#define hashdata_xor(hd1, hd2) \
|
||
|
do { \
|
||
|
int i; \
|
||
|
for (i = 0; i < NUM_HASHVALUES; i++) \
|
||
|
(hd1).hashval[i] ^= (hd2).hashval[i]; \
|
||
|
} while (0)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local Variables:
|
||
|
* tab-width: 8
|
||
|
* c-basic-offset: 2
|
||
|
* End:
|
||
|
*/
|