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