Qucs-core
0.0.19
|
00001 /* 00002 * dataset.cpp - dataset class implementation 00003 * 00004 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software 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 General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <errno.h> 00033 #include <assert.h> 00034 #include <cmath> 00035 00036 #include "logging.h" 00037 #include "complex.h" 00038 #include "object.h" 00039 #include "strlist.h" 00040 #include "vector.h" 00041 #include "dataset.h" 00042 #include "check_dataset.h" 00043 #include "check_touchstone.h" 00044 #include "check_csv.h" 00045 #include "check_citi.h" 00046 #include "check_zvr.h" 00047 #include "check_mdl.h" 00048 00049 namespace qucs { 00050 00051 // Constructor creates an unnamed instance of the dataset class. 00052 dataset::dataset () : object () { 00053 variables = dependencies = NULL; 00054 file = NULL; 00055 } 00056 00057 // Constructor creates an named instance of the dataset class. 00058 dataset::dataset (char * n) : object (n) { 00059 variables = dependencies = NULL; 00060 file = NULL; 00061 } 00062 00063 /* The copy constructor creates a new instance based on the given 00064 dataset object. */ 00065 dataset::dataset (const dataset & d) : object (d) { 00066 file = d.file ? strdup (d.file) : NULL; 00067 vector * v; 00068 // copy dependency vectors 00069 for (v = d.dependencies; v != NULL; v = (vector *) v->getNext ()) { 00070 addDependency (new vector (*v)); 00071 } 00072 // copy variable vectors 00073 for (v = variables; v != NULL; v = (vector *) v->getNext ()) { 00074 addVariable (new vector (*v)); 00075 } 00076 } 00077 00078 // Destructor deletes a dataset object. 00079 dataset::~dataset () { 00080 vector * n, * v; 00081 // delete dependency vectors 00082 for (v = dependencies; v != NULL; v = n) { 00083 n = (vector *) v->getNext (); 00084 delete v; 00085 } 00086 // delete variable vectors 00087 for (v = variables; v != NULL; v = n) { 00088 n = (vector *) v->getNext (); 00089 delete v; 00090 } 00091 free (file); 00092 } 00093 00094 // This function adds a dependency vector to the current dataset. 00095 void dataset::addDependency (vector * v) { 00096 if (dependencies) dependencies->setPrev (v); 00097 v->setNext (dependencies); 00098 v->setPrev (NULL); 00099 dependencies = v; 00100 } 00101 00102 // This function removes a dependency vector from the current dataset. 00103 void dataset::delDependency (vector * v) { 00104 if (dependencies == v) { 00105 dependencies = (vector *) v->getNext (); 00106 if (dependencies) dependencies->setPrev (NULL); 00107 } 00108 else { 00109 vector * next = (vector *) v->getNext (); 00110 vector * prev = (vector *) v->getPrev (); 00111 prev->setNext (next); 00112 if (next) next->setPrev (prev); 00113 } 00114 delete v; 00115 } 00116 00117 /* The function adds the given list of vectors to the dependency set 00118 of the current dataset. */ 00119 void dataset::addDependencies (vector * v) { 00120 vector * next; 00121 for (vector * t = v; t != NULL; t = next) { 00122 next = (vector *) t->getNext (); 00123 addDependency (t); 00124 } 00125 } 00126 00127 // This function appends a dependency vector to the current dataset. 00128 void dataset::appendDependency (vector * v) { 00129 vector * e; 00130 if (dependencies) { 00131 for (e = dependencies; e->getNext (); e = (vector *) e->getNext ()) ; 00132 v->setPrev (e); 00133 e->setNext (v); 00134 } 00135 else { 00136 v->setPrev (NULL); 00137 dependencies= v; 00138 } 00139 v->setNext (NULL); 00140 } 00141 00142 /* The function appends the given list of vectors to the dependency 00143 set of the current dataset. */ 00144 void dataset::appendDependencies (vector * v) { 00145 vector * next; 00146 for (vector * t = v; t != NULL; t = next) { 00147 next = (vector *) t->getNext (); 00148 appendDependency (t); 00149 } 00150 } 00151 00152 // This function adds a variable vector to the current dataset. 00153 void dataset::addVariable (vector * v) { 00154 if (variables) variables->setPrev (v); 00155 v->setNext (variables); 00156 v->setPrev (NULL); 00157 variables = v; 00158 } 00159 00160 // This function removes a variable vector from the current dataset. 00161 void dataset::delVariable (vector * v) { 00162 if (variables == v) { 00163 variables = (vector *) v->getNext (); 00164 if (variables) variables->setPrev (NULL); 00165 } 00166 else { 00167 vector * next = (vector *) v->getNext (); 00168 vector * prev = (vector *) v->getPrev (); 00169 prev->setNext (next); 00170 if (next) next->setPrev (prev); 00171 } 00172 delete v; 00173 } 00174 00175 /* The function adds the given list of vectors to the variable set of 00176 the current dataset. */ 00177 void dataset::addVariables (vector * v) { 00178 vector * next; 00179 for (vector * t = v; t != NULL; t = next) { 00180 next = (vector *) t->getNext (); 00181 addVariable (t); 00182 } 00183 } 00184 00185 // This function appends a variable vector to the current dataset. 00186 void dataset::appendVariable (vector * v) { 00187 vector * e; 00188 if (variables) { 00189 for (e = variables; e->getNext (); e = (vector *) e->getNext ()) ; 00190 v->setPrev (e); 00191 e->setNext (v); 00192 } 00193 else { 00194 v->setPrev (NULL); 00195 variables = v; 00196 } 00197 v->setNext (NULL); 00198 } 00199 00200 /* The function appends the given list of vectors to the variable set 00201 of the current dataset. */ 00202 void dataset::appendVariables (vector * v) { 00203 vector * next; 00204 for (vector * t = v; t != NULL; t = next) { 00205 next = (vector *) t->getNext (); 00206 appendVariable (t); 00207 } 00208 } 00209 00210 /* This function applies the dependency string list of the given 00211 vector to the list of vectors appended to this vector. */ 00212 void dataset::applyDependencies (vector * v) { 00213 strlist * deps = v->getDependencies (); 00214 if (deps != NULL) { 00215 vector * next; 00216 for (vector * t = (vector *) v->getNext (); t != NULL; t = next) { 00217 next = (vector *) t->getNext (); 00218 if (t->getDependencies () == NULL) { 00219 t->setDependencies (new strlist (*deps)); 00220 } 00221 } 00222 } 00223 } 00224 00225 /* This function returns the dataset vector (both independent and 00226 dependent) with the given origin. It returns NULL if there is no 00227 such vector. */ 00228 vector * dataset::findOrigin (char * n) { 00229 vector * v; 00230 for (v = variables; v != NULL; v = (vector *) v->getNext ()) { 00231 char * origin = v->getOrigin (); 00232 if (origin != NULL && n != NULL && !strcmp (n, origin)) 00233 return v; 00234 } 00235 for (v = dependencies; v != NULL; v = (vector *) v->getNext ()) { 00236 char * origin = v->getOrigin (); 00237 if (origin != NULL && n != NULL && !strcmp (n, origin)) 00238 return v; 00239 } 00240 return NULL; 00241 } 00242 00243 /* This function assigns dependency entries to variable vectors which 00244 do have the specified origin. */ 00245 void dataset::assignDependency (const char * const origin, const char * const depvar) { 00246 for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) { 00247 char * n = v->getOrigin (); 00248 if (n != NULL && origin != NULL && !strcmp (origin, n)) { 00249 strlist * deplist = v->getDependencies (); 00250 if (deplist != NULL) { 00251 if (!deplist->contains (depvar)) { 00252 deplist->append (depvar); 00253 } 00254 } 00255 else { 00256 deplist = new strlist (); 00257 deplist->add (depvar); 00258 v->setDependencies (deplist); 00259 } 00260 } 00261 } 00262 } 00263 00264 // Return non-zero if the given vector is an independent variable vector. 00265 int dataset::isDependency (vector * dep) { 00266 for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ()) 00267 if (v == dep) return 1; 00268 return 0; 00269 } 00270 00271 // Return non-zero if the given vector is a dependent variable vector. 00272 int dataset::isVariable (vector * var) { 00273 for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) 00274 if (v == var) return 1; 00275 return 0; 00276 } 00277 00278 /* The function goes through the list of dependencies in the dataset 00279 and returns the vector specified by the given name. Otherwise the 00280 function returns NULL. */ 00281 vector * dataset::findDependency (const char * n) { 00282 for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ()) { 00283 if (!strcmp (v->getName (), n)) 00284 return v; 00285 } 00286 return NULL; 00287 } 00288 00289 /* The function goes through the list of variables in the dataset and 00290 returns the vector specified by the given name. If there is no 00291 such variable registered the function returns NULL. */ 00292 vector * dataset::findVariable (const std::string &name) { 00293 for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) { 00294 if (!strcmp (v->getName (), name.c_str())) 00295 return v; 00296 } 00297 return NULL; 00298 } 00299 00300 // Returns the number of variable vectors. 00301 int dataset::countVariables (void) { 00302 int count = 0; 00303 for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) 00304 count++; 00305 return count; 00306 } 00307 00308 // Returns the number of dependency vectors. 00309 int dataset::countDependencies (void) { 00310 int count = 0; 00311 for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ()) 00312 count++; 00313 return count; 00314 } 00315 00316 // Returns the current output file name. 00317 char * dataset::getFile (void) { 00318 return file; 00319 } 00320 00321 /* Sets the current output file name. The file name is used during 00322 the print functionality of the dataset class. */ 00323 void dataset::setFile (const char * f) { 00324 free (file); 00325 file = f ? strdup (f) : NULL; 00326 } 00327 00328 /* This function prints the current dataset representation either to 00329 the specified file name (given by the function setFile()) or to 00330 stdout if there is no such file name given. */ 00331 void dataset::print (void) { 00332 00333 FILE * f = stdout; 00334 00335 // open file for writing 00336 if (file) { 00337 if ((f = fopen (file, "w")) == NULL) { 00338 logprint (LOG_ERROR, "cannot create file `%s': %s\n", 00339 file, strerror (errno)); 00340 return; 00341 } 00342 } 00343 00344 // print header 00345 fprintf (f, "<Qucs Dataset " PACKAGE_VERSION ">\n"); 00346 00347 // print dependencies 00348 for (vector * d = dependencies; d != NULL; d = (vector *) d->getNext ()) { 00349 printDependency (d, f); 00350 } 00351 00352 // print variables 00353 for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) { 00354 if (v->getDependencies () != NULL) 00355 printVariable (v, f); 00356 else 00357 printDependency (v, f); 00358 } 00359 00360 // close file if necessary 00361 if (file) fclose (f); 00362 } 00363 00364 /* Prints the given vector as independent dataset vector into the 00365 given file descriptor. */ 00366 void dataset::printDependency (vector * v, FILE * f) { 00367 // print data header 00368 fprintf (f, "<indep %s %d>\n", v->getName (), v->getSize ()); 00369 // print data itself 00370 printData (v, f); 00371 // print data footer 00372 fprintf (f, "</indep>\n"); 00373 } 00374 00375 /* Prints the given vector as dependent dataset vector into the given 00376 file descriptor. */ 00377 void dataset::printVariable (vector * v, FILE * f) { 00378 // print data header 00379 fprintf (f, "<dep %s", v->getName ()); 00380 if (v->getDependencies () != NULL) { 00381 for (strlistiterator it (v->getDependencies ()); *it; ++it) 00382 fprintf (f, " %s", *it); 00383 } 00384 fprintf (f, ">\n"); 00385 00386 // print data itself 00387 printData (v, f); 00388 00389 // print data footer 00390 fprintf (f, "</dep>\n"); 00391 } 00392 00393 /* This function is a helper routine for the print() functionality of 00394 the dataset class. It prints the data items of the given vector 00395 object to the given output stream. */ 00396 void dataset::printData (vector * v, FILE * f) { 00397 for (int i = 0; i < v->getSize (); i++) { 00398 nr_complex_t c = v->get (i); 00399 if (imag (c) == 0.0) { 00400 fprintf (f, " %+." "20" "e\n", (double) real (c)); 00401 } 00402 else { 00403 fprintf (f, " %+." "20" "e%cj%." "20" "e\n", (double) real (c), 00404 imag (c) >= 0.0 ? '+' : '-', (double) fabs (imag (c))); 00405 } 00406 } 00407 } 00408 00409 /* This static function read a full dataset from the given file and 00410 returns it. On failure the function emits appropriate error 00411 messages and returns NULL. */ 00412 dataset * dataset::load (const char * file) { 00413 FILE * f; 00414 if ((f = fopen (file, "r")) == NULL) { 00415 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00416 return NULL; 00417 } 00418 dataset_in = f; 00419 dataset_restart (dataset_in); 00420 if (dataset_parse () != 0) { 00421 fclose (f); 00422 return NULL; 00423 } 00424 if (dataset_result != NULL) { 00425 if (dataset_check (dataset_result) != 0) { 00426 fclose (f); 00427 delete dataset_result; 00428 return NULL; 00429 } 00430 } 00431 fclose (f); 00432 dataset_lex_destroy (); 00433 dataset_result->setFile (file); 00434 return dataset_result; 00435 } 00436 00437 /* This static function read a full dataset from the given touchstone 00438 file and returns it. On failure the function emits appropriate 00439 error messages and returns NULL. */ 00440 dataset * dataset::load_touchstone (const char * file) { 00441 FILE * f; 00442 if ((f = fopen (file, "r")) == NULL) { 00443 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00444 return NULL; 00445 } 00446 touchstone_in = f; 00447 touchstone_restart (touchstone_in); 00448 if (touchstone_parse () != 0) { 00449 fclose (f); 00450 return NULL; 00451 } 00452 if (touchstone_check () != 0) { 00453 fclose (f); 00454 return NULL; 00455 } 00456 fclose (f); 00457 touchstone_lex_destroy (); 00458 touchstone_result->setFile (file); 00459 return touchstone_result; 00460 } 00461 00462 /* This static function read a full dataset from the given CSV file 00463 and returns it. On failure the function emits appropriate error 00464 messages and returns NULL. */ 00465 dataset * dataset::load_csv (const char * file) { 00466 FILE * f; 00467 if ((f = fopen (file, "r")) == NULL) { 00468 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00469 return NULL; 00470 } 00471 csv_in = f; 00472 csv_restart (csv_in); 00473 if (csv_parse () != 0) { 00474 fclose (f); 00475 return NULL; 00476 } 00477 if (csv_check () != 0) { 00478 fclose (f); 00479 return NULL; 00480 } 00481 fclose (f); 00482 csv_lex_destroy (); 00483 csv_result->setFile (file); 00484 return csv_result; 00485 } 00486 00487 /* The function read a full dataset from the given CITIfile and 00488 returns it. On failure the function emits appropriate error 00489 messages and returns NULL. */ 00490 dataset * dataset::load_citi (const char * file) { 00491 FILE * f; 00492 if ((f = fopen (file, "r")) == NULL) { 00493 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00494 return NULL; 00495 } 00496 citi_in = f; 00497 citi_restart (citi_in); 00498 if (citi_parse () != 0) { 00499 fclose (f); 00500 return NULL; 00501 } 00502 if (citi_check () != 0) { 00503 fclose (f); 00504 return NULL; 00505 } 00506 fclose (f); 00507 citi_lex_destroy (); 00508 citi_result->setFile (file); 00509 return citi_result; 00510 } 00511 00512 /* The function read a full dataset from the given ZVR file and 00513 returns it. On failure the function emits appropriate error 00514 messages and returns NULL. */ 00515 dataset * dataset::load_zvr (const char * file) { 00516 FILE * f; 00517 if ((f = fopen (file, "r")) == NULL) { 00518 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00519 return NULL; 00520 } 00521 zvr_in = f; 00522 zvr_restart (zvr_in); 00523 if (zvr_parse () != 0) { 00524 fclose (f); 00525 return NULL; 00526 } 00527 if (zvr_check () != 0) { 00528 fclose (f); 00529 return NULL; 00530 } 00531 fclose (f); 00532 zvr_lex_destroy (); 00533 if (zvr_result) zvr_result->setFile (file); 00534 return zvr_result; 00535 } 00536 00537 /* The function read a full dataset from the given MDL file and 00538 returns it. On failure the function emits appropriate error 00539 messages and returns NULL. */ 00540 dataset * dataset::load_mdl (const char * file) { 00541 FILE * f; 00542 if ((f = fopen (file, "r")) == NULL) { 00543 logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno)); 00544 return NULL; 00545 } 00546 mdl_in = f; 00547 mdl_restart (mdl_in); 00548 if (mdl_parse () != 0) { 00549 fclose (f); 00550 return NULL; 00551 } 00552 if (mdl_check () != 0) { 00553 fclose (f); 00554 return NULL; 00555 } 00556 fclose (f); 00557 mdl_lex_destroy (); 00558 if (mdl_result) mdl_result->setFile (file); 00559 return mdl_result; 00560 } 00561 00562 } // namespace qucs