Jspice3
diff.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Do a 'diff' of two plots.
10  */
11 
12 #include "spice.h"
13 #include "ftedefs.h"
14 #include "ftecmath.h"
15 #include "util.h"
16 
17 #ifdef __STDC__
18 static bool nameeq(char*,char*);
19 static bool inwlist(char*,wordlist*);
20 #else
21 static bool nameeq();
22 static bool inwlist();
23 #endif
24 
25 
26 struct dvlist2 {
27  char *d2_name;
28  struct dvec *d2_dv1;
29  struct dvec *d2_dv2;
30  struct dvlist2 *d2_next;
31 };
32 
33 
34 
35 void
37 wordlist *wl;
38 {
39  struct plot *p1, *p2 = NULL;
40  struct dvec *v1, *v2;
41  struct dvlist2 *dl, *dl0;
42  wordlist *tw, *wn, *wl1, *wl10, *wl2, *wl20;
43  complex c1, c2, c3;
44  double vntol, abstol, reltol, tol, cmax, cm1, cm2;
45  double d1, d2;
46  int i, j;
47  extern char *kw_vntol, *kw_abstol, *kw_reltol;
48 
49  if (!cp_getvar(kw_vntol, VT_REAL, (char *) &vntol))
50  vntol = 1.0e-6;
51  if (!cp_getvar(kw_abstol, VT_REAL, (char *) &abstol))
52  abstol = 1.0e-12;
53  if (!cp_getvar(kw_reltol, VT_REAL, (char *) &reltol))
54  reltol = 0.001;
55 
56  /* Let's try to be clever about defaults. */
57  if (!wl || !wl->wl_next) {
58  p1 = plot_cur;
59  if (eq(p1->pl_typename,"constants")) {
60  fprintf(cp_err, "Error: invalid current plot (constants)\n");
61  return;
62  }
63  }
64 
65  if (!wl) {
66  /* try the current and previous plot of same name */
67  for (p2 = p1->pl_next; p2 && !eq(p1->pl_name,p2->pl_name);
68  p2 = p2->pl_next) ;
69  if (!p2) {
70  fprintf(cp_err, "Error: no previous similar plot\n");
71  return;
72  }
73  fprintf(cp_err, "Plots are \"%s\" and \"%s\"\n",
74  p1->pl_typename, p2->pl_typename);
75  }
76 
77  else if (!wl->wl_next) {
78  /* try current and named plot */
79  for (p2 = plot_list; p2 && !eq(p2->pl_typename,wl->wl_word);
80  p2 = p2->pl_next) ;
81 
82  if (!p2 || eq(p2->pl_typename,"constants")) {
83  fprintf(cp_err, "Error: invalid plot \"%s\"\n", wl->wl_word);
84  return;
85  }
86  fprintf(cp_err, "Plots are \"%s\" and \"%s\"\n",
87  p1->pl_typename, p2->pl_typename);
88  wl = NULL;
89  }
90  else {
91  for (p1 = plot_list; p1; p1 = p1->pl_next)
92  if (eq(wl->wl_word, p1->pl_typename))
93  break;
94  if (!p1) {
95  fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word);
96  return;
97  }
98  wl = wl->wl_next;
99 
100  for (p2 = plot_list; p2; p2 = p2->pl_next)
101  if (eq(wl->wl_word, p2->pl_typename))
102  break;
103  if (!p2) {
104  fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word);
105  return;
106  }
107  wl = wl->wl_next;
108  }
109 
110  if (p1 == p2)
111  return;
112 
113  /* Now do some tests to make sure these plots are really the
114  * same type, etc.
115  */
116  if (!eq(p1->pl_name, p2->pl_name))
117  fprintf(cp_err,
118  "Warning: plots %s and %s seem to be of different types\n",
119  p1->pl_typename, p2->pl_typename);
120  if (!eq(p1->pl_title, p2->pl_title))
121  fprintf(cp_err,
122  "Warning: plots %s and %s seem to be from different circuits\n",
123  p1->pl_typename, p2->pl_typename);
124 
125  wl10 = (wordlist*)htab_wl(p1->pl_hashtab);
126  wl20 = (wordlist*)htab_wl(p2->pl_hashtab);
127 
128  /* Throw out the ones that aren't in the arg list */
129  if (wl && !eq(wl->wl_word, "all")) { /* Just in case */
130  for (wl1 = wl10; wl1; wl1 = wn) {
131  wn = wl1->wl_next;
132  for (tw = wl; tw; tw = tw->wl_next)
133  if (nameeq(wl1->wl_word, tw->wl_word))
134  break;
135  if (!tw) {
136  if (!wl1->wl_prev) {
137  wl10 = wn;
138  wl10->wl_prev = NULL;
139  }
140  else {
141  wl1->wl_prev->wl_next = wn;
142  if (wn)
143  wn->wl_prev = wl1->wl_prev;
144  }
145  txfree(wl1->wl_word);
146  txfree((char*)wl1);
147  }
148  }
149  for (wl2 = wl20; wl2; wl2 = wn) {
150  wn = wl2->wl_next;
151  for (tw = wl; tw; tw = tw->wl_next)
152  if (nameeq(wl2->wl_word, tw->wl_word))
153  break;
154  if (!tw) {
155  if (!wl2->wl_prev) {
156  wl20 = wn;
157  wl20->wl_prev = NULL;
158  }
159  else {
160  wl2->wl_prev->wl_next = wn;
161  if (wn)
162  wn->wl_prev = wl2->wl_prev;
163  }
164  txfree(wl2->wl_word);
165  txfree((char*)wl2);
166  }
167  }
168  }
169 
170  /* rid anything in 1 not in 2 */
171  for (wl1 = wl10; wl1; wl1 = wn) {
172  wn = wl1->wl_next;
173  if (!inwlist(wl1->wl_word,wl20)) {
174  fprintf(cp_err,
175  ">>> vector %s in %s not in %s\n",
176  wl1->wl_word, p1->pl_typename,
177  p2->pl_typename);
178  if (!wl1->wl_prev) {
179  wl10 = wn;
180  wl10->wl_prev = NULL;
181  }
182  else {
183  wl1->wl_prev->wl_next = wn;
184  if (wn)
185  wn->wl_prev = wl1->wl_prev;
186  }
187  txfree(wl1->wl_word);
188  txfree((char*)wl1);
189  }
190  }
191 
192  /* rid 2, warn first if not in 1 */
193  for (wl2 = wl20; wl2; wl2 = wl2->wl_next) {
194  if (!inwlist(wl2->wl_word,wl10)) {
195  fprintf(cp_err,
196  ">>> vector %s in %s not in %s\n",
197  wl2->wl_word, p2->pl_typename,
198  p1->pl_typename);
199  }
200  }
201  wl_free(wl20);
202 
203  dl0 = NULL;
204  for (wl1 = wl10; wl1; wl1 = wl1->wl_next) {
205  v1 = (struct dvec*)htab_get(wl1->wl_word,p1->pl_hashtab);
206  v2 = (struct dvec*)htab_get(wl1->wl_word,p2->pl_hashtab);
207  if (((v1->v_flags & (VF_REAL | VF_COMPLEX)) ==
208  (v2->v_flags & (VF_REAL | VF_COMPLEX))) &&
209  (v1->v_type == v2->v_type)) {
210  if (!dl0)
211  dl0 = dl = alloc(struct dvlist2);
212  else {
213  dl->d2_next = alloc(struct dvlist2);
214  dl = dl->d2_next;
215  }
216  dl->d2_dv1 = v1;
217  dl->d2_dv2 = v2;
218  }
219  else {
220  fprintf(cp_err,
221  ">>> vector %s type mismatch\n", wl1->wl_word);
222  }
223  }
224  wl_free(wl10);
225 
226 
227  /* Now we have all the vectors linked to their twins. Travel
228  * down each one and print values that differ enough.
229  */
230  for (dl = dl0; dl; dl = dl->d2_next) {
231  v1 = dl->d2_dv1;
232  v2 = dl->d2_dv2;
233 
234  if (v1->v_type == SV_VOLTAGE)
235  tol = vntol;
236  else
237  tol = abstol;
238  j = MAX(v1->v_length, v2->v_length);
239  for (i = 0; i < j; i++) {
240  if (v1->v_length <= i) {
241  out_printf(
242  ">>> %s is %d long in %s and %d long in %s\n",
243  v1->v_name, v1->v_length,
244  p1->pl_typename, v2->v_length,
245  p2->pl_typename);
246  break;
247  }
248  else if (v2->v_length <= i) {
249  out_printf(
250  ">>> %s is %d long in %s and %d long in %s\n",
251  v2->v_name, v2->v_length,
252  p2->pl_typename, v1->v_length,
253  p1->pl_typename);
254  break;
255  }
256  else {
257  if (isreal(v1)) {
258  d1 = v1->v_realdata[i];
259  d2 = v2->v_realdata[i];
260  if (MAX(FABS(d1), FABS(d2)) * reltol +
261  tol < FABS(d1 - d2)) {
262  out_printf(
263  "%s.%s[%d] = %-15s ",
264  p1->pl_typename, v1->v_name, i,
265  printnum(d1));
266  out_printf(
267  "%s.%s[%d] = %s\n",
268  p2->pl_typename, v2->v_name, i,
269  printnum(d2));
270  }
271  }
272  else {
273  c1 = v1->v_compdata[i];
274  c2 = v2->v_compdata[i];
275  realpart(&c3) = realpart(&c1) - realpart(&c2);
276  imagpart(&c3) = imagpart(&c1) - imagpart(&c2);
277  /* Stupid evil PC compilers */
278  cm1 = cmag(&c1);
279  cm2 = cmag(&c2);
280  cmax = MAX(cm1, cm2);
281  if (cmax * reltol +
282  tol < cmag(&c3)) {
283  out_printf(
284  "%s.%s[%d] = %-10s, ",
285  p1->pl_typename, v1->v_name, i,
286  printnum(realpart(&c1)));
287  out_printf("%-10s ",printnum(imagpart(&c1)));
288  out_printf(
289  "%s.%s[%d] = %-10s, ",
290  p2->pl_typename, v2->v_name, i,
291  printnum(realpart(&c2)));
292  out_printf("%-10s\n",printnum(imagpart(&c2)));
293  }
294  }
295  }
296  }
297  }
298  for (; dl0; dl0 = dl) {
299  dl = dl0->d2_next;
300  txfree((char*)dl0);
301  }
302  return;
303 }
304 
305 
306 static bool
307 nameeq(n1, n2)
308 
309 /* Determine if two vectors have the 'same' name. */
310 char *n1, *n2;
311 {
312  char buf1[BSIZE_SP], buf2[BSIZE_SP];
313  int i;
314 
315  if (eq(n1, n2))
316  return (true);
317  if (isdigit(*n1))
318  (void) sprintf(buf1, "v(%s)", n1);
319  else
320  (void) strcpy(buf1, n1);
321  if (isdigit(*n2))
322  (void) sprintf(buf2, "v(%s)", n2);
323  else
324  (void) strcpy(buf2, n2);
325  for (i = 0; buf1[i]; i++)
326  if (isupper(buf1[i]))
327  buf1[i] = tolower(buf1[i]);
328  for (i = 0; buf2[i]; i++)
329  if (isupper(buf2[i]))
330  buf2[i] = tolower(buf2[i]);
331  return (eq(buf1, buf2) ? true : false);
332 }
333 
334 
335 static bool
336 inwlist(word,wl)
337 
338 char *word;
339 wordlist *wl;
340 {
341  while (wl) {
342  if (!strcmp(word,wl->wl_word))
343  return (true);
344  wl = wl->wl_next;
345  }
346  return (false);
347 }
#define BSIZE_SP
Definition: misc.h:19
#define eq(a, b)
Definition: misc.h:29
static bool nameeq()
void com_diff(wordlist *wl)
Definition: diff.c:36
static bool inwlist()
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
char * pl_typename
Definition: ftedata.h:65
#define VF_REAL
Definition: fteconst.h:39
char * pl_title
Definition: ftedata.h:62
char * printnum()
void out_printf()
char * strcpy()
struct dvec * d2_dv2
Definition: diff.c:29
char * pl_name
Definition: ftedata.h:64
#define MAX(a, b)
Definition: spdefs.h:135
struct plot * plot_cur
Definition: vectors.c:43
char * kw_abstol
Definition: options.c:335
Definition: cpstd.h:29
#define SV_VOLTAGE
Definition: fteconst.h:14
Definition: ftedata.h:61
Definition: library.c:18
char * kw_vntol
Definition: options.c:429
void * pl_hashtab
Definition: ftedata.h:66
#define alloc(type)
Definition: cdmacs.h:21
complex * v_compdata
Definition: ftedata.h:29
void * htab_wl()
Definition: diff.c:26
void wl_free()
FILE * cp_err
Definition: help.c:101
struct wordlist * wl_prev
Definition: cpstd.h:24
void txfree()
#define NULL
Definition: spdefs.h:121
char * d2_name
Definition: diff.c:27
#define isreal(v)
Definition: ftedata.h:54
Definition: ftedata.h:24
#define cmag(c)
Definition: ftecmath.h:15
char * v_name
Definition: ftedata.h:25
#define imagpart(cval)
Definition: cpstd.h:36
Definition: cpstd.h:21
struct dvec * d2_dv1
Definition: diff.c:28
#define FABS(a)
Definition: util.h:41
struct plot * pl_next
Definition: ftedata.h:69
int v_type
Definition: ftedata.h:26
struct plot * plot_list
Definition: vectors.c:44
void * htab_get()
struct wordlist * wl_next
Definition: cpstd.h:23
#define VT_REAL
Definition: cpstd.h:62
char * wl_word
Definition: cpstd.h:22
struct dvlist2 * d2_next
Definition: diff.c:30
int v_length
Definition: ftedata.h:34
char * kw_reltol
Definition: options.c:411
short v_flags
Definition: ftedata.h:27
double * v_realdata
Definition: ftedata.h:28
#define VF_COMPLEX
Definition: fteconst.h:40
#define realpart(cval)
Definition: cpstd.h:35