Qucs-core  0.0.19
check_citi.cpp
Go to the documentation of this file.
00001 /*
00002  * check_citi.cpp - checker for CITIfiles
00003  *
00004  * Copyright (C) 2006 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 <ctype.h>
00033 #include <cmath>
00034 
00035 #include "logging.h"
00036 #include "complex.h"
00037 #include "object.h"
00038 #include "vector.h"
00039 #include "matrix.h"
00040 #include "matvec.h"
00041 #include "dataset.h"
00042 #include "strlist.h"
00043 #include "constants.h"
00044 #include "check_citi.h"
00045 
00046 using namespace qucs;
00047 
00048 qucs::dataset * citi_result = NULL;
00049 struct citi_package_t * citi_root = NULL;
00050 
00051 /* Returns the number of vectors in a package. */
00052 static int citi_count_vectors (struct citi_package_t * p) {
00053   int i = 0;
00054   for (qucs::vector * v = p->data; v != NULL; v = (qucs::vector *) v->getNext ()) i++;
00055   return i;
00056 }
00057 
00058 /* Returns the number of variables in a package. */
00059 static int citi_count_variables (struct citi_package_t * p) {
00060   int i = 0;
00061   for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
00062     if (h->var != NULL) i++;
00063   }
00064   return i;
00065 }
00066 
00067 /* Returns the n-th vector in the package. */
00068 static qucs::vector * citi_get_vector (struct citi_package_t * p, int n) {
00069   qucs::vector * v = p->data;
00070   for (int i = 0; v != NULL; v = (qucs::vector *) v->getNext (), i++) {
00071     if (i == n) return v;
00072   }
00073   return NULL;
00074 }
00075 
00076 /* Returns the number of packages. */
00077 static int citi_count_packages (struct citi_package_t * p) {
00078   int i = 0;
00079   for (; p != NULL; p = p->next) i++;
00080   return i;
00081 }
00082 
00083 /* Find name of the package in its headers. */
00084 static char * citi_get_package (struct citi_package_t * p) {
00085   for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
00086     if (h->package != NULL) return h->package;
00087   }
00088   return NULL;
00089 }
00090 
00091 /* Create a valid vector for the dataset. */
00092 static qucs::vector * citi_create_vector (struct citi_package_t * p, int i,
00093                                     char * n, char * type) {
00094   qucs::vector * vec;
00095   vec = citi_get_vector (p, i); // fetch vector
00096   vec = new qucs::vector (*vec);      // copy vector
00097   vec->reverse ();              // reverse vector
00098 
00099   // convert data if necessary
00100   if (!strcmp (type, "MAGANGLE")) {
00101     for (int i = 0; i < vec->getSize (); i++) {
00102       nr_complex_t val = vec->get (i);
00103       val = std::polar (real (val), deg2rad (imag (val)));
00104       vec->set (val, i);
00105     }
00106   }
00107   else if (!strcmp (type, "DBANGLE")) {
00108     for (int i = 0; i < vec->getSize (); i++) {
00109       nr_complex_t val = vec->get (i);
00110       val = std::polar (std::pow (10.0, real (val) / 20.0), deg2rad (imag (val)));
00111       vec->set (val, i);
00112     }
00113   }
00114 
00115   // return named vector
00116   vec->setName (n);
00117   return vec;
00118 }
00119 
00120 /* Returns dependent variable length for the given dependencies. */
00121 static int citi_vector_length (strlist deps) {
00122   int n = 1;
00123   // no dependencies
00124   if (deps.length () <= 0)
00125     return 0;
00126   // calculate length of resulting dependent variable
00127   for (int i = 0; i < deps.length(); i++) {
00128     qucs::vector * v = citi_result->findDependency (deps.get (i));
00129     if (v != NULL) n *= v->getSize ();
00130   }
00131   return n;
00132 }
00133 
00134 /* Checks length of variable vectors. */
00135 static int citi_check_dep_length (qucs::vector * v, strlist deps, char * package) {
00136   int rlength = v->getSize ();
00137   int dlength = citi_vector_length (deps);
00138   if (rlength != dlength) {
00139     logprint (LOG_ERROR, "checker error, invalid vector `%s' length "
00140               "(%d != %d) in package `%s'\n", v->getName (), rlength, dlength,
00141               package);
00142     return 1;
00143   }
00144   return 0;
00145 }
00146 
00147 // Destroys data used by the CITIfile parser.
00148 void citi_finalize (void) {
00149   struct citi_package_t * p, * pn;
00150   /* go through all packages */
00151   for (p = citi_root; p != NULL; p = pn) {
00152     struct citi_header_t * h, * hn;
00153     /* go through each header */
00154     for (h = p->head; h != NULL; h = hn) {
00155       free (h->package);
00156       free (h->var);
00157       free (h->type);
00158       hn = h->next;
00159       free (h);
00160     }
00161     qucs::vector * v, * vn;
00162     /* go through each vector */
00163     for (v = p->data; v != NULL; v = vn) {
00164       vn = (qucs::vector *) v->getNext ();
00165       delete v;
00166     }
00167     pn = p->next;
00168     free (p);
00169   }
00170   citi_lex_destroy ();
00171 }
00172 
00173 /* This function is the checker routine for a parsed CITIfile.  It
00174    returns zero on success or non-zero if it contained errors. */
00175 int citi_check (void) {
00176 
00177   int errors = 0;
00178 
00179   /* create dataset */
00180   citi_result = new dataset ();
00181   /* get root package */
00182   struct citi_package_t * p = citi_root;
00183   /* count packages */
00184   int packages = citi_count_packages (p);
00185 
00186   /* go through all packages */
00187   for (p = citi_root; p != NULL; p = p->next) {
00188     struct citi_header_t * h;
00189     char * package = citi_get_package (p);
00190     int n = 0;
00191     strlist deps;
00192 
00193     /* check number of defined variables and vectors */
00194     int cvec = citi_count_vectors (p);
00195     int cvar = citi_count_variables (p);
00196     if (cvec != cvar) {
00197       logprint (LOG_ERROR, "checker error, no. of vectors (%d) does not equal "
00198                 "no. of variables (%d) in package `%s'\n", cvec, cvar,
00199                 package);
00200       errors++;
00201       break;
00202     }
00203 
00204     /* no package info if there is just one */
00205     char opack[256];
00206     if (packages < 2) {
00207       opack[0] = '\0';
00208     } else {
00209       sprintf (opack, "%s.", package);
00210     }
00211 
00212     /* go through each header */
00213     for (h = p->head; h != NULL; h = h->next) {
00214       qucs::vector * v;
00215       if (h->var != NULL) {
00216         char txt[256];
00217         if (h->i1 >= 0) {
00218           /* dependent variables */
00219           if (h->i2 >= 0) {
00220             sprintf (txt, "%s%s[%d,%d]", opack, h->var, h->i1, h->i2);
00221             v = citi_create_vector (p, n, txt, h->type);
00222             v->setDependencies (new strlist (deps));
00223             errors += citi_check_dep_length (v, deps, package);
00224             citi_result->addVariable (v);
00225             n++;
00226           } else {
00227             sprintf (txt, "%s%s[%d]", opack, h->var, h->i1);
00228             v = citi_create_vector (p, n, txt, h->type);
00229             v->setDependencies (new strlist (deps));
00230             errors += citi_check_dep_length (v, deps, package);
00231             citi_result->addVariable (v);
00232             n++;
00233           }
00234         } else if (h->n >= 0) {
00235           /* independent variable */
00236           sprintf (txt, "%s%s", opack, h->var);
00237           v = citi_create_vector (p, n, txt, h->type);
00238           deps.add (txt);
00239           if (!citi_result->findDependency (txt)) {
00240             /* add independent vectors only once */
00241             citi_result->addDependency (v);
00242           }
00243           n++;
00244           // check length of independent vector
00245           if (v->getSize () != h->n) {
00246             logprint (LOG_ERROR, "checker error, vector `%s' length (%d) "
00247                       "does not equal defined length (%d) in package `%s'\n",
00248                       h->var, v->getSize (), h->n, package);
00249             errors++;
00250           }
00251         } else {
00252           /* dependent variables, no indices */
00253           sprintf (txt, "%s%s", opack, h->var);
00254           v = citi_create_vector (p, n, txt, h->type);
00255           v->setDependencies (new strlist (deps));
00256           errors += citi_check_dep_length (v, deps, package);
00257           citi_result->addVariable (v);
00258           n++;
00259         }
00260       }
00261     }
00262   }
00263 
00264   citi_finalize ();
00265   citi_root = NULL;
00266   return errors ? -1 : 0;
00267 }
00268 
00269 // Destroys data used by the CITIfile parser and checker.
00270 void citi_destroy (void) {
00271   if (citi_result != NULL) {
00272     // delete associated dataset
00273     delete citi_result;
00274     citi_result = NULL;
00275   }
00276   if (citi_root != NULL) {
00277     citi_finalize ();
00278     citi_root = NULL;
00279   }
00280 }
00281 
00282 // Initializes the CITIfile checker.
00283 void citi_init (void) {
00284   citi_result = NULL;
00285   citi_root = NULL;
00286 }
00287