Jspice3
pzstr.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1990 UCB CAD Group
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * A variant on the "zeroin" method. This is a bit convoluted.
10  */
11 
12 #include "spice.h"
13 #include <stdio.h>
14 #include <math.h>
15 #include "devdefs.h"
16 #include "pzdefs.h"
17 #include "sperror.h"
18 #include "util.h"
19 #include "cktext.h"
20 #include "niext.h"
21 
22 #ifdef notdef
23 #define DEBUG(N) if (Debug >= (unsigned) (N))
24 static unsigned int Debug = 1;
25 #else
26 #define DEBUG(N) if (0)
27 #endif
28 
29 static void clear_trials( ), show_trial( ), check_flat( );
30 void CKTpzUpdateSet( ), zaddeq( ), CKTpzReset( );
31 
32 #define NITER_LIM 200
33 
34 #define SHIFT_LEFT 2
35 #define SHIFT_RIGHT 3
36 #define SKIP_LEFT 4
37 #define SKIP_RIGHT 5
38 #define INIT 6
39 
40 #define GUESS 7
41 #define SPLIT_LEFT 8
42 #define SPLIT_RIGHT 9
43 
44 #define MULLER 10
45 #define SYM 11
46 #define SYM2 12
47 #define COMPLEX_INIT 13
48 #define COMPLEX_GUESS 14
49 #define QUIT 15
50 
51 #define NEAR_LEFT 4
52 #define MID_LEFT 5
53 #define FAR_LEFT 6
54 #define NEAR_RIGHT 7
55 #define FAR_RIGHT 8
56 #define MID_RIGHT 9
57 
58 static char *snames[ ] = {
59  "none",
60  "none",
61  "shift left",
62  "shift right",
63  "skip left",
64  "skip right",
65  "init",
66  "guess",
67  "split left",
68  "split right",
69  "Muller",
70  "sym 1",
71  "sym 2",
72  "complex_init",
73  "complex_guess",
74  "quit",
75  "none"
76  };
77 
78 #define sgn(X) ((X) < 0 ? -1 : (X) == 0 ? 0 : 1)
79 
80 #define ISAROOT 2
81 #define ISAREPEAT 4
82 #define ISANABERRATION 8
83 #define ISAMINIMA 16
84 
85 extern double NIpzK;
86 extern int NIpzK_mag;
87 
89 
90 static int NZeros, NFlat, Max_Zeros;
92 static int Seq_Num;
93 static double Guess_Param;
94 static double High_Guess, Low_Guess;
95 static int Last_Move, Consec_Moves;
96 static int NIter, NTrials;
97 static int Aberr_Num;
98 
99 int PZeval( );
100 static PZtrial *pzseek( );
101 static int alter( );
102 
103 
104 CKTpzFindZeros(ckt, rootinfoptr, rootcount)
105 
106 CKTcircuit *ckt;
107 GENERIC **rootinfoptr;
108 int *rootcount;
109 {
110  PZtrial **rootinfo = (PZtrial**)rootinfoptr;
111  PZtrial *new_trial;
112  PZtrial *neighborhood[3];
113  int done = 0;
114  int strat;
115  int error;
116  char ebuf[513];
117 
118  NIpzK = 0.0;
119  NIpzK_mag = 0;
120  High_Guess = -1.0;
121  Low_Guess = 1.0;
122  ZeroTrial = 0;
123  Trials = 0;
124  NZeros = 0;
125  NFlat = 0;
126  Max_Zeros = spGetSize(ckt->CKTmatrix,1);
127  NIter = 0;
128  error = OK;
129  CKTpzTrapped = 0;
130  Aberr_Num = 0;
131  NTrials = 0;
132  ckt->CKTniState |= NIPZSHOULDREORDER; /* Initial for LU fill-ins */
133 
134  Seq_Num = 1;
135 
136  CKTpzReset(neighborhood);
137 
138  do {
139 
140  while ((strat = CKTpzStrat(neighborhood)) < GUESS && !CKTpzTrapped)
141  if (!CKTpzStep(strat, neighborhood)) {
142  strat = GUESS;
143  DEBUG(1) fprintf(stderr, "\t\tGuess\n");
144  break;
145  }
146 
147  NIter += 1;
148 
149  /* Evaluate current strategy */
150  error = PZeval(strat, neighborhood, &new_trial);
151  if (error != OK)
152  return (error);
153 
154  error = CKTpzRunTrial(ckt, &new_trial, neighborhood);
155  if (error != OK)
156  return (error);
157 
158  if (new_trial->flags & ISAROOT) {
159  if (CKTpzVerify(neighborhood, new_trial)) {
160  NIter = 0;
161  CKTpzReset(neighborhood);
162  }
163  else
164  /* XXX Verify fails ?!? */
165  CKTpzUpdateSet(neighborhood, new_trial);
166  }
167  else if (new_trial->flags & ISANABERRATION) {
168  CKTpzReset(neighborhood);
169  Aberr_Num += 1;
170  txfree(new_trial);
171  }
172  else if (new_trial->flags & ISAMINIMA) {
173  neighborhood[0] = NULL;
174  neighborhood[1] = new_trial;
175  neighborhood[2] = NULL;
176  }
177  else {
178  CKTpzUpdateSet(neighborhood, new_trial); /* Replace a value */
179  }
180 
181  if ((*(SPfrontEnd->IFpauseTest))( )) {
182  sprintf(ebuf,
183  "Pole-Zero analysis interrupted; %d trials, %d roots\n",
184  Seq_Num, NZeros);
185  (*(SPfrontEnd->IFerror))(ERR_WARNING, ebuf, 0);
186  error = E_PAUSE;
187  break;
188  }
189  }
190  while (High_Guess - Low_Guess < 1e40
191  && NZeros < Max_Zeros
192  && NIter < NITER_LIM && Aberr_Num < 3
193  && High_Guess - Low_Guess < 1e35 /* XXX Should use mach const */
194  && (!neighborhood[0] || !neighborhood[2] || CKTpzTrapped
195  || neighborhood[2]->s.real - neighborhood[0]->s.real < 1e22));
196  /* XXX ZZZ */
197 
198  DEBUG(1) fprintf(stderr,
199  "Finished: NFlat %d, NZeros: %d, NTrials %d, Guess %g to %g, aber %d\n",
201 
202  if (NZeros >= Seq_Num - 1) {
203  /* Short */
205  *rootinfo = NULL;
206  *rootcount = 0;
207  ERROR(E_SHORT,
208  "The input signal is shorted on the way to the output");
209  }
210  else
211  clear_trials(0);
212 
213  *rootinfo = Trials;
214  *rootcount = NZeros;
215 
216  if (Aberr_Num > 2) {
217  sprintf(ebuf,
218  "Pole-zero converging to numerical aberrations; giving up after %d trials",
219  Seq_Num);
220  (*(SPfrontEnd->IFerror))(ERR_WARNING, ebuf, 0);
221  }
222 
223  if (NIter >= NITER_LIM) {
224  sprintf(ebuf,
225  "Pole-zero iteration limit reached; giving up after %d trials",
226  Seq_Num);
227  (*(SPfrontEnd->IFerror))(ERR_WARNING, ebuf, 0);
228  }
229 
230  return (error);
231 }
232 
233 
234 /* PZeval: evaluate an estimation function (given by 'strat') for the next
235  guess (returned in a PZtrial) */
236 
237 /* XXX ZZZ */
238 int
239 PZeval(strat, set, new_trial_p)
240 
241 int strat;
242 PZtrial *set[ ];
243 PZtrial **new_trial_p;
244 {
245  int error;
246  double a, b, est, k, n;
247  PZtrial *new_trial;
248 
249  new_trial = NEW(PZtrial);
250  new_trial->multiplicity = 0;
251  new_trial->count = 0;
252  new_trial->seq_num = Seq_Num++;
253 
254  switch (strat) {
255  case GUESS:
256  if (High_Guess < Low_Guess)
257  Guess_Param = 0.0;
258  else if (Guess_Param > 0.0) {
259  if (High_Guess > 0.0)
260  Guess_Param = High_Guess * 10.0;
261  else
262  Guess_Param = 1.0;
263  }
264  else {
265  if (Low_Guess < 0.0)
266  Guess_Param = Low_Guess * 10.0;
267  else
268  Guess_Param = -1.0;
269  }
270  if (Guess_Param > High_Guess)
272  if (Guess_Param < Low_Guess)
274  new_trial->s.real = Guess_Param;
275  if (set[1])
276  new_trial->s.imag = set[1]->s.imag;
277  else
278  new_trial->s.imag = 0.0;
279  error = OK;
280  break;
281 
282  case SYM:
283  case SYM2:
284  error = NIpzSym(set, new_trial);
285 
286  if (CKTpzTrapped == 1) {
287  if (new_trial->s.real < set[0]->s.real
288  || new_trial->s.real > set[1]->s.real) {
289  DEBUG(1) fprintf(stderr,
290  "FIXED UP BAD Strat: %s (%d) was (%.15g,%.15g)\n",
291  snames[strat], CKTpzTrapped,
292  new_trial->s.real, new_trial->s.imag);
293  new_trial->s.real =
294  (set[0]->s.real + set[1]->s.real) / 2.0;
295  }
296  }
297  else if (CKTpzTrapped == 2) {
298  if (new_trial->s.real < set[1]->s.real
299  || new_trial->s.real > set[2]->s.real) {
300  DEBUG(1) fprintf(stderr,
301  "FIXED UP BAD Strat: %s (%d) was (%.15g,%.15g)\n",
302  snames[strat], CKTpzTrapped,
303  new_trial->s.real, new_trial->s.imag);
304  new_trial->s.real =
305  (set[1]->s.real + set[2]->s.real) / 2.0;
306  }
307  }
308  else if (CKTpzTrapped == 3) {
309  if (new_trial->s.real <= set[0]->s.real
310  || new_trial->s.real == set[1]->s.real
311  && new_trial->s.imag == set[1]->s.imag
312  || new_trial->s.real >= set[2]->s.real) {
313  DEBUG(1) fprintf(stderr,
314  "FIXED UP BAD Strat: %s (%d), was (%.15g %.15g)\n",
315  snames[strat], CKTpzTrapped,
316  new_trial->s.real, new_trial->s.imag);
317  new_trial->s.real =
318  (set[0]->s.real + set[2]->s.real) / 2.0;
319  if (new_trial->s.real == set[1]->s.real) {
320  DEBUG(1) fprintf(stderr, "Still off!");
321  if (Last_Move == MID_LEFT ||
323  new_trial->s.real =
324  (set[0]->s.real + set[1]->s.real) / 2.0;
325  else
326  new_trial->s.real =
327  (set[1]->s.real + set[2]->s.real) / 2.0;
328  }
329  }
330  }
331 
332  break;
333 
334  case COMPLEX_INIT:
335  /* Not automatic */
336  DEBUG(1) fprintf(stderr, "\tPZ minima at: %-30g %d\n",
337  NIpzK, NIpzK_mag);
338 
339  new_trial->s.real = set[1]->s.real;
340 
341  /* NIpzK is a good idea, but the value gets trashed
342  * due to the numerics when zooming in on a minima.
343  * The key is to know when to stop taking new values for NIpzK
344  * (which I don't). For now I take the first value indicated
345  * by the NIpzSym2 routine. A "hack".
346  */
347 
348  if (NIpzK != 0.0 && NIpzK_mag > -10) {
349  while (NIpzK_mag > 0) {
350  NIpzK *= 2.0;
351  NIpzK_mag -= 1;
352  }
353  while (NIpzK_mag < 0) {
354  NIpzK /= 2.0;
355  NIpzK_mag += 1;
356  }
357  new_trial->s.imag = NIpzK;
358  }
359  else
360  new_trial->s.imag = 10000.0;
361 
362  /*
363  * Reset NIpzK so the same value doesn't get used again.
364  */
365 
366  NIpzK = 0.0;
367  NIpzK_mag = 0;
368  error = OK;
369  break;
370 
371  case COMPLEX_GUESS:
372  if (!set[2]) {
373  new_trial->s.real = set[0]->s.real;
374  new_trial->s.imag = 1.0e8;
375  }
376  else {
377  new_trial->s.real = set[0]->s.real;
378  new_trial->s.imag = 1.0e12;
379  }
380  error = OK;
381  break;
382 
383  case MULLER:
384  error = NIpzMuller(set, new_trial);
385  break;
386 
387  case SPLIT_LEFT:
388  new_trial->s.real = (set[0]->s.real + 2 * set[1]->s.real) / 3.0;
389  error = OK;
390  break;
391 
392  case SPLIT_RIGHT:
393  new_trial->s.real = (set[2]->s.real + 2 * set[1]->s.real) / 3.0;
394  error = OK;
395  break;
396 
397  default:
398  ERROR(E_PANIC, "Step type unkown");
399  break;
400  }
401 
402  *new_trial_p = new_trial;
403  return (error);
404 }
405 
406 
407 /* CKTpzStrat: given three points, determine a good direction or method for
408  guessing the next zero */
409 
410 /* XXX ZZZ what is a strategy for complex hunting? */
412 
413 PZtrial **set;
414 {
415  int suggestion;
416  double a, b, q;
417  double d1, d2;
418  double diff;
419  int diff_mag;
420  int a_mag, b_mag, q_mag;
421  double x, y;
422  int xmag;
423  double k1, k2;
424  int new_trap;
425 
426  new_trap = 0;
427 
428  if (set[1] && (set[1]->flags & ISAMINIMA)) {
429  suggestion = COMPLEX_INIT;
430  }
431  else if (set[0] && set[0]->s.imag != 0.0) {
432  if (!set[1] || !set[2])
433  suggestion = COMPLEX_GUESS;
434  else
435  suggestion = MULLER;
436  }
437  else if (!set[0] || !set[1] || !set[2]) {
438  suggestion = INIT;
439  }
440  else {
441  if (sgn(set[0]->f_def.real) != sgn(set[1]->f_def.real)) {
442  /* Zero crossing between s[0] and s[1] */
443  new_trap = 1;
444  suggestion = SYM2;
445  }
446  else if (sgn(set[1]->f_def.real) != sgn(set[2]->f_def.real)) {
447  /* Zero crossing between s[1] and s[2] */
448  new_trap = 2;
449  suggestion = SYM2;
450  }
451  else {
452 
453  zaddeq(&a, &a_mag, set[1]->f_def.real, set[1]->mag_def,
454  -set[0]->f_def.real, set[0]->mag_def);
455  zaddeq(&b, &b_mag, set[2]->f_def.real, set[2]->mag_def,
456  -set[1]->f_def.real, set[1]->mag_def);
457 
458  if (!CKTpzTrapped) {
459 
460  k1 = set[1]->s.real - set[0]->s.real;
461  k2 = set[2]->s.real - set[1]->s.real;
462  if (a_mag + 10 < set[0]->mag_def
463  && a_mag + 10 < set[1]->mag_def
464  && b_mag + 10 < set[1]->mag_def
465  && b_mag + 10 < set[2]->mag_def) {
466  if (k1 > k2)
467  suggestion = SKIP_RIGHT;
468  else
469  suggestion = SKIP_LEFT;
470  }
471  else if (sgn(a) != -sgn(b)) {
472  if (a == 0.0)
473  suggestion = SKIP_LEFT;
474  else if (b == 0.0)
475  suggestion = SKIP_RIGHT;
476  else if (sgn(a) == sgn(set[1]->f_def.real))
477  suggestion = SHIFT_LEFT;
478  else
479  suggestion = SHIFT_RIGHT;
480  }
481  else if (sgn(a) == -sgn(set[1]->f_def.real)) {
482  new_trap = 3;
483  /* minima in magnitude above the x axis */
484  /* Search for exact mag. minima, look for complex pair */
485  suggestion = SYM;
486  }
487  else if (k1 > k2)
488  suggestion = SKIP_RIGHT;
489  else
490  suggestion = SKIP_LEFT;
491  }
492  else {
493  new_trap = 3; /* still */
494  /* XXX ? Are these tests needed or is SYM safe all the time? */
495  if (sgn(a) != sgn(b)) {
496  /* minima in magnitude */
497  /* Search for exact mag. minima, look for complex pair */
498  suggestion = SYM;
499  }
500  else if (a_mag > b_mag ||
501  a_mag == b_mag && FABS(a) > FABS(b))
502  suggestion = SPLIT_LEFT;
503  else
504  suggestion = SPLIT_RIGHT;
505  }
506  }
507  if (Consec_Moves >= 3 && CKTpzTrapped == new_trap) {
508  new_trap = CKTpzTrapped;
509  if (Last_Move == MID_LEFT || Last_Move == NEAR_RIGHT)
510  suggestion = SPLIT_LEFT;
511  else if (Last_Move == MID_RIGHT || Last_Move == NEAR_LEFT)
512  suggestion = SPLIT_RIGHT;
513  else
514  abort( ); /* XXX */
515  Consec_Moves = 0;
516  }
517  }
518 
519  CKTpzTrapped = new_trap;
520  DEBUG(1) {
521  if (set[0] && set[1] && set[2])
522  fprintf(stderr, "given %.15g %.15g / %.15g %.15g / %.15g %.15g\n",
523  set[0]->s.real, set[0]->s.imag, set[1]->s.real, set[1]->s.imag,
524  set[2]->s.real, set[2]->s.imag);
525  fprintf(stderr, "suggestion(%d/%d/%d | %d): %s\n",
526  NFlat, NZeros, Max_Zeros, CKTpzTrapped, snames[suggestion]);
527  }
528  return (suggestion);
529 }
530 
531 /* CKTpzRunTrial: eval the function at a given 's', fold in deflation */
532 
533 
534 CKTpzRunTrial(ckt, new_trialp, set)
535 
536 CKTcircuit *ckt;
537 PZtrial **new_trialp;
538 PZtrial *set[ ];
539 {
540  PZtrial *t, *match, *base, *new_trial;
541  PZtrial *p, *prev;
542  SPcomplex def_frac, diff_frac;
543  double num, den;
544  double reltol, abstol;
545  int e, def_mag, diff_mag, error;
546  int inserted, i;
547  int pretest, shifted, was_shifted;
548  int repeat;
549 
550  new_trial = *new_trialp;
551 
552  if (new_trial->s.imag < 0.0)
553  new_trial->s.imag *= -1.0;
554 
555  /* Insert the trial into the list of Trials, while calculating
556  * the deflation factor from previous zeros
557  */
558 
559  pretest = 0;
560  shifted = 0;
561  repeat = 0;
562 
563  do {
564 
565  def_mag = 0;
566  def_frac.real = 1.0;
567  def_frac.imag = 0.0;
568  was_shifted = shifted;
569  shifted = 0;
570 
571  prev = NULL;
572  base = NULL;
573  match = NULL;
574 
575  for (p = Trials; p != NULL; p = p->next) {
576 
577  C_SUBEQ(diff_frac,p->s,new_trial->s);
578 
579  if (diff_frac.real < 0.0
580  || diff_frac.real == 0.0 && diff_frac.imag < 0.0) {
581  prev = p;
582  if (p->flags & ISAMINIMA)
583  base = p;
584  }
585 
586  if (p->flags & ISAROOT) {
587  abstol = 1e-5;
588  reltol = 1e-6;
589  }
590  else {
591  abstol = 1e-20;
592  reltol = 1e-12;
593  }
594 
595  if (diff_frac.imag == 0.0 &&
596  FABS(diff_frac.real) / (FABS(p->s.real) + abstol/reltol)
597  < reltol) {
598 
599  DEBUG(1) {
600  fprintf(stderr,
601  "diff_frac.real = %10g, p->s = %10g, nt = %10g\n",
602  diff_frac.real, p->s.real, new_trial->s.real);
603  fprintf(stderr, "ab=%g,rel=%g\n", abstol, reltol);
604  }
605  if (was_shifted || p->count >= 3
606  || !alter(new_trial, set[1], abstol, reltol)) {
607  /* assume either a root or minima */
608  p->count = 0;
609  pretest = 1;
610  break;
611  }
612  else
613  p->count += 1; /* try to shift */
614 
615  shifted = 1; /* Re-calculate deflation */
616  break;
617 
618  }
619  else {
620  if (!CKTpzTrapped)
621  p->count = 0;
622  if (p->flags & ISAROOT) {
623  diff_mag = 0;
624  C_NORM(diff_frac,diff_mag);
625  if (diff_frac.imag != 0.0) {
626  C_MAG2(diff_frac);
627  diff_mag *= 2;
628  }
629  C_NORM(diff_frac,diff_mag);
630 
631  for (i = p->multiplicity; i > 0; i--) {
632  C_MUL(def_frac,diff_frac);
633  def_mag += diff_mag;
634  C_NORM(def_frac,def_mag);
635  }
636  }
637  else if (!match)
638  match = p;
639  }
640  }
641 
642  }
643  while (shifted);
644 
645  if (pretest) {
646 
647  DEBUG(1) fprintf(stderr, "Pre-test taken\n");
648 
649  /* XXX Should catch the double-zero right off
650  * if K is 0.0
651  * instead of forcing a re-converge
652  */
653  DEBUG(1) {
654  fprintf(stderr, "NIpzK == %g, mag = %d\n", NIpzK, NIpzK_mag);
655  fprintf(stderr, "over at %.30g %.30g (new %.30g %.30g, %x)\n",
656  p->s.real, p->s.imag, new_trial->s.real, new_trial->s.imag,
657  p->flags);
658  }
659  if (!(p->flags & ISAROOT) && CKTpzTrapped == 3
660  && NIpzK != 0.0 && NIpzK_mag > -10) {
661 #ifdef notdef
662  if (p->flags & ISAROOT) {
663  /* Ugh! muller doesn't work right */
664  new_trial->flags = ISAMINIMA;
665  new_trial->s.imag = scalb(NIpzK, (int) (NIpzK_mag / 2));
666  pretest = 0;
667  }
668  else {
669 #endif
670  p->flags |= ISAMINIMA;
671  txfree(new_trial);
672  *new_trialp = p;
673  repeat = 1;
674  }
675  else if (p->flags & ISAROOT) {
676  DEBUG(1) fprintf(stderr, "Repeat at %.30g %.30g\n",
677  p->s.real, p->s.imag);
678  *new_trialp = p;
679  p->flags |= ISAREPEAT;
680  p->multiplicity += 1;
681  repeat = 1;
682  }
683  else {
684  /* Regular zero, as precise as we can get it */
685  error = E_SINGULAR;
686  }
687  }
688 
689  if (!repeat) {
690  if (!pretest) {
691  /* Run the trial */
692  ckt->CKTniState |= NIPZSHOULDREORDER; /* XXX */
693  if (!(ckt->CKTniState & NIPZSHOULDREORDER)) {
694  CKTpzLoad(ckt, &new_trial->s);
695  DEBUG(3) {
696  printf("Original:\n");
697  spPrint(ckt->CKTmatrix,0,1,1);
698  }
699  spSetComplex(ckt->CKTmatrix);
700  error = spFactor(ckt->CKTmatrix);
701  if (error == E_SINGULAR) {
702  DEBUG(1) printf("Needs reordering\n");
704  }
705  else if (error != OK)
706  return (error);
707  }
708  if (ckt->CKTniState & NIPZSHOULDREORDER) {
709  CKTpzLoad(ckt, &new_trial->s);
710  spSetComplex(ckt->CKTmatrix);
711  error = spOrderAndFactor(ckt->CKTmatrix,NULL,
712  0.0 /* 0.1 Piv. Rel. */,1.0e-30,1);
713  ((PZAN *) ckt->CKTcurJob)->PZnumswaps = 1;
714  }
715 
716  if (error != E_SINGULAR) {
717  ckt->CKTniState &= ~NIPZSHOULDREORDER;
718  DEBUG(3) {
719  printf("Factored:\n");
720  spPrint(ckt->CKTmatrix,0,1,1);
721  }
722  error = spDProd(ckt->CKTmatrix, &new_trial->f_raw.real,
723  &new_trial->f_raw.imag, &new_trial->mag_raw);
724  }
725  }
726 
727  if (error == E_SINGULAR || new_trial->f_raw.real == 0.0
728  && new_trial->f_raw.imag == 0.0) {
729  new_trial->f_raw.real = 0.0;
730  new_trial->f_raw.imag = 0.0;
731  new_trial->mag_raw = 0;
732  new_trial->f_def.real = 0.0;
733  new_trial->f_def.imag = 0.0;
734  new_trial->mag_def = 0;
735  new_trial->flags = ISAROOT;
736  }
737  else if (error != OK)
738  return (error);
739  else {
740 
741  /* PZnumswaps is either 0 or 1 */
742  new_trial->f_raw.real *= ((PZAN *) ckt->CKTcurJob)->PZnumswaps;
743  new_trial->f_raw.imag *= ((PZAN *) ckt->CKTcurJob)->PZnumswaps;
744 
745  new_trial->f_def.real = new_trial->f_raw.real;
746  new_trial->f_def.imag = new_trial->f_raw.imag;
747  new_trial->mag_def = new_trial->mag_raw;
748 
749  C_DIV(new_trial->f_def,def_frac);
750  new_trial->mag_def -= def_mag;
751  C_NORM(new_trial->f_def,new_trial->mag_def);
752  }
753 
754  /* Link into the rest of the list */
755  if (prev) {
756  new_trial->next = prev->next;
757  if (prev->next)
758  prev->next->prev = new_trial;
759  prev->next = new_trial;
760  }
761  else {
762  if (Trials)
763  Trials->prev = new_trial;
764  else
765  ZeroTrial = new_trial;
766  new_trial->next = Trials;
767  Trials = new_trial;
768  }
769  new_trial->prev = prev;
770 
771  NTrials += 1;
772 
773  if (!(new_trial->flags & ISAROOT)) {
774  if (match)
775  check_flat(match, new_trial);
776  else
777  NFlat = 1;
778  }
779  }
780 
781  show_trial(new_trial, '*');
782 
783  return (OK);
784 }
785 
786 
787 /* Process a zero; inc. zero count, deflate other trials */
788 
789 CKTpzVerify(set, new_trial)
790 
791 PZtrial **set;
792 PZtrial *new_trial;
793 {
794  PZtrial *next;
795  int diff_mag;
796  SPcomplex diff_frac;
797  double tdiff;
798 
799  PZtrial *t, *prev;
800 
801  NZeros += 1;
802  if (new_trial->s.imag != 0.0)
803  NZeros += 1;
804  NFlat = 0;
805 
806  if (new_trial->multiplicity == 0) {
807  new_trial->flags |= ISAROOT;
808  new_trial->multiplicity = 1;
809  }
810 
811  prev = NULL;
812 
813  for (t = Trials; t; t = next) {
814 
815  next = t->next;
816 
817  if (t->flags & ISAROOT) {
818  prev = t;
819  /* Don't need to bother */
820  continue;
821  }
822 
823  C_SUBEQ(diff_frac,new_trial->s,t->s);
824  if (new_trial->s.imag != 0.0)
825  C_MAG2(diff_frac);
826 
827  tdiff = diff_frac.real;
828  /* Note that Verify is called for each time the root is found, so
829  * multiplicity is not significant
830  */
831  if (diff_frac.real != 0.0) {
832  diff_mag = 0;
833  C_NORM(diff_frac,diff_mag);
834  diff_mag *= -1;
835  C_DIV(t->f_def,diff_frac);
836  C_NORM(t->f_def,diff_mag);
837  t->mag_def += diff_mag;
838  }
839 
840  if (t->s.imag != 0.0
841  || FABS(tdiff) / (FABS(new_trial->s.real) + 200) < 0.005) {
842  if (prev)
843  prev->next = t->next;
844  if (t->next)
845  t->next->prev = prev;
846  NTrials -= 1;
847  show_trial(t, '-');
848  if (t == ZeroTrial) {
849  if (t->next)
850  ZeroTrial = t->next;
851  else if (t->prev)
852  ZeroTrial = t->prev;
853  else
854  ZeroTrial = NULL;
855  }
856  if (t == Trials) {
857  Trials = t->next;
858  }
859  txfree(t);
860  }
861  else {
862 
863  if (prev)
864  check_flat(prev, t);
865  else
866  NFlat = 1;
867 
868  if (t->flags & ISAMINIMA)
869  t->flags &= ~ISAMINIMA;
870 
871  prev = t;
872  show_trial(t, '+');
873  }
874  }
875 
876  return (1); /* always ok */
877 }
878 
879 /* pzseek: search the trial list (given a starting point) for the first
880  * non-zero entry; direction: -1 for prev, 1 for next, 0 for next
881  * -or- first. Also, sets "Guess_Param" at the next reasonable
882  * value to guess at if the search falls of the end of the list
883  */
884 
885 
886 static PZtrial *
887 pzseek(t, dir)
888 
889 PZtrial *t;
890 int dir;
891 {
892  Guess_Param = dir;
893  if (t == NULL)
894  return (NULL);
895 
896  if (dir == 0 && !(t->flags & ISAROOT) && !(t->flags & ISAMINIMA))
897  return (t);
898 
899  do {
900  if (dir >= 0)
901  t = t->next;
902  else
903  t = t->prev;
904  }
905  while (t && ((t->flags & ISAROOT) || (t->flags & ISAMINIMA)));
906 
907  return (t);
908 }
909 
910 
911 static void
913 
914 int mode;
915 {
916  PZtrial *t, *next, *prev;
917 
918  prev = NULL;
919 
920  for (t = Trials; t; t = next) {
921  next = t->next;
922  if (mode || !(t->flags & ISAROOT)) {
923  txfree(t);
924  }
925  else {
926  if (prev)
927  prev->next = t;
928  else
929  Trials = t;
930  t->prev = prev;
931  prev = t;
932  }
933  }
934 
935  if (prev)
936  prev->next = NULL;
937  else
938  Trials = NULL;
939 }
940 
941 
942 void
943 CKTpzUpdateSet(set, new)
944 
945 PZtrial *set[3], *new;
946 {
947  int this_move;
948 
949  this_move = 0;
950 
951  if (new->s.imag != 0.0) {
952  set[2] = set[1];
953  set[1] = set[0];
954  set[0] = new;
955  }
956  else if (!set[1])
957  set[1] = new;
958  else if (!set[2] && new->s.real > set[1]->s.real) {
959  set[2] = new;
960  }
961  else if (!set[0]) {
962  set[0] = new;
963  }
964  else if (new->flags & ISAMINIMA) {
965  set[1] = new;
966  }
967  else if (new->s.real < set[0]->s.real) {
968  set[2] = set[1];
969  set[1] = set[0];
970  set[0] = new;
971  this_move = FAR_LEFT;
972  }
973  else if (new->s.real < set[1]->s.real) {
974  if (!CKTpzTrapped || new->mag_def < set[1]->mag_def
975  || new->mag_def == set[1]->mag_def
976  && FABS(new->f_def.real) < FABS(set[1]->f_def.real)) {
977  /* Really should check signs, not just compare FABS( ) */
978  set[2] = set[1]; /* XXX = set[2]->prev :: possible opt */
979  set[1] = new;
980  this_move = MID_LEFT;
981  }
982  else {
983  set[0] = new;
984  this_move = NEAR_LEFT;
985  }
986  }
987  else if (new->s.real < set[2]->s.real) {
988  if (!CKTpzTrapped || new->mag_def < set[1]->mag_def
989  || new->mag_def == set[1]->mag_def
990  && FABS(new->f_def.real) < FABS(set[1]->f_def.real)) {
991  /* Really should check signs, not just compare FABS( ) */
992  set[0] = set[1];
993  set[1] = new;
994  this_move = MID_RIGHT;
995  }
996  else {
997  set[2] = new;
998  this_move = NEAR_RIGHT;
999  }
1000  }
1001  else {
1002  set[0] = set[1];
1003  set[1] = set[2];
1004  set[2] = new;
1005  this_move = FAR_RIGHT;
1006  }
1007 
1008  if (CKTpzTrapped && this_move == Last_Move)
1009  Consec_Moves += 1;
1010  else
1011  Consec_Moves = 0;
1012  Last_Move = this_move;
1013 }
1014 
1015 
1016 void
1017 zaddeq(a, amag, x, xmag, y, ymag)
1018 
1019 double *a, x, y;
1020 int *amag, xmag, ymag;
1021 {
1022  /* Balance magnitudes . . . */
1023  if (xmag > ymag) {
1024  *amag = xmag;
1025  if (xmag > 50 + ymag)
1026  y = 0.0;
1027  else
1028  for (xmag -= ymag; xmag > 0; xmag--)
1029  y /= 2.0;
1030  }
1031  else {
1032  *amag = ymag;
1033  if (ymag > 50 + xmag)
1034  x = 0.0;
1035  else
1036  for (ymag -= xmag; ymag > 0; ymag--)
1037  x /= 2.0;
1038  }
1039 
1040  *a = x + y;
1041  if (*a == 0.0)
1042  *amag = 0;
1043  else {
1044  while (FABS(*a) > 1.0) {
1045  *a /= 2.0;
1046  *amag += 1;
1047  }
1048  while (FABS(*a) < 0.5) {
1049  *a *= 2.0;
1050  *amag -= 1;
1051  }
1052  }
1053 }
1054 
1055 
1056 static void
1057 show_trial(new_trial, x)
1058 
1059 PZtrial *new_trial;
1060 char x;
1061 {
1062  DEBUG(1)
1063  fprintf(stderr, "%c (%3d/%3d) %.15g %.15g :: %.30g %.30g %d\n", x,
1064  NIter, new_trial->seq_num, new_trial->s.real, new_trial->s.imag,
1065  new_trial->f_def.real, new_trial->f_def.imag, new_trial->mag_def);
1066  DEBUG(1)
1067  if (new_trial->flags & ISANABERRATION) {
1068  fprintf(stderr, "*** numerical aberration ***\n");
1069  }
1070 }
1071 
1072 
1073 static void
1075 
1076 PZtrial *a, *b;
1077 {
1078  int diff_mag;
1079  SPcomplex diff_frac;
1080  double mult;
1081 
1082  diff_mag = a->mag_def - b->mag_def;
1083  if (abs(diff_mag) <= 1) {
1084  if (diff_mag == 1)
1085  mult = 2.0;
1086  else if (diff_mag == -1)
1087  mult = 0.5;
1088  else
1089  mult = 1.0;
1090  C_SUBEQ(diff_frac, mult * a->f_def, b->f_def);
1091  C_MAG2(diff_frac);
1092  if (diff_frac.real < 1.0e-20)
1093  NFlat += 1;
1094  }
1095  /* XXX else NFlat = ?????? */
1096 }
1097 
1098 
1099 /* XXX ZZZ */
1100 int
1101 CKTpzStep(strat, set)
1102 
1103 int strat;
1104 PZtrial *set[ ];
1105 {
1106  switch (strat) {
1107  case INIT:
1108  if (!set[1]) {
1109  set[1] = pzseek(ZeroTrial, 0);
1110  }
1111  else if (!set[2])
1112  set[2] = pzseek(set[1], 1);
1113  else if (!set[0])
1114  set[0] = pzseek(set[1], -1);
1115  break;
1116 
1117  case SKIP_LEFT:
1118  set[0] = pzseek(set[0], -1);
1119  break;
1120 
1121  case SKIP_RIGHT:
1122  set[2] = pzseek(set[2], 1);
1123  break;
1124 
1125  case SHIFT_LEFT:
1126  set[2] = set[1];
1127  set[1] = set[0];
1128  set[0] = pzseek(set[0], -1);
1129  break;
1130 
1131  case SHIFT_RIGHT:
1132  set[0] = set[1];
1133  set[1] = set[2];
1134  set[2] = pzseek(set[2], 1);
1135  break;
1136 
1137  }
1138  if (!set[0] || !set[1] || !set[2])
1139  return (0);
1140  else
1141  return (1);
1142 }
1143 
1144 
1145 void
1147 
1148 PZtrial *set[3];
1149 {
1150  CKTpzTrapped = 0;
1151  Consec_Moves = 0;
1152 
1153  set[1] = pzseek(ZeroTrial, 0);
1154  if (set[1] != NULL) {
1155  set[0] = pzseek(set[1], -1);
1156  set[2] = pzseek(set[1], 1);
1157  }
1158  else {
1159  set[0] = NULL;
1160  set[2] = NULL;
1161  }
1162 }
1163 
1164 
1165 static int
1166 alter(new, nearto, abstol, reltol)
1167 
1168 PZtrial *new, *nearto;
1169 double abstol, reltol;
1170 {
1171  double p1, p2;
1172 
1173  DEBUG(1) fprintf(stderr, "ALTER from: %.30g %.30g\n",
1174  new->s.real, new->s.imag);
1175  DEBUG(1) fprintf(stderr, "nt->next %g\n", nearto->prev->s.real);
1176  DEBUG(1) fprintf(stderr, "nt->next %g\n", nearto->next->s.real);
1177 
1178  if (CKTpzTrapped != 2) {
1179  DEBUG(1) fprintf(stderr, "not 2\n");
1180  p1 = nearto->s.real;
1181  if (nearto->flags & ISAROOT)
1182  p1 -= 1e-6 * nearto->s.real + 1e-5;
1183  if (nearto->prev) {
1184  p1 += nearto->prev->s.real;
1185  DEBUG(1) fprintf(stderr, "p1 %g\n", p1);
1186  }
1187  else
1188  p1 -= 10.0 * (FABS(p1) + 1.0);
1189 
1190  p1 /= 2.0;
1191  }
1192  else
1193  p1 = nearto->s.real;
1194 
1195  if (CKTpzTrapped != 1) {
1196  DEBUG(1) fprintf(stderr, "not 1\n");
1197  p2 = nearto->s.real;
1198  if (nearto->flags & ISAROOT)
1199  p2 += 1e-6 * nearto->s.real + 1e-5;
1200  /* XXX Would rather use pow(2)*/
1201  if (nearto->next) {
1202  p2 += nearto->next->s.real;
1203  DEBUG(1) fprintf(stderr, "p2 %g\n", p2);
1204  }
1205  else
1206  p2 += 10.0 * (FABS(p2)+ 1.0);
1207 
1208  p2 /= 2.0;
1209  }
1210  else
1211  p2 = nearto->s.real;
1212 
1213  if (nearto->prev && FABS(p1 - nearto->prev->s.real) /
1214  (FABS(nearto->prev->s.real) + abstol/reltol) < reltol
1215  || nearto->next && FABS(p2 - nearto->next->s.real) /
1216  (FABS(nearto->next->s.real) + abstol/reltol) < reltol) {
1217 
1218  DEBUG(1)
1219  fprintf(stderr, "Bailed out\n");
1220  return 0;
1221  }
1222 
1223  if (CKTpzTrapped != 2 && nearto->s.real - p1 > p2 - nearto->s.real) {
1224  DEBUG(1) fprintf(stderr, "take p1\n");
1225  new->s.real = p1;
1226  }
1227  else {
1228  DEBUG(1) fprintf(stderr, "take p2\n");
1229  new->s.real = p2;
1230  }
1231 
1232  DEBUG(1) fprintf(stderr, "ALTER to : %.30g %.30g\n",
1233  new->s.real, new->s.imag);
1234  return (1);
1235 }
static int NIter
Definition: pzstr.c:96
#define NEW(TYPE)
Definition: util.h:74
static int Last_Move
Definition: pzstr.c:95
#define SHIFT_RIGHT
Definition: pzstr.c:35
#define E_PAUSE
Definition: iferrmsg.h:15
int CKTpzLoad()
static double High_Guess
Definition: pzstr.c:94
SPcomplex f_def
Definition: pzdefs.h:14
static double Low_Guess
Definition: pzstr.c:94
int flags
Definition: pzdefs.h:18
#define E_PANIC
Definition: iferrmsg.h:19
int spDProd()
int count
Definition: pzdefs.h:20
#define sgn(X)
Definition: pzstr.c:78
void spPrint()
CKTpzFindZeros(CKTcircuit *ckt, GENERIC **rootinfoptr, int *rootcount)
Definition: pzstr.c:104
#define SYM
Definition: pzstr.c:45
#define FAR_RIGHT
Definition: pzstr.c:55
struct sCKTmodHead * next
Definition: cktdefs.h:58
Definition: cddefs.h:119
#define COMPLEX_GUESS
Definition: pzstr.c:48
SMPmatrix * CKTmatrix
Definition: cktdefs.h:95
#define ERROR(CODE, MESSAGE)
Definition: util.h:66
CKTpzStrat(PZtrial **set)
Definition: pzstr.c:411
#define SPLIT_LEFT
Definition: pzstr.c:41
static int NFlat
Definition: pzstr.c:90
#define NITER_LIM
Definition: pzstr.c:32
static int Consec_Moves
Definition: pzstr.c:95
static double e
Definition: vectors.c:17
FILE * p
Definition: proc2mod.c:48
IFfrontEnd * SPfrontEnd
Definition: main.c:917
static int Max_Zeros
Definition: pzstr.c:90
static void show_trial()
double real
Definition: complex.h:13
CKTpzVerify(PZtrial **set, PZtrial *new_trial)
Definition: pzstr.c:789
#define FAR_LEFT
Definition: pzstr.c:53
int NIpzMuller()
SPcomplex s
Definition: pzdefs.h:14
#define C_NORM(A, B)
Definition: complex.h:137
#define C_DIV(A, B)
Definition: complex.h:169
struct strial * prev
Definition: pzdefs.h:15
#define C_MUL(A, B)
Definition: complex.h:156
#define COMPLEX_INIT
Definition: pzstr.c:47
int NIpzK_mag
Definition: nipzmeth.c:21
#define NIPZSHOULDREORDER
Definition: cktdefs.h:127
int multiplicity
Definition: pzdefs.h:17
static int Aberr_Num
Definition: pzstr.c:97
static int NZeros
Definition: pzstr.c:90
int CKTpzTrapped
Definition: pzstr.c:88
#define SPLIT_RIGHT
Definition: pzstr.c:42
#define E_SHORT
Definition: sperror.h:24
static char * snames[]
Definition: pzstr.c:58
#define OK
Definition: iferrmsg.h:17
#define ISAREPEAT
Definition: pzstr.c:81
#define NEAR_LEFT
Definition: pzstr.c:51
static double Guess_Param
Definition: pzstr.c:93
#define MID_RIGHT
Definition: pzstr.c:56
void txfree()
#define NULL
Definition: spdefs.h:121
#define ISAMINIMA
Definition: pzstr.c:83
int CKTniState
Definition: cktdefs.h:96
#define ISAROOT
Definition: pzstr.c:80
#define SKIP_LEFT
Definition: pzstr.c:36
void zaddeq()
Definition: sced.h:120
#define NEAR_RIGHT
Definition: pzstr.c:54
CKTpzRunTrial(CKTcircuit *ckt, PZtrial **new_trialp, set)
Definition: pzstr.c:534
static int NTrials
Definition: pzstr.c:96
void CKTpzReset()
static void clear_trials()
#define ERR_WARNING
Definition: ifsim.h:517
int spFactor()
int spGetSize()
int mag_def
Definition: pzdefs.h:16
#define MULLER
Definition: pzstr.c:44
static PZtrial * Trials
Definition: pzstr.c:91
static PZtrial * ZeroTrial
Definition: pzstr.c:91
void spSetComplex()
#define FABS(a)
Definition: util.h:41
static int Seq_Num
Definition: pzstr.c:92
int spOrderAndFactor()
#define INIT
Definition: pzstr.c:38
#define SYM2
Definition: pzstr.c:46
int mag_raw
Definition: pzdefs.h:16
NIpzSym(set,*new)
Definition: nipzmeth.c:23
double imag
Definition: complex.h:14
#define C_MAG2(A)
Definition: complex.h:122
#define E_SINGULAR
Definition: sperror.h:17
void CKTpzUpdateSet()
int CKTpzStep(int strat, set)
Definition: pzstr.c:1101
struct strial * next
Definition: pzdefs.h:15
#define MID_LEFT
Definition: pzstr.c:52
double NIpzK
Definition: nipzmeth.c:20
#define SKIP_RIGHT
Definition: pzstr.c:37
#define DEBUG(N)
Definition: pzstr.c:26
SPcomplex f_raw
Definition: pzdefs.h:14
static int alter()
Definition: pzdefs.h:13
static void check_flat()
#define ISANABERRATION
Definition: pzstr.c:82
Definition: cddefs.h:192
#define C_SUBEQ(A, B, C)
Definition: complex.h:203
JOB * CKTcurJob
Definition: cktdefs.h:216
#define GUESS
Definition: pzstr.c:40
static PZtrial * pzseek()
char GENERIC
Definition: ifsim.h:27
int seq_num
Definition: pzdefs.h:19
#define SHIFT_LEFT
Definition: pzstr.c:34
Definition: pzdefs.h:23
int PZeval()