k-dot-p 0.1

function_specification.c++

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines