Branch data Line data Source code
1 : : /*
2 : : * dataset.cpp - dataset class implementation
3 : : *
4 : : * Copyright (C) 2003, 2004, 2005, 2006, 2007 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 <errno.h>
33 : : #include <assert.h>
34 : : #include <cmath>
35 : :
36 : : #include "logging.h"
37 : : #include "complex.h"
38 : : #include "object.h"
39 : : #include "strlist.h"
40 : : #include "vector.h"
41 : : #include "dataset.h"
42 : : #include "check_dataset.h"
43 : : #include "check_touchstone.h"
44 : : #include "check_csv.h"
45 : : #include "check_citi.h"
46 : : #include "check_zvr.h"
47 : : #include "check_mdl.h"
48 : :
49 : : namespace qucs {
50 : :
51 : : // Constructor creates an unnamed instance of the dataset class.
52 : 103 : dataset::dataset () : object () {
53 : 103 : variables = dependencies = NULL;
54 : 103 : file = NULL;
55 : 103 : }
56 : :
57 : : // Constructor creates an named instance of the dataset class.
58 : 0 : dataset::dataset (char * n) : object (n) {
59 : 0 : variables = dependencies = NULL;
60 : 0 : file = NULL;
61 : 0 : }
62 : :
63 : : /* The copy constructor creates a new instance based on the given
64 : : dataset object. */
65 : 0 : dataset::dataset (const dataset & d) : object (d) {
66 [ # # ][ # # ]: 0 : file = d.file ? strdup (d.file) : NULL;
[ # # ][ # # ]
67 : : vector * v;
68 : : // copy dependency vectors
69 [ # # ][ # # ]: 0 : for (v = d.dependencies; v != NULL; v = (vector *) v->getNext ()) {
70 [ # # ][ # # ]: 0 : addDependency (new vector (*v));
[ # # ][ # # ]
71 : : }
72 : : // copy variable vectors
73 [ # # ][ # # ]: 0 : for (v = variables; v != NULL; v = (vector *) v->getNext ()) {
74 [ # # ][ # # ]: 0 : addVariable (new vector (*v));
[ # # ][ # # ]
75 : : }
76 : 0 : }
77 : :
78 : : // Destructor deletes a dataset object.
79 : 103 : dataset::~dataset () {
80 : : vector * n, * v;
81 : : // delete dependency vectors
82 [ + + ][ # # ]: 298 : for (v = dependencies; v != NULL; v = n) {
83 : 195 : n = (vector *) v->getNext ();
84 [ + - ]: 195 : delete v;
[ + - # # ]
[ # # ]
85 : : }
86 : : // delete variable vectors
87 [ + + ][ # # ]: 1178 : for (v = variables; v != NULL; v = n) {
88 : 1075 : n = (vector *) v->getNext ();
89 [ + - ]: 1075 : delete v;
[ + - # # ]
[ # # ]
90 : : }
91 [ + + ][ # # ]: 103 : if (file) free (file);
92 [ - + ][ # # ]: 206 : }
93 : :
94 : : // This function adds a dependency vector to the current dataset.
95 : 195 : void dataset::addDependency (vector * v) {
96 [ + + ]: 195 : if (dependencies) dependencies->setPrev (v);
97 : 195 : v->setNext (dependencies);
98 : 195 : v->setPrev (NULL);
99 : 195 : dependencies = v;
100 : 195 : }
101 : :
102 : : // This function removes a dependency vector from the current dataset.
103 : 0 : void dataset::delDependency (vector * v) {
104 [ # # ]: 0 : if (dependencies == v) {
105 : 0 : dependencies = (vector *) v->getNext ();
106 [ # # ]: 0 : if (dependencies) dependencies->setPrev (NULL);
107 : : }
108 : : else {
109 : 0 : vector * next = (vector *) v->getNext ();
110 : 0 : vector * prev = (vector *) v->getPrev ();
111 : 0 : prev->setNext (next);
112 [ # # ]: 0 : if (next) next->setPrev (prev);
113 : : }
114 [ # # ]: 0 : delete v;
115 : 0 : }
116 : :
117 : : /* The function adds the given list of vectors to the dependency set
118 : : of the current dataset. */
119 : 0 : void dataset::addDependencies (vector * v) {
120 : : vector * next;
121 [ # # ]: 0 : for (vector * t = v; t != NULL; t = next) {
122 : 0 : next = (vector *) t->getNext ();
123 : 0 : addDependency (t);
124 : : }
125 : 0 : }
126 : :
127 : : // This function appends a dependency vector to the current dataset.
128 : 0 : void dataset::appendDependency (vector * v) {
129 : : vector * e;
130 [ # # ]: 0 : if (dependencies) {
131 [ # # ]: 0 : for (e = dependencies; e->getNext (); e = (vector *) e->getNext ()) ;
132 : 0 : v->setPrev (e);
133 : 0 : e->setNext (v);
134 : : }
135 : : else {
136 : 0 : v->setPrev (NULL);
137 : 0 : dependencies= v;
138 : : }
139 : 0 : v->setNext (NULL);
140 : 0 : }
141 : :
142 : : /* The function appends the given list of vectors to the dependency
143 : : set of the current dataset. */
144 : 0 : void dataset::appendDependencies (vector * v) {
145 : : vector * next;
146 [ # # ]: 0 : for (vector * t = v; t != NULL; t = next) {
147 : 0 : next = (vector *) t->getNext ();
148 : 0 : appendDependency (t);
149 : : }
150 : 0 : }
151 : :
152 : : // This function adds a variable vector to the current dataset.
153 : 1075 : void dataset::addVariable (vector * v) {
154 [ + + ]: 1075 : if (variables) variables->setPrev (v);
155 : 1075 : v->setNext (variables);
156 : 1075 : v->setPrev (NULL);
157 : 1075 : variables = v;
158 : 1075 : }
159 : :
160 : : // This function removes a variable vector from the current dataset.
161 : 0 : void dataset::delVariable (vector * v) {
162 [ # # ]: 0 : if (variables == v) {
163 : 0 : variables = (vector *) v->getNext ();
164 [ # # ]: 0 : if (variables) variables->setPrev (NULL);
165 : : }
166 : : else {
167 : 0 : vector * next = (vector *) v->getNext ();
168 : 0 : vector * prev = (vector *) v->getPrev ();
169 : 0 : prev->setNext (next);
170 [ # # ]: 0 : if (next) next->setPrev (prev);
171 : : }
172 [ # # ]: 0 : delete v;
173 : 0 : }
174 : :
175 : : /* The function adds the given list of vectors to the variable set of
176 : : the current dataset. */
177 : 0 : void dataset::addVariables (vector * v) {
178 : : vector * next;
179 [ # # ]: 0 : for (vector * t = v; t != NULL; t = next) {
180 : 0 : next = (vector *) t->getNext ();
181 : 0 : addVariable (t);
182 : : }
183 : 0 : }
184 : :
185 : : // This function appends a variable vector to the current dataset.
186 : 0 : void dataset::appendVariable (vector * v) {
187 : : vector * e;
188 [ # # ]: 0 : if (variables) {
189 [ # # ]: 0 : for (e = variables; e->getNext (); e = (vector *) e->getNext ()) ;
190 : 0 : v->setPrev (e);
191 : 0 : e->setNext (v);
192 : : }
193 : : else {
194 : 0 : v->setPrev (NULL);
195 : 0 : variables = v;
196 : : }
197 : 0 : v->setNext (NULL);
198 : 0 : }
199 : :
200 : : /* The function appends the given list of vectors to the variable set
201 : : of the current dataset. */
202 : 0 : void dataset::appendVariables (vector * v) {
203 : : vector * next;
204 [ # # ]: 0 : for (vector * t = v; t != NULL; t = next) {
205 : 0 : next = (vector *) t->getNext ();
206 : 0 : appendVariable (t);
207 : : }
208 : 0 : }
209 : :
210 : : /* This function applies the dependency string list of the given
211 : : vector to the list of vectors appended to this vector. */
212 : 0 : void dataset::applyDependencies (vector * v) {
213 : 0 : strlist * deps = v->getDependencies ();
214 [ # # ]: 0 : if (deps != NULL) {
215 : : vector * next;
216 [ # # ]: 0 : for (vector * t = (vector *) v->getNext (); t != NULL; t = next) {
217 : 0 : next = (vector *) t->getNext ();
218 [ # # ]: 0 : if (t->getDependencies () == NULL) {
219 [ # # ]: 0 : t->setDependencies (new strlist (*deps));
220 : : }
221 : : }
222 : : }
223 : 0 : }
224 : :
225 : : /* This function returns the dataset vector (both independent and
226 : : dependent) with the given origin. It returns NULL if there is no
227 : : such vector. */
228 : 0 : vector * dataset::findOrigin (char * n) {
229 : : vector * v;
230 [ # # ]: 0 : for (v = variables; v != NULL; v = (vector *) v->getNext ()) {
231 : 0 : char * origin = v->getOrigin ();
232 [ # # ][ # # ]: 0 : if (origin != NULL && n != NULL && !strcmp (n, origin))
[ # # ]
233 : 0 : return v;
234 : : }
235 [ # # ]: 0 : for (v = dependencies; v != NULL; v = (vector *) v->getNext ()) {
236 : 0 : char * origin = v->getOrigin ();
237 [ # # ][ # # ]: 0 : if (origin != NULL && n != NULL && !strcmp (n, origin))
[ # # ]
238 : 0 : return v;
239 : : }
240 : 0 : return NULL;
241 : : }
242 : :
243 : : /* This function assigns dependency entries to variable vectors which
244 : : do have the specified origin. */
245 : 22680 : void dataset::assignDependency (const char * const origin, const char * const depvar) {
246 [ + + ]: 108543 : for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) {
247 : 85863 : char * n = v->getOrigin ();
248 [ + - ][ + - ]: 85863 : if (n != NULL && origin != NULL && !strcmp (origin, n)) {
[ + - ]
249 : 85863 : strlist * deplist = v->getDependencies ();
250 [ + + ]: 85863 : if (deplist != NULL) {
251 [ + + ]: 85605 : if (!deplist->contains (depvar)) {
252 : 226 : deplist->append (depvar);
253 : : }
254 : : }
255 : : else {
256 [ + - ]: 258 : deplist = new strlist ();
257 : 258 : deplist->add (depvar);
258 : 258 : v->setDependencies (deplist);
259 : : }
260 : : }
261 : : }
262 : 22680 : }
263 : :
264 : : // Return non-zero if the given vector is an independent variable vector.
265 : 0 : int dataset::isDependency (vector * dep) {
266 [ # # ]: 0 : for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ())
267 [ # # ]: 0 : if (v == dep) return 1;
268 : 0 : return 0;
269 : : }
270 : :
271 : : // Return non-zero if the given vector is a dependent variable vector.
272 : 0 : int dataset::isVariable (vector * var) {
273 [ # # ]: 0 : for (vector * v = variables; v != NULL; v = (vector *) v->getNext ())
274 [ # # ]: 0 : if (v == var) return 1;
275 : 0 : return 0;
276 : : }
277 : :
278 : : /* The function goes through the list of dependencies in the dataset
279 : : and returns the vector specified by the given name. Otherwise the
280 : : function returns NULL. */
281 : 70219 : vector * dataset::findDependency (const char * n) {
282 [ + + ]: 70820 : for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ()) {
283 [ + + ]: 70542 : if (!strcmp (v->getName (), n))
284 : 69941 : return v;
285 : : }
286 : 70219 : return NULL;
287 : : }
288 : :
289 : : /* The function goes through the list of variables in the dataset and
290 : : returns the vector specified by the given name. If there is no
291 : : such variable registered the function returns NULL. */
292 : 515813 : vector * dataset::findVariable (const char * n) {
293 [ + + ]: 2496951 : for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) {
294 [ + + ]: 2495791 : if (!strcmp (v->getName (), n))
295 : 514653 : return v;
296 : : }
297 : 515813 : return NULL;
298 : : }
299 : :
300 : : // Returns the number of variable vectors.
301 : 0 : int dataset::countVariables (void) {
302 : 0 : int count = 0;
303 [ # # ]: 0 : for (vector * v = variables; v != NULL; v = (vector *) v->getNext ())
304 : 0 : count++;
305 : 0 : return count;
306 : : }
307 : :
308 : : // Returns the number of dependency vectors.
309 : 0 : int dataset::countDependencies (void) {
310 : 0 : int count = 0;
311 [ # # ]: 0 : for (vector * v = dependencies; v != NULL; v = (vector *) v->getNext ())
312 : 0 : count++;
313 : 0 : return count;
314 : : }
315 : :
316 : : // Returns the current output file name.
317 : 0 : char * dataset::getFile (void) {
318 : 0 : return file;
319 : : }
320 : :
321 : : /* Sets the current output file name. The file name is used during
322 : : the print functionality of the dataset class. */
323 : 103 : void dataset::setFile (const char * f) {
324 [ - + ]: 103 : if (file) free (file);
325 [ + + ]: 103 : file = f ? strdup (f) : NULL;
326 : 103 : }
327 : :
328 : : /* This function prints the current dataset representation either to
329 : : the specified file name (given by the function setFile()) or to
330 : : stdout if there is no such file name given. */
331 : 103 : void dataset::print (void) {
332 : :
333 : 103 : FILE * f = stdout;
334 : :
335 : : // open file for writing
336 [ + + ]: 103 : if (file) {
337 [ - + ]: 64 : if ((f = fopen (file, "w")) == NULL) {
338 : : logprint (LOG_ERROR, "cannot create file `%s': %s\n",
339 : 0 : file, strerror (errno));
340 : 103 : return;
341 : : }
342 : : }
343 : :
344 : : // print header
345 : 103 : fprintf (f, "<Qucs Dataset " PACKAGE_VERSION ">\n");
346 : :
347 : : // print dependencies
348 [ + + ]: 298 : for (vector * d = dependencies; d != NULL; d = (vector *) d->getNext ()) {
349 : 195 : printDependency (d, f);
350 : : }
351 : :
352 : : // print variables
353 [ + + ]: 1178 : for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) {
354 [ + + ]: 1075 : if (v->getDependencies () != NULL)
355 : 927 : printVariable (v, f);
356 : : else
357 : 148 : printDependency (v, f);
358 : : }
359 : :
360 : : // close file if necessary
361 [ + + ]: 103 : if (file) fclose (f);
362 : : }
363 : :
364 : : /* Prints the given vector as independent dataset vector into the
365 : : given file descriptor. */
366 : 343 : void dataset::printDependency (vector * v, FILE * f) {
367 : : // print data header
368 : 343 : fprintf (f, "<indep %s %d>\n", v->getName (), v->getSize ());
369 : : // print data itself
370 : 343 : printData (v, f);
371 : : // print data footer
372 : 343 : fprintf (f, "</indep>\n");
373 : 343 : }
374 : :
375 : : /* Prints the given vector as dependent dataset vector into the given
376 : : file descriptor. */
377 : 927 : void dataset::printVariable (vector * v, FILE * f) {
378 : : // print data header
379 : 927 : fprintf (f, "<dep %s", v->getName ());
380 [ + - ]: 927 : if (v->getDependencies () != NULL) {
381 [ + - ][ + - ]: 2092 : for (strlistiterator it (v->getDependencies ()); *it; ++it)
[ + - ][ + - ]
[ + + ]
382 [ + - ][ + - ]: 2092 : fprintf (f, " %s", *it);
[ + - ]
383 : : }
384 : 927 : fprintf (f, ">\n");
385 : :
386 : : // print data itself
387 : 927 : printData (v, f);
388 : :
389 : : // print data footer
390 : 927 : fprintf (f, "</dep>\n");
391 : 927 : }
392 : :
393 : : /* This function is a helper routine for the print() functionality of
394 : : the dataset class. It prints the data items of the given vector
395 : : object to the given output stream. */
396 : 1270 : void dataset::printData (vector * v, FILE * f) {
397 [ + + ]: 586495 : for (int i = 0; i < v->getSize (); i++) {
398 [ + - ]: 585225 : nr_complex_t c = v->get (i);
399 [ + + ]: 585225 : if (imag (c) == 0.0) {
400 [ + - ]: 537536 : fprintf (f, " %+." "20" "e\n", (double) real (c));
401 : : }
402 : : else {
403 : : fprintf (f, " %+." "20" "e%cj%." "20" "e\n", (double) real (c),
404 [ + + ][ + - ]: 47689 : imag (c) >= 0.0 ? '+' : '-', (double) fabs (imag (c)));
405 : : }
406 : : }
407 : 1270 : }
408 : :
409 : : /* This static function read a full dataset from the given file and
410 : : returns it. On failure the function emits appropriate error
411 : : messages and returns NULL. */
412 : 0 : dataset * dataset::load (const char * file) {
413 : : FILE * f;
414 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
415 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
416 : 0 : return NULL;
417 : : }
418 : 0 : dataset_in = f;
419 : 0 : dataset_restart (dataset_in);
420 [ # # ]: 0 : if (dataset_parse () != 0) {
421 : 0 : fclose (f);
422 : 0 : return NULL;
423 : : }
424 [ # # ]: 0 : if (dataset_result != NULL) {
425 [ # # ]: 0 : if (dataset_check (dataset_result) != 0) {
426 : 0 : fclose (f);
427 [ # # ]: 0 : delete dataset_result;
428 : 0 : return NULL;
429 : : }
430 : : }
431 : 0 : fclose (f);
432 : 0 : dataset_lex_destroy ();
433 : 0 : dataset_result->setFile (file);
434 : 0 : return dataset_result;
435 : : }
436 : :
437 : : /* This static function read a full dataset from the given touchstone
438 : : file and returns it. On failure the function emits appropriate
439 : : error messages and returns NULL. */
440 : 0 : dataset * dataset::load_touchstone (const char * file) {
441 : : FILE * f;
442 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
443 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
444 : 0 : return NULL;
445 : : }
446 : 0 : touchstone_in = f;
447 : 0 : touchstone_restart (touchstone_in);
448 [ # # ]: 0 : if (touchstone_parse () != 0) {
449 : 0 : fclose (f);
450 : 0 : return NULL;
451 : : }
452 [ # # ]: 0 : if (touchstone_check () != 0) {
453 : 0 : fclose (f);
454 : 0 : return NULL;
455 : : }
456 : 0 : fclose (f);
457 : 0 : touchstone_lex_destroy ();
458 : 0 : touchstone_result->setFile (file);
459 : 0 : return touchstone_result;
460 : : }
461 : :
462 : : /* This static function read a full dataset from the given CSV file
463 : : and returns it. On failure the function emits appropriate error
464 : : messages and returns NULL. */
465 : 0 : dataset * dataset::load_csv (const char * file) {
466 : : FILE * f;
467 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
468 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
469 : 0 : return NULL;
470 : : }
471 : 0 : csv_in = f;
472 : 0 : csv_restart (csv_in);
473 [ # # ]: 0 : if (csv_parse () != 0) {
474 : 0 : fclose (f);
475 : 0 : return NULL;
476 : : }
477 [ # # ]: 0 : if (csv_check () != 0) {
478 : 0 : fclose (f);
479 : 0 : return NULL;
480 : : }
481 : 0 : fclose (f);
482 : 0 : csv_lex_destroy ();
483 : 0 : csv_result->setFile (file);
484 : 0 : return csv_result;
485 : : }
486 : :
487 : : /* The function read a full dataset from the given CITIfile and
488 : : returns it. On failure the function emits appropriate error
489 : : messages and returns NULL. */
490 : 0 : dataset * dataset::load_citi (const char * file) {
491 : : FILE * f;
492 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
493 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
494 : 0 : return NULL;
495 : : }
496 : 0 : citi_in = f;
497 : 0 : citi_restart (citi_in);
498 [ # # ]: 0 : if (citi_parse () != 0) {
499 : 0 : fclose (f);
500 : 0 : return NULL;
501 : : }
502 [ # # ]: 0 : if (citi_check () != 0) {
503 : 0 : fclose (f);
504 : 0 : return NULL;
505 : : }
506 : 0 : fclose (f);
507 : 0 : citi_lex_destroy ();
508 : 0 : citi_result->setFile (file);
509 : 0 : return citi_result;
510 : : }
511 : :
512 : : /* The function read a full dataset from the given ZVR file and
513 : : returns it. On failure the function emits appropriate error
514 : : messages and returns NULL. */
515 : 0 : dataset * dataset::load_zvr (const char * file) {
516 : : FILE * f;
517 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
518 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
519 : 0 : return NULL;
520 : : }
521 : 0 : zvr_in = f;
522 : 0 : zvr_restart (zvr_in);
523 [ # # ]: 0 : if (zvr_parse () != 0) {
524 : 0 : fclose (f);
525 : 0 : return NULL;
526 : : }
527 [ # # ]: 0 : if (zvr_check () != 0) {
528 : 0 : fclose (f);
529 : 0 : return NULL;
530 : : }
531 : 0 : fclose (f);
532 : 0 : zvr_lex_destroy ();
533 [ # # ]: 0 : if (zvr_result) zvr_result->setFile (file);
534 : 0 : return zvr_result;
535 : : }
536 : :
537 : : /* The function read a full dataset from the given MDL file and
538 : : returns it. On failure the function emits appropriate error
539 : : messages and returns NULL. */
540 : 0 : dataset * dataset::load_mdl (const char * file) {
541 : : FILE * f;
542 [ # # ]: 0 : if ((f = fopen (file, "r")) == NULL) {
543 : 0 : logprint (LOG_ERROR, "error loading `%s': %s\n", file, strerror (errno));
544 : 0 : return NULL;
545 : : }
546 : 0 : mdl_in = f;
547 : 0 : mdl_restart (mdl_in);
548 [ # # ]: 0 : if (mdl_parse () != 0) {
549 : 0 : fclose (f);
550 : 0 : return NULL;
551 : : }
552 [ # # ]: 0 : if (mdl_check () != 0) {
553 : 0 : fclose (f);
554 : 0 : return NULL;
555 : : }
556 : 0 : fclose (f);
557 : 0 : mdl_lex_destroy ();
558 [ # # ]: 0 : if (mdl_result) mdl_result->setFile (file);
559 : 0 : return mdl_result;
560 : : }
561 : :
562 : : } // namespace qucs
|