Skip to content

Commit

Permalink
🧹 Make Position.UniqueIdentifier an ulong instead of a long (#1078
Browse files Browse the repository at this point in the history
)
  • Loading branch information
eduherminio authored Oct 4, 2024
1 parent c93b24b commit f9c317c
Show file tree
Hide file tree
Showing 18 changed files with 179 additions and 92 deletions.
36 changes: 18 additions & 18 deletions src/Lynx.Benchmark/MakeUnmakeMove_implementation_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public static long ResultsImpl_MakeUnmakeMove_WithZobritsKey_SwitchSpecialMove(M

public struct MakeMovePosition
{
public long UniqueIdentifier { get; private set; }
public ulong UniqueIdentifier { get; private set; }

public BitBoard[] PieceBitBoards { get; }

Expand Down Expand Up @@ -715,7 +715,7 @@ public MakeMoveGameStateWithZobristKey MakeMove_WithZobristKey(Move move)
int capturedPiece = -1;
var castleCopy = Castle;
BoardSquare enpassantCopy = EnPassant;
long uniqueIdentifierCopy = UniqueIdentifier;
var uniqueIdentifierCopy = UniqueIdentifier;

var oldSide = Side;
var offset = Utils.PieceOffset(oldSide);
Expand Down Expand Up @@ -837,7 +837,7 @@ public MakeMoveGameStateWithZobristKey MakeMove_WithZobristKey_PreSwitchSpecialM
int capturedPiece = -1;
byte castleCopy = Castle;
BoardSquare enpassantCopy = EnPassant;
long uniqueIdentifierCopy = UniqueIdentifier;
var uniqueIdentifierCopy = UniqueIdentifier;

var oldSide = (int)Side;
var offset = Utils.PieceOffset(oldSide);
Expand Down Expand Up @@ -949,7 +949,7 @@ public MakeMoveGameStateWithZobristKey MakeMove_WithZobristKey_SwitchSpecialMove

byte castleCopy = Castle;
BoardSquare enpassantCopy = EnPassant;
long uniqueIdentifierCopy = UniqueIdentifier;
var uniqueIdentifierCopy = UniqueIdentifier;

var oldSide = (int)Side;
var offset = Utils.PieceOffset(oldSide);
Expand Down Expand Up @@ -1394,15 +1394,15 @@ public MakeMoveGameState(int capturedPiece, byte castle, BoardSquare enpassant)

public readonly struct MakeMoveGameStateWithZobristKey
{
public readonly long ZobristKey;
public readonly ulong ZobristKey;

public readonly int CapturedPiece;

public readonly BoardSquare EnPassant;

public readonly byte Castle;

public MakeMoveGameStateWithZobristKey(int capturedPiece, byte castle, BoardSquare enpassant, long zobristKey)
public MakeMoveGameStateWithZobristKey(int capturedPiece, byte castle, BoardSquare enpassant, ulong zobristKey)
{
CapturedPiece = capturedPiece;
Castle = castle;
Expand All @@ -1415,18 +1415,18 @@ public MakeMoveGameStateWithZobristKey(int capturedPiece, byte castle, BoardSqua

public static class MakeMoveZobristTable
{
private static readonly long[,] _table = Initialize();
private static readonly ulong[,] _table = Initialize();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long PieceHash(int boardSquare, int piece) => _table[boardSquare, piece];
public static ulong PieceHash(int boardSquare, int piece) => _table[boardSquare, piece];

/// <summary>
/// Uses <see cref="Piece.P"/> and squares <see cref="BoardSquare.a1"/>-<see cref="BoardSquare.h1"/>
/// </summary>
/// <param name="enPassantSquare"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long EnPassantHash(int enPassantSquare)
public static ulong EnPassantHash(int enPassantSquare)
{
if (enPassantSquare == (int)BoardSquare.noSquare)
{
Expand All @@ -1443,7 +1443,7 @@ public static long EnPassantHash(int enPassantSquare)
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SideHash()
public static ulong SideHash()
{
return _table[(int)BoardSquare.h8, (int)Piece.p];
}
Expand All @@ -1456,9 +1456,9 @@ public static long SideHash()
/// <param name="castle"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long CastleHash(byte castle)
public static ulong CastleHash(byte castle)
{
long combinedHash = 0;
ulong combinedHash = 0;

if ((castle & (int)CastlingRights.WK) != default)
{
Expand Down Expand Up @@ -1489,9 +1489,9 @@ public static long CastleHash(byte castle)
/// <param name="position"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long PositionHash(MakeMovePosition position)
public static ulong PositionHash(MakeMovePosition position)
{
long positionHash = 0;
ulong positionHash = 0;

for (int squareIndex = 0; squareIndex < 64; ++squareIndex)
{
Expand All @@ -1516,16 +1516,16 @@ public static long PositionHash(MakeMovePosition position)
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static long[,] Initialize()
internal static ulong[,] Initialize()
{
var zobristTable = new long[64, 12];
var randomInstance = new Random(int.MaxValue);
var zobristTable = new ulong[64, 12];
var randomInstance = new LynxRandom(int.MaxValue);

for (int squareIndex = 0; squareIndex < 64; ++squareIndex)
{
for (int pieceIndex = 0; pieceIndex < 12; ++pieceIndex)
{
zobristTable[squareIndex, pieceIndex] = randomInstance.NextInt64();
zobristTable[squareIndex, pieceIndex] = randomInstance.NextUInt64();
}
}

Expand Down
26 changes: 13 additions & 13 deletions src/Lynx.Benchmark/MakeUnmakeMove_integration_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public static long ResultsImpl_MakeUnmakeMove_PassRef(MakeMovePosition position,

public struct MakeMovePosition
{
public long UniqueIdentifier { get; private set; }
public ulong UniqueIdentifier { get; private set; }

public BitBoard[] PieceBitBoards { get; }

Expand Down Expand Up @@ -1266,18 +1266,18 @@ public struct MakeMoveGameState_PassRef

public static class MakeMoveZobristTable
{
private static readonly long[,] _table = Initialize();
private static readonly ulong[,] _table = Initialize();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long PieceHash(int boardSquare, int piece) => _table[boardSquare, piece];
public static ulong PieceHash(int boardSquare, int piece) => _table[boardSquare, piece];

/// <summary>
/// Uses <see cref="Piece.P"/> and squares <see cref="BoardSquare.a1"/>-<see cref="BoardSquare.h1"/>
/// </summary>
/// <param name="enPassantSquare"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long EnPassantHash(int enPassantSquare)
public static ulong EnPassantHash(int enPassantSquare)
{
if (enPassantSquare == (int)BoardSquare.noSquare)
{
Expand All @@ -1294,7 +1294,7 @@ public static long EnPassantHash(int enPassantSquare)
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SideHash()
public static ulong SideHash()
{
return _table[(int)BoardSquare.h8, (int)Piece.p];
}
Expand All @@ -1307,9 +1307,9 @@ public static long SideHash()
/// <param name="castle"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long CastleHash(int castle)
public static ulong CastleHash(int castle)
{
long combinedHash = 0;
ulong combinedHash = 0;

if ((castle & (int)CastlingRights.WK) != default)
{
Expand Down Expand Up @@ -1340,9 +1340,9 @@ public static long CastleHash(int castle)
/// <param name="position"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long PositionHash(MakeMovePosition position)
public static ulong PositionHash(MakeMovePosition position)
{
long positionHash = 0;
ulong positionHash = 0;

for (int squareIndex = 0; squareIndex < 64; ++squareIndex)
{
Expand All @@ -1367,16 +1367,16 @@ public static long PositionHash(MakeMovePosition position)
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static long[,] Initialize()
internal static ulong[,] Initialize()
{
var zobristTable = new long[64, 12];
var randomInstance = new Random(int.MaxValue);
var zobristTable = new ulong[64, 12];
var randomInstance = new LynxRandom(int.MaxValue);

for (int squareIndex = 0; squareIndex < 64; ++squareIndex)
{
for (int pieceIndex = 0; pieceIndex < 12; ++pieceIndex)
{
zobristTable[squareIndex, pieceIndex] = randomInstance.NextInt64();
zobristTable[squareIndex, pieceIndex] = randomInstance.NextUInt64();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/Lynx.Benchmark/ParseGame_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ public sealed class OriginalGame
public List<Move> MoveHistory { get; }
#endif

public HashSet<long> PositionHashHistory { get; }
public HashSet<ulong> PositionHashHistory { get; }

public int HalfMovesWithoutCaptureOrPawnMove { get; set; }

Expand Down Expand Up @@ -552,7 +552,7 @@ public sealed class ImprovedGame
public List<Move> MoveHistory { get; }
#endif

public HashSet<long> PositionHashHistory { get; }
public HashSet<ulong> PositionHashHistory { get; }

public int HalfMovesWithoutCaptureOrPawnMove { get; set; }

Expand Down Expand Up @@ -633,7 +633,7 @@ public sealed class ImprovedGame2
public List<Move> MoveHistory { get; }
#endif

public HashSet<long> PositionHashHistory { get; }
public HashSet<ulong> PositionHashHistory { get; }

public int HalfMovesWithoutCaptureOrPawnMove { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/Lynx.Benchmark/TryParseFromUCIString_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public sealed class TryParseFromUCIString_Benchmark_Game
public List<Move> MoveHistory { get; }
#endif

public HashSet<long> PositionHashHistory { get; }
public HashSet<ulong> PositionHashHistory { get; }

public int HalfMovesWithoutCaptureOrPawnMove { get; set; }

Expand Down
12 changes: 6 additions & 6 deletions src/Lynx.Benchmark/ZobristPositionHash_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ public class ZobristPositionHash_Benchmark : BaseBenchmark

[Benchmark(Baseline = true)]
[ArgumentsSource(nameof(Data))]
public long Original(Position position) => PositionHash_Original_DoubleLoop(position);
public ulong Original(Position position) => PositionHash_Original_DoubleLoop(position);

[Benchmark]
[ArgumentsSource(nameof(Data))]
public long Improved(Position position) => PositionHash_Improved(position);
public ulong Improved(Position position) => PositionHash_Improved(position);

private static long PositionHash_Original_DoubleLoop(Position position)
private static ulong PositionHash_Original_DoubleLoop(Position position)
{
long positionHash = 0;
ulong positionHash = 0;

for (int squareIndex = 0; squareIndex < 64; ++squareIndex)
{
Expand All @@ -113,9 +113,9 @@ private static long PositionHash_Original_DoubleLoop(Position position)
return positionHash;
}

private static long PositionHash_Improved(Position position)
private static ulong PositionHash_Improved(Position position)
{
long positionHash = 0;
ulong positionHash = 0;

for (int pieceIndex = 0; pieceIndex < 12; ++pieceIndex)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Lynx.Dev/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ static void TesSize(int size)

Console.WriteLine("TT memory: {0} MB", lengthMb * Marshal.SizeOf(typeof(TranspositionTableElement)));
Console.WriteLine("TT array length: {0}MB, (0x{1}, {2} items)", lengthMb, length.ToString("X"), length);
Console.WriteLine("TT mask: 0x{0} ({1})\n", mask.ToString("X"), Convert.ToString(mask, 2));
Console.WriteLine("TT mask: 0x{0} ({1})\n", mask.ToString("X"), Convert.ToString((long)mask, 2));
}

Console.WriteLine($"{nameof(TranspositionTableElement)} size: {Marshal.SizeOf(typeof(TranspositionTableElement))} bytes\n");
Expand All @@ -1071,7 +1071,7 @@ static void TesSize(int size)
TesSize(512);
TesSize(1024);

var (mask, length) = TranspositionTableExtensions.CalculateLength(Configuration.EngineSettings.TranspositionTableSize);
var (length, mask) = TranspositionTableExtensions.CalculateLength(Configuration.EngineSettings.TranspositionTableSize);
var transpositionTable = new TranspositionTableElement[length];
var position = new Position(Constants.InitialPositionFEN);
position.Print();
Expand Down
86 changes: 86 additions & 0 deletions src/Lynx/LynxRandom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System.Numerics;
using System.Runtime.CompilerServices;

namespace Lynx;

public class LynxRandom : Random
{
private readonly XoshiroImpl _impl;

public LynxRandom()
{
_impl = new XoshiroImpl(this);
}

public LynxRandom(int seed) : base(seed)
{
_impl = new XoshiroImpl(this);
}

/// <summary>
/// Based on dotnet/runtime implementation,
/// https://github.com/dotnet/runtime/blob/508fef51e841aa16ffed1aae32bf4793a2cea363/src/libraries/System.Private.CoreLib/src/System/Random.Xoshiro256StarStarImpl.cs
/// </summary>
/// <returns></returns>
public ulong NextUInt64() => _impl.NextUInt64();

/// <summary>
/// Based on dotnet/runtime implementation,
/// https://github.com/dotnet/runtime/blob/a7f96cb070ffb8adf266b2e09d26759d7f978a60/src/libraries/System.Private.CoreLib/src/System/Random.Xoshiro256StarStarImpl.cs
/// <see cref="NextUInt64"/> is subsequently based on the algorithm from http://prng.di.unimi.it/xoshiro256starstar.c
/// Written in 2018 by David Blackman and Sebastiano Vigna ([email protected])
/// To the extent possible under law, the author has dedicated all copyright
/// and related and neighboring rights to this software to the public domain
/// worldwide. This software is distributed without any warranty.
/// See <http://creativecommons.org/publicdomain/zero/1.0/>.
/// </summary>
internal sealed class XoshiroImpl
{
private ulong _s0, _s1, _s2, _s3;

public XoshiroImpl(Random random)
{
do
{
_s0 = InternalNextUInt64();
_s1 = InternalNextUInt64();
_s2 = InternalNextUInt64();
_s3 = InternalNextUInt64();
}
while ((_s0 | _s1 | _s2 | _s3) == 0); // at least one value must be non-zero

// 'Naive' version of what we're trying to achieve
ulong InternalNextUInt64()
{
Span<byte> arr = stackalloc byte[8];
random.NextBytes(arr);

return BitConverter.ToUInt64(arr);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong NextUInt64()
{
ulong s0 = _s0, s1 = _s1, s2 = _s2, s3 = _s3;

ulong result = BitOperations.RotateLeft(s1 * 5, 7) * 9;
ulong t = s1 << 17;

s2 ^= s0;
s3 ^= s1;
s1 ^= s2;
s0 ^= s3;

s2 ^= t;
s3 = BitOperations.RotateLeft(s3, 45);

_s0 = s0;
_s1 = s1;
_s2 = s2;
_s3 = s3;

return result;
}
}
}
Loading

0 comments on commit f9c317c

Please sign in to comment.