My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
environment.cpp
Go to the documentation of this file.
1 /*
2  * environment.cpp - variable environment class implementation
3  *
4  * Copyright (C) 2004, 2005, 2006, 2007, 2009 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: environment.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 
33 #include "complex.h"
34 #include "variable.h"
35 #include "equation.h"
36 #include "ptrlist.h"
37 #include "logging.h"
38 #include "environment.h"
39 
40 // Constructor creates an unnamed instance of the environment class.
42  name = NULL;
43  root = NULL;
44  solvee = NULL;
45  checkee = NULL;
46  defs = NULL;
47  iscopy = false;
48  children = new ptrlist<environment>;
49 }
50 
51 // Constructor creates a named instance of the environment class.
52 environment::environment (const char * n) {
53  name = n ? strdup (n) : NULL;
54  root = NULL;
55  solvee = NULL;
56  checkee = NULL;
57  defs = NULL;
58  iscopy = false;
59  children = new ptrlist<environment>;
60 }
61 
62 /* The copy constructor creates a new instance of the environment
63  class based on the given environment object. */
65  name = e.name ? strdup (e.name) : NULL;
66  copyVariables (e.root);
67  solvee = e.solvee;
68  checkee = e.checkee;
69  defs = e.defs;
70  iscopy = true;
71  children = new ptrlist<environment>;
72 }
73 
74 /* Very alike the copy constructor the function copies the content of
75  the given environment into the calling environment. */
77  if (name) free (name);
78  name = e.name ? strdup (e.name) : NULL;
79  deleteVariables ();
80  copyVariables (e.root);
81  solvee = e.solvee;
82  checkee = e.checkee;
83  defs = e.defs;
84  delete children;
85  iscopy = true;
86  children = new ptrlist<environment>;
87 }
88 
89 // Destructor deletes the environment object.
91  if (name) free (name);
92  deleteVariables ();
93  // delete solver and checker if this is not just a reference
94  if (!iscopy) {
95  if (solvee)
96  delete solvee;
97  if (checkee) {
98  checkee->setEquations (NULL);
99  delete checkee;
100  }
101  }
102  // delete children
103  for (ptrlistiterator<environment> it (*children); *it; ++it) {
104  delete (*it);
105  }
106  delete children;
107 }
108 
109 // Sets the name of the environment.
110 void environment::setName (char * n) {
111  if (name) free (name);
112  name = n ? strdup (n) : NULL;
113 }
114 
115 // Returns the name of the environment.
116 char * environment::getName (void) {
117  return name;
118 }
119 
120 /* This function copies all variables in the given variable list into
121  an environment. */
123  variable * var;
124  root = NULL;
125  while (org != NULL) {
126  // copy variable (references only)
127  var = new variable (*org);
128  constant * c; reference * r;
129  // depending on variable type copy values too
130  switch (var->getType ()) {
131  case VAR_CONSTANT:
132  c = new constant (*(var->getConstant ()));
133  var->setConstant (c);
134  break;
135  case VAR_VALUE:
136  c = new constant (*(org->getValue ()));
137  var->setValue (c);
138  break;
139  case VAR_REFERENCE:
140  r = new reference ();
141  r->n = strdup (var->getReference()->n);
142  var->setReference (r);
143  break;
144  }
145  var->setNext (root);
146  root = var;
147  org = org->getNext ();
148  }
149 }
150 
151 // Deletes all variable in the environment.
153  variable * n;
154  for (variable * var = root; var != NULL; var = n) {
155  n = var->getNext ();
156  if (var->getType () == VAR_CONSTANT)
157  delete var->getConstant ();
158  else if (var->getType () == VAR_VALUE)
159  delete var->getValue ();
160  else if (var->getType () == VAR_SUBSTRATE)
161  delete var->getSubstrate ();
162  else if (var->getType () == VAR_REFERENCE) {
163  constant * c = var->getReference()->getResult ();
164  if (c) delete c;
165  delete var->getReference ();
166  }
167  delete var;
168  }
169  root = NULL;
170 }
171 
172 /* This function adds a variable to the environment. */
173 void environment::addVariable (variable * var, bool pass) {
174  var->setNext (root);
175  var->setPassing (pass);
176  root = var;
177 }
178 
179 /* This function looks for the variable name in the environment and
180  returns it if possible. Otherwise the function returns NULL. */
182  for (variable * var = root; var != NULL; var = var->getNext ()) {
183  if (var->getType () != VAR_VALUE)
184  if (!strcmp (var->getName (), n))
185  return var;
186  }
187  return NULL;
188 }
189 
190 // The function runs the equation checker for this environment.
191 int environment::equationChecker (int noundefined) {
192  checkee->setDefinitions (defs);
193  return checkee->check (noundefined);
194 }
195 
196 // The function runs the equation solver for this environment.
198  checkee->setDefinitions (defs);
199  solvee->setEquations (checkee->getEquations ());
200  int err = solvee->solve (data);
201  checkee->setEquations (solvee->getEquations ());
202  return err;
203 }
204 
205 // The function runs the equation solver for this environment without
206 // checking it previously and without considering an additional
207 // dataset.
209  checkee->setDefinitions (defs);
210  solvee->setEquations (checkee->getEquations ());
211  solvee->evaluate ();
212  checkee->setEquations (solvee->getEquations ());
213 }
214 
215 // Adds a child to the environment.
217  children->add (child);
218 }
219 
220 // Removes a child from the environment.
222  children->del (child);
223 }
224 
225 /* The function solves the equations of the current environment object
226  as well as these of its children, updates the variables and passes
227  the arguments to each children. */
229  int ret = 0;
230 
231  // solve equations in current environment
232  ret |= equationSolver (NULL);
233  fetchConstants ();
234 
235  // cycle through children
236  for (ptrlistiterator<environment> it (*children); *it; ++it) {
237  // pass constants to solver
238  (*it)->passConstants ();
239  // pass references
240  (*it)->updateReferences (this);
241  // actually run the solver
242  ret |= (*it)->runSolver ();
243 #if 0
244  // save local results
245  (*it)->saveResults ();
246 #endif
247  }
248 
249  return ret;
250 }
251 
252 /* Passes the constants of the environment to the equation solver.
253  This is necessary since equally typed environments use the same
254  equation checker and solver. */
256  for (variable * var = root; var != NULL; var = var->getNext ()) {
257  if (var->getPassing () && var->getType () == VAR_CONSTANT) {
258  constant * c = var->getConstant ();
259  setDouble (var->getName (), c->d);
260  }
261  }
262 }
263 
264 /* Fetches the values of variables from the equation solver. */
266  for (variable * var = root; var != NULL; var = var->getNext ()) {
267  if (var->getType () == VAR_CONSTANT) {
268  constant * c = var->getConstant ();
269  switch (c->getType ()) {
270  case TAG_DOUBLE:
271  c->d = getDouble (var->getName ());
272  break;
273  case TAG_VECTOR:
274  *c->v = getVector (var->getName ());
275  break;
276  }
277  }
278  }
279 }
280 
281 /* Looks through the environment variables for a given variable name
282  being a saved value and returns the variable pointer or NULL if
283  there is no such variable. */
285  for (variable * var = root; var != NULL; var = var->getNext ()) {
286  if (var->getType () == VAR_VALUE)
287  if (!strcmp (var->getName (), n))
288  return var;
289  }
290  return NULL;
291 }
292 
293 /* Puts the given variable name and its computed result into the list
294  of environment variables. */
295 void environment::setValue (char * n, constant * value) {
296  variable * var = findValue (n);
297  if (var != NULL) {
298  // replace variable
299  delete var->getValue ();
300  var->setValue (new constant (*value));
301  } else {
302  // create new variable
303  var = new variable (n);
304  var->setValue (new constant (*value));
305  addVariable (var);
306  }
307 }
308 
309 // Local macro definition to go through the list of equations.
310 #define foreach_equation(eqn) \
311  for (assignment * (eqn) = A (equations); \
312  (eqn) != NULL; (eqn) = A ((eqn)->getNext ()))
313 
314 // Short helper macro.
315 #define A(a) ((assignment *) (a))
316 
317 /* The function puts local variables (prameters and equation results)
318  into the set of environment variables. */
320  node * equations = checkee->getEquations ();
321  // go through equations
323  char * inst = eqn->getInstance ();
324  if (inst != NULL && eqn->evaluated) {
325  char * result = A(eqn)->result;
326  if ((inst[0] != '#' && !strchr (result, '.')) ||
327  !strcmp (inst, "#subcircuit")) {
328  setValue (result, eqn->getResult ());
329  }
330  }
331  }
332 }
333 
334 /* This function looks through all variables which are references. If
335  found the variable gets resolved in the upper (parent) environment
336  and the value put into the result of the reference as well as into
337  the equation checker of the current environment. */
339  for (variable * var = root; var != NULL; var = var->getNext ()) {
340  if (var->getType () == VAR_REFERENCE) {
341  reference * r = var->getReference ();
342  // possible because no self-referring subcircuit types possible
343  nr_double_t d = up->getDouble (r->n);
344  constant * c = r->getResult ();
345  c->d = d;
346  setDouble (var->getName (), d);
347  }
348  }
349 }
350 
351 // Returns vector of an assignment in the equation checker.
353  return checkee->getVector (ident);
354 }
355 
356 // Returns double value of an assignment in the equation checker.
357 nr_double_t environment::getDouble (char * ident) {
358  return checkee->getDouble (ident);
359 }
360 
361 // Sets the double value of an assignment in the equation checker.
362 void environment::setDouble (char * ident, nr_double_t val) {
363  checkee->setDouble (ident, val);
364 }
365 
366 // Return double value of a variable in the environment.
367 nr_double_t environment::getDoubleConstant (char * ident) {
368  variable * var = getVariable (ident);
369  if (var != NULL && var->getType () == VAR_CONSTANT) {
370  constant * c = var->getConstant ();
371  return c->d;
372  }
373  return 0.0;
374 }
375 
376 // Sets the double value of a variable in the environment.
377 void environment::setDoubleConstant (char * ident, nr_double_t val) {
378  variable * var = getVariable (ident);
379  if (var != NULL && var->getType () == VAR_CONSTANT) {
380  constant * c = var->getConstant ();
381  c->d = val;
382  }
383 }
384 
385 // Returns the referenced value of a variable in the environment.
386 char * environment::getDoubleReference (char * ident) {
387  variable * var = getVariable (ident);
388  if (var != NULL && var->getType () == VAR_REFERENCE) {
389  reference * r = var->getReference ();
390  return r->n;
391  }
392  return NULL;
393 }
394 
395 // Sets the referenced value of a variable in the environment.
396 void environment::setDoubleReference (char * ident, char * val) {
397  variable * var = getVariable (ident);
398  if (var != NULL) {
399  if (var->getType () == VAR_CONSTANT) {
400  // its a constant, so make it a reference
401  delete var->getConstant ();
402  reference * r = new reference ();
403  r->n = strdup (val);
404  constant * c = new constant (TAG_DOUBLE);
405  r->setResult (c);
406  var->setReference (r);
407  }
408  else if (var->getType () == VAR_REFERENCE) {
409  // just apply the reference
410  reference * r = var->getReference ();
411  if (r->n) free (r->n);
412  r->n = strdup (val);
413  }
414  }
415 }
416 
417 // Prints the environment.
418 void environment::print (bool all) {
420  logprint (LOG_STATUS, "environment %s\n", getName () ? getName () : "?env?");
421  for (variable * var = root; var != NULL; var = var->getNext ()) {
422  logprint (LOG_STATUS, " %s [%s]\n", var->getName (), var->toString ());
423  }
424  for (it = ptrlistiterator<environment> (*children); *it; ++it) {
425  logprint (LOG_STATUS, " %s\n", (*it)->getName ());
426  }
427  if (all) {
428  for (it = ptrlistiterator<environment> (*children); *it; ++it)
429  (*it)->print ();
430  }
431 }