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