Created
December 9, 2015 06:34
-
-
Save Ruzzie/7b823fc8b9f271a41108 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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