Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nodelist.cpp
Go to the documentation of this file.
1 /*
2  * nodelist.cpp - node list class implementation
3  *
4  * Copyright (C) 2003, 2004, 2006, 2008 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 <assert.h>
33 
34 #include "logging.h"
35 #include "object.h"
36 #include "node.h"
37 #include "complex.h"
38 #include "circuit.h"
39 #include "net.h"
40 #include "nodelist.h"
41 
42 namespace qucs {
43 
44 // Constructor creates an instance of the nodelist class.
46  root = last = NULL;
47  narray = NULL;
48  txt = NULL;
49  sorting = 0;
50 }
51 
52 /* The function creates a nodelist for the given netlist. The
53  nodelist is based on the circuit list and consists of unique nodes
54  inside the circuit list only. Each node in the list has references
55  to their actual circuit nodes and thereby to the circuits it is
56  connected to. */
57 nodelist::nodelist (net * subnet) {
58  root = last = NULL;
59  narray = NULL;
60  txt = NULL;
61  sorting = 0;
62 
63  circuit * c;
64  // go through circuit list and find unique nodes
65  for (c = subnet->getRoot (); c != NULL; c = (circuit *) c->getNext ()) {
66  for (int i = 0; i < c->getSize (); i++) {
67  node * n = c->getNode (i);
68  if (contains (n->getName ()) == 0) {
69  add (n->getName (), n->getInternal ());
70  }
71  }
72  }
73  // add circuit nodes to each unique node in the list
74  for (struct nodelist_t * n = getRoot (); n != NULL; n = n->next) {
75  for (c = subnet->getRoot (); c != NULL; c = (circuit *) c->getNext ()) {
76  for (int i = 0; i < c->getSize (); i++) {
77  assert (n->name != NULL);
78  assert (c->getNode(i)->getName () != NULL);
79  if (!strcmp (n->name, c->getNode(i)->getName ())) {
80  addCircuitNode (n, c->getNode (i));
81  }
82  }
83  }
84  }
85 }
86 
87 /* This copy constructor creates a instance of the nodelist class
88  based on the given nodelist. */
90  struct nodelist_t * n;
91  root = last = NULL;
92  narray = NULL;
93  for (n = o.root; n != NULL; n = n->next) append (copy (n));
94  txt = o.txt ? strdup (o.txt) : NULL;
95  sorting = o.sorting;
96 }
97 
98 // Destructor deletes an instance of the nodelist class.
100  struct nodelist_t * next;
101  while (root) {
102  next = root->next;
103  release (root);
104  root = next;
105  }
106  if (txt) free (txt);
107  if (narray) free (narray);
108 }
109 
110 // The function copies the given node with all its properties.
111 struct nodelist_t * nodelist::copy (struct nodelist_t * n) {
112  struct nodelist_t * copy = create (n->name, n->internal);
113  copy->n = n->n;
114  copy->nNodes = n->nNodes;
115  copy->nAlloc = n->nAlloc;
116  if (copy->nAlloc) {
117  copy->nodes = (node **) malloc (sizeof (node *) * n->nAlloc);
118  if (copy->nNodes) {
119  memcpy (copy->nodes, n->nodes, sizeof (node *) * n->nNodes);
120  }
121  }
122  return copy;
123 }
124 
125 // This function adds a node name to the list and saves the internal flag.
126 void nodelist::add (char * str, int intern) {
127  add (create (str, intern));
128 }
129 
130 // The function creates a node based upon the given arguments.
131 struct nodelist_t * nodelist::create (char * str, int intern) {
132  struct nodelist_t * n;
133  n = (struct nodelist_t *) calloc (sizeof (struct nodelist_t), 1);
134  n->internal = intern;
135  n->name = str ? strdup (str) : NULL;
136  return n;
137 }
138 
139 // This function adds a node to the list.
140 void nodelist::add (struct nodelist_t * n) {
141  n->next = root;
142  if (root == NULL) last = n;
143  root = n;
144 }
145 
146 // This function appends a node name to the list.
147 void nodelist::append (char * str, int intern) {
148  append (create (str, intern));
149 }
150 
151 // This function appends the given node to the list.
152 void nodelist::append (struct nodelist_t * n) {
153  n->next = NULL;
154  if (root)
155  last->next = n;
156  else
157  root = n;
158  last = n;
159 }
160 
161 // This function removes the node with the given name from the list.
162 void nodelist::remove (char * name) {
163  remove (getNode (name));
164 }
165 
166 // The function removes the given node from the list.
167 void nodelist::remove (struct nodelist_t * del, int keep) {
168  struct nodelist_t * prev, * n;
169  // go through the list
170  for (prev = NULL, n = root; n != NULL; prev = n, n = n->next) {
171  if (n == del) {
172  // adjust the chain properly
173  if (prev == NULL)
174  root = n->next;
175  else
176  prev->next = n->next;
177  if (n == last) last = prev;
178  // delete node if requested and return
179  if (!keep) release (n);
180  return;
181  }
182  }
183 }
184 
185 // This function free()'s the given node.
186 void nodelist::release (struct nodelist_t * n) {
187  if (n->name) free (n->name);
188  if (n->nodes) free (n->nodes);
189  free (n);
190 }
191 
192 // This function counts the node names in the list.
193 int nodelist::length (void) {
194  int res = 0;
195  for (struct nodelist_t * n = root; n != NULL; n = n->next) res++;
196  return res;
197 }
198 
199 // This function finds the specified node name in the list.
200 int nodelist::contains (char * str) {
201  int res = 0;
202  for (struct nodelist_t * n = root; n != NULL; n = n->next) {
203  if (n->name != NULL && str != NULL && !strcmp (n->name, str))
204  res++;
205  }
206  return res;
207 }
208 
209 // Returns the node number of the given node name.
210 int nodelist::getNodeNr (char * str) {
211  for (struct nodelist_t * n = root; n != NULL; n = n->next) {
212  if (n->name != NULL && str != NULL && !strcmp (n->name, str))
213  return n->n;
214  }
215  return -1;
216 }
217 
218 /* This function returns the node name positioned at the specified
219  location in the node name list. */
220 char * nodelist::get (int nr) {
221  return narray[nr + 1]->name;
222 }
223 
224 /* This function returns non-zero if the node positioned at the
225  specified location in the node name list is marked internal and
226  zero otherwise. */
227 int nodelist::isInternal (int nr) {
228  return narray[nr + 1]->internal;
229 }
230 
231 /* The function returns the nodelist structure at the specified
232  location in the node name list. */
233 struct nodelist_t * nodelist::getNode (int nr) {
234  return narray[nr + 1];
235 }
236 
237 /* The function returns the nodelist structure with the given name in
238  the node name list. It returns NULL if there is no such node. */
239 struct nodelist_t * nodelist::getNode (char * name) {
240  for (struct nodelist_t * n = root; n != NULL; n = n->next)
241  if (!strcmp (name, n->name)) return n;
242  return NULL;
243 }
244 
245 /* Returns a comma separated list of the circuits connected to the
246  node specified by the given number. */
247 char * nodelist::getNodeString (int nr) {
248  if (txt) free (txt); txt = NULL;
249  // find the specified node
250  struct nodelist_t * n = getNode (nr);
251  // append circuit names connected to the node
252  int len = (n->nNodes - 1) + 1;
253  txt = (char *) malloc (len); txt[0] = '\0';
254  for (int i = 0; i < n->nNodes; i++) {
255  char * str = n->nodes[i]->getCircuit()->getName ();
256  len += strlen (str);
257  txt = (char *) realloc (txt, len);
258  strcat (txt, str);
259  if (i != n->nNodes - 1) strcat (txt, ",");
260  }
261  return txt;
262 }
263 
264 /* The function returns the nodelist structure at the end of the node
265  name list. */
267  return last;
268 }
269 
270 // This function enumerates the nodes in the node name list.
272  int i = 1;
273 
274  // create fast array access possibility
275  if (narray) free (narray);
276  narray = (struct nodelist_t **)
277  malloc (sizeof (struct nodelist_t *) * length ());
278 
279  for (struct nodelist_t * n = root; n != NULL; n = n->next) {
280  // ground node gets a zero counter
281  if (!strcmp (n->name, "gnd")) {
282  n->n = 0;
283  narray[0] = n;
284  }
285  // others get a unique number greater than zero
286  else {
287  narray[i] = n;
288  n->n = i++;
289  }
290  }
291 }
292 
293 /* The function appends a node pointer to the given nodelist
294  structure. */
295 void nodelist::addCircuitNode (struct nodelist_t * nl, node * n) {
296  if (nl->nNodes >= nl->nAlloc) { // ensure capacity
297  if (nl->nAlloc == 0) {
298  nl->nAlloc = 2;
299  nl->nodes = (node **) malloc (sizeof (node *) * nl->nAlloc);
300  }
301  else {
302  nl->nAlloc *= 2;
303  nl->nodes = (node **) realloc (nl->nodes, sizeof (node *) * nl->nAlloc);
304  }
305  }
306  nl->nodes[nl->nNodes++] = n;
307  if (n->getInternal ()) nl->internal = n->getInternal ();
308 }
309 
310 /* This function deletes the given node from the nodelist
311  structure. */
312 void nodelist::delCircuitNode (struct nodelist_t * nl, node * n) {
313  assert (nl->nNodes > 0);
314  if (nl->nNodes > 1) {
315  int i, j;
316  // copy nodelist except the given one
317  for (j = i = 0; j < nl->nNodes - 1; i++, j++) {
318  if (nl->nodes[i] == n) i++;
319  nl->nodes[j] = nl->nodes[i];
320  }
321  }
322  else {
323  // no more nodes in the list
324  free (nl->nodes);
325  nl->nodes = NULL;
326  nl->nAlloc = 0;
327  }
328  nl->nNodes--;
329 }
330 
331 /* This function is used as sorting criteria for the S-parameter
332  analysis. It returns the number of nodes a join of the two
333  circuits connected to the given node would yield. */
334 static int sortfunc (struct nodelist_t * n) {
335  int p;
336  circuit * c1 = n->nodes[0]->getCircuit ();
337  circuit * c2 = n->nNodes > 1 ? n->nodes[1]->getCircuit () : NULL;
338  if (c1->getPort () || (c2 && c2->getPort ())) return -1;
339  if (c1 == c2) { // interconnect
340  p = c1->getSize () - 2;
341  } else { // connect
342  p = c1->getSize () + (c2 ? c2->getSize () - 2 : 0);
343  }
344  return p;
345 }
346 
347 /* The function evaluates the sorting criteria of the given two nodes.
348  It returns non-zero if 'n1' should be inserted before 'n2'. */
349 static int insfunc (struct nodelist_t * n1, struct nodelist_t * n2) {
350  int p1 = sortfunc (n1);
351  int p2 = sortfunc (n2);
352  return p1 >= 0 && (p1 <= p2 || p2 < 0);
353 }
354 
355 /* The function inserts the given node structure into the node list.
356  If the nodelist is sorted then the node gets inserted at a certain
357  position. */
358 void nodelist::insert (struct nodelist_t * n) {
359  // first node at all
360  if (root == NULL) {
361  last = root = n;
362  return;
363  }
364 
365  // sorted node list
366  if (sorting) {
367  int added = 0;
368  struct nodelist_t * nl, * prev;
369  for (prev = NULL, nl = root; nl != NULL; prev = nl, nl = nl->next) {
370  if (insfunc (n, nl)) {
371  if (prev == NULL) {
372  n->next = root;
373  root = n;
374  } else {
375  n->next = nl;
376  prev->next = n;
377  }
378  added++;
379  break;
380  }
381  }
382  if (!added) append (n);
383  return;
384  }
385 
386  // unsorted node list
387  add (n);
388 }
389 
390 /* This function removes the nodes associated with the given circuit
391  from the node list. If the node list is sorted then the order gets
392  rearranged properly. */
394  // go through each node of the circuit
395  for (int i = 0; i < c->getSize (); i++) {
396  node * n = c->getNode (i);
397  struct nodelist_t * nl;
398  if ((nl = getNode (n->getName ())) != NULL) {
399  // remove node from node structure
400  delCircuitNode (nl, n);
401  if (nl->nNodes <= 0) {
402  // completely remove the node structure
403  remove (nl);
404  }
405  else if (sorting && sortfunc (nl) > 0) {
406  // rearrange sorting
407  remove (nl, 1);
408  insert (nl);
409  }
410  }
411  }
412 }
413 
414 /* The following function can be used to insert a new circuit to the
415  node list. It goes through each node of the circuit and rearranges
416  the node list appropriately. */
418  // go through each node of the circuit
419  for (int i = 0; i < c->getSize (); i++) {
420  struct nodelist_t * nl;
421  node * n = c->getNode (i);
422  // is this node already in the nodelist?
423  if (contains (n->getName ()) == 0) {
424  // no, create new node and put it into the list
425  nl = create (n->getName (), n->getInternal ());
426  addCircuitNode (nl, n);
427  if (sorting) {
428  if (c->getPort ())
429  append (nl);
430  else
431  insert (nl);
432  }
433  else add (nl);
434  }
435  else {
436  // yes, put additional node into nodelist structure
437  if ((nl = getNode (n->getName ())) != NULL) {
438  addCircuitNode (nl, n);
439  if (sorting && sortfunc (nl) > 0) {
440  // rearrange sorting
441  remove (nl, 1);
442  insert (nl);
443  }
444  }
445  }
446  }
447 }
448 
449 /* The function completely rebuilds the nodelist. Once sort()'ed it
450  keeps being sorted when removing or inserting new circuits. */
451 void nodelist::sort (void) {
452  nodelist * nodes = new nodelist ();
453  struct nodelist_t * nl, * cand;
454  int p, i, ports, MaxPorts, len = length ();
455 
456  // go through the list until there is no node left
457  for (i = 0; i < len; i++) {
458  // find last order node
459  cand = NULL;
460  for (MaxPorts = -1, p = 0, nl = root; nl != NULL; nl = nl->next) {
461  ports = sortfunc (nl);
462  if (ports > MaxPorts || MaxPorts < 0 || ports == -1) {
463  cand = nl;
464  MaxPorts = ports;
465  }
466  if (ports == -1) break;
467  }
468  // add last order node
469  remove (cand, 1);
470  nodes->add (cand);
471  }
472 
473  // store sorted node list in current object
474  root = nodes->getRoot ();
475  last = nodes->getLastNode ();
476  nodes->root = NULL;
477  sorting = 1;
478 
479  // delete temporary node list
480  delete nodes;
481 }
482 
483 // The function returns the first two nodes of the sorted list.
484 void nodelist::sortedNodes (node ** node1, node ** node2) {
485  assert (root->nNodes == 2);
486  *node1 = root->nodes[0];
487  *node2 = root->nodes[1];
488 }
489 
490 #if DEBUG
491 // Debug function: Prints the entire nodelist.
492 void nodelist::print (void) {
493  for (struct nodelist_t * n = root; n != NULL; n = n->next) {
494  logprint (LOG_STATUS, "DEBUG: node %s-%d [", n->name, n->n);
495  for (int i = 0; i < n->nNodes; i++) {
496  logprint (LOG_STATUS, "%s", n->nodes[i]->getCircuit()->getName ());
497  if (i != n->nNodes - 1) logprint (LOG_STATUS, ",");
498  }
499  logprint (LOG_STATUS, "]\n");
500  }
501 }
502 #endif /* DEBUG */
503 
504 } // namespace qucs
void addCircuitNode(struct nodelist_t *, node *)
Definition: nodelist.cpp:295
circuit * getRoot(void)
Definition: net.h:46
char * txt
Definition: nodelist.h:83
struct nodelist_t * getRoot(void)
Definition: nodelist.h:52
name
Definition: parse_mdl.y:352
circuit * getCircuit(void)
Definition: node.cpp:91
int getNodeNr(char *)
Definition: nodelist.cpp:210
void remove(char *)
Definition: nodelist.cpp:162
void assignNodes(void)
Definition: nodelist.cpp:271
void sortedNodes(node **, node **)
Definition: nodelist.cpp:484
void release(struct nodelist_t *)
Definition: nodelist.cpp:186
struct nodelist_t * getNode(int)
Definition: nodelist.cpp:233
void sort(void)
Definition: nodelist.cpp:451
n
Definition: parse_citi.y:147
struct nodelist_t * getLastNode(void)
Definition: nodelist.cpp:266
object * getNext(void)
Definition: object.h:59
int getInternal(void)
Definition: node.h:46
static int insfunc(struct nodelist_t *n1, struct nodelist_t *n2)
Definition: nodelist.cpp:349
int getSize(void)
Get the number of ports the circuit element has.
Definition: circuit.h:143
i
Definition: parse_mdl.y:516
n2
Definition: parse_zvr.y:187
void delCircuitNode(struct nodelist_t *, node *)
Definition: nodelist.cpp:312
next
Definition: parse_spice.y:859
int contains(char *)
Definition: nodelist.cpp:200
base class for qucs circuit elements.
Definition: circuit.h:92
struct nodelist_t * root
Definition: nodelist.h:81
node ** nodes
Definition: nodelist.h:36
struct nodelist_t * copy(struct nodelist_t *)
Definition: nodelist.cpp:111
void append(char *, int intern=0)
Definition: nodelist.cpp:147
free($1)
char * get(int)
Definition: nodelist.cpp:220
eqn::constant * c1
eqn::constant * c2
Declaration sizeof(struct vcd_scope))
The circuit class header file.
nodes
int getPort(void)
Definition: circuit.h:228
struct nodelist_t * next
Definition: nodelist.h:40
int length(void)
Definition: nodelist.cpp:193
struct nodelist_t * last
Definition: nodelist.h:82
n1
Definition: parse_zvr.y:179
Definition: net.h:39
int isInternal(int)
Definition: nodelist.cpp:227
char * getName(void)
Definition: object.cpp:84
node * getNode(int)
Definition: circuit.cpp:307
#define LOG_STATUS
Definition: logging.h:29
void insert(struct nodelist_t *)
Definition: nodelist.cpp:358
void logprint(int level, const char *format,...)
Definition: logging.c:37
struct nodelist_t ** narray
Definition: nodelist.h:80
struct nodelist_t * create(char *, int)
Definition: nodelist.cpp:131
void add(char *, int intern=0)
Definition: nodelist.cpp:126
void print(void)
char * getNodeString(int)
Definition: nodelist.cpp:247
static int sortfunc(struct nodelist_t *n)
Definition: nodelist.cpp:334