Skip to content

Instantly share code, notes, and snippets.

@Ruzzie
Created December 9, 2015 06:34
Show Gist options
  • Save Ruzzie/7b823fc8b9f271a41108 to your computer and use it in GitHub Desktop.
Save Ruzzie/7b823fc8b9f271a41108 to your computer and use it in GitHub Desktop.
public class SimpleRandom : Random
{
private readonly RandomSampler _randomSampler;
private const int IntMaxValueMinusOne = int.MaxValue - 1;
public SimpleRandom(int seed, int hValue, int eValue)
{
//For bytes: 0,00106736330262713 127,5 H1741966517 E1631200041
//0,000000001594884 0,499999998405116 H1612099793 E1610967361, with _pTwo PrimeToolHash.GetPrime(hashOrValue.FindNearestPowerOfTwoLessThan())
_randomSampler = new RandomSampler(seed, hValue, eValue);
}
public SimpleRandom(int seed = 1) :this(seed, 397, 1103)
{
}
public override int Next()
{
return _randomSampler.Next(int.MaxValue);
}
public override double NextDouble()
{
int next = Next();
double random = next / (double)(IntMaxValueMinusOne);
return random;
}
protected override double Sample()
{
return NextDouble();
}
public override int Next(int minValue, int maxValue)
{
double random = NextDouble();
int range = maxValue - minValue;
return (int) (minValue + Math.Floor(random*range));
}
public override void NextBytes(byte[] buffer)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = NextByte();
}
}
public byte NextByte()
{
return (byte) (Next() & (byte.MaxValue));
}
public override int Next(int exclusiveMaximumum)
{
return _randomSampler.Next(exclusiveMaximumum);
}
internal class RandomSampler
{
private readonly ulong _moduloValue;
private readonly ulong _pOnePowThree;
private readonly ulong _pTwoPowTwo;
private readonly ConcurrentCircularOverwriteBuffer<ulong> _buffer;
public RandomSampler(int seed, int hValue, int eValue)
{
int noiseVariable;
unchecked
{
noiseVariable = eValue ^ hValue;
}
_moduloValue = (ulong)PrimeToolHash.GetPrime(int.MaxValue + Convert.ToInt64(noiseVariable));
ulong pOne = (ulong)PrimeToolHash.GetPrime(noiseVariable);
ulong pTwo = (ulong)hValue;
unchecked
{
_pOnePowThree = (pOne * pOne * pOne);
_pTwoPowTwo = pTwo * pTwo;
}
_buffer = new ConcurrentCircularOverwriteBuffer<ulong>(256);
ulong sample = Sample((ulong) seed);
_buffer.WriteNext(sample);
}
public int Next(int exclusiveMaximumum)
{
unchecked
{
ulong number = NextSample();
return (int)(number % (ulong)exclusiveMaximumum);
}
}
private ulong NextSample()
{
ulong number;
while (!_buffer.ReadNext(out number))
{
}
_buffer.WriteNext(Sample(number));
return number;
}
private ulong Sample(ulong currentSeed)
{
unchecked
{
return ((currentSeed * _pOnePowThree) - (_pTwoPowTwo)) % _moduloValue;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment