Files
caliverse_server/ServerCore/Math/MathHelper.cs
2025-11-28 16:54:56 +09:00

750 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
using Google.Protobuf.WellKnownTypes;
using Newtonsoft.Json.Linq;
using Amazon.DynamoDBv2.Model;
namespace ServerCore;
// HANDOVER: 수학적 처리 함수를 제공 한다. (float, double, decimal 자료형 제공)
public static class MathHelper
{
// The infamous ''3.14159265358979...'' value (RO).
public const float PI = (float)Math.PI;
// A representation of positive infinity (RO).
public const float Infinity = Single.PositiveInfinity;
// A representation of negative infinity (RO).
public const float NegativeInfinity = Single.NegativeInfinity;
// Degrees-to-radians conversion constant (RO).
public const float Deg2Rad = PI * 2F / 360F;
// Radians-to-degrees conversion constant (RO).
public const float Rad2Deg = 1F / Deg2Rad;
// Returns the sine of angle /value/ in radians.
public static T sin<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Sin(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Sin(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Sin(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the cosine of angle /value/ in radians.
public static T cos<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Cos(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Cos(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Sin(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the tangent of angle /value/ in radians.
public static T tan<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Tan(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Tan(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Tan(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the arc-sine of /value/ - the angle in radians whose sine is /f/.
public static T asin<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Asin(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Asin(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Asin(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the arc-cosine of /value/ - the angle in radians whose cosine is /f/.
public static T acos<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Acos(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Acos(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Acos(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the arc-tangent of /value/ - the angle in radians whose tangent is /f/.
public static T atan<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)MathF.Atan(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)Math.Atan(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)Math.Atan(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the angle in radians whose ::ref::Tan is @@y/x@@.
public static T atan2<T>(T y, T x)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result_y = Convert.ToSingle(y);
var result_x = Convert.ToSingle(x);
return (T)(object)MathF.Atan2(result_y, result_x);
}
else if (typeof(T) == typeof(double))
{
var result_y = Convert.ToDouble(y);
var result_x = Convert.ToDouble(x);
return (T)(object)Math.Atan2(result_y, result_x);
}
else if (typeof(T) == typeof(decimal))
{
var result_y = Convert.ToDecimal(y);
var round_result_y = Math.Round((double)result_y, 28);
var result_x = Convert.ToDecimal(x);
var round_result_x = Math.Round((double)result_x, 28);
return (T)(object)(decimal)Math.Atan2(round_result_y, round_result_x);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : y:{y}, x:{x}");
}
}
// Returns square root of /value/.
public static T sqrt<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = MathF.Sqrt(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Sqrt(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
var round_result = Math.Round((double)result, 28);
return (T)(object)(decimal)Math.Sqrt(round_result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the absolute value of /value/.
public static T abs<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(Int16))
{
var result = (Int16)Math.Abs(Convert.ToInt16(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(Int32))
{
var result = (Int32)Math.Abs(Convert.ToInt32(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(float))
{
var result = MathF.Abs(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Abs(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Abs(Convert.ToDecimal(value));
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// *listonly*
public static T min<T>(T a, T b)
where T : struct, IComparable<T>
{
return a.CompareTo(b) < 0 ? a : b;
}
// Returns the smallest of two or more values.
public static T min<T>(params T[] values)
where T : struct, IComparable<T>
{
int len = values.Length;
if (len == 0)
{
return default(T);
}
T min_value = values[0];
for (int i = 1; i < len; i++)
{
if (values[i].CompareTo(min_value) < 0)
min_value = values[i];
}
return min_value;
}
public static T max<T>(T a, T b)
where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
public static T max<T>(params T[] values)
where T : IComparable<T>
{
if (values.Length == 0)
{
throw new ArgumentException("At least one value must be provided.", nameof(values));
}
T max_value = values[0];
for (int i = 1; i < values.Length; i++)
{
if (values[i].CompareTo(max_value) > 0)
{
max_value = values[i];
}
}
return max_value;
}
// Returns /f/ raised to power /p/.
public static T pow<T>(T baseValue, T exponent)
where T : struct, IConvertible
{
// 타입에 따라 적절한 연산을 수행
if (typeof(T) == typeof(float))
{
var base_v = Convert.ToSingle(baseValue);
var exponent_v = Convert.ToSingle(exponent);
return (T)(object)MathF.Pow(base_v, exponent_v);
}
else if (typeof(T) == typeof(double))
{
var base_v = Convert.ToDouble(baseValue);
var exponent_v = Convert.ToDouble(exponent);
return (T)(object)(double)Math.Pow(base_v, exponent_v);
}
else if (typeof(T) == typeof(decimal))
{
var base_v = Convert.ToDecimal(baseValue);
var exponent_v = Convert.ToDecimal(exponent);
var round_result_base_v = Math.Round((double)base_v, 28);
var round_result_exponent_v = Math.Round((double)exponent_v, 28);
return (T)(object)(decimal)Math.Pow(round_result_base_v, round_result_exponent_v);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {baseValue}, {exponent}");
}
}
// Returns e raised to the specified power.
public static T exp<T>(T power)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var power_v = Convert.ToSingle(power);
return (T)(object)MathF.Exp(power_v);
}
else if (typeof(T) == typeof(double))
{
var power_v = Convert.ToDouble(power);
return (T)(object)(double)Math.Exp(power_v);
}
else if (typeof(T) == typeof(decimal))
{
var power_v = Convert.ToDecimal(power);
var round_result_power_v = Math.Round((double)power_v, 28);
return (T)(object)(decimal)Math.Exp(round_result_power_v);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {power}");
}
}
// Returns the logarithm of a specified number in a specified base.
public static T log<T>(T f, T p)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var base_v = Convert.ToSingle(f);
var power_v = Convert.ToSingle(p);
return (T)(object)MathF.Log(base_v, power_v);
}
else if (typeof(T) == typeof(double))
{
var base_v = Convert.ToDouble(f);
var power_v = Convert.ToDouble(p);
return (T)(object)(double)Math.Log(base_v, power_v);
}
else if (typeof(T) == typeof(decimal))
{
var base_v = Convert.ToDecimal(f);
var power_v = Convert.ToDecimal(p);
var round_result_base_v = Math.Round((double)base_v, 28);
var round_result_power_v = Math.Round((double)power_v, 28);
return (T)(object)(decimal)Math.Log(round_result_base_v, round_result_power_v);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {f}, {p}");
}
}
// Returns the natural (base e) logarithm of a specified number.
public static T log<T>(T f)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var base_v = Convert.ToSingle(f);
return (T)(object)MathF.Log(base_v);
}
else if (typeof(T) == typeof(double))
{
var base_v = Convert.ToDouble(f);
return (T)(object)(double)Math.Log(base_v);
}
else if (typeof(T) == typeof(decimal))
{
var base_v = Convert.ToDecimal(f);
var round_result_base_v = Math.Round((double)base_v, 28);
return (T)(object)(decimal)Math.Log(round_result_base_v);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {f}");
}
}
// Returns the base 10 logarithm of a specified number.
public static T log10<T>(T f)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var base_v = Convert.ToSingle(f);
return (T)(object)MathF.Log10(base_v);
}
else if (typeof(T) == typeof(double))
{
var base_v = Convert.ToDouble(f);
return (T)(object)(double)Math.Log10(base_v);
}
else if (typeof(T) == typeof(decimal))
{
var base_v = Convert.ToDecimal(f);
var round_result_base_v = Math.Round((double)base_v, 28);
return (T)(object)(decimal)Math.Log10(round_result_base_v);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {f}");
}
}
// Returns the smallest integer greater to or equal to /value/.
public static T ceil<T>(T value)
where T : struct
{
if (typeof(T) == typeof(float))
{
var result = MathF.Ceiling(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Ceiling(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Ceiling(Convert.ToDecimal(value));
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the largest integer smaller to or equal to /value/.
public static T floor<T>(T value)
where T : struct
{
if (typeof(T) == typeof(float))
{
var result = MathF.Floor(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Floor(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Floor(Convert.ToDecimal(value));
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns /value/ rounded to T float, double, decimal
public static T round<T>(T value)
where T : struct
{
if (typeof(T) == typeof(float))
{
var result = MathF.Round(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Round(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Round(Convert.ToDecimal(value));
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns /value/ rounded to T float, double, decimal
public static T round<T>(T value, int decimalPlaces)
where T : struct
{
if (typeof(T) == typeof(float))
{
var result = MathF.Round(Convert.ToSingle(value), decimalPlaces);
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Round(Convert.ToDouble(value), decimalPlaces);
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Round(Convert.ToDecimal(value), decimalPlaces);
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the smallest integer greater to or equal to /value/.
public static T truncate<T>(T value)
where T : struct, IComparable<T>
{
if (typeof(T) == typeof(float))
{
var result = MathF.Truncate(Convert.ToSingle(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(double))
{
var result = Math.Truncate(Convert.ToDouble(value));
return (T)(object)result;
}
else if (typeof(T) == typeof(decimal))
{
var result = Math.Truncate(Convert.ToDecimal(value));
return (T)(object)result;
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
public static T roundUpOrDown<T>(T value, int decimalPlaces = 0)
where T : struct, IComparable<T>
{
dynamic dynamic_value = value;
double factor = Math.Pow(10, decimalPlaces); // 소숫점 자리수에 따라 곱할 값 설정, 0일 경우 소수점없이 올림 처리 한다 !!!
if (TypeHelper.NumericSignType.Positive == TypeHelper.checkNumericSignType<T>(dynamic_value))
{
return (T)(Math.Ceiling(dynamic_value * factor) / factor);
}
return (T)(Math.Floor(dynamic_value * factor) / factor);
}
// Returns the smallest integer greater to or equal to /value/.
public static T ceilToInt<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)(Int32)MathF.Ceiling(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)(Int32)Math.Ceiling(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
return (T)(object)(Int32)Math.Ceiling(result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the largest integer smaller to or equal to /value/.
public static T floorToInt<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)(Int32)MathF.Floor(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)(Int32)Math.Floor(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
return (T)(object)(Int32)Math.Floor(result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns /value/ rounded to the nearest integer.
public static T roundToInt<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)(Int32)MathF.Round(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)(Int32)Math.Round(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
return (T)(object)(Int32)Math.Round(result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns /value/ truncated to the nearest integer.
public static T truncateToInt<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result = Convert.ToSingle(value);
return (T)(object)(Int32)MathF.Truncate(result);
}
else if (typeof(T) == typeof(double))
{
var result = Convert.ToDouble(value);
return (T)(object)(Int32)Math.Round(result);
}
else if (typeof(T) == typeof(decimal))
{
var result = Convert.ToDecimal(value);
return (T)(object)(Int32)Math.Round(result);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Returns the sign of /value/.
public static T sign<T>(T value)
where T : struct, IConvertible
{
if (typeof(T) == typeof(float))
{
var result_v = Convert.ToSingle(value);
return (T)(object)(result_v >= 0F ? 1F : -1F);
}
else if (typeof(T) == typeof(double))
{
var result_v = Convert.ToDouble(value);
return (T)(object)(result_v >= 0D ? 1D : -1D);
}
else if (typeof(T) == typeof(decimal))
{
var result_v = Convert.ToDecimal(value);
return (T)(object)(result_v >= 0M ? 1M : -1M);
}
else
{
throw new NotSupportedException($"Invalid Type !!! : {value}");
}
}
// Clamps a value between a minimum generic type and maximum generic type value.
public static T clamp<T>(T value, T min, T max)
where T : IComparable<T>
{
if (value.CompareTo(min) < 0)
value = min;
else if (value.CompareTo(max) > 0)
value = max;
return value;
}
}