LCOV - code coverage report
Current view: top level - src - environment.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 117 217 53.9 %
Date: 2015-01-05 16:01:02 Functions: 18 32 56.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 56 227 24.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * environment.cpp - variable environment class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2004, 2005, 2006, 2007, 2009 Stefan Jahn <stefan@lkcc.org>
       5                 :            :  *
       6                 :            :  * This is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 2, or (at your option)
       9                 :            :  * any later version.
      10                 :            :  *
      11                 :            :  * This software is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this package; see the file COPYING.  If not, write to
      18                 :            :  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
      19                 :            :  * Boston, MA 02110-1301, USA.
      20                 :            :  *
      21                 :            :  * $Id$
      22                 :            :  *
      23                 :            :  */
      24                 :            : 
      25                 :            : #if HAVE_CONFIG_H
      26                 :            : # include <config.h>
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include <list>
      30                 :            : 
      31                 :            : #include <stdio.h>
      32                 :            : #include <stdlib.h>
      33                 :            : #include <string.h>
      34                 :            : 
      35                 :            : #include "complex.h"
      36                 :            : #include "variable.h"
      37                 :            : #include "equation.h"
      38                 :            : #include "logging.h"
      39                 :            : #include "environment.h"
      40                 :            : 
      41                 :            : using namespace qucs::eqn;
      42                 :            : 
      43                 :            : namespace qucs {
      44                 :            : 
      45                 :            : // Constructor creates an unnamed instance of the environment class.
      46                 :          0 : environment::environment () :
      47                 :            :   name(),
      48 [ #  # ][ #  # ]:          0 :   children()
      49                 :            : {
      50                 :          0 :   root = NULL;
      51                 :          0 :   solvee = NULL;
      52                 :          0 :   checkee = NULL;
      53                 :          0 :   defs = NULL;
      54                 :          0 :   iscopy = false;
      55                 :          0 : }
      56                 :            : 
      57                 :            : 
      58                 :            : // Constructor creates a named instance of the environment class.
      59                 :        219 : environment::environment (const std::string & p_name) :
      60                 :            :   name(p_name),
      61 [ +  - ][ #  # ]:        219 :   children()
      62                 :            : {
      63                 :        219 :   root = NULL;
      64                 :        219 :   solvee = NULL;
      65                 :        219 :   checkee = NULL;
      66                 :        219 :   defs = NULL;
      67                 :        219 :   iscopy = false;
      68                 :        219 : }
      69                 :            : 
      70                 :            : /* The copy constructor creates a new instance of the environment
      71                 :            :    class based on the given environment object. */
      72 [ +  - ][ #  # ]:         23 : environment::environment (const environment & e)  {
      73 [ +  - ][ #  # ]:         23 :   this->name = e.name;
      74 [ +  - ][ #  # ]:         23 :   copyVariables (e.root);
      75                 :         23 :   solvee = e.solvee;
      76                 :         23 :   checkee = e.checkee;
      77                 :         23 :   defs = e.defs;
      78                 :         23 :   iscopy = true;
      79 [ +  - ][ +  - ]:         23 :   children = std::list<environment *>();
         [ #  # ][ #  # ]
      80                 :         23 : }
      81                 :            : 
      82                 :            : /* Very alike the copy constructor the function copies the content of
      83                 :            :    the given environment into the calling environment. */
      84                 :        103 : void environment::copy (const environment & e) {
      85                 :        103 :   this->name = e.name;
      86                 :        103 :   deleteVariables ();
      87                 :        103 :   copyVariables (e.root);
      88                 :        103 :   solvee = e.solvee;
      89                 :        103 :   checkee = e.checkee;
      90                 :        103 :   defs = e.defs;
      91                 :        103 :   iscopy = true;
      92         [ +  - ]:        103 :   children = std::list<environment *>();
      93                 :        103 : }
      94                 :            : 
      95                 :            : // Destructor deletes the environment object.
      96                 :        242 : environment::~environment () {
      97 [ +  - ][ #  # ]:        242 :   deleteVariables ();
      98                 :            :   // delete solver and checker if this is not just a reference
      99 [ +  + ][ #  # ]:        242 :   if (!iscopy) {
     100 [ +  - ][ #  # ]:        116 :     if (solvee)
     101 [ +  - ][ +  - ]:        116 :       delete solvee;
         [ #  # ][ #  # ]
     102 [ +  - ][ #  # ]:        116 :     if (checkee) {
     103 [ +  - ][ #  # ]:        116 :       checkee->setEquations (NULL);
     104 [ +  - ][ +  - ]:        116 :       delete checkee;
         [ #  # ][ #  # ]
     105                 :            :     }
     106                 :            :   }
     107                 :            :   // delete children
     108 [ +  + ][ #  # ]:        278 :   for (auto it = children.begin(); it != children.end(); ++it) {
     109                 :         36 :     environment * etmp = *it;
     110         [ +  - ]:         36 :     delete etmp;
           [ +  -  #  # ]
                 [ #  # ]
     111                 :            :   }
     112 [ -  + ][ #  # ]:        484 : }
     113                 :            : 
     114                 :            : 
     115                 :            : /* This function copies all variables in the given variable list into
     116                 :            :    an environment. */
     117                 :        126 : void environment::copyVariables (variable * org) {
     118                 :            :   variable * var;
     119                 :        126 :   root = NULL;
     120         [ +  + ]:        207 :   while (org != NULL) {
     121                 :            :     // copy variable (references only)
     122         [ +  - ]:         81 :     var = new variable (*org);
     123                 :            :     constant * c; reference * r;
     124                 :            :     // depending on variable type copy values too
     125   [ +  -  -  - ]:         81 :     switch (var->getType ()) {
     126                 :            :     case VAR_CONSTANT:
     127         [ +  - ]:         81 :       c = new constant (*(var->getConstant ()));
     128                 :         81 :       var->setConstant (c);
     129                 :         81 :       break;
     130                 :            :     case VAR_VALUE:
     131         [ #  # ]:          0 :       c = new constant (*(org->getValue ()));
     132                 :          0 :       var->setValue (c);
     133                 :          0 :       break;
     134                 :            :     case VAR_REFERENCE:
     135         [ #  # ]:          0 :       r = new reference ();
     136                 :          0 :       r->n = strdup (var->getReference()->n);
     137                 :          0 :       var->setReference (r);
     138                 :          0 :       break;
     139                 :            :     }
     140                 :         81 :     var->setNext (root);
     141                 :         81 :     root = var;
     142                 :         81 :     org = org->getNext ();
     143                 :            :   }
     144                 :        126 : }
     145                 :            : 
     146                 :            : // Deletes all variable in the environment.
     147                 :        345 : void environment::deleteVariables (void) {
     148                 :            :   variable * n;
     149         [ +  + ]:        510 :   for (variable * var = root; var != NULL; var = n) {
     150                 :        165 :     n = var->getNext ();
     151         [ +  + ]:        165 :     if (var->getType () == VAR_CONSTANT)
     152         [ +  - ]:        162 :       delete var->getConstant ();
     153         [ -  + ]:          3 :     else if (var->getType () == VAR_VALUE)
     154         [ #  # ]:          0 :       delete var->getValue ();
     155         [ +  - ]:          3 :     else if (var->getType () == VAR_SUBSTRATE)
     156         [ +  - ]:          3 :       delete var->getSubstrate ();
     157         [ #  # ]:          0 :     else if (var->getType () == VAR_REFERENCE) {
     158                 :          0 :       constant * c = var->getReference()->getResult ();
     159 [ #  # ][ #  # ]:          0 :       if (c) delete c;
     160         [ #  # ]:          0 :       delete var->getReference ();
     161                 :            :     }
     162         [ +  - ]:        165 :     delete var;
     163                 :            :   }
     164                 :        345 :   root = NULL;
     165                 :        345 : }
     166                 :            : 
     167                 :            : /* This function adds a variable to the environment. */
     168                 :         84 : void environment::addVariable (variable * const var, const bool pass) {
     169                 :         84 :   var->setNext (root);
     170                 :         84 :   var->setPassing (pass);
     171                 :         84 :   this->root = var;
     172                 :         84 : }
     173                 :            : 
     174                 :            : /* This function looks for the variable name in the environment and
     175                 :            :    returns it if possible.  Otherwise the function returns NULL. */
     176                 :      22955 : variable * environment::getVariable (const char * const n) const {
     177         [ +  + ]:      31270 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     178         [ +  - ]:      31248 :     if (var->getType () != VAR_VALUE)
     179         [ +  + ]:      31248 :       if (!strcmp (var->getName (), n))
     180                 :      22933 :         return var;
     181                 :            :   }
     182                 :      22955 :   return NULL;
     183                 :            : }
     184                 :            : 
     185                 :            : // The function runs the equation checker for this environment.
     186                 :        116 : int environment::equationChecker (const int noundefined) const {
     187                 :        116 :   checkee->setDefinitions (defs);
     188                 :        116 :   return checkee->check (noundefined);
     189                 :            : }
     190                 :            : 
     191                 :            : // The function runs the equation solver for this environment.
     192                 :      23187 : int environment::equationSolver (dataset * const data) {
     193                 :      23187 :   checkee->setDefinitions (defs);
     194                 :      23187 :   solvee->setEquations (checkee->getEquations ());
     195                 :      23187 :   int err = solvee->solve (data);
     196                 :      23187 :   checkee->setEquations (solvee->getEquations ());
     197                 :      23187 :   return err;
     198                 :            : }
     199                 :            : 
     200                 :            : // The function runs the equation solver for this environment without
     201                 :            : // checking it previously and without considering an additional
     202                 :            : // dataset.
     203                 :          0 : void environment::equationSolver (void) {
     204                 :          0 :   checkee->setDefinitions (defs);
     205                 :          0 :   solvee->setEquations (checkee->getEquations ());
     206                 :          0 :   solvee->evaluate ();
     207                 :          0 :   checkee->setEquations (solvee->getEquations ());
     208                 :          0 : }
     209                 :            : 
     210                 :            : 
     211                 :            : /* The function solves the equations of the current environment object
     212                 :            :    as well as these of its children, updates the variables and passes
     213                 :            :    the arguments to each children. */
     214                 :      23084 : int environment::runSolver (void) {
     215                 :      23084 :   int ret = 0;
     216                 :            : 
     217                 :            :   // solve equations in current environment
     218                 :      23084 :   ret |= equationSolver (NULL);
     219                 :      23084 :   fetchConstants ();
     220                 :            : 
     221                 :            :   // cycle through children
     222         [ +  + ]:      23366 :   for(auto it = children.begin(); it != children.end(); ++it) {
     223                 :            :     // pass constants to solver
     224         [ +  - ]:        282 :     (*it)->passConstants ();
     225                 :            :     // pass references
     226         [ +  - ]:        282 :     (*it)->updateReferences (this);
     227                 :            :     // actually run the solver
     228         [ +  - ]:        282 :     ret |= (*it)->runSolver ();
     229                 :            : #if 0
     230                 :            :     // save local results
     231                 :            :     (*it)->saveResults ();
     232                 :            : #endif
     233                 :            :   }
     234                 :            : 
     235                 :      23084 :   return ret;
     236                 :            : }
     237                 :            : 
     238                 :            : /* Passes the constants of the environment to the equation solver.
     239                 :            :    This is necessary since equally typed environments use the same
     240                 :            :    equation checker and solver. */
     241                 :        282 : void environment::passConstants (void) {
     242         [ -  + ]:        282 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     243 [ #  # ][ #  # ]:          0 :     if (var->getPassing () && var->getType () == VAR_CONSTANT) {
                 [ #  # ]
     244                 :          0 :       constant * c = var->getConstant ();
     245                 :          0 :       setDouble (var->getName (), c->d);
     246                 :            :     }
     247                 :            :   }
     248                 :        282 : }
     249                 :            : 
     250                 :            : /* Fetches the values of variables from the equation solver. */
     251                 :      23084 : void environment::fetchConstants (void) {
     252         [ +  + ]:      55772 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     253         [ +  + ]:      32688 :     if (var->getType () == VAR_CONSTANT) {
     254                 :      32685 :       constant * c = var->getConstant ();
     255      [ +  -  - ]:      32685 :       switch (c->getType ()) {
     256                 :            :       case TAG_DOUBLE:
     257                 :      32685 :         c->d = getDouble (var->getName ());
     258                 :      32685 :         break;
     259                 :            :       case TAG_VECTOR:
     260         [ #  # ]:          0 :         *c->v = getVector (var->getName ());
     261                 :      32685 :         break;
     262                 :            :       }
     263                 :            :     }
     264                 :            :   }
     265                 :      23084 : }
     266                 :            : 
     267                 :            : /* Looks through the environment variables for a given variable name
     268                 :            :    being a saved value and returns the variable pointer or NULL if
     269                 :            :    there is no such variable. */
     270                 :          0 : variable * environment::findValue (char * n) {
     271         [ #  # ]:          0 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     272         [ #  # ]:          0 :     if (var->getType () == VAR_VALUE)
     273         [ #  # ]:          0 :       if (!strcmp (var->getName (), n))
     274                 :          0 :         return var;
     275                 :            :   }
     276                 :          0 :   return NULL;
     277                 :            : }
     278                 :            : 
     279                 :            : /* Puts the given variable name and its computed result into the list
     280                 :            :    of environment variables. */
     281                 :          0 : void environment::setValue (char * n, constant * value) {
     282                 :          0 :   variable * var = findValue (n);
     283         [ #  # ]:          0 :   if (var != NULL) {
     284                 :            :     // replace variable
     285         [ #  # ]:          0 :     delete var->getValue ();
     286         [ #  # ]:          0 :     var->setValue (new constant (*value));
     287                 :            :   } else {
     288                 :            :     // create new variable
     289         [ #  # ]:          0 :     var = new variable (n);
     290         [ #  # ]:          0 :     var->setValue (new constant (*value));
     291                 :          0 :     addVariable (var);
     292                 :            :   }
     293                 :          0 : }
     294                 :            : 
     295                 :            : // Local macro definition to go through the list of equations.
     296                 :            : #define foreach_equation(eqn)                        \
     297                 :            :   for (assignment * (eqn) = A (equations);           \
     298                 :            :        (eqn) != NULL; (eqn) = A ((eqn)->getNext ()))
     299                 :            : 
     300                 :            : // Short helper macro.
     301                 :            : #define A(a) ((assignment *) (a))
     302                 :            : 
     303                 :            : /* The function puts local variables (prameters and equation results)
     304                 :            :    into the set of environment variables. */
     305                 :          0 : void environment::saveResults (void) {
     306                 :          0 :   node * equations = checkee->getEquations ();
     307                 :            :   // go through equations
     308         [ #  # ]:          0 :   foreach_equation (eqn) {
     309                 :          0 :     char * inst = eqn->getInstance ();
     310 [ #  # ][ #  # ]:          0 :     if (inst != NULL && eqn->evaluated) {
     311                 :          0 :       char * result = A(eqn)->result;
     312 [ #  # ][ #  # ]:          0 :       if ((inst[0] != '#' && !strchr (result, '.')) ||
                 [ #  # ]
     313                 :          0 :           !strcmp (inst, "#subcircuit")) {
     314                 :          0 :         setValue (result, eqn->getResult ());
     315                 :            :       }
     316                 :            :     }
     317                 :            :   }
     318                 :          0 : }
     319                 :            : 
     320                 :            : /* This function looks through all variables which are references.  If
     321                 :            :    found the variable gets resolved in the upper (parent) environment
     322                 :            :    and the value put into the result of the reference as well as into
     323                 :            :    the equation checker of the current environment. */
     324                 :        282 : void environment::updateReferences (environment * up) {
     325         [ -  + ]:        282 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     326         [ #  # ]:          0 :     if (var->getType () == VAR_REFERENCE) {
     327                 :          0 :       reference * r = var->getReference ();
     328                 :            :       // possible because no self-referring subcircuit types possible
     329                 :          0 :       nr_double_t d = up->getDouble (r->n);
     330                 :          0 :       constant * c = r->getResult ();
     331                 :          0 :       c->d = d;
     332                 :          0 :       setDouble (var->getName (), d);
     333                 :            :     }
     334                 :            :   }
     335                 :        282 : }
     336                 :            : 
     337                 :            : // Returns vector of an assignment in the equation checker.
     338                 :          0 : qucs::vector environment::getVector (const char * const ident) const {
     339                 :          0 :   return checkee->getVector (ident);
     340                 :            : }
     341                 :            : 
     342                 :            : // Returns double value of an assignment in the equation checker.
     343                 :      32685 : nr_double_t environment::getDouble (const char * const ident) const {
     344                 :      32685 :   return checkee->getDouble (ident);
     345                 :            : }
     346                 :            : 
     347                 :            : // Sets the double value of an assignment in the equation checker.
     348                 :      22739 : void environment::setDouble (const char * const ident, const nr_double_t val) {
     349                 :      22739 :   checkee->setDouble (ident, val);
     350                 :      22739 : }
     351                 :            : 
     352                 :            : // Return double value of a variable in the environment.
     353                 :          0 : nr_double_t environment::getDoubleConstant (const char * const ident) const {
     354                 :          0 :   variable * var = getVariable (ident);
     355 [ #  # ][ #  # ]:          0 :   if (var != NULL && var->getType () == VAR_CONSTANT) {
                 [ #  # ]
     356                 :          0 :     constant * c = var->getConstant ();
     357                 :          0 :     return c->d;
     358                 :            :   }
     359                 :          0 :   return 0.0;
     360                 :            : }
     361                 :            : 
     362                 :            : // Sets the double value of a variable in the environment.
     363                 :      22739 : void environment::setDoubleConstant (const char * const ident, nr_double_t val) {
     364                 :      22739 :   variable * var = getVariable (ident);
     365 [ +  - ][ +  - ]:      22739 :   if (var != NULL && var->getType () == VAR_CONSTANT) {
                 [ +  - ]
     366                 :      22739 :     constant * c = var->getConstant ();
     367                 :      22739 :     c->d = val;
     368                 :            :   }
     369                 :      22739 : }
     370                 :            : 
     371                 :            : // Returns the referenced value of a variable in the environment.
     372                 :          0 : char * environment::getDoubleReference (const char * const ident) const {
     373                 :          0 :   variable * var = getVariable (ident);
     374 [ #  # ][ #  # ]:          0 :   if (var != NULL &&  var->getType () == VAR_REFERENCE) {
                 [ #  # ]
     375                 :          0 :     reference * r = var->getReference ();
     376                 :          0 :     return r->n;
     377                 :            :   }
     378                 :          0 :   return NULL;
     379                 :            : }
     380                 :            : 
     381                 :            : // Sets the referenced value of a variable in the environment.
     382                 :          0 : void environment::setDoubleReference (const char * const ident, char * val) {
     383                 :          0 :   variable * var = getVariable (ident);
     384         [ #  # ]:          0 :   if (var != NULL) {
     385         [ #  # ]:          0 :     if (var->getType () == VAR_CONSTANT) {
     386                 :            :       // its a constant, so make it a reference
     387         [ #  # ]:          0 :       delete var->getConstant ();
     388         [ #  # ]:          0 :       reference * r = new reference ();
     389                 :          0 :       r->n = strdup (val);
     390         [ #  # ]:          0 :       constant * c = new constant (TAG_DOUBLE);
     391                 :          0 :       r->setResult (c);
     392                 :          0 :       var->setReference (r);
     393                 :            :     }
     394         [ #  # ]:          0 :     else if (var->getType () == VAR_REFERENCE) {
     395                 :            :       // just apply the reference
     396                 :          0 :       reference * r = var->getReference ();
     397         [ #  # ]:          0 :       if (r->n) free (r->n);
     398                 :          0 :       r->n = strdup (val);
     399                 :            :     }
     400                 :            :   }
     401                 :          0 : }
     402                 :            : 
     403                 :            : //! Prints the environment.
     404                 :          0 : void environment::print (const bool all) const {
     405                 :          0 :   logprint (LOG_STATUS, "environment %s\n",this->name.c_str());
     406         [ #  # ]:          0 :   for (variable * var = root; var != NULL; var = var->getNext ()) {
     407                 :          0 :     logprint (LOG_STATUS, "  %s [%s]\n", var->getName (), var->toString ());
     408                 :            :   }
     409         [ #  # ]:          0 :   for (auto it = children.begin(); it != children.end() ; ++it) {
     410         [ #  # ]:          0 :     logprint (LOG_STATUS, "  %s\n", (*it)->name.c_str ());
     411                 :            :   }
     412         [ #  # ]:          0 :   if (all) {
     413         [ #  # ]:          0 :     for (auto it = children.begin(); it != children.end() ; ++it)
     414         [ #  # ]:          0 :       (*it)->print ();
     415                 :            :   }
     416                 :          0 : }
     417                 :            : 
     418                 :            : } // namespace qucs

Generated by: LCOV version 1.11