ECF 1.5
rpn.cpp
1#include "rpn.h"
2
3//#define STARO // ovo treba ukljuciti ako se provjeravaju stara rjesenja (sa greskom u editiranju)
4
5// evaluiramo za sve poslove odjednom!
6// broj poslova je konstantan za pojedini test skup: m_iArraySize
7// m_iOffset je prvi posao kojega uzimamo u obzir; prethodni su vec rasporedjeni!
8// pIndex je polje u kojemu su do m_iOffset-a indeksi svih rasporedjenih, a iza svi ostali
9// dodano 10.08.: idemo od Offset do End (ne gledamo poslove iza End u polju indeksa)
10// dodano 06.09.: m_nTree odredjuje koje se stablo evaluira (default = 0)
11void RPN::evaluate_array(double dResult[])
12{
13 double d1[MAX_JOBS],d2[MAX_JOBS],d3[MAX_JOBS],d4[MAX_JOBS];
14 uint i;
15 m_iPosition++; // pomicemo se na sljedeci simbol; pocetna vrijednost mora biti -1 !!!
16 switch(m_pExpression[m_nTree][m_iPosition])
17 {
18 case ADD:
19 evaluate_array(d1);
20 evaluate_array(d2);
21 for(i=m_iOffset; i<m_iEnd; i++)
22 dResult[pIndex[i]] = d1[pIndex[i]] + d2[pIndex[i]];
23 break;
24 case SUB:
25 evaluate_array(d1);
26 evaluate_array(d2);
27 for(i=m_iOffset; i<m_iEnd; i++)
28 dResult[pIndex[i]] = d1[pIndex[i]] - d2[pIndex[i]];
29 break;
30 case MUL:
31 evaluate_array(d1);
32 evaluate_array(d2);
33 for(i=m_iOffset; i<m_iEnd; i++)
34 dResult[pIndex[i]] = d1[pIndex[i]] * d2[pIndex[i]];
35 break;
36 case DIV:
37 evaluate_array(d1);
38 evaluate_array(d2);
39 for(i=m_iOffset; i<m_iEnd; i++)
40 { if(fabs(d2[pIndex[i]]) < 0.000001)
41 dResult[pIndex[i]] = 1;
42 else
43 dResult[pIndex[i]] = d1[pIndex[i]] / d2[pIndex[i]];
44 }
45 break;
46 case POS:
47 evaluate_array(d1);
48 for(i=m_iOffset; i<m_iEnd; i++)
49 if(d1[pIndex[i]] > 0)
50 dResult[pIndex[i]] = d1[pIndex[i]];
51 else
52 dResult[pIndex[i]] = 0;
53 break;
54 case SIN:
55 evaluate_array(d1);
56 for(i=m_iOffset; i<m_iEnd; i++)
57 dResult[pIndex[i]] = sin(d1[pIndex[i]]);
58 break;
59 case COS:
60 evaluate_array(d1);
61 for(i=m_iOffset; i<m_iEnd; i++)
62 dResult[pIndex[i]] = cos(d1[pIndex[i]]);
63 break;
64 case EXP:
65 evaluate_array(d1);
66 for(i=m_iOffset; i<m_iEnd; i++)
67 if(d1[pIndex[i]] < 80.)
68 dResult[pIndex[i]] = cos(d1[pIndex[i]]);
69 else
70 dResult[pIndex[i]] = 1;
71 break;
72 case LOG:
73 evaluate_array(d1);
74 for(i=m_iOffset; i<m_iEnd; i++)
75 if(fabs(d1[pIndex[i]]) > 0.000001)
76 dResult[pIndex[i]] = log(fabs(d1[pIndex[i]]));
77 else
78 dResult[pIndex[i]] = 1;
79 break;
80 case SQR:
81 evaluate_array(d1);
82 for(i=m_iOffset; i<m_iEnd; i++)
83 if(d1[pIndex[i]] < 0)
84 dResult[pIndex[i]] = 1;
85 else
86 dResult[pIndex[i]] = sqrt(d1[pIndex[i]]);
87 break;
88 case IFGT:
89 evaluate_array(d1);
90 evaluate_array(d2);
91 evaluate_array(d3);
92 evaluate_array(d4);
93 for(i=m_iOffset; i<m_iEnd; i++)
94 if(d1[pIndex[i]] > d2[pIndex[i]])
95 dResult[pIndex[i]] = d3[pIndex[i]];
96 else
97 dResult[pIndex[i]] = d4[pIndex[i]];
98 break;
99 default: // terminal
100 memcpy(dResult, m_dTermValuesArray[m_pExpression[m_nTree][m_iPosition]], m_iArraySize*sizeof(double));
101 break;
102 }
103}
104
105
106double RPN::evaluate()
107{
108 double d1,d2;
109 m_iPosition++; // pomicemo se na sljedeci simbol; pocetna vrijednost mora biti -1 !!!
110 switch(m_pExpression[m_nTree][m_iPosition])
111 {
112 case ADD:
113 return evaluate() + evaluate();
114 break;
115 case SUB:
116 return evaluate() - evaluate();
117 break;
118 case MUL:
119 return evaluate() * evaluate();
120 break;
121 case DIV:
122 d1 = evaluate();
123 d2 = evaluate();
124 if(fabs(d2) < 0.000001)
125 return 1;
126 else
127 return d1/d2;
128 break;
129 case POS:
130 d1 = evaluate();
131 if(d1 > 0)
132 return d1;
133 else
134 return 0;
135 break;
136 default: // terminal
137 return m_pTermValues[m_pExpression[m_nTree][m_iPosition]];
138 break;
139 }
140}
141
142int RPN::edit()
143{
144 int r1,r2;
145 uint iCurrent,iOp1,iOp2,i;
146 m_iPosition++; // pomicemo se na sljedeci simbol; pocetna vrijednost mora biti -1 !!!
147 iCurrent = ++m_iEditedPos; // usput pamtimo gdje smo u edited polju
148 m_pEdited[m_iEditedPos] = m_pExpression[m_nTree][m_iPosition]; // prepisujemo tekuci simbol
149 switch(m_pExpression[m_nTree][m_iPosition])
150 {
151 case ADD:
152 r1 = edit(); iOp1 = m_iEditedPos;
153 r2 = edit(); iOp2 = m_iEditedPos;
154 if(r1==NUL) // 0+A = A
155 { for(i=0; i<iOp2-iOp1; i++)
156 m_pEdited[iCurrent+i] = m_pEdited[iOp1+1+i];
157 m_iEditedPos = m_iEditedPos - (iOp1 - iCurrent) - 1;
158 return r2;
159 }
160 else if(r2==NUL) // A+0 = A
161 { for(i=0; i<iOp1-iCurrent; i++)
162 m_pEdited[iCurrent+i] = m_pEdited[iCurrent+i+1];
163 m_iEditedPos = m_iEditedPos - (iOp2 - iOp1) - 1;
164 return r1;
165 }
166 else
167 return ADD;
168 break;
169 case SUB:
170 r1 = edit(); iOp1 = m_iEditedPos;
171 r2 = edit(); iOp2 = m_iEditedPos;
172#ifdef STARO
173 if(r1<100 && r1==r2) // ovo je bilo prije; krivo! 27.07.
174#else
175 if(r1<m_iTermNum && r1==r2) // A-A = 0
176#endif
177 { m_iEditedPos = iCurrent;
178 m_pEdited[m_iEditedPos] = NUL;
179 return NUL;
180 }
181 else if(r2==NUL) // A-0 = A
182 { for(i=0; i<iOp1-iCurrent; i++)
183 m_pEdited[iCurrent+i] = m_pEdited[iCurrent+i+1];
184 m_iEditedPos = m_iEditedPos - (iOp2 - iOp1) - 1;
185 return r1;
186 }
187 // prosirenje za simbolicku jednakost A-A
188 else if(r1==r2 && (iOp1-iCurrent)==(iOp2-iOp1))
189 { for(i=0; i<iOp2-iOp1; i++)
190 if(m_pEdited[iCurrent+1+i] != m_pEdited[iOp1+1+i])
191 break;
192 if(i != iOp2-iOp1) // neuspjeh...
193 return SUB;
194 m_iEditedPos = iCurrent; // uspjeh!!
195 m_pEdited[m_iEditedPos] = NUL;
196 return NUL;
197 }
198 else
199 return SUB;
200 break;
201 case MUL:
202 r1 = edit(); iOp1 = m_iEditedPos;
203 r2 = edit(); iOp2 = m_iEditedPos;
204 if(r1==ONE) // 1*A = A
205 { for(i=0; i<iOp2-iOp1; i++)
206 m_pEdited[iCurrent+i] = m_pEdited[iOp1+1+i];
207 m_iEditedPos = m_iEditedPos - (iOp1 - iCurrent) - 1;
208 return r2;
209 }
210 else if(r2==ONE) // A*1 = A
211 { for(i=0; i<iOp1-iCurrent; i++)
212 m_pEdited[iCurrent+i] = m_pEdited[iCurrent+i+1];
213 m_iEditedPos = m_iEditedPos - (iOp2 - iOp1) - 1;
214 return r1;
215 }
216#ifndef STARO
217 // dodano 27.07.
218 else if(r1==NUL || r2==NUL) // A*0 = 0*A = 0
219 { m_iEditedPos = iCurrent;
220 m_pEdited[m_iEditedPos] = NUL;
221 return NUL;
222 }
223#endif
224 else
225 return MUL;
226 break;
227 case DIV:
228 r1 = edit(); iOp1 = m_iEditedPos;
229 r2 = edit(); iOp2 = m_iEditedPos;
230#ifdef STARO
231 if(r1<100 && r1==r2) // ovo je bilo prije; krivo! 27.07.
232#else
233 if(r1<m_iTermNum && r1==r2) // A/A = 1
234#endif
235 { m_iEditedPos = iCurrent;
236 m_pEdited[m_iEditedPos] = ONE;
237 return ONE;
238 }
239 // prosirenje za simbolicku jednakost A/A
240 else if(r1==r2 && (iOp1-iCurrent)==(iOp2-iOp1))
241 { for(i=0; i<iOp2-iOp1; i++)
242 if(m_pEdited[iCurrent+1+i] != m_pEdited[iOp1+1+i])
243 break;
244 if(i != iOp2-iOp1) // neuspjeh...
245 return DIV;
246 m_iEditedPos = iCurrent; // uspjeh!!
247 m_pEdited[m_iEditedPos] = ONE;
248 return ONE;
249 }
250 else if(r2 == NUL) // A/0 = 1
251 { m_iEditedPos = iCurrent;
252 m_pEdited[m_iEditedPos] = ONE;
253 return ONE;
254 }
255#ifndef STARO
256 // dodano 27.07.
257 else if(r2 == ONE) // A/1 = A
258 { for(i=0; i<iOp1-iCurrent; i++)
259 m_pEdited[iCurrent+i] = m_pEdited[iCurrent+i+1];
260 m_iEditedPos = m_iEditedPos - (iOp2 - iOp1) - 1;
261 return r1;
262 }
263 else if(r1 == NUL) // 0/A = 0
264 { m_iEditedPos = iCurrent;
265 m_pEdited[m_iEditedPos] = NUL;
266 return NUL;
267 }
268#endif
269 else
270 return DIV;
271 break;
272 case POS:
273 r1 = edit();
274 // POS(0) = 0, POS(1) = 1
275 // a i svi ostali terminali (do T_age) su po definiciji pozitivne vrijednosti
276 if(r1 <= TERMINALS + OFFSET)
277 { m_iEditedPos = iCurrent;
278 m_pEdited[m_iEditedPos] = r1;
279 return r1;
280 }
281 else // ako je ispod funkcija, nista
282 return POS;
283 break;
284 case SQR:
285 r1 = edit();
286 // SQR(0,1) = 0,1
287 if(r1 == NUL || r1 == ONE)
288 { m_iEditedPos = iCurrent;
289 m_pEdited[m_iEditedPos] = r1;
290 return r1;
291 }
292 else
293 return SQR;
294 break;
295 case IFGT:
296 r1 = edit();
297 r1 = edit();
298 r1 = edit();
299 r1 = edit();
300 return IFGT;
301 break;
302 default: // terminal
303 return m_pExpression[m_nTree][m_iPosition];
304 break;
305 }
306}
307
308// kopira editirani izraz u izvorni
309// usput prebroji terminale!
310void RPN::copy()
311{
312 // obrisi brojace od prosle jedinke
313 for(int i = 0; i<TOTAL_NODES; i++)
314 if(Nodes[i].active)
315 m_pNodeFreq[i] = 0;
316 // prebroji za ovoga i kumulativno
317 for(int i = 0; i<m_iEditedPos+1; i++)
318 { Nodes[m_pEdited[i]].frequency++;
319 m_pNodeFreq[m_pEdited[i]] += 1;
320 m_pExpression[m_nTree][i] = m_pEdited[i];
321 }
322}
323
324// broj terminala postavlja na nulu
325void RPN::ResetNodeFreq()
326{
327 int i;
328 for(i = 0; i<TERMINALS+OFFSET; i++)
329 Nodes[i].frequency = 0;
330 for(i = FUNC_START; i<FUNC_END; i++)
331 Nodes[i].frequency = 0;
332}
333
334// ispis stabla u infix notaciji
335void RPN::write()
336{
337 m_output = " ";
338 m_iPosition = -1;
339 r_write();
340}
341
342void RPN::r_write()
343{
344 m_iPosition++; // pomicemo se na sljedeci simbol; pocetna vrijednost mora biti -1 !!!
345 switch(m_pExpression[m_nTree][m_iPosition])
346 {
347 case ADD:
348 m_output += "(";
349 r_write();
350 m_output += "+";
351 r_write();
352 m_output += ")";
353 break;
354 case SUB:
355 m_output += "(";
356 r_write();
357 m_output += "-";
358 r_write();
359 m_output += ")";
360 break;
361 case MUL:
362 m_output += "(";
363 r_write();
364 m_output += "*";
365 r_write();
366 m_output += ")";
367 break;
368 case DIV:
369 m_output += "(";
370 r_write();
371 m_output += "/";
372 r_write();
373 m_output += ")";
374 break;
375 case POS:
376 m_output += "pos(";
377 r_write();
378 m_output += ")";
379 break;
380 case SQR:
381 m_output += "sqr(";
382 r_write();
383 m_output += ")";
384 break;
385 default: // terminal
386 //itoa(m_pExpression[m_nTree][m_iPosition],pom,10);
387 m_output += Nodes[m_pExpression[m_nTree][m_iPosition]].name;
388 break;
389 }
390}