//----------------------------------------------------------------------- // ----------------------------------------------------------------------- // file="RandomGenerator" // Project: StgSharp // AuthorGroup: Nitload // Copyright (c) Nitload. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- using StgSharp.HighPerformance; using System; using System.IO; using System.Runtime.CompilerServices; using System.Text; using System.Xml.Serialization; namespace StgSharp.Data { public unsafe class RandomGenerator { private byte[] currentKey; private readonly byte[] originKey; public RandomGenerator() : this(DateTime.UtcNow.ToBinary()) { } public RandomGenerator(object source) { ArgumentNullException.ThrowIfNull(source); XmlSerializer s = new(source.GetType()); using (StringWriter sw = new()) { s.Serialize(sw, source); string data = sw.ToString(); originKey = Encoding.Unicode.GetBytes(data); } currentKey = [ 0, 0, 0, 0 ]; fixed (byte* o = originKey, c = currentKey) { *(int*)c = UnsafeCompute.CityHashSimplify((char*)o, 0, originKey.Length / 2); } TotalGeneratedRandom = 0; } public int TotalGeneratedRandom { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] private set; } public unsafe int GenRandomInt() { uint source = PrivateRand(); TotalGeneratedRandom++; M64 m = new M64(); m.Member(0) = source; m.Member(1) = source; return (m << (TotalGeneratedRandom % 32)).Member(1); } public byte GenRandomInt8() { TotalGeneratedRandom++; if (TotalGeneratedRandom % 4 == 0) { PrivateRand(); } return currentKey[TotalGeneratedRandom % 4]; } public float GenRandomSingle() { TotalGeneratedRandom++; while (true) { uint temp0 = PrivateRand(), temp1 = PrivateRand(); if (temp0 * temp1 != 0) { float ret = temp0 % temp1 * 1.0f / temp1; if (ret < 0.335f) { ret = ret * ((ret * (-0.7811934f)) + 1.4489113f); } else { ret = (ret * ((ret * (-0.1158368f)) + 1.0580600f)) + 0.0590584f; } if (ret > 1) { continue; } return ret; } } } public void Reset() { currentKey = originKey; TotalGeneratedRandom = 0; } private unsafe uint PrivateRand() { uint ret; fixed (byte* bptr = currentKey) { *(int*)bptr = UnsafeCompute.CityHashSimplify((char*)bptr, currentKey.Length / 2); ret = *(uint*)bptr; } // Console.WriteLine(ret.ToString(16)); return ret; } } }