Log In | Get Help   
Home My Page Projects Code Snippets Project Openings Mareframe
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files
[mareframe] Annotation of /trunk/gadget/formula.cc
[mareframe] / trunk / gadget / formula.cc Repository:
ViewVC logotype

Annotation of /trunk/gadget/formula.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (view) (download)

1 : agomez 1 #include "formula.h"
2 :     #include "errorhandler.h"
3 :     #include "mathfunc.h"
4 :     #include "gadget.h"
5 :     #include "global.h"
6 :    
7 :     Formula::Formula() {
8 :     value = 0.0;
9 :     type = CONSTANT;
10 :     functiontype = NONE;
11 :     }
12 :    
13 :     Formula::Formula(double initial) {
14 :     value = initial;
15 :     type = CONSTANT;
16 :     functiontype = NONE;
17 :     }
18 :    
19 :     Formula::~Formula() {
20 :     unsigned int i;
21 :     for (i = 0; i < argList.size(); i++)
22 :     delete argList[i];
23 :     }
24 :    
25 :     Formula::Formula(FunctionType ft, vector<Formula*> formlist) {
26 :     if (formlist.size() <= 0)
27 :     handle.logMessage(LOGFAIL, "Error in formula - no formula given in parameter list");
28 :    
29 :     value = 0.0;
30 :     type = FUNCTION;
31 :     functiontype = ft;
32 :     unsigned int i;
33 :     for (i = 0; i < formlist.size(); i++) {
34 :     Formula *f = new Formula(*formlist[i]);
35 :     argList.push_back(f);
36 :     }
37 :     }
38 :    
39 :     Formula::operator double() const {
40 :     switch (type) {
41 :     case CONSTANT:
42 :     case PARAMETER:
43 :     return value;
44 :     break;
45 :     case FUNCTION:
46 :     double v;
47 :     v = this->evalFunction();
48 :     return v;
49 :     break;
50 :     default:
51 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
52 :     break;
53 :     }
54 :     // JMB need to return something here even though this never happens
55 :     return value;
56 :     }
57 :    
58 :     double Formula::evalFunction() const {
59 :     double v = 0.0;
60 :     unsigned int i;
61 :     switch (functiontype) {
62 :     case NONE:
63 :     handle.logMessage(LOGFAIL, "Error in formula - no function type found");
64 :     break;
65 :    
66 :     case MULT:
67 :     v = 1.0;
68 :     for (i = 0; i < argList.size(); i++)
69 :     v *= *(argList[i]);
70 :     break;
71 :    
72 :     case DIV:
73 :     if (argList.size() == 0) {
74 :     v = 1.0;
75 :     } else if (argList.size() == 1) {
76 :     if (!isZero(*(argList[0]))) {
77 :     v = 1.0 / (*(argList[0]));
78 :     } else {
79 :     handle.logMessage(LOGWARN, "Warning in formula - divide by zero");
80 :     }
81 :     } else {
82 :     v = *(argList[0]);
83 :     for (i = 1; i < argList.size(); i++) {
84 :     if (!isZero(*(argList[0]))) {
85 :     v /= *(argList[i]);
86 :     } else {
87 :     handle.logMessage(LOGWARN, "Warning in formula - divide by zero");
88 :     }
89 :     }
90 :     }
91 :     break;
92 :    
93 :     case PLUS:
94 :     v = 0.0;
95 :     for (i = 0; i < argList.size(); i++)
96 :     v += *(argList[i]);
97 :     break;
98 :    
99 :     case MINUS:
100 :     if (argList.size() == 0) {
101 :     v = 0.0;
102 :     } else if (argList.size() == 1) {
103 :     v = -(*(argList[0]));
104 :     } else {
105 :     v = *(argList[0]);
106 :     for (i = 1; i < argList.size(); i++)
107 :     v -= *(argList[i]);
108 :     }
109 :     break;
110 :    
111 :     case SIN: //JMB note that this works in radians
112 :     if (argList.size() != 1)
113 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for sin");
114 :     v = sin(*(argList[0]));
115 :     break;
116 :    
117 :     case COS: //JMB note that this works in radians
118 :     if (argList.size() != 1)
119 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for cos");
120 :     v = cos(*(argList[0]));
121 :     break;
122 :    
123 :     case LOG:
124 :     if (argList.size() != 1)
125 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for log");
126 :     if (*(argList[0]) < verysmall)
127 :     handle.logMessage(LOGWARN, "Warning in formula - cannot take log of zero");
128 :     else
129 :     v = log(*(argList[0]));
130 :     break;
131 :    
132 :     case EXP:
133 :     if (argList.size() != 1)
134 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for exp");
135 :     v = exp(*(argList[0]));
136 :     break;
137 :    
138 :     case LOG10:
139 :     if (argList.size() != 1)
140 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for log10");
141 :     if (*(argList[0]) < verysmall)
142 :     handle.logMessage(LOGWARN, "Warning in formula - cannot take log10 of zero");
143 :     else
144 :     v = log10(*(argList[0]));
145 :     break;
146 :    
147 :     case POWER:
148 :     if (argList.size() == 1)
149 :     v = pow(10.0, *(argList[0]));
150 :     else if (argList.size() == 2)
151 :     v = pow(*(argList[0]), *(argList[1]));
152 :     else
153 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for power");
154 :     break;
155 :    
156 :     case SQRT:
157 :     if (argList.size() != 1)
158 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for sqrt");
159 :     if (*(argList[0]) < 0.0)
160 :     handle.logMessage(LOGWARN, "Warning in formula - cannot take sqrt of negative number");
161 :     else
162 :     v = sqrt(*(argList[0]));
163 :     break;
164 :    
165 :     case RAND:
166 :     if (argList.size() != 1)
167 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for rand");
168 :     v = *(argList[0]);
169 :     break;
170 :    
171 :     case LESS:
172 :     if (argList.size() < 2)
173 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for <");
174 :     v = 1.0;
175 :     for (i = 1; i < argList.size(); i++)
176 :     if (*(argList[i - 1]) >= *(argList[i]))
177 :     v = 0.0;
178 :     break;
179 :    
180 :     case GREATER:
181 :     if (argList.size() < 2)
182 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for >");
183 :     v = 1.0;
184 :     for (i = 1; i < argList.size(); i++)
185 :     if (*(argList[i - 1]) <= *(argList[i]))
186 :     v = 0.0;
187 :     break;
188 :    
189 :     case EQUAL:
190 :     if (argList.size() < 2)
191 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for =");
192 :     v = 1.0;
193 :     for (i = 1; i < argList.size(); i++)
194 :     if (!isEqual(*(argList[i - 1]), *(argList[i])))
195 :     v = 0.0;
196 :     break;
197 :    
198 :     case AND:
199 :     if (argList.size() < 1)
200 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for and");
201 :     v = 1.0;
202 :     for (i = 0; i < argList.size(); i++)
203 :     if (isZero(*(argList[i])))
204 :     v = 0.0;
205 :     break;
206 :    
207 :     case OR:
208 :     if (argList.size() < 1)
209 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for or");
210 :     v = 0.0;
211 :     for (i = 0; i < argList.size(); i++)
212 :     if (!isZero(*(argList[i])))
213 :     v = 1.0;
214 :     break;
215 :    
216 :     case NOT:
217 :     if (argList.size() != 1)
218 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for not");
219 :     v = 0.0;
220 :     if (isZero(*(argList[0])))
221 :     v = 1.0;
222 :     break;
223 :    
224 :     case ABS:
225 :     if (argList.size() != 1)
226 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for abs");
227 :     v = fabs(*(argList[0]));
228 :     break;
229 :    
230 :     case IF:
231 :     if (argList.size() != 3)
232 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for if");
233 :     v = 0.0;
234 :     if (isZero(*(argList[0])))
235 :     v = *(argList[2]);
236 :     else
237 :     v = *(argList[1]);
238 :     break;
239 :    
240 :     case PI:
241 :     if (argList.size() != 1)
242 :     handle.logMessage(LOGFAIL, "Error in formula - invalid number of parameters for pi");
243 :     v = *(argList[0]);
244 :     break;
245 :    
246 :     default:
247 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised function type", type);
248 :     break;
249 :     }
250 :    
251 :     return v;
252 :     }
253 :    
254 :     Formula::Formula(const Formula& initial) {
255 :     type = initial.type;
256 :     value = initial.value;
257 :     functiontype = initial.functiontype;
258 :     switch (type) {
259 :     case CONSTANT:
260 :     break;
261 :     case PARAMETER:
262 :     name = initial.name;
263 :     break;
264 :     case FUNCTION:
265 :     unsigned int i;
266 :     for (i = 0; i < initial.argList.size(); i++) {
267 :     Formula* f = new Formula(*initial.argList[i]);
268 :     argList.push_back(f);
269 :     }
270 :     break;
271 :     default:
272 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
273 :     break;
274 :     }
275 :     }
276 :    
277 :     void Formula::setValue(double init) {
278 :     if (type == FUNCTION)
279 :     handle.logMessage(LOGFAIL, "Error in formula - cannot set value for function");
280 :     value = init;
281 :     }
282 :    
283 :     CommentStream& operator >> (CommentStream& infile, Formula& F) {
284 :     if (F.type != CONSTANT)
285 :     handle.logFileMessage(LOGFAIL, "failed to read formula data");
286 :    
287 :     if (infile.fail())
288 :     return infile;
289 :    
290 :     /* Read formula expression. Syntax:
291 :     3.14 - Constant (CONSTANT)
292 :     #param - Single parameter, no initial value (PARAMETER)
293 :     1.0#param - Single value, initial value
294 :     (* #p1 #p2) - Function call (FUNCTION)
295 :     */
296 :    
297 :     infile >> ws;
298 :     char c = infile.peek();
299 :    
300 :     // Read FUNCTION
301 :     if (c == '(') {
302 :     infile.get(c);
303 :     F.type = FUNCTION;
304 :     // Read function 'name'
305 :     char text[MaxStrLength];
306 :     strncpy(text, "", MaxStrLength);
307 :     infile >> ws >> text >> ws;
308 :     if (strcasecmp(text, "*") == 0) {
309 :     F.functiontype = MULT;
310 :    
311 :     } else if (strcasecmp(text, "/") == 0) {
312 :     F.functiontype = DIV;
313 :    
314 :     } else if (strcasecmp(text, "+") == 0) {
315 :     F.functiontype = PLUS;
316 :    
317 :     } else if (strcasecmp(text, "-") == 0) {
318 :     F.functiontype = MINUS;
319 :    
320 :     } else if (strcasecmp(text, "sin") == 0) {
321 :     F.functiontype = SIN;
322 :    
323 :     } else if (strcasecmp(text, "cos") == 0) {
324 :     F.functiontype = COS;
325 :    
326 :     } else if ((strcasecmp(text, "log") == 0) || (strcasecmp(text, "ln") == 0)) {
327 :     F.functiontype = LOG;
328 :    
329 :     } else if (strcasecmp(text, "exp") == 0) {
330 :     F.functiontype = EXP;
331 :    
332 :     } else if (strcasecmp(text, "log10") == 0) {
333 :     F.functiontype = LOG10;
334 :    
335 :     } else if ((strcasecmp(text, "power") == 0) || (strcasecmp(text, "**") == 0)) {
336 :     F.functiontype = POWER;
337 :    
338 :     } else if (strcasecmp(text, "sqrt") == 0) {
339 :     F.functiontype = SQRT;
340 :    
341 :     } else if (strcasecmp(text, "rand") == 0) {
342 :     F.functiontype = RAND;
343 :     Formula* f = new Formula(randomNumber());
344 :     F.argList.push_back(f);
345 :     if (handle.getRunOptimise())
346 :     handle.logMessage(LOGWARN, "Warning in formula - random function used for optimising run");
347 :    
348 :     } else if (strcasecmp(text, "<") == 0) {
349 :     F.functiontype = LESS;
350 :    
351 :     } else if (strcasecmp(text, ">") == 0) {
352 :     F.functiontype = GREATER;
353 :    
354 :     } else if (strcasecmp(text, "=") == 0) {
355 :     F.functiontype = EQUAL;
356 :    
357 :     } else if (strcasecmp(text, "and") == 0) {
358 :     F.functiontype = AND;
359 :    
360 :     } else if (strcasecmp(text, "or") == 0) {
361 :     F.functiontype = OR;
362 :    
363 :     } else if (strcasecmp(text, "not") == 0) {
364 :     F.functiontype = NOT;
365 :    
366 :     } else if (strcasecmp(text, "abs") == 0) {
367 :     F.functiontype = ABS;
368 :    
369 :     } else if (strcasecmp(text, "if") == 0) {
370 :     F.functiontype = IF;
371 :     if (handle.getRunOptimise())
372 :     handle.logMessage(LOGWARN, "Warning in formula - if statement used for optimising run");
373 :    
374 :     } else if (strcasecmp(text, "pi") == 0) {
375 :     F.functiontype = PI;
376 :     Formula* f = new Formula(pivalue);
377 :     F.argList.push_back(f);
378 :    
379 :     } else {
380 :     handle.logFileMessage(LOGFAIL, "unrecognised formula function name", text);
381 :     return infile;
382 :     }
383 :    
384 :     c = infile.peek();
385 :     while (c != ')') {
386 :     Formula* f = new Formula();
387 :     infile >> *f;
388 :     F.argList.push_back(f);
389 :     infile >> ws;
390 :     if (infile.eof()) {
391 :     // Something has gone wrong, no closing bracket
392 :     handle.logFileMessage(LOGFAIL, "failed to read formula data");
393 :     return infile;
394 :     }
395 :     c = infile.peek();
396 :     }
397 :     infile.get(c);
398 :     return infile;
399 :     }
400 :    
401 :     // Read PARAMETER syntax (no initial value)
402 :     if (c == '#') {
403 :     //No initial value, parameter name only - set it to 1
404 :     F.value = 1.0;
405 :     F.type = PARAMETER;
406 :     infile.get(c);
407 :     infile >> F.name;
408 :     if (strlen(F.name.getName()) <= 0)
409 :     handle.logFileMessage(LOGFAIL, "failed to read parameter name");
410 :     return infile;
411 :     }
412 :    
413 :     if (!isdigit(c) && (c != '-')) //JMB check that we actually have a number to read
414 :     handle.logFileMessage(LOGFAIL, "failed to read formula data");
415 :    
416 :     // Read initial value (could be CONSTANT or PARAMETER)
417 :     if (!(infile >> F.value))
418 :     return infile;
419 :    
420 :     // then '#' if there is one
421 :     c = infile.peek();
422 :     if (infile.fail() && !infile.eof())
423 :     return infile;
424 :    
425 :     // Read CONSTANT
426 :     if ((c != '#') || infile.eof()) {
427 :     //If not '#' then return
428 :     F.type = CONSTANT;
429 :     return infile;
430 :     }
431 :    
432 :     // Read PARAMETER (with initial value)
433 :     if (c == '#') {
434 :     F.type = PARAMETER;
435 :     infile.get(c);
436 :     infile >> F.name;
437 :     if (strlen(F.name.getName()) <= 0)
438 :     handle.logFileMessage(LOGFAIL, "failed to read parameter name");
439 :     return infile;
440 :     }
441 :    
442 :     // If we get to here then things have failed
443 :     handle.logFileMessage(LOGFAIL, "failed to read formula data");
444 :     return infile;
445 :     }
446 :    
447 :     void Formula::Inform(Keeper* keeper) {
448 :     // let keeper know of the marked variables
449 :     switch (type) {
450 :     case CONSTANT:
451 :     break;
452 :     case PARAMETER:
453 :     // only one parameter
454 :     keeper->keepVariable(value, name);
455 :     break;
456 :     case FUNCTION:
457 :     // function with multiple parameters
458 :     unsigned int i;
459 :     for (i = 0; i < argList.size(); i++)
460 :     (*argList[i]).Inform(keeper);
461 :     break;
462 :     default:
463 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
464 :     break;
465 :     }
466 :     }
467 :    
468 :     void Formula::Interchange(Formula& newF, Keeper* keeper) const {
469 :     while (newF.argList.size() > 0)
470 :     newF.argList.pop_back();
471 :    
472 :     newF.type = type;
473 :     newF.value = value;
474 :     newF.functiontype = functiontype;
475 :     switch (type) {
476 :     case CONSTANT:
477 :     break;
478 :    
479 :     case PARAMETER:
480 :     newF.name = name;
481 :     keeper->changeVariable(value, newF.value);
482 :     break;
483 :    
484 :     case FUNCTION:
485 :     unsigned int i;
486 :     for (i = 0; i < argList.size(); i++) {
487 :     Formula* f = new Formula(*argList[i]);
488 :     newF.argList.push_back(f);
489 :     }
490 :     for (i = 0; i < argList.size(); i++)
491 :     (*argList[i]).Interchange(*newF.argList[i], keeper);
492 :     break;
493 :    
494 :     default:
495 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
496 :     break;
497 :     }
498 :     }
499 :    
500 :     void Formula::Delete(Keeper* keeper) const {
501 :     switch (type) {
502 :     case CONSTANT:
503 :     break;
504 :     case PARAMETER:
505 :     keeper->deleteParameter(value);
506 :     break;
507 :     case FUNCTION:
508 :     unsigned int i;
509 :     for (i = 0; i < argList.size(); i++)
510 :     (*argList[i]).Delete(keeper);
511 :     break;
512 :     default:
513 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
514 :     break;
515 :     }
516 :     }
517 :    
518 :     Formula& Formula::operator = (const Formula& F) {
519 :     type = F.type;
520 :     functiontype = F.functiontype;
521 :     value = F.value;
522 :     switch (type) {
523 :     case CONSTANT:
524 :     break;
525 :     case PARAMETER:
526 :     name = F.name;
527 :     break;
528 :     case FUNCTION:
529 :     unsigned int i;
530 :     for (i = 0; i < argList.size(); i++)
531 :     delete argList[i];
532 :     argList.clear();
533 :     for (i = 0; i < F.argList.size(); i++) {
534 :     Formula *f = new Formula(*F.argList[i]);
535 :     argList.push_back(f);
536 :     }
537 :     break;
538 :     default:
539 :     handle.logMessage(LOGFAIL, "Error in formula - unrecognised type", type);
540 :     break;
541 :     }
542 :     return *this;
543 :     }
544 :    

root@forge.cesga.es
ViewVC Help
Powered by ViewVC 1.0.0  

Powered By FusionForge