Qucs-core  0.0.19
dataset.cpp
Go to the documentation of this file.
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