Fixed BigInteger Random Number Generator
using System; using System.Security.Cryptography; public class FixedBigIntegerRandomNumberGenerator : RandomNumberGenerator { private readonly int _bitWidthHold; private readonly byte[] _buffer; private readonly JitterCacheRng _crng; private readonly BigDecimal _dBi; private readonly FixedBigInteger _maxValueHold = new FixedBigInteger(0, 0); public FixedBigIntegerRandomNumberGenerator(int bitWidth) { if (bitWidth < 32) bitWidth = 32; var maxValue = GetMaxValue(bitWidth); var vdp = maxValue.GetDecimalPlaces(); if (vdp > BigDecimal.MaxPrecision) BigDecimal.MaxPrecision = vdp; _bitWidthHold = bitWidth; if (_bitWidthHold < 32) _bitWidthHold = 32; _maxValueHold = maxValue; _dBi = BigDecimal.One / (BigDecimal) maxValue; _buffer = new byte[_bitWidthHold >> 3]; _crng = new JitterCacheRng(1000000); } public FixedBigIntegerRandomNumberGenerator(int bitWidth, int cacheSize) { if (bitWidth < 32) bitWidth = 32; var maxValue = GetMaxValue(bitWidth); var vdp = maxValue.GetDecimalPlaces(); if (vdp > BigDecimal.MaxPrecision) BigDecimal.MaxPrecision = vdp; _bitWidthHold = bitWidth; if (_bitWidthHold < 32) _bitWidthHold = 32; _maxValueHold = maxValue; _dBi = BigDecimal.One / (BigDecimal) maxValue; _buffer = new byte[_bitWidthHold >> 3]; _crng = new JitterCacheRng(cacheSize); } public bool OddsOnly { get; set; } public bool Unsigned { get; set; } protected override void Dispose(bool disposing) { _crng.Dispose(); } private FixedBigInteger GetMaxValue(int bitWidth) { var r = new FixedBigInteger(0, bitWidth); for (var i = 0; i < r.Data.Length; ++i) r.Data[i] = uint.MaxValue; r.Data[r.Data.Length - 1] = int.MaxValue; return r; } private FixedBigInteger GetMaxValue() { var r = new FixedBigInteger(0, _bitWidthHold); for (var i = 0; i < r.Data.Length; ++i) r.Data[i] = uint.MaxValue; r.Data[r.Data.Length - 1] = int.MaxValue; return r; } private BigDecimal Sample() { FixedBigInteger Internal() { _crng.GetBytes(_buffer); var n = new FixedBigInteger(_buffer, _bitWidthHold); return !OddsOnly ? n : n | 1; } var s = (BigDecimal) Internal() * _dBi; if (s.Sign == -1) s = s * -1; if (s.IsZero) throw new Exception("Sample is zero. SEE: MaxPrecision in BigDecimal.cs. Default value is 308."); return s; } public FixedBigInteger Next(FixedBigInteger minValue, FixedBigInteger maxValue) { var sa = Sample(); var fi = (BigDecimal) (maxValue - minValue + minValue); var n = new FixedBigInteger(sa * fi, 0); n = !OddsOnly ? n : n | 1; if (Unsigned) return n.Sign < 0 ? new FixedBigInteger(1, n.Data, 0) : n; var buffer = new byte[1]; _crng.GetBytes(buffer); if (buffer[0] > 127) return n.Sign < 0 ? n : new FixedBigInteger(-1, n.Data, 0); return n.Sign < 0 ? new FixedBigInteger(1, n.Data, 0) : n; } public FixedBigInteger Next(FixedBigInteger maxValue) { return Next(0, maxValue); } public FixedBigInteger Next() { return Next(0, _maxValueHold); } public override void GetBytes(byte[] data) { if (data == null) throw new ArgumentException("The buffer cannot be null."); _crng.GetBytes(data); } public void NextBytes(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("The buffer cannot be null."); for (var index = 0; index < buffer.Length; ++index) buffer[index] = (byte) (Sample() * byte.MaxValue); } public FixedBigInteger[] Next(FixedBigInteger minValue, FixedBigInteger maxValue, int arraySize) { var array = new FixedBigInteger[arraySize]; for (var i = 0; i < arraySize; ++i) array[i] = Next(minValue, maxValue); return array; } public char[] GetNextCharArray(int size) { var ca = new char[size]; var ptr = 0; do { ca[ptr++] = (char) Next(32, 128); } while (ptr < size); return ca; } public byte[] GetNextByteArray(int size) { var ba = new byte[size]; _crng.GetBytes(ba); return ba; } public string GetRandomString(int minLen, int maxLen) { if (minLen == maxLen) return new string(GetNextCharArray(minLen)); return new string(GetNextCharArray((int) Next((uint) minLen, (uint) maxLen))); } }