432 lines
10 KiB
C#
432 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.Windows;
|
|
|
|
namespace XericLibrary.Runtime.MacroLibrary
|
|
{
|
|
/// <summary>
|
|
/// 数学库
|
|
/// </summary>
|
|
public static partial class MacroMath
|
|
{
|
|
#region 随机
|
|
|
|
/// <summary>
|
|
/// 获取一个被特定随机数填充的矩阵,这通常是无意义的
|
|
/// </summary>
|
|
/// <param name="vec"></param>
|
|
/// <returns></returns>
|
|
public static Matrix4x4 RandomMatrix4(float range)
|
|
{
|
|
return new Matrix4x4(
|
|
RandomVector4(range),
|
|
RandomVector4(range),
|
|
RandomVector4(range),
|
|
RandomVector4(range));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取一个在指定坐标范围内的随机矢量(矩形范围)
|
|
/// </summary>
|
|
/// <param name="vec"></param>
|
|
/// <returns></returns>
|
|
public static Vector4 RandomVector4(float range)
|
|
{
|
|
var rand = new System.Random();
|
|
range *= 100;
|
|
Func<float> GetNextRand = () =>
|
|
{
|
|
return rand.Next((int)-range, (int)range) * 0.01f;
|
|
};
|
|
|
|
return new Vector4(GetNextRand(), GetNextRand(), GetNextRand(), GetNextRand());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取一个在指定坐标范围内的随机矢量(矩形范围)
|
|
/// </summary>
|
|
/// <param name="vec"></param>
|
|
/// <returns></returns>
|
|
public static Vector3 RandomVector3(float range)
|
|
{
|
|
var rand = new System.Random();
|
|
range *= 100;
|
|
Func<float> GetNextRand = () =>
|
|
{
|
|
return rand.Next((int)-range, (int)range) * 0.01f;
|
|
};
|
|
|
|
return new Vector3(GetNextRand(), GetNextRand(), GetNextRand());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取一个在指定坐标范围内的随机矢量(矩形范围)
|
|
/// </summary>
|
|
/// <param name="vec"></param>
|
|
/// <returns></returns>
|
|
public static Vector2 RandomVector2(float range)
|
|
{
|
|
var rand = new System.Random();
|
|
range *= 100;
|
|
Func<float> GetNextRand = () =>
|
|
{
|
|
return rand.Next((int)-range, (int)range) * 0.01f;
|
|
};
|
|
|
|
return new Vector2(GetNextRand(), GetNextRand());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 哈希后处理
|
|
/// </summary>
|
|
/// <param name="index"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static ulong MurmurFinalize(ulong index)
|
|
{
|
|
index ^= index >> 33;
|
|
index *= 0xff51afd7ed558ccd;
|
|
index ^= index >> 33;
|
|
index *= 0xc4ceb9fe1a85ec53;
|
|
index ^= index >> 33;
|
|
return index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 大范围随机
|
|
/// </summary>
|
|
/// <param name="index"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static ulong RandomNumber(ulong index)
|
|
{
|
|
index *= 1103515245;
|
|
index += 12345;
|
|
index *= 6364136223846793005UL;
|
|
index += 1442695040888963407UL;
|
|
index %= 18446744073709551615UL;
|
|
return index;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region 数学
|
|
|
|
/// <summary>
|
|
/// pmod
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int PMod(int a, int b)
|
|
{
|
|
if(b <= 0)
|
|
return 0;
|
|
var mod = a % b;
|
|
return a < 0 ? (b + mod) % b : mod;
|
|
}
|
|
|
|
/// <summary>
|
|
/// pmod
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static double PMod(double a, double b)
|
|
{
|
|
double z = a % b;
|
|
double w = (z < 0) ? -1 : 1;
|
|
z = (z < 0) ? -z : z;
|
|
if(w < 0)
|
|
return b - z;
|
|
else
|
|
return z;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取两者的最小值,但不包括负数;
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static float MinPositive(float a, float b)
|
|
=> Math.Min(Math.Max(0, a), Math.Max(0, b));
|
|
|
|
/// <summary>
|
|
/// 获取两者的最小值,但不包括负数;
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int MinPositive(int a, int b)
|
|
=> Math.Min(Math.Max(0, a), Math.Max(0, b));
|
|
|
|
/// <summary>
|
|
/// Interpolates t between a and b to a value between 0 and 1 using a Hermite polynomial.
|
|
/// </summary>
|
|
/// <param name="a">The first value</param>
|
|
/// <param name="b">The second value</param>
|
|
/// <param name="t">The position value</param>
|
|
/// <returns>A smoothed value between 0 and 1</returns>
|
|
public static float SmoothStep(float a, float b, float t)
|
|
{
|
|
t = Mathf.Clamp01((t - a) / (b - a));
|
|
return t * t * (3f - 2f * t);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Interpolates t between a and b to a value between 0 and 1.
|
|
/// </summary>
|
|
/// <param name="a">The first value</param>
|
|
/// <param name="b">The second value</param>
|
|
/// <param name="t">The position value</param>
|
|
/// <returns>Linear value between 0 and 1</returns>
|
|
public static float LinearStep(float a, float b, float t)
|
|
{
|
|
return Mathf.Clamp01((t - a) / (b - a));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wraps a value between min and max.
|
|
/// </summary>
|
|
/// <param name="value">The value to wrap</param>
|
|
/// <param name="min">The minimum value</param>
|
|
/// <param name="max">The maximum value</param>
|
|
/// <returns></returns>
|
|
public static double Wrap(double value, double min, double max)
|
|
{
|
|
double num = max - min;
|
|
num = ((num < 0.0) ? (0.0 - num) : num);
|
|
if(value < min)
|
|
{
|
|
return value + num * Math.Ceiling(Math.Abs(value / num));
|
|
}
|
|
|
|
if(value >= max)
|
|
{
|
|
return value - num * Math.Floor(Math.Abs(value / num));
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wraps a value between min and max.
|
|
/// </summary>
|
|
/// <param name="value">The value to wrap</param>
|
|
/// <param name="min">The minimum value</param>
|
|
/// <param name="max">The maximum value</param>
|
|
/// <returns></returns>
|
|
public static float Wrap(float value, float min, float max)
|
|
{
|
|
float num = max - min;
|
|
num = (((double)num < 0.0) ? (0f - num) : num);
|
|
if(value < min)
|
|
{
|
|
return value + num * (float)Math.Ceiling(Math.Abs(value / num));
|
|
}
|
|
|
|
if(value >= max)
|
|
{
|
|
return value - num * (float)Math.Floor(Math.Abs(value / num));
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wraps a value between min and max.
|
|
/// </summary>
|
|
/// <param name="value">The value to wrap</param>
|
|
/// <param name="min">The minimum value</param>
|
|
/// <param name="max">The maximum value</param>
|
|
/// <returns></returns>
|
|
public static int Wrap(int value, int min, int max)
|
|
{
|
|
int num = max - min;
|
|
num = ((num < 0) ? (-num) : num);
|
|
if(value < min)
|
|
{
|
|
return value + num * (Math.Abs(value / num) + 1);
|
|
}
|
|
|
|
if(value >= max)
|
|
{
|
|
return value - num * Math.Abs(value / num);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds a number based on a mininum difference.
|
|
/// </summary>
|
|
/// <param name="valueToRound">The value to round</param>
|
|
/// <param name="minDifference">The min difference</param>
|
|
/// <returns>The rounded value.</returns>
|
|
public static double RoundBasedOnMinimumDifference(double valueToRound, double minDifference)
|
|
{
|
|
if(minDifference == 0.0)
|
|
{
|
|
return DiscardLeastSignificantDecimal(valueToRound);
|
|
}
|
|
|
|
return (float)Math.Round(valueToRound, MacroMath.GetNumberOfDecimalsForMinimumDifference(minDifference), MidpointRounding.AwayFromZero);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Discards the least significant demicals.
|
|
/// </summary>
|
|
/// <param name="v">The value of insignificant decimals</param>
|
|
/// <returns>Value with significant decimals</returns>
|
|
public static double DiscardLeastSignificantDecimal(double v)
|
|
{
|
|
int digits = Math.Max(0, (int)(5.0 - Math.Log10(Math.Abs(v))));
|
|
try
|
|
{
|
|
return Math.Round(v, digits);
|
|
}
|
|
catch(ArgumentOutOfRangeException)
|
|
{
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clamps and wraps an angle between two values.
|
|
/// </summary>
|
|
/// <param name="angle"></param>
|
|
/// <param name="min"></param>
|
|
/// <param name="max"></param>
|
|
/// <returns></returns>
|
|
public static float ClampWrapAngle(float angle, float min, float max)
|
|
{
|
|
float num = 360f;
|
|
float num2 = min;
|
|
float num3 = max;
|
|
float num4 = angle;
|
|
if(num2 < 0f)
|
|
{
|
|
num2 = num2 % num + num;
|
|
}
|
|
|
|
if(num3 < 0f)
|
|
{
|
|
num3 = num3 % num + num;
|
|
}
|
|
|
|
if(num4 < 0f)
|
|
{
|
|
num4 = num4 % num + num;
|
|
}
|
|
|
|
float num5 = (float)(int)(Math.Abs(min - max) / num) * num;
|
|
num3 += num5;
|
|
num4 += num5;
|
|
if(min > max)
|
|
{
|
|
num3 += num;
|
|
}
|
|
|
|
if(num4 < num2)
|
|
{
|
|
num4 = num2;
|
|
}
|
|
|
|
if(num4 > num3)
|
|
{
|
|
num4 = num3;
|
|
}
|
|
|
|
return num4;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取最小差值的小数个数
|
|
/// </summary>
|
|
/// <param name="minDifference"></param>
|
|
/// <returns></returns>
|
|
public static int GetNumberOfDecimalsForMinimumDifference(double minDifference)
|
|
{
|
|
return Mathf.Clamp(-Mathf.FloorToInt(Mathf.Log10(Mathf.Abs((float)minDifference))), 0, 15);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 字节控制
|
|
|
|
/// <summary>
|
|
/// 设置字
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static void SetByteState(ref int target, int site, bool state)
|
|
{
|
|
if(state)
|
|
target |= 1 << site;
|
|
|
|
else
|
|
target &= 0xff - (1 << site);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置字
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static void SetByteState(ref int target, Enum site, bool state)
|
|
{
|
|
SetByteState(ref target, Convert.ToInt32(site), state);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查字
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static bool GetByteState(int target, int site)
|
|
{
|
|
return (target >> site & 0x01) > 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查字
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static bool GetByteState(int target, Enum site)
|
|
{
|
|
return GetByteState(target, Convert.ToInt32(site));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 填充
|
|
|
|
/// <summary>
|
|
/// 获取被从A到B的值填充的列表
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
public static List<int> GetListFormAToB(int a, int b)
|
|
{
|
|
var list = new List<int>();
|
|
bool way = a > b;
|
|
var step = way ? -1 : 1;
|
|
|
|
for(int i = a; (!way && i <= b) || (way && i >= b); i += step)
|
|
list.Add(i);
|
|
|
|
return list;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |