|
k-dot-p 0.1
|
00001 /* 00002 00003 00004 Copyright (C) 2009 Joseph Pingenot 00005 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU Affero General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Affero General Public License for more details. 00015 00016 You should have received a copy of the GNU Affero General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 */ 00020 00021 #include <math.h> 00022 #include <glib.h> 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <libmodelxx/function_specification.h++> 00026 00027 #define FUNCTION_SPECIFICATION_GERROR_DOMAIN 38 00028 00029 namespace kdotp { 00030 namespace libmodelxx { 00031 namespace postprocessing { 00032 00033 00034 enum function_op function_get_op_for_builtin_function(const char* bf) { 00035 if(!g_ascii_strncasecmp("exp", bf, 3)) { 00036 return EXP; 00037 }else if(!g_ascii_strncasecmp("cos", bf, 3)) { 00038 return COS; 00039 }else if(!g_ascii_strncasecmp("sin", bf, 3)) { 00040 return SIN; 00041 }else if(!g_ascii_strncasecmp("tan", bf, 3)) { 00042 return TAN; 00043 }else if(!g_ascii_strncasecmp("acos", bf, 4)) { 00044 return ACOS; 00045 }else if(!g_ascii_strncasecmp("asin", bf, 4)) { 00046 return ASIN; 00047 }else if(!g_ascii_strncasecmp("atan", bf, 4)) { 00048 return ATAN; 00049 }else if(!g_ascii_strncasecmp("log", bf, 3)) { 00050 return LOG; 00051 }else if(!g_ascii_strncasecmp("abs", bf, 3)) { 00052 return ABS; 00053 }else if(!g_ascii_strncasecmp("sqrt", bf, 4)) { 00054 return SQRT; 00055 }else{ 00056 return NOT; 00057 } 00058 } 00059 00060 void function_print_tree(struct function_const *e, GString** s, int indentation) { 00061 g_string_append_printf(*s, "%s", "const("); 00062 for(int i=0; i<(e->t-1); i++) { 00063 g_string_append_printf(*s, "%g,", e->value[i]); 00064 } 00065 g_string_append_printf(*s, "%g)", e->value[e->t-1]); 00066 } 00067 00068 void function_print_tree(struct function_symbol *e, GString** s, int indentation) { 00069 g_string_append_printf(*s, "SYMBOL(%s)", e->symbol); 00070 } 00071 00072 void function_print_tree(struct function_exp *e, GString** s, int indentation) { 00073 g_string_append_printf(*s, "\n%05d", indentation); 00074 for(int i=0; i<indentation; i++) { 00075 g_string_append_printf(*s, "%s", "\t"); 00076 } 00077 if(e == NULL) { 00078 g_string_append_printf(*s, "%s", "[*]"); 00079 return; 00080 } 00081 const char* funcname = NULL; 00082 switch(e->op) { 00083 case CONST: 00084 return function_print_tree((struct function_const*)e, s, indentation); 00085 case SYMBOL: 00086 return function_print_tree((struct function_symbol*)e, s, indentation); 00087 case EXP: 00088 funcname=(funcname==NULL)?"exp":funcname; 00089 case LOG: 00090 funcname=(funcname==NULL)?"log":funcname; 00091 case COS: 00092 funcname=(funcname==NULL)?"cos":funcname; 00093 case SIN: 00094 funcname=(funcname==NULL)?"sin":funcname; 00095 case TAN: 00096 funcname=(funcname==NULL)?"tan":funcname; 00097 case ACOS: 00098 funcname=(funcname==NULL)?"acos":funcname; 00099 case ASIN: 00100 funcname=(funcname==NULL)?"asin":funcname; 00101 case ATAN: 00102 funcname=(funcname==NULL)?"atan":funcname; 00103 case ABS: 00104 funcname=(funcname==NULL)?"abs":funcname; 00105 case SQRT: 00106 funcname=(funcname==NULL)?"sqrt":funcname; 00107 case NEG: 00108 funcname=(funcname==NULL)?"NEG":funcname; 00109 /*The above have just one argument: 00110 *NOTE that funcname will just be assigned once, when we jump in. 00111 */ 00112 g_string_append_printf(*s, "%s", funcname); 00113 /*recurse!*/ 00114 function_print_tree(e->l, s, indentation+1); 00115 return function_print_tree(e->r, s, indentation+1); 00116 case PLUS: 00117 funcname=(funcname==NULL)?"PLUS":funcname; 00118 case MINUS: 00119 funcname=(funcname==NULL)?"MINUS":funcname; 00120 case MUL: 00121 funcname=(funcname==NULL)?"MUL":funcname; 00122 case DIV: 00123 funcname=(funcname==NULL)?"DIV":funcname; 00124 case DOT: 00125 funcname=(funcname==NULL)?"DOT":funcname; 00126 case CROSS: 00127 funcname=(funcname==NULL)?"CROSS":funcname; 00128 g_string_append_printf(*s, "%s", funcname); 00129 /*recurse!*/ 00130 function_print_tree(e->l, s, indentation+1); 00131 return function_print_tree(e->r, s, indentation+1); 00132 default: 00133 g_string_append_printf(*s, "[UNKNOWN OPERATION (%d)]", e->op); 00134 function_print_tree(e->l, s, indentation+1); 00135 return function_print_tree(e->r, s, indentation+1); 00136 } 00137 g_string_append_printf(*s, "%s", "[hit end of routine (coding error)]"); 00138 } 00139 00140 GError* evaluate_function(double* value, const struct function_exp *f, GHashTable* global_symbols, GHashTable* local_symbols) { 00141 GError *err=NULL; 00142 GError *e=NULL; 00143 struct symbol_table_entry *ste; 00144 enum function_datatype lt=INVALID, rt=INVALID; 00145 double *l=NULL; 00146 double *r=NULL; 00147 /*Don't evaluate l & r if we're not actually a function_exp!!*/ 00148 //fprintf(stderr, "carteisan_evaulate_function: op=%d", f->op); 00149 if((!((f->op == SYMBOL) ||(f->op == CONST))) && (f->l != NULL)) { 00150 lt = get_function_datatype(f->l, global_symbols, local_symbols); 00151 l = new double[lt]; 00152 //fprintf(stderr, "\trecursing left\n"); 00153 e = evaluate_function(l, f->l, global_symbols, local_symbols); 00154 if(e != NULL) { 00155 g_propagate_prefixed_error(&err, e, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: binary operator %d got error on left-hand side: ", f->op); 00156 delete[] l; 00157 return err; 00158 } 00159 } else { 00160 lt = INVALID; 00161 l = NULL; 00162 } 00163 /*Don't evaluate l & r if we're not actually a function_exp!!*/ 00164 if((!((f->op == SYMBOL) ||(f->op == CONST))) && (f->r != NULL)) { 00165 rt = get_function_datatype(f->r, global_symbols, local_symbols); 00166 r = new double[rt]; 00167 //fprintf(stderr, "\trecursing right\n"); 00168 e = evaluate_function(r, f->r, global_symbols, local_symbols); 00169 if(e != NULL) { 00170 g_propagate_prefixed_error(&err, e, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: binary operator %d got error on right-hand side: ", f->op); 00171 if(l != NULL) delete[] l; 00172 delete[] r; 00173 return err; 00174 } 00175 } else { 00176 rt = INVALID; 00177 r = NULL; 00178 } 00179 /* 00180 fprintf(stderr, "carteisan_evaulate_function: lt=%d rt=%d op=%d", lt, rt, f->op); 00181 if(l != NULL) { 00182 fprintf(stderr, " l[0]=%g", l[0]); 00183 }else{ 00184 fprintf(stderr, " l[0]=NULL"); 00185 } 00186 if(r != NULL) { 00187 fprintf(stderr, " r[0]=%g", r[0]); 00188 }else{ 00189 fprintf(stderr, " r[0]=NULL"); 00190 } 00191 fprintf(stderr, "\n"); 00192 */ 00193 switch(f->op) { 00194 case PLUS: 00195 case MINUS: 00196 case MUL: 00197 case DIV: 00198 /**MUL and DIV can take scalar*vec*/ 00199 if(!( 00200 ((f->op == MUL)&&((rt == 1) || (lt == 1))) 00201 ||((f->op == DIV)&&(rt==1)) 00202 || (rt == lt) 00203 )) { 00204 if(l == NULL) delete[] l; 00205 if(r == NULL) delete[] r; 00206 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary operation, left and right dimensions are not the same or a scalar * vec or vec */ scalar! (op=%d; l=%d, r=%d)", f->op, lt, rt); 00207 } 00208 if((rt < SCALAR) || (lt < SCALAR)) { 00209 if(l == NULL) delete[] l; 00210 if(r == NULL) delete[] r; 00211 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 101, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary operation %d, arguments are invalid!", f->op); 00212 } 00213 /*Since we're iterating over rt, we need to iterate properly if 00214 *rt is 1 but lt isn't. 00215 */ 00216 if((f->op == MUL) && (lt > rt)) { 00217 for(int i=0; i<lt; i++) { 00218 value[i] = l[i] * r[0]; 00219 //fprintf(stderr, "rt*1: %g = %g*%g\n", value[i], l[i], r[i]); 00220 } 00221 }else if((f->op == DIV) && (lt > rt)) { 00222 for(int i=0; i<lt; i++) { 00223 value[i] = l[i] / r[0]; 00224 //fprintf(stderr, "rt1/: %g = %g/%g\n", value[i], l[i], r[i]); 00225 } 00226 }else{ 00227 for(int i=0; i<rt; i++) { 00228 switch(f->op) { 00229 case PLUS: 00230 value[i] = l[i] + r[i]; 00231 //fprintf(stderr, "%g = %g+%g\n", value[i], l[i], r[i]); 00232 break; 00233 case MINUS: 00234 value[i] = l[i] - r[i]; 00235 //fprintf(stderr, "%g = %g-%g\n", value[i], l[i], r[i]); 00236 break; 00237 case MUL: 00238 if(lt == 1) { 00239 value[i] = l[0] * r[i]; 00240 //fprintf(stderr, "lt1*: %g = %g*%g\n", value[i], l[0], r[i]); 00241 }else{ 00242 value[i] = l[i] * r[i]; 00243 //fprintf(stderr, "*: %g = %g*%g\n", value[i], l[i], r[i]); 00244 } 00245 break; 00246 case DIV: 00247 value[i] = l[i] / r[i]; 00248 //fprintf(stderr, "/: %g = %g/%g\n", value[i], l[i], r[i]); 00249 break; 00250 default: 00251 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 107, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary operation %d, unhandled op-specific handling!", f->op); 00252 } 00253 } 00254 } 00255 break; 00256 case CONST: 00257 if(((struct function_const*)f)->value == NULL) { 00258 value[0] = 0; 00259 break; 00260 } 00261 if(((struct function_const*)f)->t == 0) { 00262 value[0] = ((struct function_const*)f)->value[0]; 00263 break; 00264 } 00265 else for(int i=0; i<((struct function_const*)f)->t; i++) value[i] = ((struct function_const*)f)->value[i]; 00266 //fprintf(stderr, "const: value[0]=%g\n", value[0]); 00267 break; 00268 case COS: 00269 case SIN: 00270 case TAN: 00271 case LOG: 00272 case EXP: 00273 case ACOS: 00274 case ASIN: 00275 case ATAN: 00276 case ABS: 00277 case SQRT: 00278 if(rt != 1) { 00279 if(l == NULL) delete[] l; 00280 if(r == NULL) delete[] r; 00281 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 102, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with builtin function %d, argument dimension %d is not 1!", f->op, rt); 00282 } 00283 switch(f->op) { 00284 case COS: 00285 value[0] = cos(r[0]); 00286 //fprintf(stderr, "%g=cos(%g)\n", value[0], r[0]); 00287 break; 00288 case SIN: 00289 value[0] = sin(r[0]); 00290 //fprintf(stderr, "%g=sin(%g)\n", value[0], r[0]); 00291 break; 00292 case TAN: 00293 value[0] = tan(r[0]); 00294 //fprintf(stderr, "%g=tan(%g)\n", value[0], r[0]); 00295 break; 00296 case LOG: 00297 value[0] = log(r[0]); 00298 //fprintf(stderr, "%g=log(%g)\n", value[0], r[0]); 00299 break; 00300 case EXP: 00301 value[0] = ::exp(r[0]); 00302 //fprintf(stderr, "%g=exp(%g)\n", value[0], r[0]); 00303 break; 00304 case ACOS: 00305 value[0] = acos(r[0]); 00306 //fprintf(stderr, "%g=acos(%g)\n", value[0], r[0]); 00307 break; 00308 case ASIN: 00309 value[0] = asin(r[0]); 00310 //fprintf(stderr, "%g=asin(%g)\n", value[0], r[0]); 00311 break; 00312 case ATAN: 00313 value[0] = atan(r[0]); 00314 //fprintf(stderr, "%g=atan(%g)\n", value[0], r[0]); 00315 break; 00316 case ABS: 00317 value[0] = fabs(r[0]); 00318 //fprintf(stderr, "%g=abs(%g)\n", value[0], r[0]); 00319 break; 00320 case SQRT: 00321 value[0] = sqrt(r[0]); 00322 //fprintf(stderr, "%g=sqrt(%g)\n", value[0], r[0]); 00323 break; 00324 default: 00325 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 107, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with builting function %d, unhandled op-specific handling!", f->op); 00326 } 00327 break; 00328 case DOT: 00329 case CROSS: 00330 /**MUL and DIV can take scalar*vec*/ 00331 if(rt == lt) { 00332 if(l == NULL) delete[] l; 00333 if(r == NULL) delete[] r; 00334 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary vector operation, left and right dimensions are not the same or a scalar * vec or vec */ scalar! (op=%d; l=%d, r=%d)", f->op, lt, rt); 00335 } 00336 if(rt < SCALAR) { 00337 if(l == NULL) delete[] l; 00338 if(r == NULL) delete[] r; 00339 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 101, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary vector operation %d, arguments are invalid!", rt); 00340 } 00341 value[0] = 0; 00342 switch(f->op) { 00343 case DOT: 00344 for(int i=0; i<lt; i++) value[0] += l[i]*r[i]; 00345 break; 00346 case CROSS: 00347 /*THIS NEEDS A CLEVER ALGO*/ 00348 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 101, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary vector operation %d, cross product is not yet implemented!", rt); 00349 break; 00350 default: 00351 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 107, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary vector operation %d, unhandled op-specific handling!", f->op); 00352 } 00353 break; 00354 case postprocessing::OR: 00355 case postprocessing::AND: 00356 case postprocessing::XOR: 00357 if(rt == lt) { 00358 if(l == NULL) delete[] l; 00359 if(r == NULL) delete[] r; 00360 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary binary operation, left and right dimensions are not the same scalar! (op=%d; l=%d, r=%d)", f->op, lt, rt); 00361 } 00362 if(rt != BINARY) { 00363 if(l == NULL) delete[] l; 00364 if(r == NULL) delete[] r; 00365 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 101, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary binary operation %d, arguments are invalid!", rt); 00366 } 00367 switch(f->op) { 00368 case OR: 00369 value[0] = (l[0] || r[0]); 00370 break; 00371 case AND: 00372 value[0] = (l[0] && r[0]); 00373 break; 00374 case XOR: 00375 value[0] = ((l[0] || r[0]) && (!(l[0] && r[0]))); 00376 break; 00377 default: 00378 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 107, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with boolean binary operation %d, unhandled op-specific handling!", f->op); 00379 } 00380 break; 00381 case postprocessing::NOT: 00382 if(rt != BINARY) { 00383 if(l == NULL) delete[] l; 00384 if(r == NULL) delete[] r; 00385 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 101, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with binary binary operation %d, arguments are invalid!", rt); 00386 } 00387 value[0] = !r[0]; 00388 break; 00389 case SYMBOL: 00390 ste = get_symbol_table_entry(((struct function_symbol*)f)->symbol, global_symbols, local_symbols, &e); 00391 if((e != NULL) || (ste == NULL)) { 00392 if(e == NULL) { 00393 e = g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::evaluate_symbol: (%s) Unknown error looking up symbol in symbol tables.", (((struct function_symbol*)f)->symbol)); 00394 } 00395 g_propagate_prefixed_error(&err, e, "::kdotp::libmodelxx::function_specification.c++::evaluate_symbol: (%s) Error looking up symbol in symbol tables.", (((struct function_symbol*)f)->symbol)); 00396 return err; 00397 } 00398 switch(ste->st) { 00399 case CONSTANT_SYMBOL: 00400 for(int i=0; i<ste->dt; i++) { 00401 value[i]=((struct symbol_table_entry_const*)ste)->value[i]; 00402 } 00403 break; 00404 default: 00405 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::evaluate_symbol: (%s) Symbol is of unknown symbol type (%d).", (((struct function_symbol*)f)->symbol), ste->st); 00406 } 00407 //fprintf(stderr, "symbol %s: value[0]=%g\n", ((struct function_symbol*)f)->symbol, value[0]); 00408 break; 00409 case NEG: 00410 /*We can also negate a vector*/ 00411 if(rt < 1) { 00412 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 104, "::kdotp::libmodelxx::function_specification.c++::evaluate_function: with symbol (op NEG (%d)): right-hand side is not a valid number (scalar or higher-dimension)!", f->op); 00413 } 00414 for(int i=0; i<rt; i++) { 00415 value[i] = -r[i]; 00416 } 00417 break; 00418 default: 00419 //fprintf(stderr, "Unknown op: %d\n", f->op); 00420 return g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 104, "WARNING: expression operator %d not implemented!", f->op); 00421 } 00422 //fprintf(stderr, "exiting op(%d)\n", f->op); 00423 return NULL; 00424 } 00425 00426 enum function_datatype get_function_datatype(struct function_exp* f, GHashTable* global_symbols, GHashTable* local_symbols) { 00427 struct symbol_table_entry* ste; 00428 GError *e = NULL; 00429 enum function_datatype lt=INVALID, rt=INVALID; 00430 if(!((f->op == SYMBOL) || (f->op == CONST))) { 00431 if(f->l != NULL) lt = get_function_datatype(f->l, global_symbols, local_symbols); 00432 else lt = INVALID; 00433 if(f->r != NULL) rt = get_function_datatype(f->r, global_symbols, local_symbols); 00434 else lt = INVALID; 00435 } 00436 switch(f->op) { 00437 case PLUS: 00438 case MINUS: 00439 if(lt != rt) { 00440 //fprintf(stderr, "+-: lt!=rt: INVALID\n"); 00441 return INVALID; 00442 } 00443 if(rt < 1) { 00444 //fprintf(stderr, "+-: rt<1: INVALID\n"); 00445 return INVALID; 00446 } 00447 //fprintf(stderr, "+-: default (=rt=%d)\n", rt); 00448 return rt; 00449 case MUL: 00450 if((lt < 1) || (rt < 1)) { 00451 //fprintf(stderr, "*: lt||rt<1: INVALID\n"); 00452 return INVALID; 00453 } 00454 if(lt == 1) { 00455 //fprintf(stderr, "*: lt==1: =rt=%d\n", rt); 00456 return rt; 00457 } 00458 if(rt == 1) { 00459 //fprintf(stderr, "*: rt==1: =lt=\n"); 00460 return lt; 00461 } 00462 if(lt != rt) { 00463 //fprintf(stderr, "*: lt!=rt: INVALID\n"); 00464 return INVALID; 00465 } 00466 //fprintf(stderr, "*: default (=rt=%d)\n", rt); 00467 return rt; 00468 case DIV: 00469 if((lt < 1) || (rt < 1)) { 00470 //fprintf(stderr, "/: lt||rt<1: INVALID\n"); 00471 return INVALID; 00472 } 00473 if(rt == 1) { 00474 //fprintf(stderr, "/: rt==1: =lt=%d)\n", lt); 00475 return lt; 00476 } 00477 if(lt != rt) { 00478 //fprintf(stderr, "/: lt!=rt: INVALID\n"); 00479 return INVALID; 00480 } 00481 //fprintf(stderr, "/: default (=rt=%d)\n", rt); 00482 return rt; 00483 case CONST: 00484 //fprintf(stderr, "CONST: exp has type %d\n", ((struct function_const*)f)->t); 00485 return ((struct function_const*)f)->t; 00486 case COS: 00487 case SIN: 00488 case TAN: 00489 case LOG: 00490 case EXP: 00491 case ACOS: 00492 case ASIN: 00493 case ATAN: 00494 case ABS: 00495 case SQRT: 00496 if(lt != INVALID) { 00497 //fprintf(stderr, "builtin_scalar_func: lt(=%d)!=INVALID: INVALID\n", lt); 00498 return INVALID; 00499 } 00500 if(rt != 1) { 00501 //fprintf(stderr, "builtin_scalar_func: rt(=%d)!=SCALAR: INVALID\n", rt); 00502 return INVALID; 00503 } 00504 //fprintf(stderr, "builtin_scalar_func: SCALAR\n"); 00505 return SCALAR; 00506 case DOT: 00507 if((lt < 1) || (rt < 1)) { 00508 //fprintf(stderr, "DOT: lt||rt<1: INVALID\n"); 00509 return INVALID; 00510 } 00511 //fprintf(stderr, "DOT: SCALAR"); 00512 return SCALAR; 00513 case CROSS: 00514 if((lt < 1) || (rt < 1)) { 00515 //fprintf(stderr, "CROSS: lt||rt<1: INVALID\n"); 00516 return INVALID; 00517 } 00518 if(lt != rt) { 00519 //fprintf(stderr, "CROSS: lt!=rt: INVALID\n"); 00520 return INVALID; 00521 } 00522 //fprintf(stderr, "CROSS: default(=rt)\n"); 00523 return rt; 00524 case postprocessing::OR: 00525 case postprocessing::AND: 00526 case postprocessing::XOR: 00527 if((lt != 0) || (rt != 0)) { 00528 //fprintf(stderr, "|&XOR: lt||rt!=0: INVALID\n"); 00529 return INVALID; 00530 } 00531 //fprintf(stderr, "|&XOR: BINARY\n"); 00532 return BINARY; 00533 case postprocessing::NOT: 00534 if(lt != INVALID) { 00535 //fprintf(stderr, "!: lt!=INVALID\n"); 00536 return INVALID; 00537 } 00538 if(rt != 0) { 00539 //fprintf(stderr, "!: rt!=BINARY\n"); 00540 return INVALID; 00541 } 00542 //fprintf(stderr, "!: BINARY\n"); 00543 return BINARY; 00544 case SYMBOL: 00545 ste = get_symbol_table_entry(((struct function_symbol*)f)->symbol, global_symbols, local_symbols, &e); 00546 if((e != NULL) || (ste == NULL)) { 00547 return INVALID; 00548 } 00549 return ste->dt; 00550 case NEG: 00551 if(rt < 1) { 00552 //fprintf(stderr, "NEG: rt<1: INVALID\n"); 00553 return INVALID; 00554 } 00555 //fprintf(stderr, "NEG: default (=rt=%d)\n", rt); 00556 return rt; 00557 default: 00558 fprintf(stderr, "UNRECOGNIZED OP(%d): INVALID\n", f->op); 00559 return INVALID; 00560 } 00561 } 00562 00563 struct symbol_table_entry* get_symbol_table_entry(const char* symbol, GHashTable *global_symbols, GHashTable* local_symbols, GError **e) { 00564 struct symbol_table_entry *ste_global = NULL; 00565 if(global_symbols != NULL) ste_global = (struct symbol_table_entry *)g_hash_table_lookup(global_symbols, symbol); 00566 struct symbol_table_entry *ste_local = NULL; 00567 if(local_symbols != NULL) ste_local = (struct symbol_table_entry *)g_hash_table_lookup(local_symbols, symbol); 00568 if((ste_global != NULL) && (ste_local != NULL)) { 00569 *e = g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::get_symbol_table_entry: symbol (%s) defined both locally and globally!", symbol); 00570 return NULL; 00571 } 00572 if((ste_global == NULL) && (ste_local == NULL)) { 00573 *e = g_error_new(FUNCTION_SPECIFICATION_GERROR_DOMAIN, 100, "::kdotp::libmodelxx::function_specification.c++::get_symbol_table_entry: symbol (%s) not defined.", symbol); 00574 return NULL; 00575 } 00576 if(ste_global != NULL) return ste_global; 00577 return ste_local; 00578 } 00579 00580 void add_symbol_table_entry(GHashTable *st, const char* symbol, struct symbol_table_entry* entry) { 00581 /*Copy the string*/ 00582 GString* sb = g_string_new(symbol); 00583 g_hash_table_insert(st, sb->str, entry); 00584 g_string_free(sb, FALSE); 00585 } 00586 00587 /*This frees a symbol table entry, e.g. when overwriting an entry.*/ 00588 static void destroy_symbol_table_entry(void *ste_) { 00589 struct symbol_table_entry *ste = (struct symbol_table_entry *)ste_; 00590 switch(ste->st) { 00591 case CONSTANT_SYMBOL: 00592 free(((struct symbol_table_entry_const*)ste)->value); 00593 break; 00594 default: 00595 /*we can't communicate an error, so do no further processing*/ 00596 ; 00597 } 00598 /*Finally, free the structure itself*/ 00599 free((struct symbol_table_entry_const*)ste); 00600 } 00601 00602 static void destroy_symbol_table_symbol(void *symbol) { 00603 free(symbol); 00604 } 00605 00606 GHashTable* new_symbol_table() { 00607 return (GHashTable*)g_hash_table_new_full(g_str_hash, g_str_equal, destroy_symbol_table_symbol, destroy_symbol_table_entry); 00608 } 00609 00610 void parameter_list_init(GList* parameters) { 00611 /*Initialize the loop over the template parameters*/ 00612 for(GList* ll = parameters; ll!=NULL; ll=ll->next) ((struct template_parameter_range*)ll->data)->current_value = ((struct template_parameter_range*)ll->data)->from; 00613 } 00614 00615 bool update_parameters_plus_check_if_done(GList* parameters) { 00616 for(GList* ll=parameters; ll!=NULL; ll=ll->next) { 00617 ((struct template_parameter_range*)ll->data)->current_value += ((struct template_parameter_range*)ll->data)->stepsize; 00618 if(((struct template_parameter_range*)ll->data)->current_value <= ((struct template_parameter_range*)ll->data)->to) return false; 00619 /*If we reach this point, the current value is greater than the stop value. We need to reset this 00620 * value and then loop around to the next value to increment.*/ 00621 ((struct template_parameter_range*)ll->data)->current_value = ((struct template_parameter_range*)ll->data)->from; 00622 } 00623 return true; 00624 } 00625 00626 GFile* get_gfile_directory_for_template_state(const char* prefix, GList* parameters) { 00627 GString *s; 00628 if(prefix == NULL) { 00629 s = g_string_new("./"); 00630 }else{ 00631 s = g_string_new(prefix); 00632 } 00633 if(parameters != NULL) { 00634 s = g_string_append(s, ((struct template_parameter_range*)parameters->data)->symbol); 00635 g_string_append_printf(s, "=%g", ((struct template_parameter_range*)parameters->data)->current_value); 00636 /*We started with the first so that we can prefix the string with an underscore.*/ 00637 if(parameters->next!=NULL) { 00638 for(GList* ll = parameters->next; ll!=NULL; ll=ll->next) { 00639 g_string_append_printf(s, "_%s=%g", ((struct template_parameter_range*)ll->data)->symbol, ((struct template_parameter_range*)ll->data)->current_value); 00640 } 00641 } 00642 } 00643 GFile *f = g_file_new_for_commandline_arg(s->str); 00644 g_string_free(s, TRUE); 00645 return f; 00646 } 00647 00648 void add_template_parameters_to_symbol_table(GHashTable *st, GList* parms) { 00649 struct symbol_table_entry *ste; 00650 struct symbol_table_entry_const *stec=NULL; 00651 struct template_parameter_range *tpm; 00652 for(GList* ll=parms; ll!=NULL; ll=ll->next) { 00653 tpm = (struct template_parameter_range *)ll->data; 00654 ste = (struct symbol_table_entry*)g_hash_table_lookup(st, tpm->symbol); 00655 if(ste == NULL) { 00656 stec = (struct symbol_table_entry_const*)malloc(sizeof(struct symbol_table_entry_const)); 00657 if(stec == NULL) { 00658 fprintf(stderr, "ERROR: unable to allocate new symbol table entry for symbol (%s)\n", tpm->symbol); 00659 continue; 00660 } 00661 stec->st = CONSTANT_SYMBOL; 00662 stec->dt = SCALAR; 00663 stec->value = (double*)malloc(sizeof(double)); 00664 if(stec->value == NULL) { 00665 fprintf(stderr, "ERROR: unable to allocate new symbol table entry value storage for symbol (%s)\n", tpm->symbol); 00666 continue; 00667 } 00668 g_hash_table_insert(st, tpm->symbol, (struct symbol_table_entry*)stec); 00669 }else{ 00670 if(ste->st != CONSTANT_SYMBOL) { 00671 fprintf(stderr, "ERROR: symbol table entry for symbol (%s) is not a constant symbol (is %d)\n", tpm->symbol, stec->st); 00672 continue; 00673 } 00674 if(ste->dt != SCALAR) { 00675 fprintf(stderr, "ERROR: symbol table entry for symbol (%s) is not a scalar type (is %d)\n", tpm->symbol, stec->dt); 00676 continue; 00677 } 00678 stec = (struct symbol_table_entry_const*)ste; 00679 } 00680 *(stec->value)=tpm->current_value; 00681 } 00682 } 00683 00684 char* get_string_for_template_state(GList* parameters) { 00685 GString *s = g_string_new(""); 00686 if(parameters == NULL) { 00687 char *str = s->str; 00688 g_string_free(s, FALSE); 00689 return str; 00690 } 00691 g_string_append_printf(s, "%g", ((struct template_parameter_range*)parameters->data)->current_value); 00692 /*We started with the first so that we can prefix the string with an underscore.*/ 00693 if(parameters->next!=NULL) { 00694 for(GList* ll = parameters->next; ll!=NULL; ll=ll->next) { 00695 g_string_append_printf(s, "\t%g", ((struct template_parameter_range*)ll->data)->current_value); 00696 } 00697 } 00698 char *str = s->str; 00699 g_string_free(s, FALSE); 00700 return str; 00701 } 00702 00703 char* get_header_for_template_state(GList* parameters) { 00704 GString *s = g_string_new(""); 00705 if(parameters == NULL) { 00706 char *str = s->str; 00707 g_string_free(s, FALSE); 00708 return str; 00709 } 00710 s = g_string_append(s, ((struct template_parameter_range*)parameters->data)->symbol); 00711 /*We started with the first so that we can prefix the string with an underscore.*/ 00712 if(parameters->next!=NULL) { 00713 for(GList* ll = parameters->next; ll!=NULL; ll=ll->next) { 00714 g_string_append_printf(s, "\t%s", ((struct template_parameter_range*)ll->data)->symbol); 00715 } 00716 } 00717 char *str = s->str; 00718 g_string_free(s, FALSE); 00719 return str; 00720 } 00721 00722 void free_function(struct function_const* e) { 00723 free(e->value); 00724 free(e); 00725 } 00726 00727 void free_function(struct function_symbol* e) { 00728 free(e->symbol); 00729 free(e); 00730 } 00731 00732 void free_function(struct function_exp *e) { 00733 switch(e->op) { 00734 case CONST: 00735 free_function((struct function_const*)e); 00736 break; 00737 case SYMBOL: 00738 free_function((struct function_symbol*)e); 00739 break; 00740 default: 00741 if(e->l != NULL) free_function(e->l); 00742 if(e->r != NULL) free_function(e->r); 00743 free(e); 00744 } 00745 } 00746 00747 } 00748 } 00749 }