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