using System.Numerics;
using System.Runtime.CompilerServices;
namespace NTDLS.ExpressionParser
{
internal static class Extensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int ToCacheIndex(this string key) => int.Parse(key[1..^1]);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsNativeFunction(this string value) => Constants.NativeFunctions.Contains(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsIntegerExclusiveOperation(this string value) => (new string[] { "&", "|", "^", "&=", "|=", "^=", "<<", ">>" }).Contains(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsMathCharacter(this char value) => (new char[] { '*', '/', '+', '-', '>', '<', '!', '=', '&', '|', '^', '%', '~' }).Contains(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsValidVariableCharacter(this char value) => char.IsDigit(value) || (value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || value == '_';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsNumeric(this string input)
{
if (string.IsNullOrEmpty(input))
return false;
bool hasDigit = false;
int i = 0;
if (input[i] == '-' || input[i] == '+') //Explicit positive or negative number.
{
i++;
}
for (; i < input.Length; i++)
{
char c = input[i];
if (char.IsDigit(c))
{
hasDigit = true;
continue;
}
if ((c == '.' || c == ',') || (c == '-' || c == '+' && i == 0))
continue;
return false;
}
return hasDigit;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int ComputeIntegerExclusivePrimitive(this string operation, int leftValue, int rightValue)
{
return operation switch
{
"!" => (leftValue != rightValue) ? 1 : 0,
"&" => leftValue & rightValue,
"&&" => (leftValue != 0 && rightValue != 0) ? 1 : 0,
"&=" => leftValue &= rightValue,
"^" => leftValue ^ rightValue,
"^=" => leftValue ^= rightValue,
"|" => leftValue | rightValue,
"||" => (leftValue != 0 || rightValue != 0) ? 1 : 0,
"|=" => leftValue |= rightValue,
"~" => ~leftValue,
"<<" => leftValue << rightValue,
"=" => (leftValue == rightValue) ? 1 : 0,
">>" => leftValue >> rightValue,
_ => throw new Exception($"Invalid operator: {operation}"),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ComputePrivative(this string operation, double leftValue, double rightValue)
{
if (operation.IsIntegerExclusiveOperation())
{
return operation.ComputeIntegerExclusivePrimitive((int)leftValue, (int)rightValue);
}
var result = operation switch
{
"!" => (leftValue != rightValue) ? 1 : 0,
"!=" => (leftValue != rightValue) ? 1 : 0,
"-" => (leftValue - rightValue),
"%" => rightValue != 0 ? (leftValue % rightValue) : throw new Exception("Divide by zero (mod)."),
"&&" => (leftValue != 0 && rightValue != 0) ? 1 : 0,
"*" => (leftValue * rightValue),
"/" => rightValue != 0 ? (leftValue / rightValue) : throw new Exception("Divide by zero."),
"||" => (leftValue != 0 || rightValue != 0) ? 1 : 0,
"+" => (leftValue + rightValue),
"<" => (leftValue < rightValue) ? 1 : 0,
"<=" => (leftValue <= rightValue) ? 1 : 0,
"<>" => (leftValue != rightValue) ? 1 : 0,
"=" => (leftValue == rightValue) ? 1 : 0,
">" => (leftValue > rightValue) ? 1 : 0,
">=" => (leftValue >= rightValue) ? 1 : 0,
_ => throw new Exception($"Invalid operator: {operation}"),
};
if (double.IsNaN(result))
{
throw new Exception($"Result of {operation} is NaN.");
}
if (double.IsInfinity(result))
{
throw new Exception($"Result of {operation} is infinite.");
}
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ComputeNativeFunction(this string functionName, double[] parameters)
{
return functionName switch
{
"abs" => parameters.Length == 1 ? (Math.Abs(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"acos" => parameters.Length == 1 ? (Math.Acos(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"asin" => parameters.Length == 1 ? (Math.Asin(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"atan" => parameters.Length == 1 ? (Math.Atan(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"atan2" => parameters.Length == 2 ? (Math.Atan2(parameters[0], parameters[1])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"avg" => parameters.Length > 0 ? (parameters.Average()) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"ceil" => parameters.Length == 1 ? (Math.Ceiling(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"cos" => parameters.Length == 1 ? (Math.Cos(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"cosh" => parameters.Length == 1 ? (Math.Cosh(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"exp" => parameters.Length == 1 ? (Math.Exp(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"floor" => parameters.Length == 1 ? (Math.Floor(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"log" => parameters.Length == 1 ? (Math.Log(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"log10" => parameters.Length == 1 ? (Math.Log10(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"max" => parameters.Length > 0 ? (parameters.Max()) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"min" => parameters.Length > 0 ? (parameters.Min()) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"modpow" => parameters.Length == 3 ? ((double)BigInteger.ModPow((BigInteger)parameters[0], (BigInteger)parameters[1], (BigInteger)parameters[2])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"not" => parameters.Length == 1 ? ((parameters[0] == 0) ? 1 : 0) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"pow" => parameters.Length == 2 ? (Math.Pow(parameters[0], (int)parameters[1])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"sin" => parameters.Length == 1 ? (Math.Sin(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"sinh" => parameters.Length == 1 ? (Math.Sinh(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"sqrt" => parameters.Length == 1 ? (Math.Sqrt(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"sum" => parameters.Length > 0 ? (parameters.Sum()) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"tahn" => parameters.Length == 1 ? (Math.Tanh(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
"tan" => parameters.Length == 1 ? (Math.Tan(parameters[0])) : throw new Exception($"Invalid number of parameters passed to function: {functionName}"),
_ => throw new Exception($"Undefined native function: {functionName}"),
};
}
}
}Last modified by Admin @ 10/22/2025 3:55:40 PM
Comments
Login to leave a comment.View all comments