{"id":366,"date":"2021-01-07T10:19:26","date_gmt":"2021-01-07T10:19:26","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=366"},"modified":"2021-01-07T10:19:26","modified_gmt":"2021-01-07T10:19:26","slug":"randomx-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2021\/01\/07\/randomx-cs\/","title":{"rendered":"RandomX.cs"},"content":{"rendered":"\n<p>A Fast Random Number Generator Based on BigInteger<\/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.Numerics;\nusing System.Security.Cryptography;\npublic struct RandomX\n{\n    private readonly RNGCryptoServiceProvider _crng;\n    private          int                      _maxByteWidth;\n    private          int                      _bitWidth;\n    public RandomX(int bitWidth)\n    {\n        MaxValue      = BigIntegerHelper.GetMaxValueBitWidth(bitWidth);\n        _maxByteWidth = bitWidth >> 3;\n        OddsOnly      = false;\n        Unsigned      = false;\n        _crng         = new RNGCryptoServiceProvider();\n        _bitWidth     = bitWidth;\n    }\n    public bool OddsOnly;\n    public bool Unsigned;\n    public int BitWidth\n    {\n        get => _bitWidth;\n        set\n        {\n            _bitWidth     = value;\n            MaxValue      = BigIntegerHelper.GetMaxValueBitWidth(_bitWidth);\n            _maxByteWidth = _bitWidth >> 3;\n        }\n    }\n    public BigInteger MaxValue;\n    public bool NextBool()\n    {\n        return Sample() &lt; .5;\n    }\n    public char NextChar(char maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (char) (Sample() * maxValue);\n    }\n    public char NextChar(char minValue, char maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (char) Next(minValue, maxValue);\n    }\n    public sbyte NextInt8()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        return (sbyte) Internal();\n    }\n    public sbyte NextInt8(sbyte maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        return (sbyte) (Sample() * maxValue);\n    }\n    public sbyte NextInt8(sbyte minValue, sbyte maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        return (sbyte) Next(minValue, maxValue);\n    }\n    public byte NextUInt8()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        var n = Internal();\n        return (byte) n;\n    }\n    public byte NextUInt8(byte maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        return (byte) (Sample() * maxValue);\n    }\n    public byte NextUInt8(byte minValue, byte maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 8)\n            BitWidth = 8;\n        return (byte) Next(minValue, maxValue);\n    }\n    public short NextInt16()\n    {\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        if (Unsigned)\n            Unsigned = false;\n        return (short) Internal();\n    }\n    public short NextInt16(short maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (short) (Sample() * maxValue);\n    }\n    public short NextInt16(short minValue, short maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (short) Next(minValue, maxValue);\n    }\n    public ushort NextUInt16()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (ushort) Internal();\n    }\n    public ushort NextUInt16(ushort maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (ushort) (Sample() * maxValue);\n    }\n    public ushort NextUInt16(ushort minValue, ushort maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 16)\n            BitWidth = 16;\n        return (ushort) Next(minValue, maxValue);\n    }\n    public int NextInt24()\n    {\n        BitWidth = 24;\n        if (Unsigned)\n            Unsigned = false;\n        return (int) Internal();\n    }\n    public int NextInt24(int maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 24;\n        return (int) (Sample() * maxValue);\n    }\n    public int NextInt24(int minValue, int maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 24;\n        return (int) Next(minValue, maxValue);\n    }\n    public uint NextUInt24()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 24;\n        return (uint) Internal();\n    }\n    public uint NextUInt24(uint maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 24;\n        return (uint) (Sample() * maxValue);\n    }\n    public uint NextUInt24(uint minValue, uint maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 24;\n        return (uint) Next(minValue, maxValue);\n    }\n    public uint NextUInt32()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (uint) Internal();\n    }\n    public uint NextUInt32(uint maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (uint) (Sample() * maxValue);\n    }\n    public uint NextUInt32(uint minValue, uint maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (uint) Next(minValue, maxValue);\n    }\n    public int NextInt32()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (int) Internal();\n    }\n    public int NextInt32(int maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (int) (Sample() * maxValue);\n    }\n    public int NextInt32(int minValue, int maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 32)\n            BitWidth = 32;\n        return (int) Next(minValue, maxValue);\n    }\n    public long NextUInt40()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 40;\n        return (long) Internal();\n    }\n    public long NextUInt40(long maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 40;\n        return (long) (Sample() * maxValue);\n    }\n    public long NextUInt40(long minValue, long maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 40;\n        return (long) Next(minValue, maxValue);\n    }\n    public long NextInt40()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 40;\n        return (long) Internal();\n    }\n    public long NextInt40(long maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 40;\n        return (long) (Sample() * maxValue);\n    }\n    public long NextInt40(long minValue, long maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 40;\n        return (long) Next(minValue, maxValue);\n    }\n    public ulong NextUInt48()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 48;\n        return (ulong) Internal();\n    }\n    public ulong NextUInt48(ulong maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 48;\n        return (ulong) (Sample() * maxValue);\n    }\n    public ulong NextUInt48(ulong minValue, ulong maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 48;\n        return (ulong) Next(minValue, maxValue);\n    }\n    public long NextInt48()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 48;\n        return (long) Internal();\n    }\n    public long NextInt48(long maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 48;\n        return (long) (Sample() * maxValue);\n    }\n    public ulong NextUInt56()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 56;\n        return (ulong) Internal();\n    }\n    public ulong NextUInt56(ulong maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 56;\n        return (ulong) (Sample() * maxValue);\n    }\n    public ulong NextUInt56(ulong minValue, ulong maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        BitWidth = 56;\n        return (uint) Next(minValue, maxValue);\n    }\n    public long NextInt56()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 56;\n        return (long) Internal();\n    }\n    public long NextInt56(long maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 56;\n        return (long) (Sample() * maxValue);\n    }\n    public long NextInt56(long minValue, long maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        BitWidth = 48;\n        return (long) Next(minValue, maxValue);\n    }\n    public long NextInt64()\n    {\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (long) Internal();\n    }\n    public long NextInt64(long maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (long) (Sample() * maxValue);\n    }\n    public long NextInt64(long minValue, long maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (Unsigned)\n            Unsigned = false;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (long) Next(minValue, maxValue);\n    }\n    public ulong NextUInt64()\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (ulong) Internal();\n    }\n    public ulong NextUInt64(ulong maxValue)\n    {\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (ulong) (Sample() * maxValue);\n    }\n    public ulong NextUInt64(ulong minValue, ulong maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        if (!Unsigned)\n            Unsigned = true;\n        if (_bitWidth &lt; 64)\n            BitWidth = 64;\n        return (ulong) Next(minValue, maxValue);\n    }\n    public BigInteger Next()\n    {\n        return Internal();\n    }\n    public BigInteger Next(BigInteger minValue, BigInteger maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        return (BigInteger) (Sample() * (maxValue - minValue)) + minValue;\n    }\n    public UInt512 Next(UInt512 minValue, UInt512 maxValue)\n    {\n        if (minValue > maxValue)\n            throw new ArgumentException(\"maxValue must be greater than or equal to minValue\");\n        var s = Sample();\n        var f = (BigDecimal) ((BigInteger) maxValue - (BigInteger) minValue);\n        return (BigInteger) (s * f);\n    }\n    public BigInteger Next(BigInteger maxValue)\n    {\n        if (maxValue &lt; 0)\n            throw new ArgumentException(\"maxValue must be greater than zero.\");\n        return (BigInteger) (Sample() * maxValue);\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 * (1.0 \/ ulong.MaxValue) * ulong.MaxValue;\n        }\n    }\n    public BigRational NextBigRational()\n    {\n        return new BigRational(Internal(), Internal());\n    }\n    public decimal NextDecimal()\n    {\n        return new decimal(NextInt32(), NextInt32(), NextInt32(), NextBool(), NextUInt8(255));\n    }\n    public BigDecimal NextBigDecimal()\n    {\n        return Sample();\n    }\n    public byte[] GetNextByteArray(int size)\n    {\n        var ba = new byte[size];\n        _crng.GetBytes(ba);\n        return ba;\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 >= 0x20 &amp;&amp; c &lt;= 0x7F)\n                ca[ptr++] = (char) c;\n        } while (ptr &lt; size);\n        return ca;\n    }\n    public char NextChar()\n    {\n        var xbc = new byte[1];\n        while (true)\n        {\n            _crng.GetBytes(xbc);\n            var c = xbc[0];\n            if (c >= 0x20 &amp;&amp; c &lt;= 0x7F)\n                return (char) c;\n        }\n    }\n    public string GetRandomString(int minLen, int maxLen)\n    {\n        return minLen == maxLen ? new string(GetNextCharArray(minLen)) : new string(GetNextCharArray((int) NextUInt32((uint) minLen, (uint) maxLen)));\n    }\n    private BigDecimal Sample()\n    {\n        var i = Internal();\n        var s = i * (BigDecimal.One \/ MaxValue);\n        if (s.Sign == -1)\n            s = s * -1;\n        if (s.IsZero)\n            throw new Exception(\"Sample is zero.\");\n        return s;\n    }\n    public void GetBytes(byte[] data)\n    {\n        if (data == null)\n            throw new ArgumentException(\"The buffer cannot be null.\");\n        _crng.GetBytes(data);\n    }\n    private BigInteger Internal()\n    {\n        if (Unsigned)\n        {\n            var buffer = new byte[_maxByteWidth + 1];\n            _crng.GetBytes(buffer);\n            buffer[_maxByteWidth] = 0;\n            var n = new BigInteger(buffer);\n            return !OddsOnly ? n : n | 1;\n        }\n        else\n        {\n            var buffer = new byte[_maxByteWidth];\n            _crng.GetBytes(buffer);\n            var n = new BigInteger(buffer);\n            return !OddsOnly ? n : n | 1;\n        }\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>A Fast Random Number Generator Based on BigInteger<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[14,100,167,51,103],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/366"}],"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=366"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/366\/revisions"}],"predecessor-version":[{"id":367,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/366\/revisions\/367"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}