Initial commit to new repository

This commit is contained in:
2026-04-03 18:22:19 +09:00
commit 4458bb0f52
7672 changed files with 452440 additions and 0 deletions

View File

@@ -0,0 +1,256 @@
using System;
using System.Globalization;
namespace AxCopilot.Handlers;
internal static class MathEvaluator
{
private class Evaluator
{
private readonly string _s;
private int _i;
public Evaluator(string s)
{
_s = s;
_i = 0;
}
public double Parse()
{
double result = ParseExpr();
if (_i < _s.Length)
{
throw new InvalidOperationException($"예기치 않은 문자: '{_s[_i]}'");
}
return result;
}
private double ParseExpr()
{
double num = ParseTerm();
while (_i < _s.Length && (_s[_i] == '+' || _s[_i] == '-'))
{
char c = _s[_i++];
double num2 = ParseTerm();
num = ((c == '+') ? (num + num2) : (num - num2));
}
return num;
}
private double ParseTerm()
{
double num = ParsePower();
while (_i < _s.Length && (_s[_i] == '*' || _s[_i] == '/' || _s[_i] == '%'))
{
char c = _s[_i++];
double num2 = ParsePower();
num = c switch
{
'/' => num / num2,
'*' => num * num2,
_ => num % num2,
};
}
return num;
}
private double ParsePower()
{
double num = ParseUnary();
if (_i < _s.Length && _s[_i] == '^')
{
_i++;
double y = ParseUnary();
return Math.Pow(num, y);
}
return num;
}
private double ParseUnary()
{
if (_i < _s.Length && _s[_i] == '-')
{
_i++;
return 0.0 - ParsePrimary();
}
if (_i < _s.Length && _s[_i] == '+')
{
_i++;
return ParsePrimary();
}
return ParsePrimary();
}
private double ParsePrimary()
{
if (_i >= _s.Length)
{
throw new InvalidOperationException("수식이 불완전합니다.");
}
if (_i + 1 < _s.Length && _s[_i] == '0' && _s[_i + 1] == 'x')
{
_i += 2;
int i = _i;
while (_i < _s.Length && "0123456789abcdef".Contains(_s[_i]))
{
_i++;
}
string s = _s;
int num = i;
return Convert.ToInt64(s.Substring(num, _i - num), 16);
}
if (char.IsDigit(_s[_i]) || _s[_i] == '.')
{
int i2 = _i;
while (_i < _s.Length && (char.IsDigit(_s[_i]) || _s[_i] == '.'))
{
_i++;
}
if (_i < _s.Length && _s[_i] == 'e')
{
_i++;
if (_i < _s.Length && (_s[_i] == '+' || _s[_i] == '-'))
{
_i++;
}
while (_i < _s.Length && char.IsDigit(_s[_i]))
{
_i++;
}
}
string s2 = _s;
int num = i2;
return double.Parse(s2.Substring(num, _i - num), NumberStyles.Float, CultureInfo.InvariantCulture);
}
if (_s[_i] == '(')
{
_i++;
double result = ParseExpr();
if (_i < _s.Length && _s[_i] == ')')
{
_i++;
}
return result;
}
if (char.IsLetter(_s[_i]))
{
int i3 = _i;
while (_i < _s.Length && (char.IsLetterOrDigit(_s[_i]) || _s[_i] == '_'))
{
_i++;
}
string s3 = _s;
int num = i3;
string text = s3.Substring(num, _i - num);
switch (text)
{
case "pi":
return Math.PI;
case "e":
return Math.E;
case "inf":
return double.PositiveInfinity;
default:
if (_i < _s.Length && _s[_i] == '(')
{
_i++;
double num2 = ParseExpr();
double? num3 = null;
if (_i < _s.Length && _s[_i] == ',')
{
_i++;
num3 = ParseExpr();
}
if (_i < _s.Length && _s[_i] == ')')
{
_i++;
}
if (1 == 0)
{
}
double result2;
switch (text)
{
case "sqrt":
result2 = Math.Sqrt(num2);
break;
case "abs":
result2 = Math.Abs(num2);
break;
case "ceil":
result2 = Math.Ceiling(num2);
break;
case "floor":
result2 = Math.Floor(num2);
break;
case "round":
result2 = (num3.HasValue ? Math.Round(num2, (int)num3.Value) : Math.Round(num2));
break;
case "sin":
result2 = Math.Sin(num2 * Math.PI / 180.0);
break;
case "cos":
result2 = Math.Cos(num2 * Math.PI / 180.0);
break;
case "tan":
result2 = Math.Tan(num2 * Math.PI / 180.0);
break;
case "asin":
result2 = Math.Asin(num2) * 180.0 / Math.PI;
break;
case "acos":
result2 = Math.Acos(num2) * 180.0 / Math.PI;
break;
case "atan":
result2 = Math.Atan(num2) * 180.0 / Math.PI;
break;
case "log":
result2 = (num3.HasValue ? Math.Log(num2, num3.Value) : Math.Log10(num2));
break;
case "log2":
result2 = Math.Log2(num2);
break;
case "ln":
result2 = Math.Log(num2);
break;
case "exp":
result2 = Math.Exp(num2);
break;
case "pow":
if (!num3.HasValue)
{
throw new InvalidOperationException("pow(x,y) 형식으로 사용하세요.");
}
result2 = Math.Pow(num2, num3.Value);
break;
case "min":
result2 = (num3.HasValue ? Math.Min(num2, num3.Value) : num2);
break;
case "max":
result2 = (num3.HasValue ? Math.Max(num2, num3.Value) : num2);
break;
default:
throw new InvalidOperationException("알 수 없는 함수: " + text + "()");
}
if (1 == 0)
{
}
return result2;
}
throw new InvalidOperationException("알 수 없는 식별자: " + text);
}
}
throw new InvalidOperationException($"예기치 않은 문자: '{_s[_i]}'");
}
}
public static double Evaluate(string expr)
{
Evaluator evaluator = new Evaluator(expr.Replace(" ", "").Replace("×", "*").Replace("÷", "/")
.Replace("", ",")
.ToLowerInvariant());
return evaluator.Parse();
}
}