RandomX.cs

A Fast Random Number Generator Based on BigInteger

using System;
using System.Numerics;
using System.Security.Cryptography;
public struct RandomX
{
private readonly RNGCryptoServiceProvider _crng;
private int _maxByteWidth;
private int _bitWidth;
public RandomX(int bitWidth)
{
MaxValue = BigIntegerHelper.GetMaxValueBitWidth(bitWidth);
_maxByteWidth = bitWidth >> 3;
OddsOnly = false;
Unsigned = false;
_crng = new RNGCryptoServiceProvider();
_bitWidth = bitWidth;
}
public bool OddsOnly;
public bool Unsigned;
public int BitWidth
{
get => _bitWidth;
set
{
_bitWidth = value;
MaxValue = BigIntegerHelper.GetMaxValueBitWidth(_bitWidth);
_maxByteWidth = _bitWidth >> 3;
}
}
public BigInteger MaxValue;
public bool NextBool()
{
return Sample() < .5;
}
public char NextChar(char maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 16)
BitWidth = 16;
return (char) (Sample() * maxValue);
}
public char NextChar(char minValue, char maxValue)
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 16)
BitWidth = 16;
return (char) Next(minValue, maxValue);
}
public sbyte NextInt8()
{
if (Unsigned)
Unsigned = false;
if (_bitWidth < 8)
BitWidth = 8;
return (sbyte) Internal();
}
public sbyte NextInt8(sbyte maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 8)
BitWidth = 8;
return (sbyte) (Sample() * maxValue);
}
public sbyte NextInt8(sbyte minValue, sbyte maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 8)
BitWidth = 8;
return (sbyte) Next(minValue, maxValue);
}
public byte NextUInt8()
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 8)
BitWidth = 8;
var n = Internal();
return (byte) n;
}
public byte NextUInt8(byte maxValue)
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 8)
BitWidth = 8;
return (byte) (Sample() * maxValue);
}
public byte NextUInt8(byte minValue, byte maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 8)
BitWidth = 8;
return (byte) Next(minValue, maxValue);
}
public short NextInt16()
{
if (_bitWidth < 16)
BitWidth = 16;
if (Unsigned)
Unsigned = false;
return (short) Internal();
}
public short NextInt16(short maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 16)
BitWidth = 16;
return (short) (Sample() * maxValue);
}
public short NextInt16(short minValue, short maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 16)
BitWidth = 16;
return (short) Next(minValue, maxValue);
}
public ushort NextUInt16()
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 16)
BitWidth = 16;
return (ushort) Internal();
}
public ushort NextUInt16(ushort maxValue)
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 16)
BitWidth = 16;
return (ushort) (Sample() * maxValue);
}
public ushort NextUInt16(ushort minValue, ushort maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 16)
BitWidth = 16;
return (ushort) Next(minValue, maxValue);
}
public int NextInt24()
{
BitWidth = 24;
if (Unsigned)
Unsigned = false;
return (int) Internal();
}
public int NextInt24(int maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
BitWidth = 24;
return (int) (Sample() * maxValue);
}
public int NextInt24(int minValue, int maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
BitWidth = 24;
return (int) Next(minValue, maxValue);
}
public uint NextUInt24()
{
if (!Unsigned)
Unsigned = true;
BitWidth = 24;
return (uint) Internal();
}
public uint NextUInt24(uint maxValue)
{
if (!Unsigned)
Unsigned = true;
BitWidth = 24;
return (uint) (Sample() * maxValue);
}
public uint NextUInt24(uint minValue, uint maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
BitWidth = 24;
return (uint) Next(minValue, maxValue);
}
public uint NextUInt32()
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 32)
BitWidth = 32;
return (uint) Internal();
}
public uint NextUInt32(uint maxValue)
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 32)
BitWidth = 32;
return (uint) (Sample() * maxValue);
}
public uint NextUInt32(uint minValue, uint maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 32)
BitWidth = 32;
return (uint) Next(minValue, maxValue);
}
public int NextInt32()
{
if (Unsigned)
Unsigned = false;
if (_bitWidth < 32)
BitWidth = 32;
return (int) Internal();
}
public int NextInt32(int maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 32)
BitWidth = 32;
return (int) (Sample() * maxValue);
}
public int NextInt32(int minValue, int maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 32)
BitWidth = 32;
return (int) Next(minValue, maxValue);
}
public long NextUInt40()
{
if (!Unsigned)
Unsigned = true;
BitWidth = 40;
return (long) Internal();
}
public long NextUInt40(long maxValue)
{
if (!Unsigned)
Unsigned = true;
BitWidth = 40;
return (long) (Sample() * maxValue);
}
public long NextUInt40(long minValue, long maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
BitWidth = 40;
return (long) Next(minValue, maxValue);
}
public long NextInt40()
{
if (Unsigned)
Unsigned = false;
BitWidth = 40;
return (long) Internal();
}
public long NextInt40(long maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
BitWidth = 40;
return (long) (Sample() * maxValue);
}
public long NextInt40(long minValue, long maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
BitWidth = 40;
return (long) Next(minValue, maxValue);
}
public ulong NextUInt48()
{
if (!Unsigned)
Unsigned = true;
BitWidth = 48;
return (ulong) Internal();
}
public ulong NextUInt48(ulong maxValue)
{
if (!Unsigned)
Unsigned = true;
BitWidth = 48;
return (ulong) (Sample() * maxValue);
}
public ulong NextUInt48(ulong minValue, ulong maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
BitWidth = 48;
return (ulong) Next(minValue, maxValue);
}
public long NextInt48()
{
if (Unsigned)
Unsigned = false;
BitWidth = 48;
return (long) Internal();
}
public long NextInt48(long maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
BitWidth = 48;
return (long) (Sample() * maxValue);
}
public ulong NextUInt56()
{
if (!Unsigned)
Unsigned = true;
BitWidth = 56;
return (ulong) Internal();
}
public ulong NextUInt56(ulong maxValue)
{
if (!Unsigned)
Unsigned = true;
BitWidth = 56;
return (ulong) (Sample() * maxValue);
}
public ulong NextUInt56(ulong minValue, ulong maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
BitWidth = 56;
return (uint) Next(minValue, maxValue);
}
public long NextInt56()
{
if (Unsigned)
Unsigned = false;
BitWidth = 56;
return (long) Internal();
}
public long NextInt56(long maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
BitWidth = 56;
return (long) (Sample() * maxValue);
}
public long NextInt56(long minValue, long maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
BitWidth = 48;
return (long) Next(minValue, maxValue);
}
public long NextInt64()
{
if (Unsigned)
Unsigned = false;
if (_bitWidth < 64)
BitWidth = 64;
return (long) Internal();
}
public long NextInt64(long maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 64)
BitWidth = 64;
return (long) (Sample() * maxValue);
}
public long NextInt64(long minValue, long maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (Unsigned)
Unsigned = false;
if (_bitWidth < 64)
BitWidth = 64;
return (long) Next(minValue, maxValue);
}
public ulong NextUInt64()
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 64)
BitWidth = 64;
return (ulong) Internal();
}
public ulong NextUInt64(ulong maxValue)
{
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 64)
BitWidth = 64;
return (ulong) (Sample() * maxValue);
}
public ulong NextUInt64(ulong minValue, ulong maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
if (!Unsigned)
Unsigned = true;
if (_bitWidth < 64)
BitWidth = 64;
return (ulong) Next(minValue, maxValue);
}
public BigInteger Next()
{
return Internal();
}
public BigInteger Next(BigInteger minValue, BigInteger maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return (BigInteger) (Sample() * (maxValue - minValue)) + minValue;
}
public UInt512 Next(UInt512 minValue, UInt512 maxValue)
{
if (minValue > maxValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
var s = Sample();
var f = (BigDecimal) ((BigInteger) maxValue - (BigInteger) minValue);
return (BigInteger) (s * f);
}
public BigInteger Next(BigInteger maxValue)
{
if (maxValue < 0)
throw new ArgumentException("maxValue must be greater than zero.");
return (BigInteger) (Sample() * maxValue);
}
public unsafe double NextDouble()
{
var buf = new byte[8];
GetBytes(buf);
fixed (byte* ptr = buf)
{
return *(ulong*) ptr * (1.0 / ulong.MaxValue) * ulong.MaxValue;
}
}
public BigRational NextBigRational()
{
return new BigRational(Internal(), Internal());
}
public decimal NextDecimal()
{
return new decimal(NextInt32(), NextInt32(), NextInt32(), NextBool(), NextUInt8(255));
}
public BigDecimal NextBigDecimal()
{
return Sample();
}
public byte[] GetNextByteArray(int size)
{
var ba = new byte[size];
_crng.GetBytes(ba);
return ba;
}
public char[] GetNextCharArray(int size)
{
var xbc = new byte[1];
var ca = new char[size];
var ptr = 0;
do
{
_crng.GetBytes(xbc);
var c = xbc[0];
if (c >= 0x20 && c <= 0x7F)
ca[ptr++] = (char) c;
} while (ptr < size);
return ca;
}
public char NextChar()
{
var xbc = new byte[1];
while (true)
{
_crng.GetBytes(xbc);
var c = xbc[0];
if (c >= 0x20 && c <= 0x7F)
return (char) c;
}
}
public string GetRandomString(int minLen, int maxLen)
{
return minLen == maxLen ? new string(GetNextCharArray(minLen)) : new string(GetNextCharArray((int) NextUInt32((uint) minLen, (uint) maxLen)));
}
private BigDecimal Sample()
{
var i = Internal();
var s = i * (BigDecimal.One / MaxValue);
if (s.Sign == -1)
s = s * -1;
if (s.IsZero)
throw new Exception("Sample is zero.");
return s;
}
public void GetBytes(byte[] data)
{
if (data == null)
throw new ArgumentException("The buffer cannot be null.");
_crng.GetBytes(data);
}
private BigInteger Internal()
{
if (Unsigned)
{
var buffer = new byte[_maxByteWidth + 1];
_crng.GetBytes(buffer);
buffer[_maxByteWidth] = 0;
var n = new BigInteger(buffer);
return !OddsOnly ? n : n | 1;
}
else
{
var buffer = new byte[_maxByteWidth];
_crng.GetBytes(buffer);
var n = new BigInteger(buffer);
return !OddsOnly ? n : n | 1;
}
}
}
using System; using System.Numerics; using System.Security.Cryptography; public struct RandomX { private readonly RNGCryptoServiceProvider _crng; private int _maxByteWidth; private int _bitWidth; public RandomX(int bitWidth) { MaxValue = BigIntegerHelper.GetMaxValueBitWidth(bitWidth); _maxByteWidth = bitWidth >> 3; OddsOnly = false; Unsigned = false; _crng = new RNGCryptoServiceProvider(); _bitWidth = bitWidth; } public bool OddsOnly; public bool Unsigned; public int BitWidth { get => _bitWidth; set { _bitWidth = value; MaxValue = BigIntegerHelper.GetMaxValueBitWidth(_bitWidth); _maxByteWidth = _bitWidth >> 3; } } public BigInteger MaxValue; public bool NextBool() { return Sample() < .5; } public char NextChar(char maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (!Unsigned) Unsigned = true; if (_bitWidth < 16) BitWidth = 16; return (char) (Sample() * maxValue); } public char NextChar(char minValue, char maxValue) { if (!Unsigned) Unsigned = true; if (_bitWidth < 16) BitWidth = 16; return (char) Next(minValue, maxValue); } public sbyte NextInt8() { if (Unsigned) Unsigned = false; if (_bitWidth < 8) BitWidth = 8; return (sbyte) Internal(); } public sbyte NextInt8(sbyte maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; if (_bitWidth < 8) BitWidth = 8; return (sbyte) (Sample() * maxValue); } public sbyte NextInt8(sbyte minValue, sbyte maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; if (_bitWidth < 8) BitWidth = 8; return (sbyte) Next(minValue, maxValue); } public byte NextUInt8() { if (!Unsigned) Unsigned = true; if (_bitWidth < 8) BitWidth = 8; var n = Internal(); return (byte) n; } public byte NextUInt8(byte maxValue) { if (!Unsigned) Unsigned = true; if (_bitWidth < 8) BitWidth = 8; return (byte) (Sample() * maxValue); } public byte NextUInt8(byte minValue, byte maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; if (_bitWidth < 8) BitWidth = 8; return (byte) Next(minValue, maxValue); } public short NextInt16() { if (_bitWidth < 16) BitWidth = 16; if (Unsigned) Unsigned = false; return (short) Internal(); } public short NextInt16(short maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; if (_bitWidth < 16) BitWidth = 16; return (short) (Sample() * maxValue); } public short NextInt16(short minValue, short maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; if (_bitWidth < 16) BitWidth = 16; return (short) Next(minValue, maxValue); } public ushort NextUInt16() { if (!Unsigned) Unsigned = true; if (_bitWidth < 16) BitWidth = 16; return (ushort) Internal(); } public ushort NextUInt16(ushort maxValue) { if (!Unsigned) Unsigned = true; if (_bitWidth < 16) BitWidth = 16; return (ushort) (Sample() * maxValue); } public ushort NextUInt16(ushort minValue, ushort maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; if (_bitWidth < 16) BitWidth = 16; return (ushort) Next(minValue, maxValue); } public int NextInt24() { BitWidth = 24; if (Unsigned) Unsigned = false; return (int) Internal(); } public int NextInt24(int maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; BitWidth = 24; return (int) (Sample() * maxValue); } public int NextInt24(int minValue, int maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; BitWidth = 24; return (int) Next(minValue, maxValue); } public uint NextUInt24() { if (!Unsigned) Unsigned = true; BitWidth = 24; return (uint) Internal(); } public uint NextUInt24(uint maxValue) { if (!Unsigned) Unsigned = true; BitWidth = 24; return (uint) (Sample() * maxValue); } public uint NextUInt24(uint minValue, uint maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; BitWidth = 24; return (uint) Next(minValue, maxValue); } public uint NextUInt32() { if (!Unsigned) Unsigned = true; if (_bitWidth < 32) BitWidth = 32; return (uint) Internal(); } public uint NextUInt32(uint maxValue) { if (!Unsigned) Unsigned = true; if (_bitWidth < 32) BitWidth = 32; return (uint) (Sample() * maxValue); } public uint NextUInt32(uint minValue, uint maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; if (_bitWidth < 32) BitWidth = 32; return (uint) Next(minValue, maxValue); } public int NextInt32() { if (Unsigned) Unsigned = false; if (_bitWidth < 32) BitWidth = 32; return (int) Internal(); } public int NextInt32(int maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; if (_bitWidth < 32) BitWidth = 32; return (int) (Sample() * maxValue); } public int NextInt32(int minValue, int maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; if (_bitWidth < 32) BitWidth = 32; return (int) Next(minValue, maxValue); } public long NextUInt40() { if (!Unsigned) Unsigned = true; BitWidth = 40; return (long) Internal(); } public long NextUInt40(long maxValue) { if (!Unsigned) Unsigned = true; BitWidth = 40; return (long) (Sample() * maxValue); } public long NextUInt40(long minValue, long maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; BitWidth = 40; return (long) Next(minValue, maxValue); } public long NextInt40() { if (Unsigned) Unsigned = false; BitWidth = 40; return (long) Internal(); } public long NextInt40(long maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; BitWidth = 40; return (long) (Sample() * maxValue); } public long NextInt40(long minValue, long maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; BitWidth = 40; return (long) Next(minValue, maxValue); } public ulong NextUInt48() { if (!Unsigned) Unsigned = true; BitWidth = 48; return (ulong) Internal(); } public ulong NextUInt48(ulong maxValue) { if (!Unsigned) Unsigned = true; BitWidth = 48; return (ulong) (Sample() * maxValue); } public ulong NextUInt48(ulong minValue, ulong maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; BitWidth = 48; return (ulong) Next(minValue, maxValue); } public long NextInt48() { if (Unsigned) Unsigned = false; BitWidth = 48; return (long) Internal(); } public long NextInt48(long maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; BitWidth = 48; return (long) (Sample() * maxValue); } public ulong NextUInt56() { if (!Unsigned) Unsigned = true; BitWidth = 56; return (ulong) Internal(); } public ulong NextUInt56(ulong maxValue) { if (!Unsigned) Unsigned = true; BitWidth = 56; return (ulong) (Sample() * maxValue); } public ulong NextUInt56(ulong minValue, ulong maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; BitWidth = 56; return (uint) Next(minValue, maxValue); } public long NextInt56() { if (Unsigned) Unsigned = false; BitWidth = 56; return (long) Internal(); } public long NextInt56(long maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; BitWidth = 56; return (long) (Sample() * maxValue); } public long NextInt56(long minValue, long maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; BitWidth = 48; return (long) Next(minValue, maxValue); } public long NextInt64() { if (Unsigned) Unsigned = false; if (_bitWidth < 64) BitWidth = 64; return (long) Internal(); } public long NextInt64(long maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); if (Unsigned) Unsigned = false; if (_bitWidth < 64) BitWidth = 64; return (long) (Sample() * maxValue); } public long NextInt64(long minValue, long maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (Unsigned) Unsigned = false; if (_bitWidth < 64) BitWidth = 64; return (long) Next(minValue, maxValue); } public ulong NextUInt64() { if (!Unsigned) Unsigned = true; if (_bitWidth < 64) BitWidth = 64; return (ulong) Internal(); } public ulong NextUInt64(ulong maxValue) { if (!Unsigned) Unsigned = true; if (_bitWidth < 64) BitWidth = 64; return (ulong) (Sample() * maxValue); } public ulong NextUInt64(ulong minValue, ulong maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); if (!Unsigned) Unsigned = true; if (_bitWidth < 64) BitWidth = 64; return (ulong) Next(minValue, maxValue); } public BigInteger Next() { return Internal(); } public BigInteger Next(BigInteger minValue, BigInteger maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); return (BigInteger) (Sample() * (maxValue - minValue)) + minValue; } public UInt512 Next(UInt512 minValue, UInt512 maxValue) { if (minValue > maxValue) throw new ArgumentException("maxValue must be greater than or equal to minValue"); var s = Sample(); var f = (BigDecimal) ((BigInteger) maxValue - (BigInteger) minValue); return (BigInteger) (s * f); } public BigInteger Next(BigInteger maxValue) { if (maxValue < 0) throw new ArgumentException("maxValue must be greater than zero."); return (BigInteger) (Sample() * maxValue); } public unsafe double NextDouble() { var buf = new byte[8]; GetBytes(buf); fixed (byte* ptr = buf) { return *(ulong*) ptr * (1.0 / ulong.MaxValue) * ulong.MaxValue; } } public BigRational NextBigRational() { return new BigRational(Internal(), Internal()); } public decimal NextDecimal() { return new decimal(NextInt32(), NextInt32(), NextInt32(), NextBool(), NextUInt8(255)); } public BigDecimal NextBigDecimal() { return Sample(); } public byte[] GetNextByteArray(int size) { var ba = new byte[size]; _crng.GetBytes(ba); return ba; } public char[] GetNextCharArray(int size) { var xbc = new byte[1]; var ca = new char[size]; var ptr = 0; do { _crng.GetBytes(xbc); var c = xbc[0]; if (c >= 0x20 && c <= 0x7F) ca[ptr++] = (char) c; } while (ptr < size); return ca; } public char NextChar() { var xbc = new byte[1]; while (true) { _crng.GetBytes(xbc); var c = xbc[0]; if (c >= 0x20 && c <= 0x7F) return (char) c; } } public string GetRandomString(int minLen, int maxLen) { return minLen == maxLen ? new string(GetNextCharArray(minLen)) : new string(GetNextCharArray((int) NextUInt32((uint) minLen, (uint) maxLen))); } private BigDecimal Sample() { var i = Internal(); var s = i * (BigDecimal.One / MaxValue); if (s.Sign == -1) s = s * -1; if (s.IsZero) throw new Exception("Sample is zero."); return s; } public void GetBytes(byte[] data) { if (data == null) throw new ArgumentException("The buffer cannot be null."); _crng.GetBytes(data); } private BigInteger Internal() { if (Unsigned) { var buffer = new byte[_maxByteWidth + 1]; _crng.GetBytes(buffer); buffer[_maxByteWidth] = 0; var n = new BigInteger(buffer); return !OddsOnly ? n : n | 1; } else { var buffer = new byte[_maxByteWidth]; _crng.GetBytes(buffer); var n = new BigInteger(buffer); return !OddsOnly ? n : n | 1; } } }
using System;
using System.Numerics;
using System.Security.Cryptography;
public struct RandomX
{
    private readonly RNGCryptoServiceProvider _crng;
    private          int                      _maxByteWidth;
    private          int                      _bitWidth;
    public RandomX(int bitWidth)
    {
        MaxValue      = BigIntegerHelper.GetMaxValueBitWidth(bitWidth);
        _maxByteWidth = bitWidth >> 3;
        OddsOnly      = false;
        Unsigned      = false;
        _crng         = new RNGCryptoServiceProvider();
        _bitWidth     = bitWidth;
    }
    public bool OddsOnly;
    public bool Unsigned;
    public int BitWidth
    {
        get => _bitWidth;
        set
        {
            _bitWidth     = value;
            MaxValue      = BigIntegerHelper.GetMaxValueBitWidth(_bitWidth);
            _maxByteWidth = _bitWidth >> 3;
        }
    }
    public BigInteger MaxValue;
    public bool NextBool()
    {
        return Sample() < .5;
    }
    public char NextChar(char maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (char) (Sample() * maxValue);
    }
    public char NextChar(char minValue, char maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (char) Next(minValue, maxValue);
    }
    public sbyte NextInt8()
    {
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 8)
            BitWidth = 8;
        return (sbyte) Internal();
    }
    public sbyte NextInt8(sbyte maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 8)
            BitWidth = 8;
        return (sbyte) (Sample() * maxValue);
    }
    public sbyte NextInt8(sbyte minValue, sbyte maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 8)
            BitWidth = 8;
        return (sbyte) Next(minValue, maxValue);
    }
    public byte NextUInt8()
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 8)
            BitWidth = 8;
        var n = Internal();
        return (byte) n;
    }
    public byte NextUInt8(byte maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 8)
            BitWidth = 8;
        return (byte) (Sample() * maxValue);
    }
    public byte NextUInt8(byte minValue, byte maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 8)
            BitWidth = 8;
        return (byte) Next(minValue, maxValue);
    }
    public short NextInt16()
    {
        if (_bitWidth < 16)
            BitWidth = 16;
        if (Unsigned)
            Unsigned = false;
        return (short) Internal();
    }
    public short NextInt16(short maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (short) (Sample() * maxValue);
    }
    public short NextInt16(short minValue, short maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (short) Next(minValue, maxValue);
    }
    public ushort NextUInt16()
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (ushort) Internal();
    }
    public ushort NextUInt16(ushort maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (ushort) (Sample() * maxValue);
    }
    public ushort NextUInt16(ushort minValue, ushort maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 16)
            BitWidth = 16;
        return (ushort) Next(minValue, maxValue);
    }
    public int NextInt24()
    {
        BitWidth = 24;
        if (Unsigned)
            Unsigned = false;
        return (int) Internal();
    }
    public int NextInt24(int maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 24;
        return (int) (Sample() * maxValue);
    }
    public int NextInt24(int minValue, int maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 24;
        return (int) Next(minValue, maxValue);
    }
    public uint NextUInt24()
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 24;
        return (uint) Internal();
    }
    public uint NextUInt24(uint maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 24;
        return (uint) (Sample() * maxValue);
    }
    public uint NextUInt24(uint minValue, uint maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 24;
        return (uint) Next(minValue, maxValue);
    }
    public uint NextUInt32()
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (uint) Internal();
    }
    public uint NextUInt32(uint maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (uint) (Sample() * maxValue);
    }
    public uint NextUInt32(uint minValue, uint maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (uint) Next(minValue, maxValue);
    }
    public int NextInt32()
    {
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (int) Internal();
    }
    public int NextInt32(int maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (int) (Sample() * maxValue);
    }
    public int NextInt32(int minValue, int maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 32)
            BitWidth = 32;
        return (int) Next(minValue, maxValue);
    }
    public long NextUInt40()
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 40;
        return (long) Internal();
    }
    public long NextUInt40(long maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 40;
        return (long) (Sample() * maxValue);
    }
    public long NextUInt40(long minValue, long maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 40;
        return (long) Next(minValue, maxValue);
    }
    public long NextInt40()
    {
        if (Unsigned)
            Unsigned = false;
        BitWidth = 40;
        return (long) Internal();
    }
    public long NextInt40(long maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 40;
        return (long) (Sample() * maxValue);
    }
    public long NextInt40(long minValue, long maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 40;
        return (long) Next(minValue, maxValue);
    }
    public ulong NextUInt48()
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 48;
        return (ulong) Internal();
    }
    public ulong NextUInt48(ulong maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 48;
        return (ulong) (Sample() * maxValue);
    }
    public ulong NextUInt48(ulong minValue, ulong maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 48;
        return (ulong) Next(minValue, maxValue);
    }
    public long NextInt48()
    {
        if (Unsigned)
            Unsigned = false;
        BitWidth = 48;
        return (long) Internal();
    }
    public long NextInt48(long maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 48;
        return (long) (Sample() * maxValue);
    }
    public ulong NextUInt56()
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 56;
        return (ulong) Internal();
    }
    public ulong NextUInt56(ulong maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 56;
        return (ulong) (Sample() * maxValue);
    }
    public ulong NextUInt56(ulong minValue, ulong maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        BitWidth = 56;
        return (uint) Next(minValue, maxValue);
    }
    public long NextInt56()
    {
        if (Unsigned)
            Unsigned = false;
        BitWidth = 56;
        return (long) Internal();
    }
    public long NextInt56(long maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 56;
        return (long) (Sample() * maxValue);
    }
    public long NextInt56(long minValue, long maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        BitWidth = 48;
        return (long) Next(minValue, maxValue);
    }
    public long NextInt64()
    {
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (long) Internal();
    }
    public long NextInt64(long maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (long) (Sample() * maxValue);
    }
    public long NextInt64(long minValue, long maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (Unsigned)
            Unsigned = false;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (long) Next(minValue, maxValue);
    }
    public ulong NextUInt64()
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (ulong) Internal();
    }
    public ulong NextUInt64(ulong maxValue)
    {
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (ulong) (Sample() * maxValue);
    }
    public ulong NextUInt64(ulong minValue, ulong maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        if (!Unsigned)
            Unsigned = true;
        if (_bitWidth < 64)
            BitWidth = 64;
        return (ulong) Next(minValue, maxValue);
    }
    public BigInteger Next()
    {
        return Internal();
    }
    public BigInteger Next(BigInteger minValue, BigInteger maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        return (BigInteger) (Sample() * (maxValue - minValue)) + minValue;
    }
    public UInt512 Next(UInt512 minValue, UInt512 maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentException("maxValue must be greater than or equal to minValue");
        var s = Sample();
        var f = (BigDecimal) ((BigInteger) maxValue - (BigInteger) minValue);
        return (BigInteger) (s * f);
    }
    public BigInteger Next(BigInteger maxValue)
    {
        if (maxValue < 0)
            throw new ArgumentException("maxValue must be greater than zero.");
        return (BigInteger) (Sample() * maxValue);
    }
    public unsafe double NextDouble()
    {
        var buf = new byte[8];
        GetBytes(buf);
        fixed (byte* ptr = buf)
        {
            return *(ulong*) ptr * (1.0 / ulong.MaxValue) * ulong.MaxValue;
        }
    }
    public BigRational NextBigRational()
    {
        return new BigRational(Internal(), Internal());
    }
    public decimal NextDecimal()
    {
        return new decimal(NextInt32(), NextInt32(), NextInt32(), NextBool(), NextUInt8(255));
    }
    public BigDecimal NextBigDecimal()
    {
        return Sample();
    }
    public byte[] GetNextByteArray(int size)
    {
        var ba = new byte[size];
        _crng.GetBytes(ba);
        return ba;
    }
    public char[] GetNextCharArray(int size)
    {
        var xbc = new byte[1];
        var ca  = new char[size];
        var ptr = 0;
        do
        {
            _crng.GetBytes(xbc);
            var c = xbc[0];
            if (c >= 0x20 && c <= 0x7F)
                ca[ptr++] = (char) c;
        } while (ptr < size);
        return ca;
    }
    public char NextChar()
    {
        var xbc = new byte[1];
        while (true)
        {
            _crng.GetBytes(xbc);
            var c = xbc[0];
            if (c >= 0x20 && c <= 0x7F)
                return (char) c;
        }
    }
    public string GetRandomString(int minLen, int maxLen)
    {
        return minLen == maxLen ? new string(GetNextCharArray(minLen)) : new string(GetNextCharArray((int) NextUInt32((uint) minLen, (uint) maxLen)));
    }
    private BigDecimal Sample()
    {
        var i = Internal();
        var s = i * (BigDecimal.One / MaxValue);
        if (s.Sign == -1)
            s = s * -1;
        if (s.IsZero)
            throw new Exception("Sample is zero.");
        return s;
    }
    public void GetBytes(byte[] data)
    {
        if (data == null)
            throw new ArgumentException("The buffer cannot be null.");
        _crng.GetBytes(data);
    }
    private BigInteger Internal()
    {
        if (Unsigned)
        {
            var buffer = new byte[_maxByteWidth + 1];
            _crng.GetBytes(buffer);
            buffer[_maxByteWidth] = 0;
            var n = new BigInteger(buffer);
            return !OddsOnly ? n : n | 1;
        }
        else
        {
            var buffer = new byte[_maxByteWidth];
            _crng.GetBytes(buffer);
            var n = new BigInteger(buffer);
            return !OddsOnly ? n : n | 1;
        }
    }
}

Leave a Reply

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