eis/inc/glob/MathExpression.h

148 lines
4.0 KiB
C
Raw Permalink Normal View History

#ifndef _MATH_EXPRESSION_H_
#define _MATH_EXPRESSION_H_
/******************************************************************************************************************
* Arithmetic operation expression
*
* support function: "random","floor", "abs", "sqrt", "sin", "cos", "tan", "atan", "log", "exp", "atan2", "pow"
*
* function can be customized,for exmple:
* double len2(double a, double b) {
* return sqrt(a*a + b*b);
* }
* MathExpression::AddFunction("len2", len2);
*
* exp: std::map<std::string, double> vars;
* vars["x"] = 100;
* vars["y"] = 200;
* MathExpression e("(sqrt(x)>y)&&(x>y)", vars);
* double ret = e.Evaluator();
*
* MathExpression expr1 = MathExpression::Parse("x>y", vars);
* std::cout<<"expr1:"<<expr1.Evaluator()<<std::endl;
*
* 1.0 2020-12-07 zoufuzhou
******************************************************************************************************************/
#include <vector>
#include <string>
#include <map>
#include <stdexcept>
#include <algorithm>
#include <iostream>
#include <string.h>
class MathExpression {
public:
struct Error : std::runtime_error {
int position;
Error(const std::string& msg, int position = -1)
: std::runtime_error(msg), position(position)
{}
};
//evaluation expression
double Evaluator() const;
//parse expression
static MathExpression Parse(const char *expstr, std::map<std::string, double>& vars);
MathExpression(double x = 0.0) {
m_resreg = 0;
m_wrk.push_back(x);
}
void Swap(MathExpression& other) {
std::swap(m_resreg, other.m_resreg);
m_code.swap(other.m_code);
m_wrk.swap(other.m_wrk);
m_variables.swap(other.m_variables);
}
//structure evaluation expression
MathExpression(const char *expstr, std::map<std::string, double>& m) {
MathExpression e = Parse(expstr, m);
Swap(e);
}
//add custom function
static void AddFunction(const char *name, double (*f)()) {
m_func0.push_back(f);
mp_functions[name] = std::make_pair(m_func0.size()-1, 0);
}
//add custom function
static void AddFunction(const char *name, double (*f)(double)) {
m_func1.push_back(f);
mp_functions[name] = std::make_pair(m_func1.size()-1, 1);
}
//add custom function
static void AddFunction(const char *name, double (*f)(double, double)) {
m_func2.push_back(f);
mp_functions[name] = std::make_pair(m_func2.size()-1, 2);
}
//evaluation expression disassemble
std::string Disassemble() const;
private:
//skip space
static void SkipSP(const char *& expstr);
static MathExpression PartialParse(const char *& expstr, std::map<std::string, double>& vars);
int Compile(std::vector<int>& regs,const char *& expstr, std::map<std::string, double>& vars, int level);
private:
enum { MOVE, LOAD,
NEG, NOT,
ADD, SUB, MUL, DIV, LT, LE, GT, GE, EQ, NE, AND, OR,
B_SHL, B_SHR, B_AND, B_OR, B_XOR,
FSIN, FCOS, FFLOOR, FABS, FSQRT, FTAN, FATAN, FLOG, FEXP, FATAN2, FPOW,
FUNC0, FUNC1, FUNC2 };
int m_resreg;
std::vector<int> m_code;
mutable std::vector<double> m_wrk;
std::vector<double *> m_variables;
struct Operator {
const char *name;
int level;
int opcode;
};
static std::map<std::string, Operator> mp_operators;
static int m_max_level;
static std::map<std::string, std::pair<int, int> > mp_inlined;
static std::map<std::string, std::pair<int, int> > mp_functions;
static std::vector<double (*)()> m_func0;
static std::vector<double (*)(double)> m_func1;
static std::vector<double (*)(double,double)> m_func2;
class Init;
friend class Init;
enum { READONLY = 0x4000000 };
int reg(std::vector<int>& regs) {
if (regs.size() == 0) {
m_wrk.resize(1 + m_wrk.size());
regs.push_back(m_wrk.size()-1);
}
int r = regs.back();
regs.pop_back();
return r;
}
};
#endif