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 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 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 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 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 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 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 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 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 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 a, T b) where T : struct, IComparable { return a.CompareTo(b) < 0 ? a : b; } // Returns the smallest of two or more values. public static T min(params T[] values) where T : struct, IComparable { 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 a, T b) where T : IComparable { return a.CompareTo(b) > 0 ? a : b; } public static T max(params T[] values) where T : IComparable { 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 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 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 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 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 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 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 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 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 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 value) where T : struct, IComparable { 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 value, int decimalPlaces = 0) where T : struct, IComparable { dynamic dynamic_value = value; double factor = Math.Pow(10, decimalPlaces); // 소숫점 자리수에 따라 곱할 값 설정, 0일 경우 소수점없이 올림 처리 한다 !!! if (TypeHelper.NumericSignType.Positive == TypeHelper.checkNumericSignType(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 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 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 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 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 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 value, T min, T max) where T : IComparable { if (value.CompareTo(min) < 0) value = min; else if (value.CompareTo(max) > 0) value = max; return value; } }