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

Last change on this file since 2532 was 2532, checked in by ansari, 21 years ago

Correction pb compilation sous Linux (putenv()) - Reza 28/04/2004

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