00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "DataFunc.h"
00036
00037 #include <string>
00038 #include <cmath>
00039 #include <iostream>
00040
00041
00042 CDataFunc::op *(CDataFunc::ops) = NULL;
00043 int CDataFunc::nOps = 0;
00044 int CDataFunc::instances = 0;
00045
00046
00047 #define BUILDOP(str, pres, lass, arg) ops[i].tag = new char[strlen(str)+1]; \
00048 strcpy(ops[i].tag, str); \
00049 ops[i].tag[strlen(str)] = '\0'; \
00050 ops[i].precedence = pres; \
00051 ops[i].lassociative = lass; \
00052 ops[i].args = arg; \
00053 ++i;
00054
00055
00056
00057
00058
00059 CDataFunc::CDataFunc()
00060 {
00061 valid = true;
00062 nValues = 0;
00063 nQueue = 0;
00064 values = NULL;
00065 queue = NULL;
00066 if (instances == 0)
00067 {
00068 int i = 0;
00069 ops = new op[100];
00070
00071
00072
00073
00074 BUILDOP("r", -1, true, 0)
00075 BUILDOP("(", 12, false, 0)
00076 BUILDOP(")", 11, true, 0)
00077
00078 BUILDOP("v", -1, true, 0)
00079 BUILDOP("-", 1, true, 2)
00080 BUILDOP("+", 1, true, 2)
00081 BUILDOP("*", 3, true, 2)
00082 BUILDOP("/", 3, true, 2)
00083 BUILDOP("^", 4, false, 2)
00084 BUILDOP("exp", 5, false, 1)
00085 BUILDOP("cos", 6, false, 1)
00086 BUILDOP("sin", 6, false, 1)
00087 BUILDOP("tan", 6, false, 1)
00088 BUILDOP("pi", -1, true, 0)
00089 BUILDOP("x", -1, true, 0)
00090 BUILDOP("y", -1, true, 0)
00091 BUILDOP("z", -1, true, 0)
00092 BUILDOP("abs", 6, false, 1)
00093 BUILDOP("blend", 6, false, 3)
00094 BUILDOP("clamp", 6, false, 3)
00095 BUILDOP("large", 6, false, 2)
00096 BUILDOP("small", 6, false, 2)
00097 BUILDOP("select", 6, false, 4)
00098 BUILDOP("int", 6, false, 1)
00099 BUILDOP("col", 9, false, 1)
00100 BUILDOP("plane", 6, false, 4)
00101 BUILDOP("NEGATE", 0, false, 1)
00102 BUILDOP("hsl", 6, false, 1)
00103 BUILDOP("hsr", 6, false, 1)
00104 BUILDOP("acos", 6, false, 1)
00105 BUILDOP("asin", 6, false, 1)
00106 BUILDOP("atan", 6, false, 1)
00107 BUILDOP("cosh", 6, false, 1)
00108 BUILDOP("sinh", 6, false, 1)
00109 BUILDOP("tanh", 6, false, 1)
00110 BUILDOP("log", 6, false, 1)
00111 BUILDOP("ln", 6, false, 1)
00112 BUILDOP("th", 6, false, 2)
00113
00114 nOps = i;
00115 }
00116 ++instances;
00117 }
00118
00119
00120
00121
00122
00123
00124 CDataFunc::~CDataFunc()
00125 {
00126 --instances;
00127 if (instances == 0)
00128 {
00129 int i;
00130 for (i = 0; i < nOps; ++i)
00131 delete[] ops[i].tag;
00132 delete[] ops;
00133 }
00134
00135
00136 if (queue != NULL) delete[] queue;
00137 if (values != NULL) delete[] values;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146 int CDataFunc::FindTagID(char *string)
00147 {
00148 int i;
00149 for (i = 0; i < nOps; ++i)
00150 if (strcmp(string, ops[i].tag) == 0)
00151 return(i);
00152 return(-1);
00153 }
00154
00155
00156
00157 #define NONNUMBER " \n,abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ!\"£$%^&*()-=+:;\'@#~<>/?\\|`¬[]{}"
00158
00159
00160
00161
00162
00163
00164 CDataFunc::status CDataFunc::InfixToRPN(char *input)
00165 {
00166 nQueue = 0;
00167 nValues = 0;
00168 valid = false;
00169 char prevNonSpace = 0;
00170
00171 token *stack;
00172 stack = new token;
00173 token *top = stack;
00174 top->tagid = -1;
00175 top->prev = NULL;
00176 top->next = NULL;
00177
00178 token *opstack = new token;
00179 token *topop = opstack;
00180 topop->tagid = -1;
00181 topop->next = NULL;
00182 topop->prev = NULL;
00183
00184 char *strptr = input;
00185
00186 while (strptr[0] != '\0')
00187 {
00188 if (strptr[0] == '$')
00189 {
00190 int eov = strcspn(&strptr[1], "+-/* ()^,");
00191 char *readtag = new char[eov+1];
00192 strncpy(readtag, &strptr[1], eov);
00193 readtag[eov] = '\0';
00194
00195 top->next = new token;
00196 top->next->next = NULL;
00197 top->next->prev = top;
00198 top = top->next;
00199 top->value = 0.0;
00200 top->tagid = FindTagID(readtag);
00201 delete[] readtag;
00202 if (top->tagid == -1) return(UNKNOWN_TAG);
00203 prevNonSpace = strptr[eov];
00204 strptr = &strptr[eov+1];
00205 ++nValues;
00206 ++nQueue;
00207 }
00208 else if (((strptr[0] >= '0') && (strptr[0] <= '9')) || (strptr[0] == '.'))
00209 {
00210 int eov = strcspn(&strptr[0], NONNUMBER);
00211 if ((strptr[eov] == 'e') || (strptr[eov] == 'E'))
00212 {
00213 if (strptr[eov+1] == '-')
00214 eov += 2+strcspn(&strptr[eov+2], NONNUMBER);
00215 else if (strptr[eov+1] == '+')
00216 eov += 2+strcspn(&strptr[eov+2], NONNUMBER);
00217 else if ((strptr[eov+1] >= '0') && (strptr[eov+1] <= '9'))
00218 eov += 1+strcspn(&strptr[eov+1], NONNUMBER);
00219 }
00220 char *readtag = new char[eov+1];
00221 strncpy(readtag, &strptr[0], eov);
00222 readtag[eov] = '\0';
00223
00224 top->next = new token;
00225 top->next->next = NULL;
00226 top->next->prev = top;
00227 top = top->next;
00228 top->tagid = FindTagID("v\0");
00229 top->value = atof(readtag);
00230 delete[] readtag;
00231 if (top->tagid == -1) return(UNKNOWN_TAG);
00232 prevNonSpace = strptr[eov-1];
00233 strptr = &strptr[eov];
00234 ++nValues;
00235 ++nQueue;
00236 }
00237 else if (strptr[0] == '(')
00238 {
00239 topop->next = new token;
00240 topop->next->next = NULL;
00241 topop->next->prev = topop;
00242 topop = topop->next;
00243 topop->tagid = 1;
00244 prevNonSpace = strptr[0];
00245 strptr = &strptr[1];
00246 }
00247 else if (strptr[0] == ')')
00248 {
00249 while (topop->tagid != 1)
00250 {
00251 if (topop->tagid == -1) return(UNMATCHED_PARENTHESES);
00252 top->next = new token;
00253 top->next->next = NULL;
00254 top->next->prev = top;
00255 top = top->next;
00256 top->value = 0.0;
00257 top->tagid = topop->tagid;
00258 topop = topop->prev;
00259 delete topop->next;
00260 topop->next = NULL;
00261 }
00262 topop = topop->prev;
00263 delete topop->next;
00264 topop->next = NULL;
00265 prevNonSpace = strptr[0];
00266 strptr = &strptr[1];
00267 }
00268 else if (strcspn(&strptr[0], "+-*/^") == 0)
00269 {
00270 char *readtag = new char[2];
00271 readtag[0] = strptr[0];
00272 readtag[1] = '\0';
00273
00274
00275 if (readtag[0] == '-')
00276 {
00277 if ((prevNonSpace == '(') || (prevNonSpace == ',') || (prevNonSpace == '*') || (prevNonSpace == '/') || (prevNonSpace == '^') || (prevNonSpace == 0))
00278 {
00279 delete[] readtag;
00280 readtag = new char[7];
00281 strcpy(readtag, "NEGATE");
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 }
00305 }
00306
00307
00308 int tagid = FindTagID(readtag);
00309 delete[] readtag;
00310 if (tagid == -1) return(UNKNOWN_TAG);
00311
00312 while (((topop->tagid != -1) && (topop->tagid != 1) && (topop->tagid != 3)) &&
00313 (((ops[tagid].lassociative == true) && (ops[tagid].precedence <= ops[topop->tagid].precedence)) ||
00314 ((ops[tagid].lassociative == false) && (ops[tagid].precedence < ops[topop->tagid].precedence))))
00315 {
00316 top->next = new token;
00317 top->next->next = NULL;
00318 top->next->prev = top;
00319 top = top->next;
00320 top->tagid = topop->tagid;
00321 top->value = topop->value;
00322 topop = topop->prev;
00323 delete topop->next;
00324 topop->next = NULL;
00325 }
00326 topop->next = new token;
00327 topop->next->next = NULL;
00328 topop->next->prev = topop;
00329 topop = topop->next;
00330 topop->value = 0.0;
00331 topop->tagid = tagid;
00332 prevNonSpace = strptr[0];
00333 strptr = &strptr[1];
00334 ++nQueue;
00335 }
00336 else if (strptr[0] == ',')
00337 {
00338 while (topop->tagid != 1)
00339 {
00340 if (topop->tagid == -1) return(INVALID_SEPARATOR);
00341 top->next = new token;
00342 top->next->next = NULL;
00343 top->next->prev = top;
00344 top = top->next;
00345 top->value = 0.0;
00346 top->tagid = topop->tagid;
00347 topop = topop->prev;
00348 delete topop->next;
00349 topop->next = NULL;
00350 }
00351
00352 prevNonSpace = strptr[0];
00353 strptr = &strptr[1];
00354 }
00355 else if ((strptr[0] != ' ') && (strptr[0] != '\t') && (strptr[0] != '\n'))
00356 {
00357 int eov = strcspn(&strptr[0], "0123456789. ()");
00358 char *readtag = new char[eov+1];
00359 strncpy(readtag, strptr, eov);
00360 readtag[eov] = '\0';
00361
00362 int tagid = FindTagID(readtag);
00363 delete[] readtag;
00364 if (tagid == -1) return(UNKNOWN_TAG);
00365
00366 while (((topop->tagid != -1) && (topop->tagid != 1) && (topop->tagid != 3)) &&
00367 (((ops[tagid].lassociative == true) && (ops[tagid].precedence <= ops[topop->tagid].precedence)) ||
00368 ((ops[tagid].lassociative == false) && (ops[tagid].precedence < ops[topop->tagid].precedence))))
00369 {
00370 top->next = new token;
00371 top->next->next = NULL;
00372 top->next->prev = top;
00373 top = top->next;
00374 top->tagid = topop->tagid;
00375 top->value = topop->value;
00376 topop = topop->prev;
00377 delete topop->next;
00378 topop->next = NULL;
00379 }
00380 topop->next = new token;
00381 topop->next->next = NULL;
00382 topop->next->prev = topop;
00383 topop = topop->next;
00384 topop->value = 0.0;
00385 topop->tagid = tagid;
00386 prevNonSpace = strptr[eov-1];
00387 strptr = &strptr[eov];
00388 ++nQueue;
00389 }
00390 else
00391 strptr = &strptr[1];
00392 }
00393 while (topop->tagid != -1)
00394 {
00395 if (topop->tagid == 1) return(UNMATCHED_PARENTHESES);
00396 top->next = new token;
00397 top->next->next = NULL;
00398 top->next->prev = top;
00399 top = top->next;
00400 top->tagid = topop->tagid;
00401 top->value = 0.0;
00402 topop = topop->prev;
00403 delete topop->next;
00404 topop->next = NULL;
00405 }
00406 delete topop;
00407
00408
00409 if (queue != NULL) delete[] queue;
00410 if (values != NULL) delete[] values;
00411 queue = NULL;
00412 values = NULL;
00413 if (nQueue != 0)
00414 queue = new token[nQueue];
00415 if (nValues != 0)
00416 {
00417 values = new real[nValues];
00418 }
00419 top = stack->next;
00420 int i;
00421 for (i = 0; i < nQueue; ++i)
00422 {
00423 queue[i].tagid = top->tagid;
00424 queue[i].value = top->value;
00425
00426 top = top->next;
00427 }
00428 top = stack;
00429 while (top->next != NULL)
00430 {
00431 top = top->next;
00432 delete top->prev;
00433 }
00434 delete top;
00435
00436 return(TestEvaluate());
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 double CDataFunc::Evaluate(double x, double y, double z, int cols, double coldata[])
00451 {
00452 int val = 0, i;
00453 for (i = 0; i < nQueue; ++i)
00454 {
00455 switch (queue[i].tagid)
00456 {
00457
00458
00459
00460 case 3:
00461 {
00462 values[val] = queue[i].value;
00463 ++val;
00464 }
00465 break;
00466 case 4:
00467 {
00468 --val;
00469 values[val-1] = values[val-1]-values[val];
00470 }
00471 break;
00472 case 5:
00473 {
00474 --val;
00475 values[val-1] = values[val-1]+values[val];
00476 }
00477 break;
00478 case 6:
00479 {
00480 --val;
00481 values[val-1] = values[val-1]*values[val];
00482 }
00483 break;
00484 case 7:
00485 {
00486 --val;
00487 values[val-1] = values[val-1]/values[val];
00488 }
00489 break;
00490 case 8:
00491 {
00492 --val;
00493 values[val-1] = pow(values[val-1], values[val]);
00494 }
00495 break;
00496 case 9:
00497 {
00498 values[val-1] = exp(values[val-1]);
00499 }
00500 break;
00501 case 10:
00502 {
00503 values[val-1] = cos(values[val-1]);
00504 }
00505 break;
00506 case 11:
00507 {
00508 values[val-1] = sin(values[val-1]);
00509 }
00510 break;
00511 case 12:
00512 {
00513 values[val-1] = tan(values[val-1]);
00514 }
00515 break;
00516 case 13:
00517 {
00518 values[val] = PI;
00519 ++val;
00520 }
00521 break;
00522 case 14:
00523 {
00524 values[val] = x;
00525 ++val;
00526 }
00527 break;
00528 case 15:
00529 {
00530 values[val] = y;
00531 ++val;
00532 }
00533 break;
00534 case 16:
00535 {
00536 values[val] = z;
00537 ++val;
00538 }
00539 break;
00540 case 17:
00541 {
00542 values[val-1] = fabs(values[val-1]);
00543 }
00544 break;
00545 case 18:
00546 {
00547 val -= 2;
00548 values[val-1] = values[val-1]*(1-values[val+1])+values[val]*values[val+1];
00549 }
00550 break;
00551 case 19:
00552 {
00553 val -= 2;
00554 if (values[val-1] < values[val])
00555 values[val-1] = values[val];
00556 else if (values[val-1] > values[val+1])
00557 values[val-1] = values[val+1];
00558
00559 }
00560 break;
00561 case 20:
00562 {
00563 --val;
00564 if (values[val-1] < values[val])
00565 values[val-1] = values[val];
00566 }
00567 break;
00568 case 21:
00569 {
00570 --val;
00571 if (values[val-1] > values[val])
00572 values[val-1] = values[val];
00573 }
00574 break;
00575 case 22:
00576 {
00577 val -= 3;
00578 if (values[val+1] > values[val+2])
00579 values[val-1] = values[val];
00580 }
00581 break;
00582 case 23:
00583 {
00584 values[val-1] = (real)((int)(values[val-1]));
00585 }
00586 break;
00587 case 24:
00588 {
00589 if (values[val-1] > (cols-1))
00590 return(1e-100);
00591 values[val-1] = coldata[(int)(values[val-1])];
00592 }
00593 break;
00594 case 25:
00595 {
00596 val -= 3;
00597 values[val-1] = (0.0-values[val+2]-values[val-1]*x-values[val]*y)/values[val+1];
00598 }
00599 break;
00600 case 26:
00601 {
00602 values[val-1] = -values[val-1];
00603 }
00604 break;
00605 case 27:
00606 {
00607 if (values[val-1] <= 0.0)
00608 values[val-1] = 1.0;
00609 else
00610 values[val-1] = 0.0;
00611 }
00612 break;
00613 case 28:
00614 {
00615 if (values[val-1] >= 0.0)
00616 values[val-1] = 1.0;
00617 else
00618 values[val-1] = 0.0;
00619 }
00620 break;
00621 case 29:
00622 {
00623 values[val-1] = acos(values[val-1]);
00624 }
00625 break;
00626 case 30:
00627 {
00628 values[val-1] = asin(values[val-1]);
00629 }
00630 break;
00631 case 31:
00632 {
00633 values[val-1] = atan(values[val-1]);
00634 }
00635 break;
00636 case 32:
00637 {
00638 values[val-1] = cosh(values[val-1]);
00639 }
00640 break;
00641 case 33:
00642 {
00643 values[val-1] = sinh(values[val-1]);
00644 }
00645 break;
00646 case 34:
00647 {
00648 values[val-1] = tanh(values[val-1]);
00649 }
00650 break;
00651 case 35:
00652 {
00653 values[val-1] = log10(values[val-1]);
00654 }
00655 break;
00656 case 36:
00657 {
00658 values[val-1] = log(values[val-1]);
00659 }
00660 break;
00661 case 37:
00662 {
00663 --val;
00664 if ((values[val-1] >= 0.0) && (values[val] <= 0))
00665 values[val-1] = 1.0;
00666 else
00667 values[val-1] = 0.0;
00668 }
00669 break;
00670 }
00671 }
00672 return(values[val-1]);
00673 }
00674
00675
00676
00677
00678
00679
00680
00681 CDataFunc::status CDataFunc::TestEvaluate(void)
00682 {
00683 int val = 0, i;
00684 for (i = 0; i < nQueue; ++i)
00685 {
00686 val -= ops[queue[i].tagid].args;
00687 if (val < 0)
00688 return(TOO_FEW_VARS);
00689 ++val;
00690 }
00691 if (val < 1)
00692 return(TOO_FEW_VARS);
00693 valid = true;
00694 return(OK);
00695 }