Skip to content

Instantly share code, notes, and snippets.

@usagi
Created February 6, 2010 10:34
Show Gist options
  • Save usagi/296647 to your computer and use it in GitHub Desktop.
Save usagi/296647 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.IO;
namespace wrp
{
namespace random_number_generator
{
public class XorShift
{
[StructLayout(LayoutKind.Explicit)]
public struct RANDOMBITFIELD32
{
[FieldOffset(0)]
public Char SignedInt8_0;
[FieldOffset(1)]
public Char SignedInt8_1;
[FieldOffset(2)]
public Char SignedInt8_2;
[FieldOffset(3)]
public Char SignedInt8_3;
[FieldOffset(0)]
public Byte UnsignedInt8_0;
[FieldOffset(1)]
public Byte UnsignedInt8_1;
[FieldOffset(2)]
public Byte UnsignedInt8_2;
[FieldOffset(3)]
public Byte UnsignedInt8_3;
[FieldOffset(0)]
public Int16 SignedInt16_0;
[FieldOffset(2)]
public Int16 SignedInt16_1;
[FieldOffset(0)]
public UInt16 UnsignedInt16_0;
[FieldOffset(2)]
public UInt16 UnsignedInt16_1;
[FieldOffset(0)]
public UInt32 UnsignedInt32;
[FieldOffset(0)]
public Int32 SignedInt32;
[FieldOffset(0)]
public float FloatIEEE754;
static public implicit operator UInt32(RANDOMBITFIELD32 v) { return v.UnsignedInt32; }
static public implicit operator Int32(RANDOMBITFIELD32 v) { return v.SignedInt32; }
static public implicit operator float(RANDOMBITFIELD32 v) { return v.FloatIEEE754; }
}
[StructLayout(LayoutKind.Explicit)]
public struct RANDOMBITFIELD64
{
[FieldOffset(0)]
public UInt64 UnsignedInt64;
[FieldOffset(0)]
public Int64 SignedInt64;
[FieldOffset(0)]
public Double DoubleIEEE754;
[FieldOffset(0)]
public RANDOMBITFIELD32 RBF32_0;
[FieldOffset(4)]
public RANDOMBITFIELD32 RBF32_1;
static public implicit operator UInt64(RANDOMBITFIELD64 v) { return v.UnsignedInt64; }
static public implicit operator Int64(RANDOMBITFIELD64 v) { return v.SignedInt64; }
static public implicit operator Double(RANDOMBITFIELD64 v) { return v.DoubleIEEE754; }
}
[StructLayout(LayoutKind.Explicit)]
public struct RANDOMBITFIELD128
{
[FieldOffset(0)]
public RANDOMBITFIELD32 RBF32_0;
[FieldOffset(4)]
public RANDOMBITFIELD32 RBF32_1;
[FieldOffset(8)]
public RANDOMBITFIELD32 RBF32_2;
[FieldOffset(12)]
public RANDOMBITFIELD32 RBF32_3;
[FieldOffset(0)]
public RANDOMBITFIELD64 RBF64_0;
[FieldOffset(4)]
public RANDOMBITFIELD64 RBF64_h;
[FieldOffset(8)]
public RANDOMBITFIELD64 RBF64_1;
}
static public XorShift FromDateTimeNowSHA1
{ get { return FromDateTimeSHA1(DateTime.Now); } }
static public XorShift FromDateTimeSHA1(DateTime datetime)
{ return FromHash(BitConverter.GetBytes((datetime - new DateTime(0)).TotalSeconds), new SHA1Managed()); }
static public XorShift FromHash(byte[] bin, HashAlgorithm hash_algorithm)
{ return FromHash(new MemoryStream(bin, false), hash_algorithm); }
// its need ({computed hash binary size} >= 64 [bytes]) to HashAlgorithm.
// but its trivial now, therefore its implement HashAlgorithm class directly without explicit limitations.
static public XorShift FromHash(System.IO.Stream ios, HashAlgorithm hash_algorithm)
{
var ret = new XorShift();
var hash = hash_algorithm.ComputeHash(ios);
ret._data.RBF64_0.UnsignedInt64 = BitConverter.ToUInt64(hash, 0);
ret._data.RBF64_1.UnsignedInt64 = BitConverter.ToUInt64(hash, 8);
return ret;
}
protected RANDOMBITFIELD128 _data;
//public UInt32 x, y, z, w;
protected XorShift() { }
public XorShift(UInt32 s) : this(s, 362436069, 521288629, 88675123) { }
public XorShift(UInt32 _x, UInt32 _y, UInt32 _z, UInt32 _w)
{
_data.RBF32_0.UnsignedInt32 = _x;
_data.RBF32_1.UnsignedInt32 = _y;
_data.RBF32_2.UnsignedInt32 = _z;
_data.RBF32_3.UnsignedInt32 = _w;
}
protected void _Next()
{
var t = (_data.RBF32_0.UnsignedInt32 ^ (_data.RBF32_0.UnsignedInt32 << 11));
_data.RBF32_0.UnsignedInt32 = _data.RBF32_1.UnsignedInt32; // x = y
_data.RBF64_h.UnsignedInt64 = _data.RBF64_1.UnsignedInt64; // y = z, z = w
_data.RBF32_3.UnsignedInt32 = (_data.RBF32_0.UnsignedInt32 ^ (_data.RBF32_0.UnsignedInt32 >> 19)) ^ (t ^ (t >> 8));
}
public UInt32 Next()
{
_Next();
return _data.RBF32_3.UnsignedInt32;
}
public RANDOMBITFIELD32 NextRANDOMBITFIELD32()
{
_Next();
_Next();
return _data.RBF32_3;
}
public RANDOMBITFIELD64 NextRANDOMBITFIELD64()
{
_Next(); _Next();
return _data.RBF64_1;
}
public RANDOMBITFIELD128 NextRANDOMBITFIELD128()
{
_Next(); _Next(); _Next(); _Next();
return _data;
}
public float NextFloatUNorm()
{
const UInt16 moldOR = 0x3F80;
_Next();
var ret = _data.RBF32_3;
ret.UnsignedInt8_3 = 0;
ret.UnsignedInt16_1 |= moldOR;
return ret.FloatIEEE754 - 1.0f;
}
public double NextDoubleUNorm()
{
const UInt16 moldOR = 0x3FF0;
_Next();
_Next();
var ret = _data.RBF64_1;
ret.RBF32_1.UnsignedInt8_3 = 0;
ret.RBF32_1.UnsignedInt16_1 |= moldOR;
return ret.DoubleIEEE754 - 1.0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment