-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathformula.h
More file actions
149 lines (124 loc) · 3.69 KB
/
formula.h
File metadata and controls
149 lines (124 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef __FORMULA_H__
#define __FORMULA_H__
#include <string>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <exception>
#include <functional>
#ifdef _MSC_VER
class __declspec(dllexport) Formula
#else
class Formula
#endif
{
public:
Formula();
Formula(const std::string& str);
Formula(const char* str);
Formula& operator =(const std::string& str);
Formula& operator =(const char* str);
Formula& input(const std::string& str_promt);
void clear();
bool empty()const;
void check()const;
double eval(const std::unordered_map<std::string, double>& variables);
double eval(const std::vector<double>& variables);
template<typename ... DataTypes>
double eval(DataTypes ... rest);
double operator ()(const std::unordered_map<std::string, double>& variables);
double operator ()(const std::vector<double>& variables);
template<typename ... DataTypes>
double operator ()(DataTypes ... rest);
void define(const std::string& var_name, double value);
void define(const std::string& func_name, const std::function<double(double)>& f);
friend std::ostream& operator <<(std::ostream& out_stream, const Formula& f);
friend std::istream& operator >>(std::istream& in_stream, Formula& f);
public:
class Exception: public std::exception
{
public:
enum Type
{
UNKNOWN,
NOT_SUPPORTED_TOKEN,
NOT_ENOUGH_OPERANDS,
INTERNAL_ERROR,
NOT_DEFINED_FUNCTION,
WRONG_FORMAT,
NOT_DEFINED_VARIABLE,
DIVIDIED_BY_ZERO,
OUT_OF_RANGE,
EMPTY_STRING,
NOT_SUPPORTED_CHARACTER,
};
Exception(Type code = UNKNOWN, const std::string& _message = "", double _value = 0.0, const std::string& _interval = "");
const char* what() const throw();
std::string message()const;
Type type()const;
private:
Type m_type;
std::string m_message;
};
private:
struct Token
{
enum Type
{
Error,
Operator,
Number,
Function,
Variable
};
Type type;
std::string name;
double data;
public:
Token();
Token(const std::string& _type);
Token(char ch);
Token(double _data);
Token(Type _type, const std::string& _name, double _data);
int innerPriority()const;
int outerPriority()const;
};
private:
static void preprocess(std::string& str);
static Token getNumber(const std::string& str, int& i);
Token getWord(const std::string& str, int& i);
Token getToken(const std::string& str, int& i);
void generatePostfix();
private:
static const std::unordered_set<char> s_supported_chars;
static const std::unordered_map<std::string, double> s_built_in_variables;
static const std::unordered_map<std::string, std::function<double(double)> > s_built_in_functions;
std::vector<Token> m_postfix;
std::string m_formula_string;
std::set<std::string> m_found_variables;
std::unordered_map<std::string, double> m_defined_variables;
std::unordered_map<std::string, std::function<double(double)> > m_defined_functions;
};
std::vector<double> varargin2vector();
template<typename ... DataTypes>
std::vector<double> varargin2vector(double first, DataTypes ... rest)
{
std::vector<double> variables(1, first), variables_rest;
variables_rest = varargin2vector(rest...);
variables.insert(variables.end(), variables_rest.begin(), variables_rest.end());
return variables;
}
template<typename ... DataTypes>
double Formula::eval(DataTypes... varargin)
{
std::vector<double> variables = varargin2vector(varargin...);
return eval(variables);
}
template<typename ... DataTypes>
double Formula::operator ()(DataTypes... varargin)
{
return eval(varargin...);
}
#endif