source: Sophya/trunk/SophyaLib/SysTools/rpneval.cc@ 2518

Last change on this file since 2518 was 2512, checked in by ansari, 22 years ago

Correction bugs ds CExpression/RPNExpression et adaptation classe Commander avec utilisation classe CExpressionEvaluator - Reza 16 Mars 2004

File size: 7.3 KB
Line 
1#include "rpneval.h"
2#include <stdlib.h>
3#include "strutilxx.h"
4#include "srandgen.h"
5#include <iostream>
6#include <math.h>
7
8namespace SOPHYA {
9
10/*!
11 \class SOPHYA::RPNExpressionEvaluator
12 \ingroup SysTools
13 Arithmetic expression (double precision float) evaluator
14 in Reverse Polish Notation (RPN). This is an HP calculator
15 like syntax. Space are used for separating the string
16 expression into tokens.
17*/
18
19RPNExpressionEvaluator::RPNExpressionEvaluator(string const & sex)
20{
21 vector<string> exe;
22 FillVStringFrString(sex, exe, ' ');
23 int rc = EvalRPNExpr(exe, 0);
24 if (rc < exe.size()) {
25 string msg = "RPNExpressionEvaluator() - syntax error near ";
26 msg += exe[rc];
27 char buff[32];
28 sprintf(buff," (word %d)",rc);
29 msg += buff;
30 throw RPNExprException(msg);
31 }
32}
33
34RPNExpressionEvaluator::RPNExpressionEvaluator(vector<string> & exe, int off)
35{
36 int rc = EvalRPNExpr(exe, off);
37 if (rc < exe.size()) {
38 string msg = "RPNExpressionEvaluator() - syntax error near ";
39 msg += exe[rc];
40 char buff[32];
41 sprintf(buff," (word %d)",rc);
42 msg += buff;
43 throw RPNExprException(msg);
44 }
45}
46
47RPNExpressionEvaluator::~RPNExpressionEvaluator()
48{
49}
50
51/* Operations sur le stack RPN */
52/* --Methode-- */
53double RPNExpressionEvaluator::Evaluate() const
54{
55 double x;
56 if ( CheckStack( x) )
57 throw RPNExprException("RPNExpressionEvaluator::Evaluate() EmptyStack");
58 else return x;
59}
60
61/* --Methode-- */
62int RPNExpressionEvaluator::EvalRPNExpr(vector<string> & args, int off)
63{
64
65 if (args.size() <= off) return 1;
66 double x,y;
67 x = y = 0.;
68
69 for(int k=off; k<args.size(); k++) {
70 // Les 4 operations de base + - * /
71 if (args[k] == "+") {
72 if ( CheckStack( x, y) ) return k;
73 rpnstack_.top() = y+x;
74 }
75 else if (args[k] == "-") {
76 if ( CheckStack( x, y) ) return k;
77 rpnstack_.top() = y-x;
78 }
79 else if (args[k] == "*") {
80 if ( CheckStack( x, y) ) return k;
81 rpnstack_.top() = y*x;
82 }
83 else if (args[k] == "/") {
84 if ( CheckStack( x, y) ) return k;
85 rpnstack_.top() = y/x;
86 }
87 else if (args[k] == "%") {
88 if ( CheckStack( x, y) ) return k;
89 rpnstack_.top() = (int)y % (int)x;
90 }
91 // Les constantes : e , pi
92 else if (args[k] == "e") {
93 rpnstack_.push(M_E);
94 }
95 else if (args[k] == "pi") {
96 rpnstack_.push(M_PI);
97 }
98 // Les fonctions usuelles a 1 argument f(x)
99 else if (args[k] == "cos") {
100 if ( CheckStack( x) ) return k;
101 rpnstack_.top() = cos(x);
102 }
103 else if (args[k] == "sin") {
104 if ( CheckStack( x) ) return k;
105 rpnstack_.top() = sin(x);
106 }
107 else if (args[k] == "tan") {
108 if ( CheckStack( x) ) return k;
109 rpnstack_.top() = tan(x);
110 }
111 else if (args[k] == "acos") {
112 if ( CheckStack( x) ) return k;
113 rpnstack_.top() = acos(x);
114 }
115 else if (args[k] == "asin") {
116 if ( CheckStack( x) ) return k;
117 rpnstack_.top() = asin(x);
118 }
119 else if (args[k] == "atan") {
120 if ( CheckStack( x) ) return k;
121 rpnstack_.top() = atan(x);
122 }
123 else if (args[k] == "chs") {
124 if ( CheckStack( x) ) return k;
125 rpnstack_.top() = -x;
126 }
127 else if (args[k] == "sqrt") {
128 if ( CheckStack( x) ) return k;
129 rpnstack_.top() = sqrt(x);
130 }
131 else if (args[k] == "sq") { // x^2
132 if ( CheckStack( x) ) return k;
133 rpnstack_.top() = x*x;
134 }
135 else if (args[k] == "log") {
136 if ( CheckStack( x) ) return k;
137 rpnstack_.top() = log(x);
138 }
139 else if (args[k] == "log10") {
140 if ( CheckStack( x) ) return k;
141 rpnstack_.top() = log10(x);
142 }
143 else if (args[k] == "exp") {
144 if ( CheckStack( x) ) return k;
145 rpnstack_.top() = exp(x);
146 }
147 else if (args[k] == "fabs") {
148 if ( CheckStack( x) ) return k;
149 rpnstack_.top() = fabs(x);
150 }
151 else if (args[k] == "floor") {
152 if ( CheckStack( x) ) return k;
153 rpnstack_.top() = floor(x);
154 }
155 else if (args[k] == "ceil") {
156 if ( CheckStack( x) ) return k;
157 rpnstack_.top() = ceil(x);
158 }
159 // trunc et nint vire - ca ne compile pas sous linux - Reza 01/2003
160 else if (args[k] == "deg2rad") {
161 if ( CheckStack( x) ) return k;
162 rpnstack_.top() = x*M_PI/180.;
163 }
164 else if (args[k] == "rad2deg") {
165 if ( CheckStack( x) ) return k;
166 rpnstack_.top() = x*180./M_PI;
167 }
168 // Les fonctions usuelles a 2 argument f(x,y)
169 else if (args[k] == "pow") {
170 if ( CheckStack( x, y) ) return k;
171 rpnstack_.top() = pow(y,x);
172 }
173 else if (args[k] == "atan2") {
174 if ( CheckStack( x, y) ) return k;
175 rpnstack_.top() = atan2(x,y);
176 }
177 // generateur aleatoire
178 else if (args[k] == "rand") {
179 double rnd = drand01();
180 rpnstack_.push(rnd);
181 }
182 else if (args[k] == "norand") {
183 double rnd = GauRnd(0., 1.);
184 rpnstack_.push(rnd);
185 }
186 // Fonction a N arguments - Somme, produit, etc ...
187 else if ((args[k] == "sum") || (args[k] == "mean") || (args[k] == "sigmean") ||
188 (args[k] == "sigma") || (args[k] == "sigma2") ) {
189 double sx, sx2;
190 int nn = SumStack( sx, sx2);
191 if (args[k] == "sum") rpnstack_.push(sx);
192 else {
193 if (nn == 0) return 1;
194 double fnn = nn;
195 if ((args[k] == "sigma") || (args[k] == "sigmean"))
196 rpnstack_.push(sqrt(sx2/fnn-(x*x/(fnn*fnn))));
197 else if ((args[k] == "mean") || (args[k] == "sigmean")) rpnstack_.push(sx/fnn);
198 else rpnstack_.push(sx2/fnn-(x*x/(fnn*fnn)));
199 }
200 }
201 else if (args[k] == "product") {
202 double px;
203 int nn = ProductStack( px);
204 if (nn == 0) return k;
205 rpnstack_.push(px);
206 }
207 // Fonctions de manipulation de stack
208 else if (args[k] == "print") {
209 PrintStack();
210 }
211 else if (args[k] == "x<>y") {
212 if ( CheckStack( x, y) ) return k;
213 rpnstack_.top() = x; rpnstack_.push(y);
214 }
215 else if (args[k] == "pop") {
216 rpnstack_.pop();
217 }
218 else if (args[k] == "push") {
219 if (rpnstack_.empty()) rpnstack_.push(0.);
220 else rpnstack_.push(rpnstack_.top());
221 }
222 // On met un nombre sur le stack
223 else {
224 char * esptr;
225 x = strtod(args[k].c_str(), &esptr);
226 // if (ctof(args[k].c_str(),&x) < 0) {
227 if (esptr == args[k].c_str()) return k;
228 rpnstack_.push(x);
229 }
230
231 }
232 return(args.size()+1);
233}
234
235inline void RPNExpressionEvaluator::PrintStack()
236{
237 if (rpnstack_.empty())
238 cout << "RPNExpressionEvaluator::PrintStack() Empty stack " << endl;
239 else {
240 stack<double> s;
241 s = rpnstack_;
242 int k = 0;
243 cout << "RPNExpressionEvaluator::PrintStack() Size()= " << s.size() << endl;
244 while( !s.empty() ) {
245 cout << " " << k << ": " << s.top() << " ";
246 if (k == 0) cout << " (x) " << endl;
247 else if (k == 1) cout << " (y) " << endl;
248 else if (k == 2) cout << " (z) " << endl;
249 else cout << endl;
250 s.pop(); k++;
251 }
252 }
253
254}
255
256int RPNExpressionEvaluator::SumStack(double& sx, double& sx2)
257{
258 sx = sx2 = 0.;
259 int nn = 0;
260 double x = 0.;
261 while( !rpnstack_.empty() ) {
262 x = rpnstack_.top(); rpnstack_.pop();
263 sx += x; sx2 += x*x;
264 nn++;
265 }
266 return(nn);
267}
268
269int RPNExpressionEvaluator::ProductStack(double& px)
270{
271 px = 1.;
272 int nn = 0;
273 double x = 0.;
274 while( !rpnstack_.empty() ) {
275 x = rpnstack_.top(); rpnstack_.pop();
276 px *= x; nn++;
277 }
278 return(nn);
279}
280
281
282} // End of namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.