Files
stgsharp/StgSharp.Common/Mathematics/Scalar/Random.cs
T
2026-01-07 18:06:36 +08:00

127 lines
4.1 KiB
C#

//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="Random"
// 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.Mathematics;
using System;
using System.Collections.Generic;
using System.Data;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
namespace StgSharp.Mathematics
{
public static unsafe partial class Scalar
{
private static byte[] randomSeed;
internal static float currentSeed
#if DEBUG
= 0.5f;
#else
= Abs(System.DateTime.UtcNow.GetHashCode());
#endif
/// <summary>
/// returns a random float number between 0 and 1.
/// </summary>
/// <returns>
///
/// </returns>
public static unsafe float LowProceisionRandom()
{
float seed = currentSeed;
float sample = Scalar.Pow(Scalar.SeedSqrt(seed), 2);
float sample2 = (sample - seed) / seed;
sample2 = Scalar.Abs(sample2);
if (sample == 1) {
sample = sample2;
}
currentSeed = sample;
sample2 *= 1000000;
float result = sample2 - ((int)sample2);
if (result == 0)
{
currentSeed = sample2 + 0.1f;
result = Scalar.LowProceisionRandom();
}
return result;
}
/// <summary>
///
/// </summary>
/// <returns>
///
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Random<T>() where T : unmanaged, IConvertible, INumber<T>
{
if (randomSeed == null)
{
randomSeed = new byte[64];
string originSeed =
($"{((Assembly.GetEntryAssembly() == null) ? (Assembly.GetAssembly(typeof(World))!) :
Assembly.GetEntryAssembly())}") + ($"{DateTime.UtcNow.ToString("o")}");
randomSeed = SHA256.HashData(Encoding.UTF8.GetBytes(originSeed));
}
randomSeed = SHA256.HashData(randomSeed);
fixed (byte* bptr = randomSeed) {
return *(T*)bptr;
}
}
/// <summary>
/// Generates a random seed in int value.
/// </summary>
/// <returns>
///
/// </returns>
public static unsafe int RandomSeed()
{
float seedValue1 = LowProceisionRandom();
float seedValue2 = LowProceisionRandom();
uint seedValueBits = *(uint*)&seedValue1;
float seedValue = seedValueBits * seedValue2;
return *(int*)&seedValue;
}
}
}