Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
check_citi.cpp
Go to the documentation of this file.
1 /*
2  * check_citi.cpp - checker for CITIfiles
3  *
4  * Copyright (C) 2006 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id$
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <cmath>
34 
35 #include "logging.h"
36 #include "complex.h"
37 #include "object.h"
38 #include "vector.h"
39 #include "matrix.h"
40 #include "matvec.h"
41 #include "dataset.h"
42 #include "strlist.h"
43 #include "constants.h"
44 #include "check_citi.h"
45 
46 using namespace qucs;
47 
49 struct citi_package_t * citi_root = NULL;
50 
51 /* Returns the number of vectors in a package. */
52 static int citi_count_vectors (struct citi_package_t * p) {
53  int i = 0;
54  for (qucs::vector * v = p->data; v != NULL; v = (qucs::vector *) v->getNext ()) i++;
55  return i;
56 }
57 
58 /* Returns the number of variables in a package. */
59 static int citi_count_variables (struct citi_package_t * p) {
60  int i = 0;
61  for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
62  if (h->var != NULL) i++;
63  }
64  return i;
65 }
66 
67 /* Returns the n-th vector in the package. */
68 static qucs::vector * citi_get_vector (struct citi_package_t * p, int n) {
69  qucs::vector * v = p->data;
70  for (int i = 0; v != NULL; v = (qucs::vector *) v->getNext (), i++) {
71  if (i == n) return v;
72  }
73  return NULL;
74 }
75 
76 /* Returns the number of packages. */
77 static int citi_count_packages (struct citi_package_t * p) {
78  int i = 0;
79  for (; p != NULL; p = p->next) i++;
80  return i;
81 }
82 
83 /* Find name of the package in its headers. */
84 static char * citi_get_package (struct citi_package_t * p) {
85  for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
86  if (h->package != NULL) return h->package;
87  }
88  return NULL;
89 }
90 
91 /* Create a valid vector for the dataset. */
92 static qucs::vector * citi_create_vector (struct citi_package_t * p, int i,
93  char * n, char * type) {
94  qucs::vector * vec;
95  vec = citi_get_vector (p, i); // fetch vector
96  vec = new qucs::vector (*vec); // copy vector
97  vec->reverse (); // reverse vector
98 
99  // convert data if necessary
100  if (!strcmp (type, "MAGANGLE")) {
101  for (int i = 0; i < vec->getSize (); i++) {
102  nr_complex_t val = vec->get (i);
103  val = std::polar (real (val), rad (imag (val)));
104  vec->set (val, i);
105  }
106  }
107  else if (!strcmp (type, "DBANGLE")) {
108  for (int i = 0; i < vec->getSize (); i++) {
109  nr_complex_t val = vec->get (i);
110  val = std::polar (std::pow (10.0, real (val) / 20.0), rad (imag (val)));
111  vec->set (val, i);
112  }
113  }
114 
115  // return named vector
116  vec->setName (n);
117  return vec;
118 }
119 
120 /* Returns dependent variable length for the given dependencies. */
121 static int citi_vector_length (strlist deps) {
122  int n = 1;
123  // no dependencies
124  if (deps.length () <= 0)
125  return 0;
126  // calculate length of resulting dependent variable
127  for (int i = 0; i < deps.length(); i++) {
128  qucs::vector * v = citi_result->findDependency (deps.get (i));
129  if (v != NULL) n *= v->getSize ();
130  }
131  return n;
132 }
133 
134 /* Checks length of variable vectors. */
135 static int citi_check_dep_length (qucs::vector * v, strlist deps, char * package) {
136  int rlength = v->getSize ();
137  int dlength = citi_vector_length (deps);
138  if (rlength != dlength) {
139  logprint (LOG_ERROR, "checker error, invalid vector `%s' length "
140  "(%d != %d) in package `%s'\n", v->getName (), rlength, dlength,
141  package);
142  return 1;
143  }
144  return 0;
145 }
146 
147 // Destroys data used by the CITIfile parser.
148 void citi_finalize (void) {
149  struct citi_package_t * p, * pn;
150  /* go through all packages */
151  for (p = citi_root; p != NULL; p = pn) {
152  struct citi_header_t * h, * hn;
153  /* go through each header */
154  for (h = p->head; h != NULL; h = hn) {
155  if (h->package) free (h->package);
156  if (h->var) free (h->var);
157  if (h->type) free (h->type);
158  hn = h->next;
159  free (h);
160  }
161  qucs::vector * v, * vn;
162  /* go through each vector */
163  for (v = p->data; v != NULL; v = vn) {
164  vn = (qucs::vector *) v->getNext ();
165  delete v;
166  }
167  pn = p->next;
168  free (p);
169  }
170  citi_lex_destroy ();
171 }
172 
173 /* This function is the checker routine for a parsed CITIfile. It
174  returns zero on success or non-zero if it contained errors. */
175 int citi_check (void) {
176 
177  int errors = 0;
178 
179  /* create dataset */
180  citi_result = new dataset ();
181  /* get root package */
182  struct citi_package_t * p = citi_root;
183  /* count packages */
184  int packages = citi_count_packages (p);
185 
186  /* go through all packages */
187  for (p = citi_root; p != NULL; p = p->next) {
188  struct citi_header_t * h;
189  char * package = citi_get_package (p);
190  int n = 0;
191  strlist deps;
192 
193  /* check number of defined variables and vectors */
194  int cvec = citi_count_vectors (p);
195  int cvar = citi_count_variables (p);
196  if (cvec != cvar) {
197  logprint (LOG_ERROR, "checker error, no. of vectors (%d) does not equal "
198  "no. of variables (%d) in package `%s'\n", cvec, cvar,
199  package);
200  errors++;
201  break;
202  }
203 
204  /* no package info if there is just one */
205  char opack[256];
206  if (packages < 2) {
207  opack[0] = '\0';
208  } else {
209  sprintf (opack, "%s.", package);
210  }
211 
212  /* go through each header */
213  for (h = p->head; h != NULL; h = h->next) {
214  qucs::vector * v;
215  if (h->var != NULL) {
216  char txt[256];
217  if (h->i1 >= 0) {
218  /* dependent variables */
219  if (h->i2 >= 0) {
220  sprintf (txt, "%s%s[%d,%d]", opack, h->var, h->i1, h->i2);
221  v = citi_create_vector (p, n, txt, h->type);
222  v->setDependencies (new strlist (deps));
223  errors += citi_check_dep_length (v, deps, package);
225  n++;
226  } else {
227  sprintf (txt, "%s%s[%d]", opack, h->var, h->i1);
228  v = citi_create_vector (p, n, txt, h->type);
229  v->setDependencies (new strlist (deps));
230  errors += citi_check_dep_length (v, deps, package);
232  n++;
233  }
234  } else if (h->n >= 0) {
235  /* independent variable */
236  sprintf (txt, "%s%s", opack, h->var);
237  v = citi_create_vector (p, n, txt, h->type);
238  deps.add (txt);
239  if (!citi_result->findDependency (txt)) {
240  /* add independent vectors only once */
242  }
243  n++;
244  // check length of independent vector
245  if (v->getSize () != h->n) {
246  logprint (LOG_ERROR, "checker error, vector `%s' length (%d) "
247  "does not equal defined length (%d) in package `%s'\n",
248  h->var, v->getSize (), h->n, package);
249  errors++;
250  }
251  } else {
252  /* dependent variables, no indices */
253  sprintf (txt, "%s%s", opack, h->var);
254  v = citi_create_vector (p, n, txt, h->type);
255  v->setDependencies (new strlist (deps));
256  errors += citi_check_dep_length (v, deps, package);
258  n++;
259  }
260  }
261  }
262  }
263 
264  citi_finalize ();
265  citi_root = NULL;
266  return errors ? -1 : 0;
267 }
268 
269 // Destroys data used by the CITIfile parser and checker.
270 void citi_destroy (void) {
271  if (citi_result != NULL) {
272  // delete associated dataset
273  delete citi_result;
274  citi_result = NULL;
275  }
276  if (citi_root != NULL) {
277  citi_finalize ();
278  citi_root = NULL;
279  }
280 }
281 
282 // Initializes the CITIfile checker.
283 void citi_init (void) {
284  citi_result = NULL;
285  citi_root = NULL;
286 }
287 
void addDependency(qucs::vector *)
Definition: dataset.cpp:95
static int citi_vector_length(strlist deps)
Definition: check_citi.cpp:121
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
matrix real(matrix a)
Real part matrix.
Definition: matrix.cpp:568
void citi_init(void)
Definition: check_citi.cpp:283
int getSize(void) const
Definition: vector.cpp:192
void reverse(void)
Definition: vector.cpp:903
nr_complex_t pow(const nr_complex_t z, const nr_double_t d)
Compute power function with real exponent.
Definition: complex.cpp:238
char * type
Definition: check_citi.h:39
static int citi_count_variables(struct citi_package_t *p)
Definition: check_citi.cpp:59
void citi_destroy(void)
Definition: check_citi.cpp:270
Global physical constants header file.
int citi_check(void)
Definition: check_citi.cpp:175
struct citi_package_t * next
Definition: check_citi.h:48
n
Definition: parse_citi.y:147
h
Definition: parse_vcd.y:214
object * getNext(void)
Definition: object.h:59
static qucs::vector * citi_create_vector(struct citi_package_t *p, int i, char *n, char *type)
Definition: check_citi.cpp:92
void setDependencies(strlist *)
Definition: vector.cpp:143
i
Definition: parse_mdl.y:516
char * package
Definition: check_citi.h:37
matrix imag(matrix a)
Imaginary part matrix.
Definition: matrix.cpp:581
void setName(const char *)
Definition: object.cpp:78
void citi_finalize(void)
Definition: check_citi.cpp:148
free($1)
static int citi_count_packages(struct citi_package_t *p)
Definition: check_citi.cpp:77
char * var
Definition: check_citi.h:38
void set(nr_double_t, int)
Definition: vector.cpp:183
Dense matrix class header file.
struct citi_header_t * next
Definition: check_citi.h:42
qucs::vector * data
Definition: check_citi.h:47
struct citi_package_t * citi_root
Definition: check_citi.cpp:49
void addVariable(qucs::vector *)
Definition: dataset.cpp:153
#define rad(x)
Convert degree to radian.
Definition: constants.h:118
type
Definition: parse_vcd.y:164
static int citi_check_dep_length(qucs::vector *v, strlist deps, char *package)
Definition: check_citi.cpp:135
v
Definition: parse_zvr.y:141
HeaderLine package
Definition: parse_citi.y:141
int citi_lex_destroy(void)
qucs::dataset * citi_result
Definition: check_citi.cpp:48
struct citi_header_t * head
Definition: check_citi.h:46
#define LOG_ERROR
Definition: logging.h:28
char * getName(void)
Definition: object.cpp:84
qucs::vector * findDependency(const char *)
Definition: dataset.cpp:281
nr_complex_t polar(const nr_double_t mag, const nr_double_t ang)
Construct a complex number using polar notation.
Definition: complex.cpp:551
static qucs::vector * citi_get_vector(struct citi_package_t *p, int n)
Definition: check_citi.cpp:68
void logprint(int level, const char *format,...)
Definition: logging.c:37
nr_complex_t get(int)
Definition: vector.cpp:179
static char * citi_get_package(struct citi_package_t *p)
Definition: check_citi.cpp:84
static int citi_count_vectors(struct citi_package_t *p)
Definition: check_citi.cpp:52