114 lines
2.1 KiB
Python

from dataclasses import dataclass
import numpy as np
from .types import FunctionType, OperatorType, ValueType
# Additional functions that are not defined in numpy
def acot(x: ValueType):
return np.arctan(1 / x)
def cot(x: ValueType):
return 1 / np.tan(x)
# Function and operation names to evaluators mapping
functions: dict[str, FunctionType] = {
"abs": np.abs,
"acos": np.arccos,
"acosh": np.arccosh,
"acot": acot,
"asin": np.arcsin,
"asinh": np.arcsinh,
"atan": np.arctan,
"avg": np.average,
"cos": np.cos,
"cosh": np.cosh,
"cot": cot,
"exp": np.exp,
"inf": np.inf,
"lg": np.log10,
"ln": np.log,
"log10": np.log10,
"log2": np.log2,
"max": np.max,
"min": np.min,
"prod": np.prod,
"sgn": np.sign,
"sign": np.sign,
"sin": np.sin,
"sinh": np.sinh,
"sqrt": np.sqrt,
"sum": np.sum,
"sup": np.max,
"tanh": np.tanh,
"tan": np.tan,
}
operators: dict[str, OperatorType] = {
"+": np.add,
"-": np.subtract,
"*": np.multiply,
"/": np.divide,
"%": np.mod,
"^": np.float_power,
}
priorities: dict[str, int] = {
"(": 0,
"+": 1,
"-": 1,
"*": 2,
"/": 2,
"%": 2,
"^": 3,
"f": 4, # function
")": 5,
}
@dataclass
class Operation:
"""
Base class for math operation token (function, brace, operator).
It stores the way it is evaluated, evaluation priority and number
of arguments it supports.
"""
evaluator: (FunctionType | OperatorType | str)
priority: int
size: int
class FunctionOperation(Operation):
"""
`Operator` class factory that represents function
"""
def __init__(self, name: str):
super().__init__(functions[name], priorities["f"], 1)
class BraceOperation(Operation):
"""
`Operator` class factory that represents brace
"""
def __init__(self, name: str):
super().__init__(name, priorities[name], 0)
class OperatorOperation(Operation):
"""
`Operator` class factory that represents binary operator
"""
def __init__(self, name: str):
super().__init__(operators[name], priorities[name], 2)