148 lines
4.0 KiB
C
148 lines
4.0 KiB
C
|
|
#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
|