64 Bit Random Number Generator Using RNGCryptoServiceProvider
using System;
using System.Security.Cryptography;
[Serializable]
public class Random64csp : RandomNumberGenerator
{
private byte[] _buffer;
private RNGCryptoServiceProvider _crng;
private double _dBi;
private ulong UpperLimit = ulong.MaxValue;
public Random64csp()
{
SetDataUse = 8;
_crng = new RNGCryptoServiceProvider();
}
public Random64csp(int dataSize)
{
SetDataUse = dataSize;
_crng = new RNGCryptoServiceProvider();
}
public int SetDataUse
{
get => _buffer.Length;
set
{
var v = value;
if (v < 1 || v > 8 || v == 3 || v == 5 || v == 6 || v == 7)
throw new ArgumentException($"Value {v} must be either 1 or 2 or 4 or 8");
switch (v)
{
case 1:
_dBi = 1.0D / byte.MaxValue;
UpperLimit = byte.MaxValue;
_buffer = new byte[1];
break;
case 2:
_dBi = 1.0D / ushort.MaxValue;
UpperLimit = ushort.MaxValue;
_buffer = new byte[2];
break;
case 4:
_dBi = 1.0D / uint.MaxValue;
UpperLimit = uint.MaxValue;
_buffer = new byte[4];
break;
case 8:
_dBi = 1.0D / ulong.MaxValue;
UpperLimit = ulong.MaxValue;
_buffer = new byte[8];
break;
default:
_dBi = 1.0D / ulong.MaxValue;
UpperLimit = ulong.MaxValue;
_buffer = new byte[8];
break;
}
}
}
/// <summary>
/// Will generate only odd values
/// </summary>
public bool OddsOnly
{
get;
set;
}
private double Sample()
{
ulong Internal()
{
_crng.GetBytes(_buffer);
return BufferToLong(_buffer);
}
return Internal() * _dBi;
}
public ulong Next(ulong minValue, ulong maxValue)
{
var sa = Sample();
var fi = (double)(maxValue - minValue + minValue);
var n = (ulong)(sa * fi);
n = !OddsOnly ? n : n | 1;
if (n < minValue)
return Next(minValue, maxValue);
return n;
}
public ulong Next(ulong maxValue)
{
return Next(0, maxValue);
}
public ulong Next()
{
return Next(0, UpperLimit);
}
public unsafe double NextDouble()
{
var buf = new byte[8];
GetBytes(buf);
fixed (byte* ptr = buf)
{
return *(ulong*)ptr * _dBi * ulong.MaxValue;
}
}
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 >= 32 && c <= 127)
ca[ptr++] = (char)c;
} while (ptr < size);
return ca;
}
public char[] GetNextCharArrayX(int size)
{
var xbc = new byte[2];
var ca = new char[size];
var ptr = 0;
do
{
_crng.GetBytes(xbc);
ca[ptr++] = Convert.ToChar(xbc.ToShort());
} while (ptr < size);
return ca;
}
public byte[] GetNextByteArray(int size)
{
var ba = new byte[size];
_crng.GetBytes(ba);
return ba;
}
/// <summary>
/// Next(0,2)==0?false:true; has a distribution error of 1% weighted toward zero.
/// The distribution error here is 0.000000046% which is statistically insignificant in this context.
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public bool[] GetNextBoolArrayLimit(int size)
{
var ba = new bool[size];
const uint ll = uint.MaxValue >> 1;
for (var i = 0; i < size; ++i)
ba[i] = Next(0, uint.MaxValue) > ll;
return ba;
}
public byte[] GetNextByteArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new byte[size];
for (var i = 0; i < size; ++i)
ba[i] = (byte)Next(minValue, maxValue);
return ba;
}
public ushort[] GetNextUShortArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new ushort[size];
for (var i = 0; i < size; ++i)
ba[i] = (ushort)Next(minValue, maxValue);
return ba;
}
public uint[] GetNextUIntArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new uint[size];
for (var i = 0; i < size; ++i)
ba[i] = (uint)Next(minValue, maxValue);
return ba;
}
public ulong[] GetNextULongArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new ulong[size];
for (var i = 0; i < size; ++i)
ba[i] = Next(minValue, maxValue);
return ba;
}
public string GetRandomString(int minLen, int maxLen)
{
if (minLen == maxLen)
return new string(GetNextCharArray(minLen));
return new string(GetNextCharArray((int)Next((ulong)minLen, (ulong)maxLen)));
}
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 + 1);
}
public override void GetNonZeroBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException("The buffer cannot be null.");
var index = 0;
do
{
var v = (byte)(Sample() * byte.MaxValue + 1);
if (v > 0)
{
buffer[index] = v;
index++;
}
} while (index < buffer.Length);
}
private unsafe ulong BufferToLong(byte[] buffer)
{
var len = buffer.Length;
if (len < 1 || len > 8)
throw new ArgumentException($"The array length {len} must be between 1 and 8");
fixed (byte* Ptr = &buffer[0])
{
switch (len)
{
case 1:
return *Ptr;
case 2:
return (uint)(*Ptr | (Ptr[1] << 8));
case 3:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16));
case 4:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24));
case 5:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)Ptr[4] << 32);
case 6:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8)) << 32);
case 7:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16)) << 32);
case 8:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16) | (Ptr[7] << 24)) << 32);
default:
return 0;
}
}
}
}
using System;
using System.Security.Cryptography;
[Serializable]
public class Random64csp : RandomNumberGenerator
{
private byte[] _buffer;
private RNGCryptoServiceProvider _crng;
private double _dBi;
private ulong UpperLimit = ulong.MaxValue;
public Random64csp()
{
SetDataUse = 8;
_crng = new RNGCryptoServiceProvider();
}
public Random64csp(int dataSize)
{
SetDataUse = dataSize;
_crng = new RNGCryptoServiceProvider();
}
public int SetDataUse
{
get => _buffer.Length;
set
{
var v = value;
if (v < 1 || v > 8 || v == 3 || v == 5 || v == 6 || v == 7)
throw new ArgumentException($"Value {v} must be either 1 or 2 or 4 or 8");
switch (v)
{
case 1:
_dBi = 1.0D / byte.MaxValue;
UpperLimit = byte.MaxValue;
_buffer = new byte[1];
break;
case 2:
_dBi = 1.0D / ushort.MaxValue;
UpperLimit = ushort.MaxValue;
_buffer = new byte[2];
break;
case 4:
_dBi = 1.0D / uint.MaxValue;
UpperLimit = uint.MaxValue;
_buffer = new byte[4];
break;
case 8:
_dBi = 1.0D / ulong.MaxValue;
UpperLimit = ulong.MaxValue;
_buffer = new byte[8];
break;
default:
_dBi = 1.0D / ulong.MaxValue;
UpperLimit = ulong.MaxValue;
_buffer = new byte[8];
break;
}
}
}
/// <summary>
/// Will generate only odd values
/// </summary>
public bool OddsOnly
{
get;
set;
}
private double Sample()
{
ulong Internal()
{
_crng.GetBytes(_buffer);
return BufferToLong(_buffer);
}
return Internal() * _dBi;
}
public ulong Next(ulong minValue, ulong maxValue)
{
var sa = Sample();
var fi = (double)(maxValue - minValue + minValue);
var n = (ulong)(sa * fi);
n = !OddsOnly ? n : n | 1;
if (n < minValue)
return Next(minValue, maxValue);
return n;
}
public ulong Next(ulong maxValue)
{
return Next(0, maxValue);
}
public ulong Next()
{
return Next(0, UpperLimit);
}
public unsafe double NextDouble()
{
var buf = new byte[8];
GetBytes(buf);
fixed (byte* ptr = buf)
{
return *(ulong*)ptr * _dBi * ulong.MaxValue;
}
}
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 >= 32 && c <= 127)
ca[ptr++] = (char)c;
} while (ptr < size);
return ca;
}
public char[] GetNextCharArrayX(int size)
{
var xbc = new byte[2];
var ca = new char[size];
var ptr = 0;
do
{
_crng.GetBytes(xbc);
ca[ptr++] = Convert.ToChar(xbc.ToShort());
} while (ptr < size);
return ca;
}
public byte[] GetNextByteArray(int size)
{
var ba = new byte[size];
_crng.GetBytes(ba);
return ba;
}
/// <summary>
/// Next(0,2)==0?false:true; has a distribution error of 1% weighted toward zero.
/// The distribution error here is 0.000000046% which is statistically insignificant in this context.
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public bool[] GetNextBoolArrayLimit(int size)
{
var ba = new bool[size];
const uint ll = uint.MaxValue >> 1;
for (var i = 0; i < size; ++i)
ba[i] = Next(0, uint.MaxValue) > ll;
return ba;
}
public byte[] GetNextByteArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new byte[size];
for (var i = 0; i < size; ++i)
ba[i] = (byte)Next(minValue, maxValue);
return ba;
}
public ushort[] GetNextUShortArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new ushort[size];
for (var i = 0; i < size; ++i)
ba[i] = (ushort)Next(minValue, maxValue);
return ba;
}
public uint[] GetNextUIntArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new uint[size];
for (var i = 0; i < size; ++i)
ba[i] = (uint)Next(minValue, maxValue);
return ba;
}
public ulong[] GetNextULongArrayLimit(int size, ulong minValue, ulong maxValue)
{
var ba = new ulong[size];
for (var i = 0; i < size; ++i)
ba[i] = Next(minValue, maxValue);
return ba;
}
public string GetRandomString(int minLen, int maxLen)
{
if (minLen == maxLen)
return new string(GetNextCharArray(minLen));
return new string(GetNextCharArray((int)Next((ulong)minLen, (ulong)maxLen)));
}
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 + 1);
}
public override void GetNonZeroBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException("The buffer cannot be null.");
var index = 0;
do
{
var v = (byte)(Sample() * byte.MaxValue + 1);
if (v > 0)
{
buffer[index] = v;
index++;
}
} while (index < buffer.Length);
}
private unsafe ulong BufferToLong(byte[] buffer)
{
var len = buffer.Length;
if (len < 1 || len > 8)
throw new ArgumentException($"The array length {len} must be between 1 and 8");
fixed (byte* Ptr = &buffer[0])
{
switch (len)
{
case 1:
return *Ptr;
case 2:
return (uint)(*Ptr | (Ptr[1] << 8));
case 3:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16));
case 4:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24));
case 5:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)Ptr[4] << 32);
case 6:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8)) << 32);
case 7:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16)) << 32);
case 8:
return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16) | (Ptr[7] << 24)) << 32);
default:
return 0;
}
}
}
}
using System; using System.Security.Cryptography; [Serializable] public class Random64csp : RandomNumberGenerator { private byte[] _buffer; private RNGCryptoServiceProvider _crng; private double _dBi; private ulong UpperLimit = ulong.MaxValue; public Random64csp() { SetDataUse = 8; _crng = new RNGCryptoServiceProvider(); } public Random64csp(int dataSize) { SetDataUse = dataSize; _crng = new RNGCryptoServiceProvider(); } public int SetDataUse { get => _buffer.Length; set { var v = value; if (v < 1 || v > 8 || v == 3 || v == 5 || v == 6 || v == 7) throw new ArgumentException($"Value {v} must be either 1 or 2 or 4 or 8"); switch (v) { case 1: _dBi = 1.0D / byte.MaxValue; UpperLimit = byte.MaxValue; _buffer = new byte[1]; break; case 2: _dBi = 1.0D / ushort.MaxValue; UpperLimit = ushort.MaxValue; _buffer = new byte[2]; break; case 4: _dBi = 1.0D / uint.MaxValue; UpperLimit = uint.MaxValue; _buffer = new byte[4]; break; case 8: _dBi = 1.0D / ulong.MaxValue; UpperLimit = ulong.MaxValue; _buffer = new byte[8]; break; default: _dBi = 1.0D / ulong.MaxValue; UpperLimit = ulong.MaxValue; _buffer = new byte[8]; break; } } } /// <summary> /// Will generate only odd values /// </summary> public bool OddsOnly { get; set; } private double Sample() { ulong Internal() { _crng.GetBytes(_buffer); return BufferToLong(_buffer); } return Internal() * _dBi; } public ulong Next(ulong minValue, ulong maxValue) { var sa = Sample(); var fi = (double)(maxValue - minValue + minValue); var n = (ulong)(sa * fi); n = !OddsOnly ? n : n | 1; if (n < minValue) return Next(minValue, maxValue); return n; } public ulong Next(ulong maxValue) { return Next(0, maxValue); } public ulong Next() { return Next(0, UpperLimit); } public unsafe double NextDouble() { var buf = new byte[8]; GetBytes(buf); fixed (byte* ptr = buf) { return *(ulong*)ptr * _dBi * ulong.MaxValue; } } 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 >= 32 && c <= 127) ca[ptr++] = (char)c; } while (ptr < size); return ca; } public char[] GetNextCharArrayX(int size) { var xbc = new byte[2]; var ca = new char[size]; var ptr = 0; do { _crng.GetBytes(xbc); ca[ptr++] = Convert.ToChar(xbc.ToShort()); } while (ptr < size); return ca; } public byte[] GetNextByteArray(int size) { var ba = new byte[size]; _crng.GetBytes(ba); return ba; } /// <summary> /// Next(0,2)==0?false:true; has a distribution error of 1% weighted toward zero. /// The distribution error here is 0.000000046% which is statistically insignificant in this context. /// </summary> /// <param name="size"></param> /// <returns></returns> public bool[] GetNextBoolArrayLimit(int size) { var ba = new bool[size]; const uint ll = uint.MaxValue >> 1; for (var i = 0; i < size; ++i) ba[i] = Next(0, uint.MaxValue) > ll; return ba; } public byte[] GetNextByteArrayLimit(int size, ulong minValue, ulong maxValue) { var ba = new byte[size]; for (var i = 0; i < size; ++i) ba[i] = (byte)Next(minValue, maxValue); return ba; } public ushort[] GetNextUShortArrayLimit(int size, ulong minValue, ulong maxValue) { var ba = new ushort[size]; for (var i = 0; i < size; ++i) ba[i] = (ushort)Next(minValue, maxValue); return ba; } public uint[] GetNextUIntArrayLimit(int size, ulong minValue, ulong maxValue) { var ba = new uint[size]; for (var i = 0; i < size; ++i) ba[i] = (uint)Next(minValue, maxValue); return ba; } public ulong[] GetNextULongArrayLimit(int size, ulong minValue, ulong maxValue) { var ba = new ulong[size]; for (var i = 0; i < size; ++i) ba[i] = Next(minValue, maxValue); return ba; } public string GetRandomString(int minLen, int maxLen) { if (minLen == maxLen) return new string(GetNextCharArray(minLen)); return new string(GetNextCharArray((int)Next((ulong)minLen, (ulong)maxLen))); } 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 + 1); } public override void GetNonZeroBytes(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("The buffer cannot be null."); var index = 0; do { var v = (byte)(Sample() * byte.MaxValue + 1); if (v > 0) { buffer[index] = v; index++; } } while (index < buffer.Length); } private unsafe ulong BufferToLong(byte[] buffer) { var len = buffer.Length; if (len < 1 || len > 8) throw new ArgumentException($"The array length {len} must be between 1 and 8"); fixed (byte* Ptr = &buffer[0]) { switch (len) { case 1: return *Ptr; case 2: return (uint)(*Ptr | (Ptr[1] << 8)); case 3: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16)); case 4: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)); case 5: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)Ptr[4] << 32); case 6: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8)) << 32); case 7: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16)) << 32); case 8: return (uint)(*Ptr | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24)) | ((ulong)(Ptr[4] | (Ptr[5] << 8) | (Ptr[6] << 16) | (Ptr[7] << 24)) << 32); default: return 0; } } } }