Biorbd
Equation.cpp
1 #define BIORBD_API_EXPORTS
2 #include "Utils/Equation.h"
3 
4 #ifdef _WIN32
5 #include <string>
6 #endif
7 
8 #include <math.h>
9 #include "Utils/Error.h"
10 
11 std::vector<biorbd::utils::Equation> biorbd::utils::Equation::prepareMathSymbols(){
12  // Classify in the order of priority of the operations
13  std::vector<biorbd::utils::Equation> symbols;
14  symbols.push_back("(");
15  symbols.push_back(")");
16  symbols.push_back("e");
17  symbols.push_back("/");
18  symbols.push_back("*");
19  symbols.push_back("+");
20  symbols.push_back("-");
21 
22  return symbols;
23 }
24 
26  biorbd::utils::String("")
27 {
28 
29 }
30 
32  biorbd::utils::String(c)
33 {
34 
35 }
36 
38  biorbd::utils::String(s)
39 {
40 
41 }
42 
43 biorbd::utils::Equation::Equation(const std::basic_string<char> &c) :
44  biorbd::utils::String(c)
45 {
46 
47 }
48 
49 std::vector<biorbd::utils::Equation> biorbd::utils::Equation::splitIntoEquation(
51  const std::map<biorbd::utils::Equation, double>& variables)
52 {
53  // output variable
54  std::vector<biorbd::utils::Equation> eq;
55 
56  // Replace the variables by a number
57  replaceVar(wholeEq, variables);
58 
59  // Declaration of the arithmetic markers
60  const std::vector<biorbd::utils::Equation>& symbols(prepareMathSymbols());
61 
62  // All along the string
63  while (1){
64  int firstIdx(static_cast<int>(wholeEq.size())+1);// Assign an index too big
65  unsigned int toStop(0); // Set stop at 0
66  // Go through each symbol to see if it's in the equation
67  for (unsigned int i=0; i<symbols.size(); ++i){
68  int idx = static_cast<int>(wholeEq.find(symbols[i]));
69  if (idx < 0){ // If not, write it down
70  ++toStop;
71  continue;
72  }
73  if (idx < firstIdx && idx != -1) // If yes, look if it's before another symbol
74  firstIdx = idx;
75  }
76  if (toStop == symbols.size()){ // If no symbols left, exit the while loop
77  eq.push_back(wholeEq);
78  break;
79  }
80  if (wholeEq.size() == 1){
81  eq.push_back(wholeEq(0));
82  break;
83  }
84  if (firstIdx+1 == static_cast<int>(wholeEq.size())){
85  eq.push_back(wholeEq.substr(0,static_cast<unsigned int>(firstIdx)));
86  eq.push_back(wholeEq(static_cast<unsigned int>(firstIdx)));
87  break;
88  }
89  else if (firstIdx == 0){
90  if (!wholeEq(0).compare("-")){
91  // If the equation starts with "-"
92  std::vector<biorbd::utils::Equation> tp(splitIntoEquation(wholeEq.substr(1), variables));
93  if (eq.size() != 0 && !eq[eq.size()-1].compare("e") ){
94  // special case of scientific notation (1e-x)
95  eq.push_back(wholeEq(0));
96  wholeEq = wholeEq.substr(1);
97  } else if (!tp[0].compare("(")) {
98  // Resolve now the parenthese to apply the minus after
99  size_t idx = wholeEq.find_first_of(")");
100  biorbd::utils::Equation newWholeEq(wholeEq.substr(2, idx-2));
101  double res(-1*evaluateEquation(splitIntoEquation(newWholeEq, variables)));
102  wholeEq = to_string(res) + wholeEq.substr(idx+1);
103  } else {
104  tp[0] = "-" + tp[0];
105  eq.insert(eq.end(), tp.begin(), tp.end());
106  return eq;
107  }
108  }
109  else if (!wholeEq(0).compare("+")){
110  // If the equation starts with +
111  std::vector<biorbd::utils::Equation> tp(splitIntoEquation(wholeEq.substr(1), variables));
112  if (eq.size() != 0) // If there's nothing before, it's false in all cases 1ex
113  eq.push_back("+");
114  eq.insert(eq.end(), tp.begin(), tp.end());
115  return eq;
116  }
117  else{
118  eq.push_back(wholeEq(0));
119  wholeEq = wholeEq.substr(1);
120  }
121  }
122  else{
123  eq.push_back(wholeEq.substr(0,static_cast<unsigned int>(firstIdx))); // Take everything before symbol
124  eq.push_back(wholeEq(static_cast<unsigned int>(firstIdx))); // Get the symbol
125  wholeEq = wholeEq.substr(static_cast<unsigned int>(firstIdx)+1); // Keep everything after the symbol and restart
126  }
127 
128  }
129 
130  // Replace constant with numbers
131  replaceCste(eq);
132 
133  // Return the equation
134  return eq;
135 }
136 
138  std::vector<biorbd::utils::Equation> &eq)
139 {
140  for (unsigned int i=0; i<eq.size(); ++i)
141  if (!eq[i].tolower().compare("pi")){
142  eq[i] = to_string(M_PI);
143  }
144 }
145 
148  const std::map<biorbd::utils::Equation, double>& variables)
149 {
150  for (auto var : variables)
151  while (eq.find(var.first) != std::string::npos){
152  size_t pos(eq.find(var.first));
153  size_t length(var.first.length());
154  eq = eq.substr(0, pos) + "(" +
155  to_string(var.second) + ")" +
156  eq.substr(pos + length);
157  }
158 }
159 
160 
162  std::vector<biorbd::utils::Equation> wholeEq)
163 {
164  return evaluateEquation(wholeEq,0);
165 }
166 
168  std::vector<biorbd::utils::Equation> eq,
169  unsigned int math)
170 {
171  // If everything was done
172  if (eq.size() == 1)
173  return stod(eq[0]);
174 
175  // Declaration of the arithmetic markers
176  const std::vector<biorbd::utils::Equation>& symbols(prepareMathSymbols());
177  std::vector<biorbd::utils::Equation> eq2;
178  bool continuer(true);
179 
180  for (unsigned int j=0; j<eq.size(); ++j){
181  if (!eq[j].compare(symbols[math]) && continuer){
182  if (j==0 && (!symbols[math].compare("+") || !symbols[math].compare("-"))){
183  // Crush the previous value
184  if (!symbols[math].compare("+"))
185  eq2[j-1] = to_string(0.0 + stod(eq[j+1]));
186  else if (!symbols[math].compare("-"))
187  eq2[j-1] = to_string(0.0 - stod(eq[j+1]));
188  }
189  else{
190  // Crush the previous value
191  if (!symbols[math].compare("(")){
192  std::vector<biorbd::utils::Equation> eq_tp;
193  bool foundIdx(false);
194  int cmpValues(0);
195  unsigned int cmpOpen(0);
196  for (unsigned int k=j+1; k<eq.size();++k){
197  if (!eq[k].compare("("))
198  cmpOpen++;
199  else if (!eq[k].compare(")")){
200  if (cmpOpen == 0){
201  foundIdx = true;
202  break;
203  }
204  else
205  cmpOpen--;
206  }
207 
208  eq_tp.push_back(eq[k]);
209  ++cmpValues;
210  }
211  biorbd::utils::Error::check(foundIdx, "You must close brackets!");
212 
213  eq2.push_back(to_string(evaluateEquation(eq_tp)));
214  j+=static_cast<unsigned int>(cmpValues);
215  }
216  else if (!symbols[math].compare("/"))
217  eq2[j-1] = to_string(stod(eq[j-1]) / stod(eq[j+1]));
218  else if (!symbols[math].compare("*"))
219  eq2[j-1] = to_string(stod(eq[j-1]) * stod(eq[j+1]));
220  else if (!symbols[math].compare("+"))
221  eq2[j-1] = to_string(stod(eq[j-1]) + stod(eq[j+1]));
222  else if (!symbols[math].compare("-"))
223  eq2[j-1] = to_string(stod(eq[j-1]) - stod(eq[j+1]));
224  else if (!symbols[math].compare("e")){
225  if (!eq[j+1].compare("-")){
226  eq2[j-1] = to_string(stod(eq[j-1]) * pow(10,-1*stod(eq[j+2])));
227  ++j;
228  }
229  else if (!eq[j+1].compare("+")){
230  eq2[j-1] = to_string(stod(eq[j-1]) * pow(10,stod(eq[j+2])));
231  ++j;
232  }
233  else
234  eq2[j-1] = to_string(stod(eq[j-1]) * pow(10,stod(eq[j+1])));
235 
236  }
237  }
238 
239  j+=2;
240  continuer = false;
241  }
242  if (j<eq.size())
243  eq2.push_back(eq[j]);
244  }
245 
246  if (continuer)
247  return evaluateEquation(eq2, ++math);
248  else
249  return evaluateEquation(eq2, math);
250 }
251 
253  biorbd::utils::Equation wholeEq,
254  const std::map<biorbd::utils::Equation, double>& variables)
255 {
256  return evaluateEquation(splitIntoEquation(wholeEq, variables));
257 }
259  biorbd::utils::Equation wholeEq)
260 {
261  std::map<biorbd::utils::Equation, double> dumb;
262  return evaluateEquation(splitIntoEquation(wholeEq, dumb));
263 }
biorbd::utils::Equation::Equation
Equation()
Construct Equation.
Definition: Equation.cpp:25
biorbd::utils::Equation::replaceCste
static void replaceCste(std::vector< biorbd::utils::Equation > &eq)
Replace constants in the split equation by a number.
Definition: Equation.cpp:137
biorbd::utils::Equation::splitIntoEquation
static std::vector< biorbd::utils::Equation > splitIntoEquation(biorbd::utils::Equation wholeEq, const std::map< biorbd::utils::Equation, double > &variables)
Split equation into smaller parts, down to number or math symbols.
Definition: Equation.cpp:49
biorbd::utils::Equation::prepareMathSymbols
static std::vector< biorbd::utils::Equation > prepareMathSymbols()
Prepare the mathematical symbols.
Definition: Equation.cpp:11
biorbd::utils::String
Wrapper around the std::string class with augmented functionality.
Definition: String.h:17
biorbd::utils::Equation
Strings that are to be interpreted as equation that can be evaluated.
Definition: Equation.h:16
biorbd::utils::Equation::evaluateEquation
static double evaluateEquation(std::vector< biorbd::utils::Equation > wholeEq)
Evaluate and return an equation.
Definition: Equation.cpp:161
biorbd::utils::Equation::replaceVar
static void replaceVar(biorbd::utils::Equation &eq, const std::map< biorbd::utils::Equation, double > &variables)
Replace the varirables in the equation by their values.
Definition: Equation.cpp:146
biorbd::utils::Error::check
static void check(bool cond, const biorbd::utils::String &message)
Assert that raises the error message if false.
Definition: Error.cpp:10