My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
equation.cpp
Go to the documentation of this file.
1 /*
2  * equation.cpp - checker for the Qucs equations
3  *
4  * Copyright (C) 2004-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: equation.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 <math.h>
33 #include <ctype.h>
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 "netdefs.h"
44 #include "equation.h"
45 #include "evaluate.h"
46 #include "differentiate.h"
47 #include "constants.h"
48 #include "range.h"
49 #include "exception.h"
50 #include "exceptionstack.h"
51 
52 using namespace eqn;
53 using namespace qucs;
54 
55 #define A(a) ((assignment *) (a))
56 #define N(n) ((node *) (n))
57 #define C(c) ((constant *) (c))
58 #define R(r) ((reference *) (r))
59 
60 // Constructor creates an untyped instance of the constant class.
62  type = TAG_UNKNOWN;
63  dataref = false;
64  d = 0.0;
65  setType (type);
66 }
67 
68 // This constructor creates an typed instance of the constant class.
69 constant::constant (int tag) : node (CONSTANT) {
70  type = tag;
71  dataref = false;
72  d = 0.0;
73  setType (type);
74 }
75 
76 /* This copy constructor creates a instance of the constant class
77  based on the given constant. */
78 constant::constant (const constant & o) : node (o) {
79  type = o.type;
80  dataref = o.dataref;
81  d = 0.0;
82  setType (type);
83  switch (type) {
84  case TAG_BOOLEAN:
85  b = o.b;
86  break;
87  case TAG_DOUBLE:
88  d = o.d;
89  break;
90  case TAG_COMPLEX:
91  c = dataref ? o.c : new nr_complex_t (*o.c);
92  break;
93  case TAG_VECTOR:
94  v = dataref ? o.v : new vector (*o.v);
95  break;
96  case TAG_MATRIX:
97  m = dataref ? o.m : new matrix (*o.m);
98  break;
99  case TAG_MATVEC:
100  mv = dataref ? o.mv : new matvec (*o.mv);
101  break;
102  case TAG_STRING:
103  s = dataref ? o.s : strdup (s);
104  break;
105  case TAG_CHAR:
106  chr = o.chr;
107  break;
108  case TAG_RANGE:
109  r = dataref ? o.r : new range (*o.r);
110  break;
111  }
112 }
113 
114 // Re-creates the given instance.
116  return new constant (*this);
117 }
118 
119 // Destructor deletes an instance of the constant class.
121  if (!dataref) {
122  switch (type) {
123  case TAG_COMPLEX:
124  delete c;
125  break;
126  case TAG_VECTOR:
127  delete v;
128  break;
129  case TAG_MATRIX:
130  delete m;
131  break;
132  case TAG_MATVEC:
133  delete mv;
134  break;
135  case TAG_STRING:
136  free (s);
137  break;
138  case TAG_RANGE:
139  delete r;
140  break;
141  }
142  }
143 }
144 
145 /* Depending on the type of constant the function prints the textual
146  representation of the object. */
147 void constant::print (void) {
148  logprint (LOG_STATUS, "%s", toString ());
149 }
150 
151 // Returns the string representation of a complex value.
152 static char * Cplx2String (nr_complex_t c) {
153  static char str[256]; // enough for a real or complex number
154  if (imag (c) == 0.0) {
155  sprintf (str, "%g", (double) real (c));
156  }
157  else {
158  sprintf (str, "(%g%cj%g)", (double ) real (c),
159  imag (c) >= 0.0 ? '+' : '-', (double) fabs (imag (c)));
160  }
161  return str;
162 }
163 
164 /* This function returns a string representation depending on the type
165  of constant. */
166 char * constant::toString (void) {
167  char str[256];
168  if (txt != NULL) free (txt);
169  switch (type) {
170  case TAG_BOOLEAN:
171  sprintf (str, "%d", b ? 1 : 0);
172  txt = strdup (str);
173  break;
174  case TAG_DOUBLE:
175  sprintf (str, "%g", (double) d);
176  txt = strdup (str);
177  break;
178  case TAG_COMPLEX:
179  txt = strdup (Cplx2String (*c));
180  break;
181  case TAG_VECTOR:
182  {
183  int pos = 1, len = 3 + v->getSize () - 1;
184  txt = (char *) malloc (len);
185  strcpy (txt, "[");
186  for (int i = 0; i < v->getSize (); i++) {
187  char * s = Cplx2String (v->get (i));
188  txt = (char *) realloc (txt, len += strlen (s));
189  strcpy (&txt[pos], s); pos += strlen (s);
190  if (i != v->getSize () - 1) strcpy (&txt[pos++], ";");
191  }
192  strcpy (&txt[pos], "]");
193  }
194  break;
195  case TAG_MATRIX:
196  {
197  int len = 3 + (m->getRows () - 1) * m->getCols () + (m->getCols () - 1);
198  txt = (char *) malloc (len);
199  strcpy (txt, "[");
200  for (int r = 0; r < m->getRows (); r++) {
201  for (int c = 0; c < m->getCols (); c++) {
202  char * s = Cplx2String (m->get (r, c));
203  txt = (char *) realloc (txt, len += strlen (s));
204  strcat (txt, s);
205  if (c != m->getCols () - 1) strcat (txt, ",");
206  }
207  if (r != m->getRows () - 1) strcat (txt, ";");
208  }
209  strcat (txt, "]");
210  }
211  break;
212  case TAG_MATVEC:
213  sprintf (str, "[%dx%d](%d)",
214  mv->getRows (), mv->getCols (), mv->getSize ());
215  txt = strdup (str);
216  break;
217  case TAG_CHAR:
218  sprintf (str, "'%c'", chr);
219  txt = strdup (str);
220  break;
221  case TAG_STRING:
222  sprintf (str, "'%s'", s);
223  txt = strdup (str);
224  break;
225  case TAG_RANGE:
226  txt = strdup (r->toString ());
227  break;
228  default:
229  txt = strdup ("(no such type)");
230  break;
231  }
232  return txt;
233 }
234 
235 // Returns the type of constant.
236 int constant::evalType (void) {
237  return getType ();
238 }
239 
240 // Returns the result stored in the constant.
242  setResult (this);
243  return getResult ();
244 }
245 
246 // Returns the derivative of a constant.
248  constant * res = new constant (TAG_DOUBLE);
249  res->d = 0;
250  return res;
251 }
252 
253 // Constructor creates an instance of the reference class.
255  n = NULL;
256  ref = NULL;
257 }
258 
259 /* This copy constructor creates a instance of the reference class
260  based on the given reference. */
261 reference::reference (const reference & o) : node (o) {
262  n = o.n ? strdup (o.n) : NULL;
263  ref = o.ref;
264 }
265 
266 // Re-creates the given instance.
268  return new reference (*this);
269 }
270 
271 // Replaces reference name by the new given name.
272 void reference::replace (char * src, char * dst) {
273  if (!strcmp (src, n)) {
274  free (n);
275  n = dst ? strdup (dst) : NULL;
276  }
277 }
278 
279 // Destructor deletes an instance of the reference class.
281  if (n) free (n);
282 }
283 
284 // Prints textual representation of the reference object.
285 void reference::print (void) {
286  logprint (LOG_STATUS, "%s", toString ());
287 }
288 
289 // Returns textual representation of the reference object.
290 char * reference::toString (void) {
291  if (txt) free (txt);
292  txt = strdup (n);
293  return txt;
294 }
295 
296 // Adds the name of the reference to the list of dependencies.
298  depends->add (n);
299  findVariable ();
300 }
301 
302 // Find and save the actual equation reference.
304  ref = NULL; // force reference to be updated
305  if (!ref) {
306  node * eqn;
307  if (checkee != NULL) {
308  for (eqn = checkee->getEquations (); eqn; eqn = eqn->getNext ()) {
309  if (!strcmp (n, A(eqn)->result)) {
310  ref = eqn;
311  break;
312  }
313  }
314  }
315  if (solvee != NULL && !ref) {
316  for (eqn = solvee->getEquations (); eqn; eqn = eqn->getNext ()) {
317  if (!strcmp (n, A(eqn)->result)) {
318  ref = eqn;
319  break;
320  }
321  }
322  }
323  }
324 }
325 
326 // Returns the type of reference.
329  findVariable ();
330  if (ref != NULL) {
331  setType (A(ref)->body->evalType ());
332  }
333  return getType ();
334 }
335 
336 // Returns the actual result of the reference.
338  setResult (NULL);
339  findVariable ();
340  if (ref != NULL) {
341  setResult (A(ref)->body->getResult ());
342  }
343  return getResult ();
344 }
345 
346 // Returns the derivative of a reference.
347 node * reference::differentiate (char * derivative) {
348  constant * res = new constant (TAG_DOUBLE);
349  if (n != NULL && !strcmp (n, derivative))
350  res->d = 1;
351  else
352  res->d = 0;
353  return res;
354 }
355 
356 // Constructor creates an instance of the assignment class.
358  body = NULL;
359  result = NULL;
360 }
361 
362 /* This copy constructor creates a instance of the assignment class
363  based on the given assignment. */
364 assignment::assignment (const assignment & o) : node (o) {
365  body = o.body->recreate ();
366  result = o.result ? strdup (o.result) : NULL;
367 }
368 
369 // Re-creates the given instance.
371  return new assignment (*this);
372 }
373 
374 // Replaces reference name by the new given name.
375 void assignment::replace (char * src, char * dst) {
376  body->replace (src, dst);
377 }
378 
379 // Renames the left hand side of the assignment.
380 void assignment::rename (char * n) {
381  if (result) free (result);
382  result = n ? strdup (n) : NULL;
383 }
384 
385 // Destructor deletes an instance of the assignment class.
387  delete body;
388  if (result) free (result);
389 }
390 
391 // Prints textual representation of the assignment object.
392 void assignment::print (void) {
393  logprint (LOG_STATUS, "%s", toString ());
394 }
395 
396 // Returns textual representation of the assignment object.
397 char * assignment::toString (void) {
398  if (txt) free (txt);
399  char * str = body->toString ();
400  txt = (char *) malloc (strlen (result) + strlen (str) + 4);
401  sprintf (txt, "%s = %s", result, str);
402  return txt;
403 }
404 
405 // Adds the right hand side of the assignment to the list of dependencies.
407  body->checkee = checkee;
408  body->addDependencies (depends);
409 }
410 
411 // Returns the type of assignment.
413  setType (body->evalType ());
414  return getType ();
415 }
416 
417 // Returns the result of the assignment.
419  body->solvee = solvee;
420  setResult (body->evaluate ());
421  // inherit drop/prep dependencies of applications
422  if (body->getResult()->dropdeps) {
424  strlist * preps = body->getPrepDependencies ();
425  if (preps) getResult()->setPrepDependencies (new strlist (*preps));
426  }
427  return getResult ();
428 }
429 
430 // Returns the derivative of an assignment.
431 node * assignment::differentiate (char * derivative) {
432  char * txt = (char *) malloc (strlen (result) + strlen (derivative) + 4);
433  sprintf (txt, "d%s_d%s", result, derivative);
434  assignment * res = new assignment ();
435  res->result = txt;
436  res->body = body->differentiate (derivative);
437  return res;
438 }
439 
440 // Some small helpers.
441 #define D(con) (C(con)->d)
442 #define isConst(n) ((n)->getTag()==CONSTANT && C(n)->getType()==TAG_DOUBLE)
443 #define isZero(n) (isConst(n) && D(n) == 0.0)
444 #define isOne(n) (isConst(n) && D(n) == 1.0)
445 #define defCon(res,val) res = new constant (TAG_DOUBLE); C(res)->d = val;
446 
447 /* Multiply two assignments. */
449  node * factor = f->body->recreate ();
450  if (isZero (body) || isZero (factor)) {
451  delete body; delete factor;
452  defCon (body, 0);
453  } else if (isOne (body)) {
454  delete body;
455  body = factor;
456  } else if (isOne (factor)) {
457  delete factor;
458  body = body;
459  } else {
460  application * mul = new application ("*", 2);
461  mul->args = body;
462  mul->args->append (factor);
463  body = mul;
464  }
465 }
466 
467 /* Multiply two assignments by reference. */
469  node * factor = f->body->recreate ();
470  reference * r = new reference ();
471  r->n = strdup (f->result);
472  if (isZero (body) || isZero (factor)) {
473  delete body;
474  defCon (body, 0);
475  } else if (isOne (body)) {
476  body = r;
477  } else if (isOne (factor)) {
478  body = body;
479  } else {
480  application * mul = new application ("*", 2);
481  mul->args = body;
482  mul->args->append (r);
483  body = mul;
484  }
485 }
486 
487 /* Add two assignments. */
489  node * factor = f->body->recreate ();
490  if (isZero (body) && isZero (factor)) {
491  delete body; delete factor;
492  defCon (body, 0);
493  } else if (isZero (body)) {
494  delete body;
495  body = factor;
496  } else if (isZero (factor)) {
497  delete factor;
498  body = body;
499  } else {
500  application * add = new application ("+", 2);
501  add->args = body;
502  add->args->append (factor);
503  body = add;
504  }
505 }
506 
507 // Constructor creates an instance of the application class.
509  n = NULL;
510  nargs = 0;
511  args = NULL;
512  eval = NULL;
513  derive = NULL;
514  ddx = NULL;
515 }
516 
517 /* Constructor creates an instance of the application class with a
518  given function name and the number of arguments. */
519 application::application (const char * func, int a) : node (APPLICATION) {
520  n = func ? strdup (func) : NULL;
521  nargs = a;
522  args = NULL;
523  eval = NULL;
524  derive = NULL;
525  ddx = NULL;
526 }
527 
528 /* This copy constructor creates a instance of the application class
529  based on the given application. */
530 application::application (const application & o) : node (o) {
531  n = o.n ? strdup (o.n) : NULL;
532  nargs = o.nargs;
533  if (o.args != NULL) {
534  node * arg = o.args;
535  args = arg->recreate ();
536  for (arg = arg->getNext (); arg != NULL; arg = arg->getNext ()) {
537  args->append (arg->recreate ());
538  }
539  }
540  else args = NULL;
541  eval = o.eval;
542  derive = o.derive;
543  ddx = o.ddx ? o.ddx->recreate () : NULL;
544 }
545 
546 // Re-creates the given instance.
548  return new application (*this);
549 }
550 
551 // Replaces reference name by the new given name.
552 void application::replace (char * src, char * dst) {
553  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
554  arg->replace (src, dst);
555  }
556  if (ddx) ddx->replace (src, dst);
557 }
558 
559 // Destructor deletes an instance of the application class.
561  node * next, * res;
562  for (node * arg = args; arg != NULL; arg = next) {
563  next = arg->getNext ();
564  delete arg;
565  }
566  if ((res = getResult ()) != NULL) delete res;
567  if (n) free (n);
568  if (ddx) delete ddx;
569 }
570 
571 // Prints textual representation of the application object.
572 void application::print (void) {
573  logprint (LOG_STATUS, "%s", toString ());
574 }
575 
576 // Returns textual representation of the application object.
577 char * application::toString (void) {
578  if (txt) free (txt);
579  // binary operations
580  if ((!strcmp (n, "+") || !strcmp (n, "-") || !strcmp (n, "*") ||
581  !strcmp (n, "/") || !strcmp (n, "^") || !strcmp (n, "%") ||
582  !strcmp (n, "<") || !strcmp (n, ">") || !strcmp (n, "<=") ||
583  !strcmp (n, ">=") || !strcmp (n, "&&") || !strcmp (n, "||") ||
584  !strcmp (n, "==") || !strcmp (n, "!="))
585  && nargs == 2) {
586  char * arg1 = args->toString ();
587  char * arg2 = args->getNext()->toString ();
588  txt = (char *) malloc (strlen (n) + strlen (arg1) + strlen (arg2) + 3);
589  sprintf (txt, "(%s%s%s)", arg1, n, arg2);
590  }
591  // ternary ?: operator
592  else if (!strcmp (n, "?:")) {
593  char * arg1 = args->toString ();
594  char * arg2 = args->getNext()->toString ();
595  char * arg3 = args->getNext()->getNext()->toString ();
596  txt = (char *) malloc (strlen (arg3) + strlen (arg1) + strlen (arg2) + 5);
597  sprintf (txt, "(%s?%s:%s)", arg1, arg2, arg3);
598  }
599  // array indices
600  else if (!strcmp (n, "array")) {
601  int len = strlen (args->toString ()) + 3 + nargs - 1;
602  txt = (char *) malloc (len);
603  sprintf (txt, "%s[", args->toString ());
604  for (node * arg = args->getNext (); arg != NULL; arg = arg->getNext ()) {
605  char * str = arg->toString ();
606  txt = (char *) realloc (txt, len += strlen (str));
607  strcat (txt, str);
608  if (arg->getNext ()) strcat (txt, ",");
609  }
610  strcat (txt, "]");
611  }
612  // vectors and matrices
613  else if (!strcmp (n, "vector") || !strcmp (n, "matrix")) {
614  int len = 3 + nargs - 1;
615  txt = (char *) malloc (len);
616  sprintf (txt, "[");
617  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
618  if (arg->getType () == TAG_CHAR) {
619  txt = (char *) realloc (txt, len++);
620  strcat (txt, ";");
621  } else {
622  char * str = arg->toString ();
623  txt = (char *) realloc (txt, len += strlen (str));
624  strcat (txt, str);
625  node * next = arg->getNext ();
626  if (next && next->getType () != TAG_CHAR) strcat (txt, ",");
627  }
628  }
629  strcat (txt, "]");
630  }
631  // unary and n-ary operations here
632  else {
633  int len = strlen (n) + 3 + nargs - 1;
634  txt = (char *) malloc (len);
635  sprintf (txt, "%s(", n);
636  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
637  char * str = arg->toString ();
638  txt = (char *) realloc (txt, len += strlen (str));
639  strcat (txt, str);
640  if (arg->getNext ()) strcat (txt, ",");
641  }
642  strcat (txt, ")");
643  }
644  return txt;
645 }
646 
647 // Adds the arguments of the application to the list of dependencies.
649  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
650  arg->checkee = checkee;
651  arg->addDependencies (depends);
652  }
653 }
654 
655 /* This function goes through the arguments of an application and
656  evaluates their return types. */
657 void application::evalTypeArgs (void) {
658  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
659  // Skip evaluating generated reference variables.
660  if (arg->getTag () == REFERENCE)
661  if (checker::isGenerated (R (arg)->n))
662  continue;
663  // Evaluate the type of argument.
664  arg->evalType ();
665  }
666 }
667 
668 #include "gperfapphash.cpp"
669 
670 /* The function creates a hash key for the given type of
671  application. */
672 char * application::createKey (void) {
673  char * key = (char *) calloc (1, strlen (n) + nargs * 3 + 5);
674  strcat (key, n);
675  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
676  strcat (key, "_");
677  strcat (key, checker::tag2key (arg->getType ()));
678  }
679  return key;
680 }
681 
682 /* This function returns the return type of the application using a
683  gperf-generated hash. */
684 int application::evalTypeFast (void) {
685  char * key = createKey ();
686  struct appindex * idx = gperfapphash::get (key, strlen (key));
687  free (key);
688  if (idx != NULL) {
689  application_t * app = &applications[idx->index];
690  if (app->eval) {
691  eval = app->eval;
692  setType (app->retval);
693  }
694  }
695  return getType ();
696 }
697 
698 // Macro to identify ddx() application.
699 #define isDDX() (nargs == 2 && !strcmp (n, "ddx") && \
700  args->getNext()->getTag () == REFERENCE)
701 
702 /* Returns the type of application and applies the appropriate
703  evaluation function if any. */
705  // Evaluate type of ddx().
706  if (isDDX ()) {
707  args->evalType ();
708  if (!ddx) ddx = args->differentiate (R(args->getNext())->n);
709  setType (ddx->evalType ());
710  return getType ();
711  }
713  // Evaluate type of arguments.
714  evalTypeArgs ();
715  // Find an appropriate differentiator.
716  findDifferentiator ();
717  // Try the fast method.
718  if (evalTypeFast () != TAG_UNKNOWN) return getType ();
719 
720  // Go through the list of available applications.
721  for (int i = 0; applications[i].application != NULL; i++) {
722  application_t * app = &applications[i];
723  // The correct application?
724  if (!strcmp (n, app->application)) {
725  int nr = 0;
726  if (app->nargs >= 0) {
727  // The correct number of arguments?
728  if (nargs != app->nargs) continue;
729  // The correct types of arguments?
730  for (node * arg = args; arg != NULL; arg = arg->getNext (), nr++) {
731  if (arg->getTag () == REFERENCE)
732  // Skip checking generated reference variables.
733  if (checker::isGenerated (R (arg)->n))
734  continue;
735  // Evaluate and check the type of argument.
736  if (!(arg->getType () & app->args[nr])) { nr = -1; break; }
737  }
738  if (nr == -1) continue;
739  }
740  // A valid application function?
741  if (app->eval == NULL) continue;
742  // Everything just fine here.
743  eval = app->eval;
744  setType (app->retval);
745  break;
746  }
747  }
748  // Emit error message if necessary.
749  if (getType () == TAG_UNKNOWN) {
750  logprint (LOG_ERROR, "checker error, no appropriate function for `%s'"
751  " found\n", toString ());
752  }
753  return getType ();
754 }
755 
756 /* This function returns zero if the applications differentiation
757  function could be found and otherwise non-zero. */
758 int application::findDifferentiator (void) {
759  for (int i = 0; differentiations[i].application != NULL; i++) {
760  if (!strcmp (n, differentiations[i].application) &&
763  return 0;
764  }
765  }
766  return -1;
767 }
768 
769 /* This function runs the actual evaluation function and the returns
770  the result. */
772  // Evaluate ddx() function.
773  if (isDDX ()) {
774  if (getResult ()) delete getResult ();
775  setResult (C (ddx->evaluate()->recreate ()));
776  return getResult ();
777  }
778 
779  int errors = 0;
780  strlist * apreps = new strlist ();
781 
782  // first evaluate each argument
783  for (node * arg = args; arg != NULL; arg = arg->getNext ()) {
784  // FIXME: Can save evaluation of already evaluated equations?
785  if (arg->evaluated == 0 || 1) {
786  arg->solvee = solvee;
787  arg->evaluate ();
788  if (arg->getResult () == NULL) {
789  if (arg->getTag () == REFERENCE) {
790  logprint (LOG_ERROR, "evaluate error, no such generated variable "
791  "`%s'\n", arg->toString ());
792  }
793  else {
794  logprint (LOG_ERROR, "evaluate error, unable to evaluate "
795  "`%s'\n", arg->toString ());
796  }
797  errors++;
798  }
799  else {
800  // inherit drop/prep dependencies
801  if (arg->getResult()->dropdeps) {
802  strlist * preps = arg->getResult()->getPrepDependencies ();
803  // recall longest prep dependencies' list of arguments
804  if (preps && (preps->length () > apreps->length ())) {
805  delete apreps;
806  apreps = new strlist (*preps);
807  }
808  }
809  arg->evaluated++;
810  }
811  }
812  }
813 
814  // then evaluate application itself
815  if (!errors) {
816  node * res;
817  // delete previous result if necessary
818  if ((res = getResult ()) != NULL) delete res;
819  // then evaluate the application
820  setResult (eval (C (args)));
821  // check the returned type once again
822  if (getResult()->getType () != getType ()) {
823  logprint (LOG_ERROR, "evaluate error, function `%s' returned invalid "
824  "constant type\n", toString ());
825  }
826  }
827 
828  // inherit prep dependencies of arguments if necessary
829  if (!getResult()->dropdeps && apreps->length () > 0) {
830  getResult()->dropdeps = 1;
831  getResult()->appendPrepDependencies (apreps);
832  }
833  delete apreps;
834 
835  return getResult ();
836 }
837 
838 // Returns the derivative of an application.
839 node * application::differentiate (char * derivative) {
840  if (isDDX ()) {
841  return ddx->differentiate (derivative);
842  }
843  if (derive)
844  return derive (this, derivative);
845  return recreate ();
846 }
847 
848 // Constructor creates an untyped instance of the equation node class.
850  tag = UNKNOWN;
852  next = NULL;
853  dependencies = NULL;
854  dataDependencies = NULL;
855  dropDependencies = NULL;
856  prepDependencies = NULL;
857  txt = NULL;
858  res = NULL;
859  instance = NULL;
860  solvee = NULL;
861  checkee = NULL;
862 }
863 
864 // This constructor creates an typed instance of the equation node class.
865 node::node (int type) {
866  tag = type;
868  next = NULL;
869  dependencies = NULL;
870  dataDependencies = NULL;
871  dropDependencies = NULL;
872  prepDependencies = NULL;
873  txt = NULL;
874  res = NULL;
875  instance = NULL;
876  solvee = NULL;
877  checkee = NULL;
878 }
879 
880 /* This copy constructor creates a instance of the node class based on
881  the given node. */
882 node::node (const node & o) {
883  tag = o.tag;
885  next = NULL;
886  dependencies = NULL;
887  dataDependencies = NULL;
888  dropDependencies = NULL;
889  prepDependencies = NULL;
890  txt = NULL;
891  res = NULL;
892  instance = NULL;
893  solvee = o.solvee;
894  checkee = o.checkee;
895 }
896 
897 // Destructor deletes an instance of the equation node class.
899  if (dependencies) delete dependencies;
900  if (dataDependencies) delete dataDependencies;
901  if (dropDependencies) delete dropDependencies;
902  if (prepDependencies) delete prepDependencies;
903  if (txt) free (txt);
904  if (instance) free (instance);
905 }
906 
907 // Sets the instance name where the node occurred.
908 void node::setInstance (const char * n) {
909  if (instance) free (instance);
910  instance = n ? strdup (n) : NULL;
911 }
912 
913 // Returns the instance name where the node occurred.
914 char * node::getInstance (void) {
915  return instance;
916 }
917 
918 /* The function applies the instance name of the current equation node
919  to any following node within the list up to the node with a valid
920  instance name. */
921 void node::applyInstance (void) {
922  char * i = getInstance ();
923  for (node * n = getNext (); n != NULL; n = n->getNext ()) {
924  if (n->getInstance () == NULL)
925  n->setInstance (i);
926  else
927  break;
928  }
929 }
930 
931 // Counts the number of equations node attached to the node.
932 int node::count (void) {
933  int c = 0;
934  for (node * n = this; n != NULL; n = n->getNext ()) c++;
935  return c;
936 }
937 
938 // Appends yet another node to the equation node object.
939 void node::append (node * last) {
940  if (!last) return;
941  node * n;
942  for (n = this; n->getNext () != NULL; n = n->getNext ()) ;
943  last->setNext (NULL);
944  n->setNext (last);
945 }
946 
947 // Appends othere nodes to the equation node object.
948 void node::appendNodes (node * last) {
949  if (!last) return;
950  node * n;
951  for (n = this; n->getNext () != NULL; n = n->getNext ()) ;
952  n->setNext (last);
953 }
954 
955 // Returns the equation node at the given argument position.
956 node * node::get (int pos) {
957  node * n = this;
958  for (int i = 0; i < pos && n != NULL; n = n->getNext (), i++) ;
959  return n;
960 }
961 
962 // Sets the constant equation node result.
964  res = r;
965 }
966 
967 // Returns the constant equation node at the given argument position.
968 constant * node::getResult (int pos) {
969  node * n = this;
970  for (int i = 0; i < pos && n != NULL; n = n->getNext (), i++) ;
971  return n ? n->getResult () : NULL;
972 }
973 
974 /* Returns a double value depending on the type of the equation nodes
975  result type. */
976 nr_double_t node::getResultDouble (void) {
977  constant * c = getResult ();
978  if (c != NULL) {
979  switch (getType ()) {
980  case TAG_DOUBLE:
981  return c->d; break;
982  case TAG_COMPLEX:
983  return real (*(c->c)); break;
984  case TAG_BOOLEAN:
985  return c->b ? 1.0 : 0.0; break;
986  }
987  }
988  return 0.0;
989 }
990 
991 /* Returns a complex value depending on the type of the equation nodes
992  result type. */
994  constant * c = getResult ();
995  if (c != NULL) {
996  switch (getType ()) {
997  case TAG_DOUBLE:
998  return rect (c->d, 0.0); break;
999  case TAG_COMPLEX:
1000  return *(c->c); break;
1001  case TAG_BOOLEAN:
1002  return c->b ? 1.0 : 0.0; break;
1003  }
1004  }
1005  return 0.0;
1006 }
1007 
1008 /* Returns an immediate vector depending on the type of the equation
1009  nodes result type. */
1011  constant * c = getResult ();
1012  vector v;
1013  if (c != NULL) {
1014  switch (getType ()) {
1015  case TAG_MATRIX:
1016  {
1017  int ro, co, n = 0;
1018  v = vector (c->m->getRows () * c->m->getCols ());
1019  for (co = 0; co < c->m->getCols (); co++)
1020  for (ro = 0; ro < c->m->getRows (); ro++)
1021  v (n++) = c->m->get (ro, co);
1022  }
1023  break;
1024  case TAG_VECTOR:
1025  v = *(c->v); break;
1026  case TAG_DOUBLE:
1027  v = vector (1); v (0) = c->d; break;
1028  case TAG_COMPLEX:
1029  v = vector (1); v (0) = *(c->c); break;
1030  case TAG_BOOLEAN:
1031  v = vector (1); v (0) = c->b ? 1.0 : 0.0; break;
1032  }
1033  }
1034  return v;
1035 }
1036 
1037 // Assigns the dependency list to the equation node object.
1038 void node::setDependencies (strlist * depends) {
1039  if (dependencies) delete dependencies;
1040  dependencies = depends;
1041 }
1042 
1043 // Returns the dependency list of the equation node object.
1045  return dependencies;
1046 }
1047 
1048 /* This function recursively finds the variable dependencies for each
1049  equation initially passed to the equation checker and returns the
1050  list of variable dependencies regarding this equation instance.
1051  The caller is responsible for deleting the returned string list
1052  object. */
1054 
1055  strlist * res, * sub = NULL;
1056 
1057  /* The abort condition for recursion first. */
1058  if (deps->contains (A(this)->result)) {
1059  res = new strlist (*deps);
1060  cycle = 1;
1061  return res;
1062  }
1063 
1064  /* Go through the list of passed dependency variables. */
1065  for (int i = 0; i < deps->length (); i++) {
1066  char * var = deps->get (i);
1067  node * child = check->findEquation (check->equations, var);
1068  /* Check each child equation. */
1069  if (child != NULL) {
1070  if (child->cycle == 0) {
1071  strlist * cdeps = child->getDependencies ();
1072  /* And append the dependencies of the child equation. */
1073  if (cdeps->length () > 0) {
1074  res = strlist::join (sub, cdeps);
1075  if (sub) delete sub; sub = res;
1076  }
1077  }
1078  /* If any child is cyclic, the parent is too. */
1079  else {
1080  cycle = 1;
1081  }
1082  }
1083  }
1084 
1085  /* Recurse once again if the child equations revealed any more
1086  dependencies. */
1087  if (cycle && sub && sub->length () > 0) {
1088  res = recurseDependencies (check, sub);
1089  delete sub;
1090  sub = res;
1091  }
1092 
1093  /* Return the result. */
1094  res = strlist::join (deps, sub);
1095  if (sub) delete (sub);
1096  return res;
1097 }
1098 
1099 /* The function adds the given data dependency to the list of
1100  dependencies which are going to be dropped during the data
1101  export. */
1102 void node::addDropDependencies (char * dep) {
1103  if (dropDependencies == NULL) dropDependencies = new strlist ();
1104  dropDependencies->add (dep);
1105 }
1106 
1107 /* The function adds the given data dependency to the list of
1108  dependencies which are going to be prepend. */
1109 void node::addPrepDependencies (char * dep) {
1110  if (prepDependencies == NULL) prepDependencies = new strlist ();
1111  prepDependencies->add (dep);
1112 }
1113 
1114 /* This function appends the given dependency list to the list of
1115  dependencies which are going to be prepend. */
1117  if (prepDependencies == NULL) prepDependencies = new strlist ();
1118  prepDependencies->append (deps);
1119 }
1120 
1121 /* The function sets the data dependency list of the equation node. */
1123  if (dataDependencies != NULL) delete dataDependencies;
1124  dataDependencies = deps ? new strlist (*deps) : NULL;
1125 }
1126 
1127 /* Evaluates the equation node and applies the data dependencies. */
1129  constant * res = evaluate ();
1130  if (getResult ()) {
1131  strlist * deps = solvee->collectDataDependencies (this);
1132  getResult()->setDataDependencies (deps);
1133  if (deps) delete deps;
1134  }
1135  else {
1137  e->setText ("evaluator exception"); throw_exception (e);
1138  }
1139  return res;
1140 }
1141 
1142 /* Collects the equation dependencies for a specific node. */
1144  strlist * depends = new strlist ();
1145  addDependencies (depends);
1147  return getDependencies ();
1148 }
1149 
1150 /* Collects the data dependencies for a specific node. */
1152  strlist * deps = getResult()->getDataDependencies ();
1153  if (deps) {
1154  // data dependencies already collected
1155  setDataDependencies (deps);
1156  return deps;
1157  }
1158  // collect equation dependencies
1159  if (!getDependencies ())
1161  if (solvee) {
1162  // finally collect the appropriate data dependencies
1163  deps = solvee->collectDataDependencies (this);
1164  setDataDependencies (deps);
1165  delete deps;
1166  }
1167  return getDataDependencies ();
1168 }
1169 
1170 // Constructor creates an instance of the checker class.
1172  defs = NULL;
1173  equations = NULL;
1174  consts = false;
1175 }
1176 
1177 // Destructor deletes an instance of the checker class.
1179  node * next;
1180  for (node * eqn = equations; eqn != NULL; eqn = next) {
1181  next = eqn->getNext ();
1182  delete eqn;
1183  }
1184 }
1185 
1186 // Local macro definition to go through the list of equations.
1187 #define foreach_equation(eqn) \
1188  for (assignment * (eqn) = A (equations); \
1189  (eqn) != NULL; (eqn) = A ((eqn)->getNext ()))
1190 
1191 /* The function goes through the list of equations assigned to the
1192  checker and applies the dependency list. */
1194  foreach_equation (eqn) {
1196  }
1197 }
1198 
1199 // Creates dependency list of given equation node.
1201  strlist * depends = new strlist ();
1202  eqn->addDependencies (depends);
1203  eqn->setDependencies (depends);
1204 }
1205 
1206 /* The following function goes through the list of equations and
1207  checks whether there is any kind of 'Export="yes|no"' assignment in
1208  it. Depending on the value the referred equation results are saved
1209  into the dataset or not. */
1211  int errors = 0;
1212  assignment * next;
1213  // go through all equations
1214  for (assignment * eqn = A (equations); eqn != NULL; eqn = next) {
1215  next = A (eqn->getNext ());
1216  // 'Export' equation found ?
1217  if (!strcmp (eqn->result, "Export")) {
1218  // is the type and value correct ?
1219  if (eqn->body->getTag () != REFERENCE ||
1220  (strcmp (R (eqn->body)->n, "yes") &&
1221  strcmp (R (eqn->body)->n, "no"))) {
1222  logprint (LOG_ERROR, "checker error, variable `%s' alternatives "
1223  "are `yes' or `no'\n", eqn->result);
1224  errors++;
1225  }
1226  else {
1227  int flag = !strcmp (R (eqn->body)->n, "yes") ? 1 : 0;
1228  char * i = eqn->getInstance ();
1229  int found = 0;
1230  // set output flag for each equation with the same instance name
1231  foreach_equation (res) {
1232  if (!strcmp (res->getInstance (), i))
1233  res->output = flag;
1234  if (!strcmp (res->result, "Export") &&
1235  !strcmp (res->getInstance (), i)) {
1236  found++;
1237  }
1238  }
1239  // check for duplicate definitions of 'Export'
1240  if (found > 1) {
1241  logprint (LOG_ERROR, "checker error, variable `%s' "
1242  "occurred %dx in `Eqn:%s'\n", eqn->result, found, i);
1243  errors++;
1244  }
1245  // drop the 'Export' equation being useless now
1246  dropEquation (eqn);
1247  delete eqn;
1248  }
1249  }
1250  }
1251  return errors;
1252 }
1253 
1254 // Logs the textual representation of all equations.
1255 void checker::list (void) {
1256  for (node * eqn = equations; eqn != NULL; eqn = eqn->getNext ()) {
1257  logprint (LOG_STATUS, "%s", eqn->evalPossible ? "!" : "?");
1258  logprint (LOG_STATUS, "%s", eqn->evalPossible ?
1259  (eqn->getType () == TAG_UNKNOWN ? "U!" :
1260  eqn->getType () == TAG_DOUBLE ? "D!" :
1261  eqn->getType () == TAG_BOOLEAN ? "B!" :
1262  eqn->getType () == TAG_COMPLEX ? "C!" :
1263  eqn->getType () == TAG_VECTOR ? "V!" :
1264  eqn->getType () == TAG_CHAR ? "CHR!" :
1265  eqn->getType () == TAG_STRING ? "STR!" :
1266  eqn->getType () == TAG_MATVEC ? "MV!" :
1267  eqn->getType () == TAG_RANGE ? "R!" :
1268  eqn->getType () == TAG_MATRIX ? "M!" : "?!") : "");
1269  eqn->print ();
1270  logprint (LOG_STATUS, "\n");
1271  }
1272 }
1273 
1274 /* Checks whether the variable name is a generated name which is
1275  identified by a ".[0-9]{4}" suffix. */
1276 int checker::isGenerated (char * var) {
1277  int len = strlen (var);
1278  if (len > 5) {
1279  if (isdigit (var[len-1]) && isdigit (var[len-2]) &&
1280  isdigit (var[len-3]) && isdigit (var[len-4]) &&
1281  var[len-5] == '.') {
1282  return 1;
1283  }
1284  }
1285  return 0;
1286 }
1287 
1288 /* This function checks whether the variable references could be
1289  resolved within the equations and returns zero if so. */
1290 int checker::findUndefined (int noundefined) {
1291  int err = 0;
1292  strlist * idents = getVariables ();
1293 
1294  foreach_equation (eqn) {
1295  strlist * depends = eqn->getDependencies ();
1296  for (int i = 0; i < depends->length (); i++) {
1297  char * var = depends->get (i);
1298  if (idents->contains (var) <= 0) {
1299  // check if this is a circuit property
1300  if (defs) {
1301  node * eqn = findProperty (var);
1302  if (eqn) {
1303  idents->append (var);
1304  eqn->collectDependencies ();
1305  continue;
1306  }
1307  }
1308  // give an error
1309  if (noundefined) {
1310  if (isGenerated (var)) // skip probably generated variables
1311  continue;
1312  logprint (LOG_ERROR, "checker error, undefined variable `%s' in "
1313  "equation `%s'\n", var, eqn->result);
1314  err++;
1315  }
1316  // give a notice only
1317  else {
1318  logprint (LOG_STATUS, "checker notice, variable `%s' in "
1319  "equation `%s' not yet defined\n", var, eqn->result);
1320  }
1321  }
1322  }
1323  }
1324  delete idents;
1325  return err;
1326 }
1327 
1328 /* This function tries to find the given variable name which occurred
1329  in an equation dependency in the netlist. If there is such a
1330  circuit property it returns a new assignment equation. */
1331 node * checker::findProperty (char * var) {
1332 
1333  node * eqn = NULL;
1334  int found = 0;
1335 
1336  // split into instance and property name
1337  char * ret, * inst, * prop;
1338  if ((ret = strchr (var, '.')) != NULL) {
1339  int len = ret - var;
1340  inst = (char *) calloc (1, len + 1);
1341  memcpy (inst, var, len);
1342  prop = &var[len + 1];
1343  }
1344  else return NULL;
1345 
1346  // go through list of circuit elements
1347  for (struct definition_t * def = defs; def; def = def->next) {
1348  if (!strcmp (def->instance, inst)) {
1349  for (struct pair_t * pair = def->pairs; pair; pair = pair->next) {
1350  if (!strcmp (pair->key, prop)) {
1351  if (++found == 1) {
1352  if (pair->value->ident != NULL) {
1353  // reference
1354  eqn = createReference ("#property", var, pair->value->ident);
1355  }
1356  else {
1357  // value
1358  eqn = createDouble ("#property", var, pair->value->value);
1359  }
1360  }
1361  }
1362  }
1363  }
1364  }
1365  if (found > 1) {
1366  logprint (LOG_ERROR, "checker error, desired property variable `%s' found "
1367  "%dx, is not unique'\n", var, found);
1368  delete eqn; eqn = NULL;
1369  }
1370  else if (found == 1)
1371  appendEquation (eqn);
1372  free (inst);
1373  return eqn;
1374 }
1375 
1376 /* Go through the list of equations and store the left hand side in
1377  a string list. */
1379  strlist * idents = new strlist ();
1380  foreach_equation (eqn) {
1381  idents->add (eqn->result);
1382  }
1383  return idents;
1384 }
1385 
1386 /* Finds duplicate equation definitions in the list of equations,
1387  emits appropriate error messages and returns zero if everything is
1388  ok. */
1390  int err = 0;
1391  strlist * idents = getVariables ();
1392  strlist * dups = new strlist ();
1393 
1394  // Collect duplicate entries.
1395  foreach_equation (eqn) {
1396  if (!eqn->duplicate && dups->contains (eqn->result) == 0) {
1397  eqn->duplicate = idents->contains (eqn->result);
1398  dups->add (eqn->result);
1399  }
1400  else {
1401  eqn->duplicate = 1;
1402  }
1403  }
1404  // Emit appropriate error messages.
1405  foreach_equation (eqndups) {
1406  if (eqndups->duplicate > 1) {
1407  logprint (LOG_ERROR, "checker error, variable `%s' assigned %dx\n",
1408  eqndups->result, eqndups->duplicate);
1409  err++;
1410  }
1411  }
1412  delete idents;
1413  delete dups;
1414  return err;
1415 }
1416 
1417 /* The function returns the equation resulting in the passed variable
1418  or NULL if there is no such equation. The function looks through
1419  the passed equation root. */
1420 node * checker::findEquation (node * root, char * n) {
1421  for (node * eqn = root; eqn != NULL; eqn = eqn->getNext ()) {
1422  if (!strcmp (A(eqn)->result, n)) return eqn;
1423  }
1424  return NULL;
1425 }
1426 
1427 /* The function returns the equation resulting in the passed variable
1428  or NULL if there is no such equation. */
1429 node * checker::findEquation (char * n) {
1430  foreach_equation (eqn) {
1431  if (!strcmp (A(eqn)->result, n)) return eqn;
1432  }
1433  return NULL;
1434 }
1435 
1436 /* This function display the error messages due to equation cycles and
1437  returns zero if there are no such cycles. */
1439  int err = 0;
1440 
1441  foreach_equation (eqn) {
1442  strlist * deps = eqn->recurseDependencies (this, eqn->getDependencies ());
1443  if (deps->contains (eqn->result) || eqn->cycle) {
1444  logprint (LOG_ERROR, "checker error, cyclic definition of variable "
1445  "`%s' involves: `%s'\n", eqn->result, deps->toString ());
1446  err++;
1447  delete deps;
1448  }
1449  else {
1450  // Set folded variable dependencies.
1451  deps = foldDependencies (deps);
1452  eqn->setDependencies (deps);
1453  }
1454  }
1455  return err;
1456 }
1457 
1458 /* The function returns a variable dependency list with unique entries
1459  only. The given string list gets deleted and a new one is created
1460  and returned. */
1462  strlist * res = new strlist ();
1463  for (int i = 0; deps && i < deps->length (); i++) {
1464  char * var = deps->get (i);
1465  if (!res->contains (var)) res->append (var);
1466  }
1467  if (deps) delete deps;
1468  return res;
1469 }
1470 
1471 // The function appends the given last node to the given equation root.
1472 node * checker::appendEquation (node * root, node * last) {
1473  last->setNext (NULL);
1474  if (root != NULL) {
1475  node * eqn = lastEquation (root);
1476  eqn->setNext (last);
1477  }
1478  else root = last;
1479  return root;
1480 }
1481 
1482 // Returns the last node in the given equation root.
1484  node * eqn;
1485  for (eqn = root; eqn && eqn->getNext () != NULL; eqn = eqn->getNext ()) ;
1486  return eqn;
1487 }
1488 
1489 // Removes the given equation node from the list of known equations.
1491  if (eqn == equations) {
1492  equations = eqn->getNext ();
1493  }
1494  else {
1495  node * prev;
1496  for (prev = equations; prev->getNext () != eqn; prev = prev->getNext()) ;
1497  prev->setNext (eqn->getNext ());
1498  }
1499 }
1500 
1501 /* This function reorders the list of equations. The new order can be
1502  used to evaluate the list step by step. Each equation being
1503  evaluable is properly marked, remaining equations are appended. */
1505  node * root = NULL, * next, * last;
1506 
1507  // Go through the list of equations.
1508  for (node * eqn = equations; eqn != NULL; eqn = next) {
1509  strlist * deps = eqn->getDependencies ();
1510  int i, found, gens;
1511  next = eqn->getNext ();
1512  /* Check whether the variable dependencies can be found in
1513  previous equations. */
1514  for (found = gens = i = 0; i < deps->length (); i++) {
1515  char * var = deps->get (i);
1516  if (findEquation (root, var) != NULL) found++;
1517  if (isGenerated (var)) gens++;
1518  }
1519  // Yes.
1520  if (found == (deps->length () - gens)) {
1521  /* Remove the equation from the current list and append it to
1522  the new list. */
1523  dropEquation (eqn);
1524  root = appendEquation (root, eqn);
1525  eqn->evalPossible = 1;
1526  // Now start over from the beginning.
1527  next = equations;
1528  }
1529  }
1530  // Any remaining equations get appended.
1531  if (root != NULL) {
1532  last = lastEquation (root);
1533  last->setNext (equations);
1534  equations = root;
1535  }
1536 }
1537 
1538 
1539 /* The function passes a list of equations to the checker and also
1540  passes the checker instance to each equation. */
1542  equations = eqns;
1543  foreach_equation (eqn) { eqn->checkee = this; }
1544 }
1545 
1546 /* The function evaluates the types for each equation and recursively
1547  checks the availability of the appropriate function. */
1549  int err = 0;
1550  foreach_equation (eqn) {
1551  if (eqn->evalPossible) {
1552  if (eqn->evalType () == TAG_UNKNOWN) {
1553  logprint (LOG_ERROR, "checker error, type of equation `%s' "
1554  "undefined\n", eqn->result);
1555  err++;
1556  }
1557  }
1558  else break;
1559  }
1560  return err;
1561 }
1562 
1563 /* This function is the checker routine for a parsed equations. It
1564  returns zero on success or non-zero if the parsed equations
1565  contained errors. */
1566 int checker::check (int noundefined) {
1567  int err = 0;
1568  err += checkExport ();
1570  err += findUndefined (noundefined);
1571  err += findDuplicate ();
1572  err += detectCycles ();
1573  reorderEquations ();
1574  err += applyTypes ();
1575 #if DEBUG && 0
1576  list ();
1577 #endif /* DEBUG */
1578  return err;
1579 }
1580 
1581 // Constructor creates an instance of the solver class.
1583  equations = NULL;
1584  data = NULL;
1585  generated = 0;
1586  checkee = c;
1587 }
1588 
1589 // Destructor deletes an instance of the solver class.
1591  node * next;
1592  for (node * eqn = equations; eqn != NULL; eqn = next) {
1593  next = eqn->getNext ();
1594  delete eqn;
1595  }
1596 }
1597 
1598 // The function finally evaluates each equation passed to the solver.
1599 void solver::evaluate (void) {
1600  foreach_equation (eqn) {
1601  // FIXME: Can save evaluation of already evaluated equations?
1602  if (eqn->evalPossible && !eqn->skip /* && eqn->evaluated == 0 */) {
1603  // exception handling around evaluation
1604  try_running () {
1605  eqn->solvee = this;
1606  eqn->calculate ();
1607  }
1608  // handle evaluation exceptions
1609  catch_exception () {
1610  default:
1611  estack.print ("evaluation");
1612  break;
1613  }
1614  eqn->evaluated++;
1615 #if DEBUG && 0
1616  // print equation results
1617  logprint (LOG_STATUS, "%s = %s\n", A(eqn)->result,
1618  eqn->getResult () ? eqn->getResult()->toString () : "error");
1619 #if TESTING_DERIVATIVE || 0
1620  // print equation
1621  logprint (LOG_STATUS, "%s\n", eqn->toString ());
1622  // print derivations
1623  logprint (LOG_STATUS, "%s\n", eqn->differentiate("x")->toString ());
1624 #endif
1625 #endif
1626  }
1627  }
1628 }
1629 
1630 /* This function adds the given dataset vector to the set of equations
1631  stored in the equation solver. */
1632 node * solver::addEquationData (vector * v, bool ref) {
1633  constant * con = new constant (TAG_VECTOR);
1634  con->v = v;
1635  con->dataref = ref;
1636  assignment * assign = new assignment ();
1637  assign->result = strdup (v->getName ());
1638  assign->body = con;
1639  assign->setNext (equations);
1640  equations = assign;
1641  return assign;
1642 }
1643 
1644 /* The function puts the given vector into the equation set. The
1645  resulting data vector is going to be copied and exported - given a
1646  generated name based upon the second argument. */
1647 node * solver::addGeneratedEquation (vector * v, const char * n) {
1648  // create generated name
1649  char * str = (char *) malloc (strlen (n) + 6);
1650  sprintf (str, "%s.%04d", n, ++generated);
1651  // copy data vector
1652  vector * c = new vector (*v);
1653  c->setName (str);
1654  // put vector into the equation set and ensure data export as
1655  // independent variable
1656  node * res = addEquationData (c);
1657  res->setInstance ("#generated");
1658  res->setDependencies (new strlist ());
1659  res->evalType ();
1660  res->solvee = this;
1661  res->evaluate ();
1662  res->output = 1;
1663  free (str);
1664  return res;
1665 }
1666 
1667 /* Depending on the type of equation result the function converts the
1668  given equation node to one or more valid dataset vector(s). */
1670  vector * v = NULL;
1671  if (!eqn->getResult ()) return NULL;
1672  switch (eqn->getType ()) {
1673  case TAG_VECTOR: // simple vector
1674  v = new vector (* (eqn->getResult()->v));
1675  v->setNext (NULL); v->setPrev (NULL);
1676  break;
1677  case TAG_DOUBLE: // double value
1678  v = new vector ();
1679  v->add (eqn->getResult()->d);
1680  break;
1681  case TAG_BOOLEAN: // boolean value
1682  v = new vector ();
1683  v->add (eqn->getResult()->b ? 1 : 0);
1684  break;
1685  case TAG_COMPLEX: // complex value
1686  v = new vector ();
1687  v->add (* (eqn->getResult()->c));
1688  break;
1689  case TAG_MATVEC: // matrix vector
1690  {
1691  // convert matrix vector to a list of vectors
1692  matvec * mv = eqn->getResult()->mv;
1693  mv->setName (A(eqn)->result);
1694  for (int r = 0; r < mv->getRows (); r++) {
1695  for (int c = 0; c < mv->getCols (); c++) {
1696  // name gets automatically assigned
1697  vector * t = new vector (mv->get (r, c));
1698  // chain the vectors appropriately
1699  t->setNext (v); v = t;
1700  }
1701  }
1702  }
1703  return v;
1704  case TAG_MATRIX: // single matrix
1705  {
1706  // convert matrix to a list of vectors
1707  matrix * m = eqn->getResult()->m;
1708  for (int r = 0; r < m->getRows (); r++) {
1709  for (int c = 0; c < m->getCols (); c++) {
1710  vector * t = new vector ();
1711  t->setName (matvec::createMatrixString (A(eqn)->result, r, c));
1712  t->add (m->get (r, c));
1713  // chain the vectors appropriately
1714  t->setNext (v); v = t;
1715  }
1716  }
1717  }
1718  return v;
1719  default:
1720  return NULL;
1721  }
1722  v->setName (A(eqn)->result);
1723  return v;
1724 }
1725 
1726 /* This function collects the data vectors in a dataset and appends
1727  these to the list of equation node inside the equation solver. */
1729  if (data == NULL) return;
1730  vector * v;
1731  findMatrixVectors (data->getDependencies ());
1732  findMatrixVectors (data->getVariables ());
1733  for (v = data->getDependencies (); v != NULL; v = (vector *) v->getNext ()) {
1734  if (v->getRequested () != -1) {
1735  node * eqn = addEquationData (v, true);
1736  strlist * deps = new strlist ();
1737  deps->add (v->getName ());
1738  eqn->setDataDependencies (deps);
1739  delete deps;
1740  }
1741  }
1742  for (v = data->getVariables (); v != NULL; v = (vector *) v->getNext ()) {
1743  if (v->getRequested () != -1) {
1744  node * eqn = addEquationData (v, true);
1745  eqn->setDataDependencies (v->getDependencies ());
1746  }
1747  }
1748 }
1749 
1750 /* This function searches through the dataset of the equation solver
1751  for possible matrix vectors. These are detected by the vectors'
1752  names (e.g. S[1,1]). The matrix vectors found in the dataset get
1753  converted and saved into the set of equations. */
1755  vector * vec;
1756  strlist * deps;
1757  char * p, * cand;
1758  int s, r, c, a, b, n = 1;
1759 
1760  // initialize the 'found' flag
1761  for (vec = v; vec != NULL; vec = (vector *) vec->getNext ())
1762  vec->setRequested (0);
1763 
1764  // loop through the dataset vector until no more matrix vector is found
1765  do {
1766  r = c = s = -1; cand = NULL; deps = NULL;
1767  // go through the dataset
1768  for (vec = v; vec != NULL; vec = (vector *) vec->getNext ()) {
1769  // skip detected vectors
1770  if (vec->getRequested ()) continue;
1771  // is the vector a possible matrix vector element ?
1772  if ((p = matvec::isMatrixVector (vec->getName (), a, b)) != NULL) {
1773  if (cand != NULL) {
1774  // does this vectors name equals the current one ?
1775  if (!strcmp (p, cand) && s == vec->getSize ()) {
1776  // save largest row and column index and set the 'found' flag
1777  if (a > r) r = a;
1778  if (b > c) c = b;
1779  vec->setRequested (n);
1780  }
1781  }
1782  else {
1783  /* new possible matrix vector:
1784  save its name, row and column index, its size (length of
1785  the vector) and data dependencies; then set the 'found' flag */
1786  cand = strdup (p);
1787  r = a;
1788  c = b;
1789  s = vec->getSize ();
1790  vec->setRequested (n);
1791  deps = vec->getDependencies ();
1792  }
1793  free (p);
1794  }
1795  }
1796 
1797  // new matrix vector detected
1798  if (cand != NULL) {
1799  // create a new matrix vector and set the appropriate name
1800  matvec * mv = new matvec (s, r + 1, c + 1);
1801  mv->setName (cand);
1802  // go through the dataset vector once again
1803  for (vec = v; vec != NULL; vec = (vector *) vec->getNext ()) {
1804  // and collect the vectors with the same 'found' flags
1805  if (vec->getRequested () == n) {
1806  p = matvec::isMatrixVector (vec->getName (), a, b);
1807  mv->set (*vec, a, b);
1808  free (p);
1809  vec->setRequested (-1);
1810  }
1811  }
1812  // now store this new matrix vector into the set of equations
1813  node * eqn = addEquationData (mv);
1814  eqn->solvee = this;
1815  eqn->evaluate ();
1816  if (deps == NULL) {
1817  strlist * deps = new strlist ();
1818  deps->add (mv->getName ());
1819  eqn->setDataDependencies (deps);
1820  delete deps;
1821  } else {
1822  eqn->setDataDependencies (deps);
1823  }
1824  free (cand); cand = NULL;
1825  }
1826  // increase the current 'found' flag
1827  n++;
1828  } while (cand != NULL);
1829 }
1830 
1831 /* The function creates an assignment equation from the given matrix
1832  vector and returns it. The new assignment is appended to the list
1833  of available equations. */
1835  constant * con = new constant (TAG_MATVEC);
1836  con->mv = mv;
1837  assignment * assign = new assignment ();
1838  assign->result = strdup (mv->getName ());
1839  assign->body = con;
1840  assign->setNext (equations);
1841  equations = assign;
1842  return assign;
1843 }
1844 
1845 /* The function returns the dataset entry length of the given equation
1846  node (a constant). The constant must already been evaluated when
1847  this function is called. */
1848 int solver::dataSize (constant * eqn) {
1849  int size = 0;
1850  switch (eqn->getType ()) {
1851  case TAG_VECTOR: // simple vector
1852  size = eqn->getResult()->v->getSize ();
1853  break;
1854  case TAG_MATVEC: // matrix vector
1855  size = eqn->getResult()->mv->getSize ();
1856  default:
1857  size = 1;
1858  }
1859  return size;
1860 }
1861 
1862 /* This function returns the dataset entry length of the given
1863  variable name. It must be ensured that the variable actually
1864  exists and is already evaluated. */
1865 int solver::getDataSize (char * var) {
1866  node * eqn = checker::findEquation (equations, var);
1867  return dataSize (C (eqn));
1868 }
1869 
1870 /* Depending on the index the function returns the cumulative product
1871  of the dataset entries stored in the given dependency list or one
1872  if there are no data dependencies at all. */
1873 int solver::getDependencySize (strlist * deps, int idx) {
1874  int size = 1;
1875  if (deps == NULL) return 1;
1876  for (int i = 0; i < deps->length () - idx; i++) {
1877  size *= getDataSize (deps->get (i));
1878  }
1879  return size;
1880 }
1881 
1882 /* This function goes through the given string list and calculates the
1883  data entries within these dataset dependencies. It returns at
1884  least one no matter whether the data vectors can be found or not. */
1885 int solver::dataSize (strlist * deps) {
1886  int size = 1;
1887  for (int i = 0; deps != NULL && i < deps->length (); i++) {
1888  char * str = deps->get (i);
1889  vector * dep = data->findDependency (str);
1890  vector * var = data->findVariable (str);
1891  size *= dep ? dep->getSize () : var ? var->getSize () : 1;
1892  }
1893  return size;
1894 }
1895 
1896 /* The function returns the data vector in the dataset according to
1897  the given variable name. If there is no such variable, it returns
1898  NULL. */
1900  vector * var;
1901  /* search for variables in dataset */
1902  if (data != NULL) {
1903  if ((var = data->findVariable (str)) != NULL)
1904  return var;
1905  if ((var = data->findDependency (str)) != NULL)
1906  return var;
1907  }
1908  /* search for variables in equation set */
1909  if (equations != NULL) {
1910  node * eqn = checker::findEquation (equations, str);
1911  constant * res = eqn->getResult ();
1912  if (res->getTag () == CONSTANT && res->getType () == TAG_VECTOR) {
1913  return res->v;
1914  }
1915  }
1916  return NULL;
1917 }
1918 
1919 /* The following function collects the inherited dataset dependencies
1920  for the given equation node and returns it as a string list. It
1921  returns NULL if there are no such dependencies. */
1923  strlist * sub = NULL, * datadeps = NULL;
1924  // should all data dependencies be dropped?
1925  if (!eqn->getResult()->dropdeps) {
1926  strlist * deps = eqn->getDependencies ();
1927  datadeps = eqn->getDataDependencies ();
1928  datadeps = datadeps ? new strlist (*datadeps) : NULL;
1929  // go through equation dependencies
1930  for (int i = 0; deps && i < deps->length (); i++) {
1931  char * var = deps->get (i);
1932  // find equation node for the dependency
1933  node * n = checker::findEquation (equations, var);
1934  // try again in the solver equations
1935  if (n == NULL && eqn->solvee != NULL)
1936  n = checker::findEquation (eqn->solvee->getEquations (), var);
1937  // if finally founf the equation node
1938  if (n != NULL) {
1939  // pass resulting data dependencies up
1940  strlist * resdeps;
1941  if ((resdeps = n->getResult()->getDataDependencies ()) != NULL)
1942  n->setDataDependencies (resdeps);
1943  // add data dependencies
1944  sub = strlist::join (datadeps, n->getDataDependencies ());
1945  sub->del (n->getResult()->getDropDependencies ());
1946  sub->add (n->getResult()->getPrepDependencies ());
1947  }
1948  if (datadeps) delete datadeps;
1949  datadeps = sub;
1950  }
1951  }
1952  // prepend dependencies if necessary
1953  strlist * preps = eqn->getResult()->getPrepDependencies ();
1954  if (datadeps) {
1955  if (preps) datadeps->add (preps);
1956  } else {
1957  datadeps = new strlist ();
1958  if (preps) datadeps->add (preps);
1959  }
1960  // drop duplicate entries
1961  datadeps = checker::foldDependencies (datadeps);
1962  // delete the dependencies to be dropped intentionally
1963  datadeps->del (eqn->getResult()->getDropDependencies ());
1964  // finally return the correct data dependencies
1965  if (datadeps->length () == 0) {
1966  delete datadeps;
1967  datadeps = NULL;
1968  }
1969  return datadeps;
1970 }
1971 
1972 // The function stores the equation solver results back into a dataset.
1974  // return if nothing todo
1975  if (data == NULL) return;
1976  // go through each equation
1977  foreach_equation (eqn) {
1978 
1979  // skip variables which don't need to be exported
1980  if (!eqn->output) continue;
1981 
1982  // is the equation result already in the dataset ?
1983  if (!findEquationResult (eqn)) {
1984  vector * v = dataVector (eqn);
1985  if (v == NULL) continue;
1986 
1987  // collect inherited dataset dependencies
1988  strlist * datadeps = collectDataDependencies (eqn);
1989 
1990  // check whether dataset is smaller than its dependencies
1991  if (v->getSize () <= 1 && dataSize (datadeps) > v->getSize ()) {
1992  delete datadeps;
1993  datadeps = NULL;
1994  }
1995 
1996  // store variable vector(s)
1997  if (datadeps && datadeps->length () > 0) {
1998  v->setDependencies (datadeps);
1999  if (v->getNext () != NULL) {
2000  data->applyDependencies (v);
2001  data->addVariables (v);
2002  }
2003  else {
2004  data->addVariable (v);
2005  }
2006  }
2007  // store independent vector(s)
2008  else {
2009  if (v->getNext () != NULL)
2010  data->addDependencies (v);
2011  else
2012  data->addDependency (v);
2013  delete datadeps;
2014  }
2015  }
2016  }
2017 }
2018 
2019 /* This function checks whether the given equation solver result is
2020  already within the dataset. It returns non-zero if so, otherwise
2021  the function returns zero. */
2023  // check each vector of a given matrix vector
2024  if (eqn->getType () == TAG_MATVEC) {
2025  matvec * mv = eqn->getResult()->mv;
2026  for (int r = 0; r < mv->getRows (); r++) {
2027  for (int c = 0; c < mv->getCols (); c++) {
2028  char * str = matvec::createMatrixString (A(eqn)->result, r, c);
2029  if (data->findDependency (str) || data->findVariable (str))
2030  return 1;
2031  }
2032  }
2033  }
2034  // check normal data vectors
2035  else {
2036  char * str = A(eqn)->result;
2037  if (data->findDependency (str) || data->findVariable (str))
2038  return 1;
2039  }
2040  return 0;
2041 }
2042 
2043 /* This function is called in order to run the equation checker and
2044  the solver. The optional dataset passed to the function receives
2045  the results of the calculations. */
2047  // load additional dataset equations
2048  setData (data);
2049  checkinDataset ();
2050  // put these into the checker
2051  checkee->setEquations (equations);
2052  // and check
2053  if (checkee->check (data ? 1 : 0) != 0) {
2054  return -1;
2055  }
2056  equations = checkee->getEquations ();
2057  // finally evaluate equations
2058  evaluate ();
2059  // put results into the dataset
2060  checkoutDataset ();
2061  return 0;
2062 }
2063 
2064 /* Go through the list of equations and store the left hand side in
2065  a string list. */
2067  strlist * idents = new strlist ();
2068  foreach_equation (eqn) {
2069  idents->add (eqn->result);
2070  }
2071  return idents;
2072 }
2073 
2074 // Checks if the given variable name is an equation.
2075 bool checker::containsVariable (char * ident) {
2076  foreach_equation (eqn) {
2077  if (!strcmp (ident, eqn->result))
2078  return true;
2079  }
2080  return false;
2081 }
2082 
2083 // Structure defining a predefined constant.
2084 struct pconstant {
2085  const char * ident;
2086  nr_double_t value;
2087 };
2088 
2089 // List of global constant variables.
2090 static struct pconstant pconstants[] = {
2091  { "pi", M_PI },
2092  { "e", M_E },
2093  { "kB", kB },
2094  { "q", Q },
2095  { NULL, 0 }
2096 };
2097 
2098 /* The function should be called before parsing the netlist. It
2099  appends the predefined constants to the list of equations. */
2100 void checker::constants (void) {
2101 
2102  // return if nothing to do
2103  if (consts) return;
2104 
2105  // go through constants and add these to the equations
2106  for (int i = 0; pconstants[i].ident != NULL; i++) {
2107  addDouble ("#predefined", pconstants[i].ident, pconstants[i].value);
2108  }
2109 
2110  // indicate that constants have been added
2111  consts = true;
2112 }
2113 
2114 /* The function adds a new equation to the equation checker consisting
2115  of an assignment of a reference. */
2116 node * checker::addReference (const char * type, const char * ident,
2117  char * value) {
2118  node * eqn = createReference (type, ident, value);
2119  addEquation (eqn);
2120  return eqn;
2121 }
2122 
2123 /* The function adds a new equation to the equation checker consisting
2124  of an assignment of a double variable. */
2125 node * checker::addDouble (const char * type, const char * ident,
2126  nr_double_t value) {
2127  node * eqn = createDouble (type, ident, value);
2128  addEquation (eqn);
2129  return eqn;
2130 }
2131 
2132 /* The function adds a new equation to the equation checker consisting
2133  of an assignment of a complex variable. */
2134 node * checker::addComplex (const char * type, const char * ident,
2135  nr_complex_t value) {
2136  node * eqn = createComplex (type, ident, value);
2137  addEquation (eqn);
2138  return eqn;
2139 }
2140 
2141 // Adds given equation to the equation list.
2143  eqn->setNext (equations);
2144  equations = eqn;
2145 }
2146 
2147 // Appends the given equation to the equation list.
2148 void checker::appendEquation (node * eqn) {
2149  eqn->setNext (NULL);
2150  node * last = lastEquation (equations);
2151  if (last != NULL)
2152  last->setNext (eqn);
2153  else
2154  equations = eqn;
2155 }
2156 
2157 /* This function creates a equation consisting of an assignment of a
2158  double variable. */
2159 node * checker::createDouble (const char * type, const char * ident,
2160  nr_double_t value) {
2161  // create constant double value
2162  constant * c = new constant (TAG_DOUBLE);
2163  c->checkee = this;
2164  c->d = value;
2165  // create the appropriate assignment
2166  assignment * a = new assignment ();
2167  a->checkee = this;
2168  a->result = strdup (ident);
2169  a->body = c;
2170  a->output = 0;
2171  a->setInstance (type);
2172  return a;
2173 }
2174 
2175 /* This function creates a equation consisting of an assignment of a
2176  complex variable. */
2177 node * checker::createComplex (const char * type, const char * ident,
2178  nr_complex_t value) {
2179  // create constant double value
2180  constant * c = new constant (TAG_COMPLEX);
2181  c->checkee = this;
2182  c->c = new nr_complex_t (value);
2183  // create the appropriate assignment
2184  assignment * a = new assignment ();
2185  a->checkee = this;
2186  a->result = strdup (ident);
2187  a->body = c;
2188  a->output = 0;
2189  a->setInstance (type);
2190  return a;
2191 }
2192 
2193 /* This function creates a equation consisting of an assignment of a
2194  reference. */
2195 node * checker::createReference (const char * type, const char * ident,
2196  char * value) {
2197  // create reference value
2198  reference * r = new reference ();
2199  r->checkee = this;
2200  r->n = strdup (value);
2201  // create the appropriate assignment
2202  assignment * a = new assignment ();
2203  a->checkee = this;
2204  a->result = strdup (ident);
2205  a->body = r;
2206  a->output = 0;
2207  a->setInstance (type);
2208  return a;
2209 }
2210 
2211 /* The functions looks through the set of equations for a real valued
2212  result and returns it. If there is no such assignment, zero is
2213  returned. */
2214 nr_double_t checker::getDouble (char * ident) {
2215  foreach_equation (eqn) {
2216  if (!strcmp (ident, eqn->result)) {
2217  return eqn->getResultDouble ();
2218  }
2219  }
2220  return 0.0;
2221 }
2222 
2223 /* The function goes through the equation set and looks for the
2224  specified assignment. If found the given value is set. */
2225 void checker::setDouble (char * ident, nr_double_t val) {
2226  foreach_equation (eqn) {
2227  if (!strcmp (ident, eqn->result)) {
2228  if (eqn->body->getTag () == CONSTANT) {
2229  constant * c = C (eqn->body);
2230  if (c->type == TAG_DOUBLE) c->d = val;
2231  }
2232  }
2233  }
2234 }
2235 
2236 /* The functions looks through the set of equations for a vector
2237  result and returns it. If there is no such assignment, an empty
2238  vector is returned. */
2240  foreach_equation (eqn) {
2241  if (!strcmp (ident, eqn->result)) {
2242  return eqn->getResultVector ();
2243  }
2244  }
2245  return vector ();
2246 }