2020-01-19 08:55:10 +00:00
namespace PKHeX.Core
{
/// <summary>
/// Self-mutating value that returns a crypto value to be xor-ed with another (unaligned) byte stream.
/// <para>
/// This implementation allows for yielding crypto bytes on demand.
/// </para>
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Unused")]
2021-01-07 23:33:42 +00:00
public ref struct SCXorShift32
2020-01-19 08:55:10 +00:00
{
private int Counter ;
private uint Seed ;
public SCXorShift32 ( uint seed )
{
var pop_count = PopCount ( seed ) ;
for ( var i = 0 ; i < pop_count ; i + + )
XorshiftAdvance ( ref seed ) ;
Counter = 0 ;
Seed = seed ;
}
/// <summary>
/// Gets a <see cref="byte"/> from the current state.
/// </summary>
public uint Next ( )
{
var c = Counter ;
var val = ( Seed > > ( c < < 3 ) ) & 0xFF ;
if ( c = = 3 )
{
XorshiftAdvance ( ref Seed ) ;
Counter = 0 ;
}
else
{
+ + Counter ;
}
return val ;
}
/// <summary>
/// Gets a <see cref="uint"/> from the current state.
/// </summary>
public uint Next32 ( )
{
return Next ( ) | ( Next ( ) < < 8 ) | ( Next ( ) < < 16 ) | ( Next ( ) < < 24 ) ;
}
private static void XorshiftAdvance ( ref uint key )
{
key ^ = key < < 2 ;
key ^ = key > > 15 ;
key ^ = key < < 13 ;
}
/// <summary>
/// Count of bits set in value
/// </summary>
private static uint PopCount ( uint x )
{
x - = ( ( x > > 1 ) & 0x55555555 u ) ;
x = ( x & 0x33333333 u ) + ( ( x > > 2 ) & 0x33333333 u ) ;
x = ( x + ( x > > 4 ) ) & 0x0F0F0F0F u ;
x + = ( x > > 8 ) ;
x + = ( x > > 16 ) ;
return x & 0x0000003F u ;
}
}
2021-01-07 23:33:42 +00:00
}