LCOV - code coverage report
Current view: top level - src - equation.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 696 1254 55.5 %
Date: 2015-01-05 16:01:02 Functions: 90 161 55.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 435 1396 31.2 %

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

Generated by: LCOV version 1.11