|
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 00022 #include <stdlib.h> 00023 #include <stdio.h> 00024 #include <glib.h> 00025 #include <libmodelxx/shapes.h++> 00026 #include <libmodelxx/key_values.h++> 00027 00028 using namespace ::kdotp::libmodelxx::postprocessing; 00029 00030 namespace kdotp { 00031 namespace libmodelxx { 00032 namespace grid { 00033 00034 struct shape_block* make_block_from_shape(struct shape *s, int dim, bool abs) { 00035 shape_block* b = (struct shape_block*)malloc(sizeof(struct shape_block)); 00036 b->op = LEAF; 00037 if(abs) { 00038 b->type = ABSBLOCK; 00039 }else{ 00040 b->type = BLOCK; 00041 } 00042 b->generic = false; 00043 b->center = (struct function_exp*)malloc(sizeof(struct function_exp)); 00044 if((b->center == NULL)) { 00045 if(abs) { 00046 fprintf(stderr, "kdotp::libmodelxx::grid::make_block_from_shape: ERROR allocating memory for first corner coordinate\n"); 00047 }else{ 00048 fprintf(stderr, "kdotp::libmodelxx::grid::make_block_from_shape: ERROR allocating memory for center\n"); 00049 } 00050 exit(15); 00051 } 00052 b->L = (struct function_exp*)malloc(sizeof(struct function_exp)); 00053 if((b->L == NULL)) { 00054 if(abs) { 00055 fprintf(stderr, "kdotp::libmodelxx::grid::make_block_from_shape: ERROR allocating memory for second corner coordinate\n"); 00056 }else{ 00057 fprintf(stderr, "kdotp::libmodelxx::grid::make_block_from_shape: ERROR allocating memory for L\n"); 00058 } 00059 exit(16); 00060 } 00061 /*There should be two vectors: the center of the box, and the width 00062 * of the box (vector from one corner to the other) 00063 *As a convenience, the vectors may be scalars if there is only 00064 * one dimension 00065 */ 00066 GString* str = g_string_new(""); 00067 GList *l = s->descriptor; 00068 if(l == NULL) { 00069 fprintf(stderr, "kdotp::libmodelxx::grid::make_global_from_shape: ERROR: insufficient shape description was given to a \"block\" or \"absblock\" shape, which takes only two vectors. This superfluous information will be ignored.\n"); 00070 exit(17); 00071 } 00072 b->center = (struct function_exp*)(l->data); 00073 function_print_tree(b->center, &str, 1); 00074 fprintf(stderr, "b->center:\n%s\n", str->str); 00075 g_string_free(str, TRUE); 00076 l = l->next; 00077 if(l == NULL) { 00078 fprintf(stderr, "kdotp::libmodelxx::grid::make_global_from_shape: ERROR: insufficient shape description was given to a \"block\" or \"absblock\" shape, which takes only two vectors. This superfluous information will be ignored.\n"); exit(18); 00079 } 00080 b->L = (struct function_exp*)(l->data); 00081 str = g_string_new(""); 00082 function_print_tree(b->L, &str, 1); 00083 fprintf(stderr, "b->L:\n%s\n", str->str); 00084 g_string_free(str, TRUE); 00085 l=l->next; 00086 if(l != NULL) { 00087 fprintf(stderr, "kdotp::libmodelxx::grid::make_global_from_shape: WARNING: extra shape description was given to a \"block\" shape, which takes only two vectors. This superfluous information will be ignored.\n"); 00088 } 00089 return b; 00090 } 00091 struct shape_global* make_global_from_shape(struct shape *s, int dim) { 00092 shape_global* g = (struct shape_global*)malloc(sizeof(struct shape_global)); 00093 g->op = LEAF; 00094 g->type = GLOBAL; 00095 g->generic = false; 00096 if((s->descriptor) != NULL) { 00097 fprintf(stderr, "kdotp::libmodelxx::grid::make_global_from_shape: WARNING: a shape description was given to a \"global\" shape, which takes no description. This superfluous information will be ignored.\n"); 00098 } 00099 return g; 00100 } 00101 00102 /** 00103 *\note Algorithm: 00104 *1) Recurse on non-leaf nodes 00105 *2) Set l, r from recursion. 00106 *3) If leaf, set the respective type using above helper function. 00107 *\note caller MUST set the return value; you may just have a leaf node. 00108 */ 00109 struct shape_tree* postprocess_shape_tree(struct shape_tree* st, int dim) { 00110 /*Simple bounce for NULL links.*/ 00111 if(st == NULL) return NULL; 00112 if(st->op != LEAF) { 00113 if(st->l == NULL){ 00114 fprintf(stderr, "kdotp::libmodelxx::grid::postprocess_shape_tree: left subtree of a non-LEAF shape tree node should never be NULL, but is! (op is %d)\n", st->op); 00115 return NULL; 00116 } 00117 if(((st->l) = postprocess_shape_tree(st->l, dim)) != NULL) { 00118 /*If this was already NULL, we're fine.*/ 00119 if((st->r == NULL) || (((st->r) = postprocess_shape_tree(st->r, dim)) != NULL)) { 00120 return st; 00121 }else{ 00122 fprintf(stderr, "kdotp::libmodelxx::grid::postprocess_shape_tree: got NULL postprocessing right subtree (op is %d)\n", st->op); 00123 } 00124 }else{ 00125 fprintf(stderr, "kdotp::libmodelxx::grid::postprocess_shape_tree: got NULL postprocessing left subtree (op is %d)\n", st->op); 00126 } 00127 /*If we get to here, one or the other of the ones failed.*/ 00128 return NULL; 00129 } 00130 /*This will only execute for leaf nodes.*/ 00131 struct shape* s = (struct shape*)st; 00132 if(!(s->generic)) { 00133 fprintf(stderr, "kdotp::libmodelxx::grid::postprocess_shape_tree: WARNING shape is not generic, although it's expected to be!\n"); 00134 /*For some reason, this shape has already been 00135 *postprocessed. Just return it, then. 00136 */ 00137 return st; 00138 } 00139 struct shape* n = NULL; 00140 switch (s->type) { 00141 case BLOCK: 00142 n = (struct shape*)make_block_from_shape(s, dim, false); 00143 break; 00144 case ABSBLOCK: 00145 n = (struct shape*)make_block_from_shape(s, dim, true); 00146 break; 00147 case GLOBAL: 00148 n = (struct shape*)make_global_from_shape(s, dim); 00149 break; 00150 default: 00151 fprintf(stderr, "kdotp::libmodelxx::grid::process_shape_tree: ERROR unrecognized shape type (numeric: %d)\n", s->type); 00152 return NULL; 00153 } 00154 shape_free(s); 00155 return (struct shape_tree*)n; 00156 } 00157 00158 void shape_block_free(struct shape_block *b) { 00159 free_function(b->center); 00160 free_function(b->L); 00161 free(b); 00162 } 00163 00164 void shape_global_free(struct shape_global *b) { 00165 free(b); 00166 } 00167 00168 00169 void shape_free(struct shape *s) { 00170 /*Free the value list.*/ 00171 GList* l; 00172 if(s->generic){ 00173 /*The functions are moved over to the new structure; just free the list.*/ 00174 g_list_free(s->descriptor); 00175 }else{ 00176 switch(s->type){ 00177 case GLOBAL: 00178 shape_global_free((struct shape_global*)s); 00179 break; 00180 case BLOCK: 00181 shape_block_free((struct shape_block*)s); 00182 break; 00183 case ABSBLOCK: 00184 shape_block_free((struct shape_block*)s); 00185 break; 00186 default: 00187 fprintf(stderr, "kdotp::libmodelxx::grid::shape_free: didn't recognize non-generic shape type (numeric %d)\n", s->type); 00188 } 00189 } 00190 free(s); 00191 } 00192 00193 void shape_tree_free(struct shape_tree *st) { 00194 if(st == NULL) return; 00195 if(st->op != LEAF) { 00196 shape_tree_free(st->l); 00197 shape_tree_free(st->r); 00198 }else{ 00199 shape_free((struct shape*)st); 00200 } 00201 } 00202 00203 enum shape_type get_shape_from_identifier(const char* identifier) { 00204 if(!g_ascii_strcasecmp(identifier, "block")){ 00205 return BLOCK; 00206 }else if(!g_ascii_strcasecmp(identifier, "absblock")){ 00207 return ABSBLOCK; 00208 }else if(!g_ascii_strcasecmp(identifier, "global")){ 00209 return GLOBAL; 00210 } 00211 return INVALID; 00212 } 00213 00214 00215 void get_string_from_shape_type(char** str, enum shape_type t) { 00216 GString *s = NULL; 00217 switch(t) { 00218 case INVALID: 00219 s = g_string_new("invalid"); 00220 break; 00221 case BLOCK: 00222 s = g_string_new("block"); 00223 break; 00224 case ABSBLOCK: 00225 s = g_string_new("absblock"); 00226 break; 00227 case GLOBAL: 00228 s = g_string_new("global"); 00229 break; 00230 default: 00231 s = g_string_new("unkdnown("); 00232 g_string_append_printf(s, "%d)", t); 00233 } 00234 *str = s->str; 00235 g_string_free(s, FALSE); 00236 } 00237 00238 00239 } 00240 } 00241 }