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

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

changement de nom de rand et norrand ds rpneval.cc - Reza, 9 Aout 2004

File size: 7.4 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] == "rand01") {
180 double rnd = drand01();
181 rpnstack_.push(rnd);
182 }
183 else if (args[k] == "randpm1") {
184 double rnd = drandpm1();
185 rpnstack_.push(rnd);
186 }
187 else if (args[k] == "gaurand") {
188 double rnd = GauRnd(0., 1.);
189 rpnstack_.push(rnd);
190 }
191 // Fonction a N arguments - Somme, produit, etc ...
192 else if ((args[k] == "sum") || (args[k] == "mean") || (args[k] == "sigmean") ||
193 (args[k] == "sigma") || (args[k] == "sigma2") ) {
194 double sx, sx2;
195 int nn = SumStack( sx, sx2);
196 if (args[k] == "sum") rpnstack_.push(sx);
197 else {
198 if (nn == 0) return 1;
199 double fnn = nn;
200 if ((args[k] == "sigma") || (args[k] == "sigmean"))
201 rpnstack_.push(sqrt(sx2/fnn-(x*x/(fnn*fnn))));
202 else if ((args[k] == "mean") || (args[k] == "sigmean")) rpnstack_.push(sx/fnn);
203 else rpnstack_.push(sx2/fnn-(x*x/(fnn*fnn)));
204 }
205 }
206 else if (args[k] == "product") {
207 double px;
208 int nn = ProductStack( px);
209 if (nn == 0) return k;
210 rpnstack_.push(px);
211 }
212 // Fonctions de manipulation de stack
213 else if (args[k] == "print") {
214 PrintStack();
215 }
216 else if (args[k] == "x<>y") {
217 if ( CheckStack( x, y) ) return k;
218 rpnstack_.top() = x; rpnstack_.push(y);
219 }
220 else if (args[k] == "pop") {
221 rpnstack_.pop();
222 }
223 else if (args[k] == "push") {
224 if (rpnstack_.empty()) rpnstack_.push(0.);
225 else rpnstack_.push(rpnstack_.top());
226 }
227 // On met un nombre sur le stack
228 else {
229 char * esptr;
230 x = strtod(args[k].c_str(), &esptr);
231 // if (ctof(args[k].c_str(),&x) < 0) {
232 if (esptr == args[k].c_str()) return k;
233 rpnstack_.push(x);
234 }
235
236 }
237 return(args.size()+1);
238}
239
240inline void RPNExpressionEvaluator::PrintStack()
241{
242 if (rpnstack_.empty())
243 cout << "RPNExpressionEvaluator::PrintStack() Empty stack " << endl;
244 else {
245 stack<double> s;
246 s = rpnstack_;
247 int k = 0;
248 cout << "RPNExpressionEvaluator::PrintStack() Size()= " << s.size() << endl;
249 while( !s.empty() ) {
250 cout << " " << k << ": " << s.top() << " ";
251 if (k == 0) cout << " (x) " << endl;
252 else if (k == 1) cout << " (y) " << endl;
253 else if (k == 2) cout << " (z) " << endl;
254 else cout << endl;
255 s.pop(); k++;
256 }
257 }
258
259}
260
261int RPNExpressionEvaluator::SumStack(double& sx, double& sx2)
262{
263 sx = sx2 = 0.;
264 int nn = 0;
265 double x = 0.;
266 while( !rpnstack_.empty() ) {
267 x = rpnstack_.top(); rpnstack_.pop();
268 sx += x; sx2 += x*x;
269 nn++;
270 }
271 return(nn);
272}
273
274int RPNExpressionEvaluator::ProductStack(double& px)
275{
276 px = 1.;
277 int nn = 0;
278 double x = 0.;
279 while( !rpnstack_.empty() ) {
280 x = rpnstack_.top(); rpnstack_.pop();
281 px *= x; nn++;
282 }
283 return(nn);
284}
285
286
287} // End of namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.