Branch data Line data Source code
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 : :
48 : : qucs::dataset * citi_result = NULL;
49 : : struct citi_package_t * citi_root = NULL;
50 : :
51 : : /* Returns the number of vectors in a package. */
52 : 0 : static int citi_count_vectors (struct citi_package_t * p) {
53 : 0 : int i = 0;
54 [ # # ]: 0 : for (qucs::vector * v = p->data; v != NULL; v = (qucs::vector *) v->getNext ()) i++;
55 : 0 : return i;
56 : : }
57 : :
58 : : /* Returns the number of variables in a package. */
59 : 0 : static int citi_count_variables (struct citi_package_t * p) {
60 : 0 : int i = 0;
61 [ # # ]: 0 : for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
62 [ # # ]: 0 : if (h->var != NULL) i++;
63 : : }
64 : 0 : return i;
65 : : }
66 : :
67 : : /* Returns the n-th vector in the package. */
68 : 0 : static qucs::vector * citi_get_vector (struct citi_package_t * p, int n) {
69 : 0 : qucs::vector * v = p->data;
70 [ # # ]: 0 : for (int i = 0; v != NULL; v = (qucs::vector *) v->getNext (), i++) {
71 [ # # ]: 0 : if (i == n) return v;
72 : : }
73 : 0 : return NULL;
74 : : }
75 : :
76 : : /* Returns the number of packages. */
77 : 0 : static int citi_count_packages (struct citi_package_t * p) {
78 : 0 : int i = 0;
79 [ # # ]: 0 : for (; p != NULL; p = p->next) i++;
80 : 0 : return i;
81 : : }
82 : :
83 : : /* Find name of the package in its headers. */
84 : 0 : static char * citi_get_package (struct citi_package_t * p) {
85 [ # # ]: 0 : for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
86 [ # # ]: 0 : if (h->package != NULL) return h->package;
87 : : }
88 : 0 : return NULL;
89 : : }
90 : :
91 : : /* Create a valid vector for the dataset. */
92 : 0 : static qucs::vector * citi_create_vector (struct citi_package_t * p, int i,
93 : : char * n, char * type) {
94 : : qucs::vector * vec;
95 : 0 : vec = citi_get_vector (p, i); // fetch vector
96 [ # # ]: 0 : vec = new qucs::vector (*vec); // copy vector
97 : 0 : vec->reverse (); // reverse vector
98 : :
99 : : // convert data if necessary
100 [ # # ]: 0 : if (!strcmp (type, "MAGANGLE")) {
101 [ # # ]: 0 : for (int i = 0; i < vec->getSize (); i++) {
102 [ # # ]: 0 : nr_complex_t val = vec->get (i);
103 : 0 : val = std::polar (real (val), rad (imag (val)));
104 [ # # ]: 0 : vec->set (val, i);
105 : : }
106 : : }
107 [ # # ]: 0 : else if (!strcmp (type, "DBANGLE")) {
108 [ # # ]: 0 : for (int i = 0; i < vec->getSize (); i++) {
109 [ # # ]: 0 : nr_complex_t val = vec->get (i);
110 : 0 : val = std::polar (std::pow (10.0, real (val) / 20.0), rad (imag (val)));
111 [ # # ]: 0 : vec->set (val, i);
112 : : }
113 : : }
114 : :
115 : : // return named vector
116 : 0 : vec->setName (n);
117 : 0 : return vec;
118 : : }
119 : :
120 : : /* Returns dependent variable length for the given dependencies. */
121 : 0 : static int citi_vector_length (strlist deps) {
122 : 0 : int n = 1;
123 : : // no dependencies
124 [ # # ]: 0 : if (deps.length () <= 0)
125 : 0 : return 0;
126 : : // calculate length of resulting dependent variable
127 [ # # ]: 0 : for (int i = 0; i < deps.length(); i++) {
128 : 0 : qucs::vector * v = citi_result->findDependency (deps.get (i));
129 [ # # ]: 0 : if (v != NULL) n *= v->getSize ();
130 : : }
131 : 0 : return n;
132 : : }
133 : :
134 : : /* Checks length of variable vectors. */
135 : 0 : static int citi_check_dep_length (qucs::vector * v, strlist deps, char * package) {
136 : 0 : int rlength = v->getSize ();
137 [ # # ]: 0 : int dlength = citi_vector_length (deps);
138 [ # # ]: 0 : 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 : 0 : package);
142 : 0 : return 1;
143 : : }
144 : 0 : return 0;
145 : : }
146 : :
147 : : // Destroys data used by the CITIfile parser.
148 : 0 : void citi_finalize (void) {
149 : : struct citi_package_t * p, * pn;
150 : : /* go through all packages */
151 [ # # ]: 0 : for (p = citi_root; p != NULL; p = pn) {
152 : : struct citi_header_t * h, * hn;
153 : : /* go through each header */
154 [ # # ]: 0 : for (h = p->head; h != NULL; h = hn) {
155 [ # # ]: 0 : if (h->package) free (h->package);
156 [ # # ]: 0 : if (h->var) free (h->var);
157 [ # # ]: 0 : if (h->type) free (h->type);
158 : 0 : hn = h->next;
159 : 0 : free (h);
160 : : }
161 : : qucs::vector * v, * vn;
162 : : /* go through each vector */
163 [ # # ]: 0 : for (v = p->data; v != NULL; v = vn) {
164 : 0 : vn = (qucs::vector *) v->getNext ();
165 [ # # ]: 0 : delete v;
166 : : }
167 : 0 : pn = p->next;
168 : 0 : free (p);
169 : : }
170 : 0 : citi_lex_destroy ();
171 : 0 : }
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 : 0 : int citi_check (void) {
176 : :
177 : 0 : int errors = 0;
178 : :
179 : : /* create dataset */
180 [ # # ]: 0 : citi_result = new dataset ();
181 : : /* get root package */
182 : 0 : struct citi_package_t * p = citi_root;
183 : : /* count packages */
184 : 0 : int packages = citi_count_packages (p);
185 : :
186 : : /* go through all packages */
187 [ # # ]: 0 : for (p = citi_root; p != NULL; p = p->next) {
188 : : struct citi_header_t * h;
189 : 0 : char * package = citi_get_package (p);
190 : 0 : int n = 0;
191 [ # # ]: 0 : strlist deps;
192 : :
193 : : /* check number of defined variables and vectors */
194 : 0 : int cvec = citi_count_vectors (p);
195 : 0 : int cvar = citi_count_variables (p);
196 [ # # ]: 0 : 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 [ # # ]: 0 : package);
200 : 0 : errors++;
201 : : break;
202 : : }
203 : :
204 : : /* no package info if there is just one */
205 : : char opack[256];
206 [ # # ]: 0 : if (packages < 2) {
207 : 0 : opack[0] = '\0';
208 : : } else {
209 : 0 : sprintf (opack, "%s.", package);
210 : : }
211 : :
212 : : /* go through each header */
213 [ # # ]: 0 : for (h = p->head; h != NULL; h = h->next) {
214 : : qucs::vector * v;
215 [ # # ]: 0 : if (h->var != NULL) {
216 : : char txt[256];
217 [ # # ]: 0 : if (h->i1 >= 0) {
218 : : /* dependent variables */
219 [ # # ]: 0 : if (h->i2 >= 0) {
220 : 0 : sprintf (txt, "%s%s[%d,%d]", opack, h->var, h->i1, h->i2);
221 [ # # ]: 0 : v = citi_create_vector (p, n, txt, h->type);
222 [ # # ][ # # ]: 0 : v->setDependencies (new strlist (deps));
[ # # ]
223 [ # # ][ # # ]: 0 : errors += citi_check_dep_length (v, deps, package);
[ # # ]
224 [ # # ]: 0 : citi_result->addVariable (v);
225 : 0 : n++;
226 : : } else {
227 : 0 : sprintf (txt, "%s%s[%d]", opack, h->var, h->i1);
228 [ # # ]: 0 : v = citi_create_vector (p, n, txt, h->type);
229 [ # # ][ # # ]: 0 : v->setDependencies (new strlist (deps));
[ # # ]
230 [ # # ][ # # ]: 0 : errors += citi_check_dep_length (v, deps, package);
[ # # ]
231 [ # # ]: 0 : citi_result->addVariable (v);
232 : 0 : n++;
233 : : }
234 [ # # ]: 0 : } else if (h->n >= 0) {
235 : : /* independent variable */
236 : 0 : sprintf (txt, "%s%s", opack, h->var);
237 [ # # ]: 0 : v = citi_create_vector (p, n, txt, h->type);
238 [ # # ]: 0 : deps.add (txt);
239 [ # # ][ # # ]: 0 : if (!citi_result->findDependency (txt)) {
240 : : /* add independent vectors only once */
241 [ # # ]: 0 : citi_result->addDependency (v);
242 : : }
243 : 0 : n++;
244 : : // check length of independent vector
245 [ # # ][ # # ]: 0 : 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 [ # # ][ # # ]: 0 : h->var, v->getSize (), h->n, package);
249 : 0 : errors++;
250 : : }
251 : : } else {
252 : : /* dependent variables, no indices */
253 : 0 : sprintf (txt, "%s%s", opack, h->var);
254 [ # # ]: 0 : v = citi_create_vector (p, n, txt, h->type);
255 [ # # ][ # # ]: 0 : v->setDependencies (new strlist (deps));
[ # # ]
256 [ # # ][ # # ]: 0 : errors += citi_check_dep_length (v, deps, package);
[ # # ]
257 [ # # ]: 0 : citi_result->addVariable (v);
258 : 0 : n++;
259 : : }
260 : : }
261 : : }
262 [ # # ][ # # ]: 0 : }
263 : :
264 : 0 : citi_finalize ();
265 : 0 : citi_root = NULL;
266 [ # # ]: 0 : return errors ? -1 : 0;
267 : : }
268 : :
269 : : // Destroys data used by the CITIfile parser and checker.
270 : 0 : void citi_destroy (void) {
271 [ # # ]: 0 : if (citi_result != NULL) {
272 : : // delete associated dataset
273 [ # # ]: 0 : delete citi_result;
274 : 0 : citi_result = NULL;
275 : : }
276 [ # # ]: 0 : if (citi_root != NULL) {
277 : 0 : citi_finalize ();
278 : 0 : citi_root = NULL;
279 : : }
280 : 0 : }
281 : :
282 : : // Initializes the CITIfile checker.
283 : 0 : void citi_init (void) {
284 : 0 : citi_result = NULL;
285 : 0 : citi_root = NULL;
286 : 0 : }
287 : :
|