Qucs-core
0.0.19
|
00001 /* 00002 * nodelist.cpp - node list class implementation 00003 * 00004 * Copyright (C) 2003, 2004, 2006, 2008 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <algorithm> 00030 #include <cassert> 00031 00032 #include "logging.h" 00033 #include "object.h" 00034 #include "node.h" 00035 #include "complex.h" 00036 #include "circuit.h" 00037 #include "net.h" 00038 #include "nodelist.h" 00039 00040 namespace qucs { 00041 00042 00043 00044 /* The function creates a nodelist for the given netlist. The 00045 nodelist is based on the circuit list and consists of unique nodes 00046 inside the circuit list only. Each node in the list has references 00047 to their actual circuit nodes and thereby to the circuits it is 00048 connected to. */ 00049 nodelist::nodelist (net * subnet) { 00050 sorting = 0; 00051 00052 circuit * c; 00053 // go through circuit list and find unique nodes 00054 for (c = subnet->getRoot (); c != NULL; c = (circuit *) c->getNext ()) { 00055 for (int i = 0; i < c->getSize (); i++) { 00056 node * n = c->getNode (i); 00057 if (contains (n->getName ()) == 0) { 00058 root.push_front(new nodelist_t(n->getName (), n->getInternal ()));; 00059 } 00060 } 00061 } 00062 // add circuit nodes to each unique node in the list 00063 for (auto &n : this->root) { 00064 for (c = subnet->getRoot (); c != NULL; c = (circuit *) c->getNext ()) { 00065 for (int i = 0; i < c->getSize (); i++) { 00066 assert (c->getNode(i)->getName () != NULL); 00067 if (n->name == c->getNode(i)->getName ()) { 00068 addCircuitNode(n, c->getNode (i)); 00069 } 00070 } 00071 } 00072 } 00073 } 00074 00075 // Destructor deletes an instance of the nodelist class. 00076 nodelist::~nodelist () { 00077 for (auto &n: root) { 00078 delete n; 00079 } 00080 } 00081 00082 00083 // This function counts the node names in the list. 00084 int nodelist::length (void) const { 00085 return root.size(); 00086 } 00087 00088 // This function finds the specified node name in the list. 00089 bool nodelist::contains (const std::string &str) const { 00090 return std::find_if(root.begin(),root.end(),[str](nodelist_t *n) { return n->name == str; }) != root.end(); 00091 } 00092 00093 // Returns the node number of the given node name. 00094 int nodelist::getNodeNr (const std::string &str) const { 00095 00096 if(sorting) { 00097 auto it = std::find_if(narray.begin(),narray.end(),[str](nodelist_t *n) { return n->name == str; }); 00098 if(it == narray.end()) 00099 return -1; 00100 return (*it)->n; 00101 } 00102 auto it = std::find_if(root.begin(),root.end(),[str](nodelist_t *n) { return n->name == str; }); 00103 if(it == root.end()) 00104 return -1; 00105 return (*it)->n; 00106 } 00107 00108 /* This function returns the node name positioned at the specified 00109 location in the node name list. */ 00110 std::string nodelist::get (int nr) const { 00111 return narray[nr + 1]->name; 00112 } 00113 00114 /* This function returns non-zero if the node positioned at the 00115 specified location in the node name list is marked internal and 00116 zero otherwise. */ 00117 bool nodelist::isInternal (int nr) const { 00118 return narray[nr + 1]->internal; 00119 } 00120 00121 /* The function returns the nodelist structure with the given name in 00122 the node name list. It returns NULL if there is no such node. */ 00123 struct nodelist_t * nodelist::getNode (const std::string &str) const { 00124 auto it = std::find_if(root.begin(),root.end(),[str](nodelist_t *n) { return n->name == str; }); 00125 if(it != root.end()) 00126 return *it; 00127 return nullptr; 00128 } 00129 00130 /* Returns a comma separated list of the circuits connected to the 00131 node specified by the given number. */ 00132 std::string nodelist::getNodeString (int nr) const { 00133 std::string txt; 00134 // find the specified node 00135 struct nodelist_t * n = getNode (nr); 00136 // append circuit names connected to the node 00137 std::size_t i=0; 00138 for (auto ¤tn: *n) { 00139 const std::string str = currentn->getCircuit()->getName (); 00140 txt+=str; 00141 if (i != n->size() - 1) 00142 txt+=","; 00143 ++i; 00144 } 00145 return txt; 00146 } 00147 00148 00149 // This function enumerates the nodes in the node name list. 00150 void nodelist::assignNodes (void) { 00151 int i = 1; 00152 00153 // create fast array access possibility 00154 narray.clear(); 00155 narray.reserve(this->length()); 00156 00157 for (auto n: root) { 00158 // ground node gets a zero counter 00159 if (n->name=="gnd") { 00160 n->n = 0; 00161 narray[0] = n; 00162 } 00163 // others get a unique number greater than zero 00164 else { 00165 narray[i] = n; 00166 n->n = i++; 00167 } 00168 } 00169 } 00170 00171 /* The function appends a node pointer to the given nodelist 00172 structure. */ 00173 void nodelist::addCircuitNode (struct nodelist_t * nl, node * n) { 00174 (*nl).push_back(n); 00175 if (n->getInternal ()) nl->internal = n->getInternal (); 00176 } 00177 00178 00179 /* This function is used as sorting criteria for the S-parameter 00180 analysis. It returns the number of nodes a join of the two 00181 circuits connected to the given node would yield. */ 00182 static int sortfunc (struct nodelist_t * n) { 00183 int p; 00184 circuit * c1 = (*n)[0]->getCircuit (); 00185 circuit * c2 = (*n).size() > 1 ? (*n)[1]->getCircuit () : nullptr; 00186 if (c1->getPort () || (c2 && c2->getPort ())) return -1; 00187 if (c1 == c2) { // interconnect 00188 p = c1->getSize () - 2; 00189 } else { // connect 00190 p = c1->getSize () + (c2 ? c2->getSize () - 2 : 0); 00191 } 00192 return p; 00193 } 00194 00195 /* The function evaluates the sorting criteria of the given two nodes. 00196 It returns non-zero if 'n1' should be inserted before 'n2'. */ 00197 static int insfunc (struct nodelist_t * n1, struct nodelist_t * n2) { 00198 int p1 = sortfunc (n1); 00199 int p2 = sortfunc (n2); 00200 return p1 >= 0 && (p1 <= p2 || p2 < 0); 00201 } 00202 00203 /* The function inserts the given node structure into the node list. 00204 If the nodelist is sorted then the node gets inserted at a certain 00205 position. */ 00206 void nodelist::insert (struct nodelist_t * n) { 00207 // first node at all 00208 if (root.empty()) { 00209 root.push_front(n); 00210 return; 00211 } 00212 00213 // sorted node list 00214 if (sorting) { 00215 int added = 0; 00216 for (auto it = root.begin();it != root.end();it++) { 00217 if (insfunc (n, *it)) { 00218 root.insert(it,n); 00219 added++; 00220 break; 00221 } 00222 } 00223 if (!added) 00224 root.push_back (n); 00225 return; 00226 } 00227 00228 // unsorted node list 00229 root.push_front(n); 00230 } 00231 00232 /* This function removes the nodes associated with the given circuits 00233 from the node list. If the node list is sorted then the order gets 00234 rearranged properly. */ 00235 void nodelist::remove (circuit * c) { 00236 // go through each node of the circuit 00237 for (int i = 0; i < c->getSize (); i++) { 00238 node * n = c->getNode (i); 00239 struct nodelist_t * nl; 00240 if ((nl = this->getNode (n->getName ())) != NULL) { 00241 // remove node from node structure 00242 nl->erase(std::remove(nl->begin(), nl->end(), n), nl->end()); 00243 if (nl->empty()) { 00244 // completely remove the node structure 00245 root.erase(std::remove(root.begin(), root.end(), nl), root.end()); 00246 delete nl; 00247 } 00248 else if (sorting && sortfunc (nl) > 0) { 00249 // rearrange sorting 00250 root.erase(std::remove(root.begin(), root.end(), nl), root.end()); 00251 insert (nl); 00252 } 00253 } 00254 } 00255 } 00256 00257 /* The following function can be used to insert a new circuit to the 00258 node list. It goes through each node of the circuit and rearranges 00259 the node list appropriately. */ 00260 void nodelist::insert (circuit * c) { 00261 // go through each node of the circuit 00262 for (int i = 0; i < c->getSize (); i++) { 00263 struct nodelist_t * nl; 00264 node * n = c->getNode (i); 00265 // is this node already in the nodelist? 00266 if (contains (n->getName ()) == 0) { 00267 // no, create new node and put it into the list 00268 nl = new nodelist_t(n->getName (), n->getInternal ()); 00269 addCircuitNode (nl, n); 00270 if (sorting) { 00271 if (c->getPort ()) 00272 root.push_back (nl); 00273 else 00274 insert (nl); 00275 } 00276 else root.push_front (nl); 00277 } 00278 else { 00279 // yes, put additional node into nodelist structure 00280 if ((nl = getNode (n->getName ())) != NULL) { 00281 addCircuitNode (nl, n); 00282 if (sorting && sortfunc (nl) > 0) { 00283 // rearrange sorting 00284 root.erase(std::remove(root.begin(), root.end(), nl), root.end()); 00285 insert (nl); 00286 } 00287 } 00288 } 00289 } 00290 } 00291 00292 /* The function completely rebuilds the nodelist. Once sort()'ed it 00293 keeps being sorted when removing or inserting new circuits. */ 00294 void nodelist::sort (void) { 00295 nodelist * nodes = new nodelist (); 00296 struct nodelist_t * cand; 00297 int i, ports, MaxPorts, len = length (); 00298 00299 // go through the list until there is no node left 00300 for (i = 0; i < len; i++) { 00301 // find last order node 00302 cand = NULL; 00303 auto nl = root.begin(); 00304 for (MaxPorts = -1, nl = root.begin(); nl != root.end(); nl++) { 00305 ports = sortfunc (*nl); 00306 if (ports > MaxPorts || MaxPorts < 0 || ports == -1) { 00307 cand = *nl; 00308 MaxPorts = ports; 00309 } 00310 if (ports == -1) break; 00311 } 00312 // add last order node 00313 root.erase(std::remove(root.begin(), root.end(), cand), root.end()); 00314 nodes->root.push_front (cand); 00315 } 00316 00317 // store sorted node list in current object 00318 root = nodes->root; 00319 sorting = 1; 00320 00321 // delete temporary node list: UGLY todo proper lifetime 00322 nodes->root.clear(); 00323 delete nodes; 00324 } 00325 00326 // The function returns the first two nodes of the sorted list. 00327 void nodelist::sortedNodes (node ** node1, node ** node2) { 00328 assert ((*root.begin())->size() == 2); 00329 *node1 = (**(root.begin()))[0]; 00330 *node2 = (**(root.begin()))[1]; 00331 } 00332 00333 #if DEBUG 00334 // Debug function: Prints the entire nodelist. 00335 void nodelist::print (void) const { 00336 for (auto n: root) { 00337 logprint (LOG_STATUS, "DEBUG: node %s-%d [", n->name.c_str(), n->n); 00338 std::size_t i=0; 00339 for (const auto ¤tnode : *n) { 00340 logprint (LOG_STATUS, "%s", currentnode->getCircuit()->getName ()); 00341 if (i != n->size() - 1) logprint (LOG_STATUS, ","); 00342 ++i; 00343 } 00344 logprint (LOG_STATUS, "]\n"); 00345 } 00346 } 00347 #endif /* DEBUG */ 00348 00349 } // namespace qucs