FixedBigIntegerRandomNumberGenerator.cs

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)));
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *