Created
February 6, 2010 10:34
-
-
Save usagi/296647 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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