{"id":42,"date":"2020-06-05T10:20:37","date_gmt":"2020-06-05T10:20:37","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=42"},"modified":"2020-06-05T10:20:37","modified_gmt":"2020-06-05T10:20:37","slug":"fixedbigintegerrandomnumbergenerator-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/05\/fixedbigintegerrandomnumbergenerator-cs\/","title":{"rendered":"FixedBigIntegerRandomNumberGenerator.cs"},"content":{"rendered":"\n<p>Fixed BigInteger Random Number Generator<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Security.Cryptography;\npublic class FixedBigIntegerRandomNumberGenerator : RandomNumberGenerator\n{\n    private readonly int             _bitWidthHold;\n    private readonly byte[]          _buffer;\n    private readonly JitterCacheRng  _crng;\n    private readonly BigDecimal      _dBi;\n    private readonly FixedBigInteger _maxValueHold = new FixedBigInteger(0, 0);\n    public FixedBigIntegerRandomNumberGenerator(int bitWidth)\n    {\n        if (bitWidth &lt; 32)\n            bitWidth = 32;\n        var maxValue = GetMaxValue(bitWidth);\n        var vdp      = maxValue.GetDecimalPlaces();\n        if (vdp > BigDecimal.MaxPrecision)\n            BigDecimal.MaxPrecision = vdp;\n        _bitWidthHold = bitWidth;\n        if (_bitWidthHold &lt; 32)\n            _bitWidthHold = 32;\n        _maxValueHold = maxValue;\n        _dBi          = BigDecimal.One \/ (BigDecimal) maxValue;\n        _buffer       = new byte[_bitWidthHold >> 3];\n        _crng         = new JitterCacheRng(1000000);\n    }\n    public FixedBigIntegerRandomNumberGenerator(int bitWidth, int cacheSize)\n    {\n        if (bitWidth &lt; 32)\n            bitWidth = 32;\n        var maxValue = GetMaxValue(bitWidth);\n        var vdp      = maxValue.GetDecimalPlaces();\n        if (vdp > BigDecimal.MaxPrecision)\n            BigDecimal.MaxPrecision = vdp;\n        _bitWidthHold = bitWidth;\n        if (_bitWidthHold &lt; 32)\n            _bitWidthHold = 32;\n        _maxValueHold = maxValue;\n        _dBi          = BigDecimal.One \/ (BigDecimal) maxValue;\n        _buffer       = new byte[_bitWidthHold >> 3];\n        _crng         = new JitterCacheRng(cacheSize);\n    }\n    public bool OddsOnly\n    {\n        get;\n        set;\n    }\n    public bool Unsigned\n    {\n        get;\n        set;\n    }\n    protected override void Dispose(bool disposing)\n    {\n        _crng.Dispose();\n    }\n    private FixedBigInteger GetMaxValue(int bitWidth)\n    {\n        var r = new FixedBigInteger(0, bitWidth);\n        for (var i = 0; i &lt; r.Data.Length; ++i)\n            r.Data[i] = uint.MaxValue;\n        r.Data[r.Data.Length - 1] = int.MaxValue;\n        return r;\n    }\n    private FixedBigInteger GetMaxValue()\n    {\n        var r = new FixedBigInteger(0, _bitWidthHold);\n        for (var i = 0; i &lt; r.Data.Length; ++i)\n            r.Data[i] = uint.MaxValue;\n        r.Data[r.Data.Length - 1] = int.MaxValue;\n        return r;\n    }\n    private BigDecimal Sample()\n    {\n        FixedBigInteger Internal()\n        {\n            _crng.GetBytes(_buffer);\n            var n = new FixedBigInteger(_buffer, _bitWidthHold);\n            return !OddsOnly ? n : n | 1;\n        }\n        var s = (BigDecimal) Internal() * _dBi;\n        if (s.Sign == -1)\n            s = s * -1;\n        if (s.IsZero)\n            throw new Exception(\"Sample is zero. SEE: MaxPrecision in BigDecimal.cs. Default value is 308.\");\n        return s;\n    }\n    public FixedBigInteger Next(FixedBigInteger minValue, FixedBigInteger maxValue)\n    {\n        var sa = Sample();\n        var fi = (BigDecimal) (maxValue - minValue + minValue);\n        var n  = new FixedBigInteger(sa * fi, 0);\n        n = !OddsOnly ? n : n | 1;\n        if (Unsigned)\n            return n.Sign &lt; 0 ? new FixedBigInteger(1, n.Data, 0) : n;\n        var buffer = new byte[1];\n        _crng.GetBytes(buffer);\n        if (buffer[0] > 127)\n            return n.Sign &lt; 0 ? n : new FixedBigInteger(-1, n.Data, 0);\n        return n.Sign &lt; 0 ? new FixedBigInteger(1, n.Data, 0) : n;\n    }\n    public FixedBigInteger Next(FixedBigInteger maxValue)\n    {\n        return Next(0, maxValue);\n    }\n    public FixedBigInteger Next()\n    {\n        return Next(0, _maxValueHold);\n    }\n    public override void GetBytes(byte[] data)\n    {\n        if (data == null)\n            throw new ArgumentException(\"The buffer cannot be null.\");\n        _crng.GetBytes(data);\n    }\n    public void NextBytes(byte[] buffer)\n    {\n        if (buffer == null)\n            throw new ArgumentNullException(\"The buffer cannot be null.\");\n        for (var index = 0; index &lt; buffer.Length; ++index)\n            buffer[index] = (byte) (Sample() * byte.MaxValue);\n    }\n    public FixedBigInteger[] Next(FixedBigInteger minValue, FixedBigInteger maxValue, int arraySize)\n    {\n        var array = new FixedBigInteger[arraySize];\n        for (var i = 0; i &lt; arraySize; ++i)\n            array[i] = Next(minValue, maxValue);\n        return array;\n    }\n    public char[] GetNextCharArray(int size)\n    {\n        var ca  = new char[size];\n        var ptr = 0;\n        do\n        {\n            ca[ptr++] = (char) Next(32, 128);\n        } while (ptr &lt; size);\n        return ca;\n    }\n    public byte[] GetNextByteArray(int size)\n    {\n        var ba = new byte[size];\n        _crng.GetBytes(ba);\n        return ba;\n    }\n    public string GetRandomString(int minLen, int maxLen)\n    {\n        if (minLen == maxLen)\n            return new string(GetNextCharArray(minLen));\n        return new string(GetNextCharArray((int) Next((uint) minLen, (uint) maxLen)));\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Fixed BigInteger Random Number Generator<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/42"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=42"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/42\/revisions"}],"predecessor-version":[{"id":43,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/42\/revisions\/43"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}