{"id":194,"date":"2020-08-15T10:41:15","date_gmt":"2020-08-15T10:41:15","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=194"},"modified":"2020-08-15T10:41:15","modified_gmt":"2020-08-15T10:41:15","slug":"random64csp-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/08\/15\/random64csp-cs\/","title":{"rendered":"Random64csp.cs"},"content":{"rendered":"\n<p>64 Bit Random Number Generator Using RNGCryptoServiceProvider<\/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;\n[Serializable]\npublic class Random64csp : RandomNumberGenerator\n{\n    private byte[] _buffer;\n    private RNGCryptoServiceProvider _crng;\n    private double _dBi;\n    private ulong UpperLimit = ulong.MaxValue;\n    public Random64csp()\n    {\n        SetDataUse = 8;\n        _crng = new RNGCryptoServiceProvider();\n    }\n    \n    public Random64csp(int dataSize)\n    {\n        SetDataUse = dataSize;\n        _crng      = new RNGCryptoServiceProvider();\n    }\n    \n    public int SetDataUse\n    {\n        get => _buffer.Length;\n        set\n        {\n            var v = value;\n            if (v &lt; 1 || v > 8 || v == 3 || v == 5 || v == 6 || v == 7)\n                throw new ArgumentException($\"Value {v} must be either 1 or 2 or 4 or 8\");\n            switch (v)\n            {\n                case 1:\n                    _dBi = 1.0D \/ byte.MaxValue;\n                    UpperLimit = byte.MaxValue;\n                    _buffer = new byte[1];\n                    break;\n                case 2:\n                    _dBi = 1.0D \/ ushort.MaxValue;\n                    UpperLimit = ushort.MaxValue;\n                    _buffer = new byte[2];\n                    break;\n                case 4:\n                    _dBi = 1.0D \/ uint.MaxValue;\n                    UpperLimit = uint.MaxValue;\n                    _buffer = new byte[4];\n                    break;\n                case 8:\n                    _dBi = 1.0D \/ ulong.MaxValue;\n                    UpperLimit = ulong.MaxValue;\n                    _buffer = new byte[8];\n                    break;\n                default:\n                    _dBi = 1.0D \/ ulong.MaxValue;\n                    UpperLimit = ulong.MaxValue;\n                    _buffer = new byte[8];\n                    break;\n            }\n        }\n    }\n    \/\/\/ &lt;summary>\n    \/\/\/     Will generate only odd values\n    \/\/\/ &lt;\/summary>\n    public bool OddsOnly\n    {\n        get;\n        set;\n    }\n    private double Sample()\n    {\n        ulong Internal()\n        {\n            _crng.GetBytes(_buffer);\n            return BufferToLong(_buffer);\n        }\n        return Internal() * _dBi;\n    }\n    public ulong Next(ulong minValue, ulong maxValue)\n    {\n        var sa = Sample();\n        var fi = (double)(maxValue - minValue + minValue);\n        var n = (ulong)(sa * fi);\n        n = !OddsOnly ? n : n | 1;\n        if (n &lt; minValue)\n            return Next(minValue, maxValue);\n        return n;\n    }\n    public ulong Next(ulong maxValue)\n    {\n        return Next(0, maxValue);\n    }\n    public ulong Next()\n    {\n        return Next(0, UpperLimit);\n    }\n    public unsafe double NextDouble()\n    {\n        var buf = new byte[8];\n        GetBytes(buf);\n        fixed (byte* ptr = buf)\n        {\n            return *(ulong*)ptr * _dBi * ulong.MaxValue;\n        }\n    }\n    public char[] GetNextCharArray(int size)\n    {\n        var xbc = new byte[1];\n        var ca = new char[size];\n        var ptr = 0;\n        do\n        {\n            _crng.GetBytes(xbc);\n            var c = xbc[0];\n            if (c >= 32 &amp;&amp; c &lt;= 127)\n                ca[ptr++] = (char)c;\n        } while (ptr &lt; size);\n        return ca;\n    }\n    public char[] GetNextCharArrayX(int size)\n    {\n        var xbc = new byte[2];\n        var ca = new char[size];\n        var ptr = 0;\n        do\n        {\n            _crng.GetBytes(xbc);\n            ca[ptr++] = Convert.ToChar(xbc.ToShort());\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    \/\/\/ &lt;summary>\n    \/\/\/     Next(0,2)==0?false:true; has a distribution error of 1% weighted toward zero.\n    \/\/\/     The distribution error here is 0.000000046% which is statistically insignificant in this context.\n    \/\/\/ &lt;\/summary>\n    \/\/\/ &lt;param name=\"size\">&lt;\/param>\n    \/\/\/ &lt;returns>&lt;\/returns>\n    public bool[] GetNextBoolArrayLimit(int size)\n    {\n        var ba = new bool[size];\n        const uint ll = uint.MaxValue >> 1;\n        for (var i = 0; i &lt; size; ++i)\n            ba[i] = Next(0, uint.MaxValue) > ll;\n        return ba;\n    }\n    public byte[] GetNextByteArrayLimit(int size, ulong minValue, ulong maxValue)\n    {\n        var ba = new byte[size];\n        for (var i = 0; i &lt; size; ++i)\n            ba[i] = (byte)Next(minValue, maxValue);\n        return ba;\n    }\n    public ushort[] GetNextUShortArrayLimit(int size, ulong minValue, ulong maxValue)\n    {\n        var ba = new ushort[size];\n        for (var i = 0; i &lt; size; ++i)\n            ba[i] = (ushort)Next(minValue, maxValue);\n        return ba;\n    }\n    public uint[] GetNextUIntArrayLimit(int size, ulong minValue, ulong maxValue)\n    {\n        var ba = new uint[size];\n        for (var i = 0; i &lt; size; ++i)\n            ba[i] = (uint)Next(minValue, maxValue);\n        return ba;\n    }\n    public ulong[] GetNextULongArrayLimit(int size, ulong minValue, ulong maxValue)\n    {\n        var ba = new ulong[size];\n        for (var i = 0; i &lt; size; ++i)\n            ba[i] = Next(minValue, maxValue);\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((ulong)minLen, (ulong)maxLen)));\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 + 1);\n    }\n    public override void GetNonZeroBytes(byte[] buffer)\n    {\n        if (buffer == null)\n            throw new ArgumentNullException(\"The buffer cannot be null.\");\n        var index = 0;\n        do\n        {\n            var v = (byte)(Sample() * byte.MaxValue + 1);\n            if (v > 0)\n            {\n                buffer[index] = v;\n                index++;\n            }\n        } while (index &lt; buffer.Length);\n    }\n    private unsafe ulong BufferToLong(byte[] buffer)\n    {\n        var len = buffer.Length;\n        if (len &lt; 1 || len > 8)\n            throw new ArgumentException($\"The array length {len} must be between 1 and 8\");\n        fixed (byte* Ptr = &amp;buffer[0])\n        {\n            switch (len)\n            {\n                case 1:\n                    return *Ptr;\n                case 2:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8));\n                case 3:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16));\n                case 4:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16) | (Ptr[3] &lt;&lt; 24));\n                case 5:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16) | (Ptr[3] &lt;&lt; 24)) | ((ulong)Ptr[4] &lt;&lt; 32);\n                case 6:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16) | (Ptr[3] &lt;&lt; 24)) | ((ulong)(Ptr[4] | (Ptr[5] &lt;&lt; 8)) &lt;&lt; 32);\n                case 7:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16) | (Ptr[3] &lt;&lt; 24)) | ((ulong)(Ptr[4] | (Ptr[5] &lt;&lt; 8) | (Ptr[6] &lt;&lt; 16)) &lt;&lt; 32);\n                case 8:\n                    return (uint)(*Ptr | (Ptr[1] &lt;&lt; 8) | (Ptr[2] &lt;&lt; 16) | (Ptr[3] &lt;&lt; 24)) | ((ulong)(Ptr[4] | (Ptr[5] &lt;&lt; 8) | (Ptr[6] &lt;&lt; 16) | (Ptr[7] &lt;&lt; 24)) &lt;&lt; 32);\n                default:\n                    return 0;\n            }\n        }\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>64 Bit Random Number Generator Using RNGCryptoServiceProvider<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[36,102,38,37,51,103],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/194"}],"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=194"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/194\/revisions"}],"predecessor-version":[{"id":195,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/194\/revisions\/195"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}