Initial commit at Tue Apr 25 08:36:02 EDT 2017 by tim on stravinsky
[xcircuit.git] / spiceparser / eqnlist.c
blob64d124350b4c9dd3951ecd97d76b3d3aa948a0e1
1 /********************
2 This file is part of the software library CADLIB written by Conrad Ziesler
3 Copyright 2003, Conrad Ziesler, all rights reserved.
5 *************************
6 This program 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 of the License, or
9 (at your option) any later version.
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 ******************/
21 /* eqnlist.c, routines for equation dependency lists, part of package eqn
22 Conrad Ziesler
25 #include <stdio.h>
26 #include "debug.h"
28 #include "names.h"
29 #include "list.h"
30 #include "eqn.h"
31 #include "bitlist.h"
35 int __debug_eqnlist__=1;
37 #ifndef STRIP_DEBUGGING
38 #define D(level,a) do { if(__debug_eqnlist__>(level)) a; } while(0)
39 #else
40 #define D(level,a)
41 #endif
43 void eqnl_init(eqnlist_t *nl)
45 nl->params=names_new();
46 list_init(&(nl->eqnlist),sizeof(eqn_t),LIST_DEFMODE);
47 list_init(&(nl->cache),sizeof(float),LIST_DEFMODE);
49 void eqnl_free(eqnlist_t *nl)
51 list_empty(&(nl->eqnlist));
52 list_empty(&(nl->cache));
53 names_free(nl->params);
56 int eqnl_find(eqnlist_t *nl, char *str)
58 int ind;
59 ind=names_check(nl->params,str);
60 return ind;
63 eqn_t eqnl_eqn(eqnlist_t *nl, int index)
65 eqn_t *ep;
66 ep=list_data(&(nl->eqnlist),index);
67 if(ep!=NULL)
68 return *ep;
69 return eqn_empty();
73 int eqnl_add(eqnlist_t *nl, eqn_t e, char *str)
75 #ifdef NO_EQUATIONS
76 return -1;
77 #else
78 int i;
79 eqn_t ed;
80 float fv=0.0;
82 ed=eqn_copy(e);
83 i=list_add(&(nl->eqnlist),&ed);
84 if(names_check(nl->params,str)>=0)
85 { fprintf(stderr,"eqnlist equations: you are doing something wierd w/ hier. (%s) \n",str); assert(0); }
86 names_add(nl->params,i,str);
87 list_add(&(nl->cache),&fv);
88 D(10,fprintf(stderr,"eqnl_add: adding %s as index %i\n",str,i));
89 return i;
90 #endif
93 /* here we evaluate terminals for the user, that is equations
94 for which no other equation depends,
96 we first lookup in the parameter cache any dependencies
97 and then call eqntok_eval to do the dirty work
100 float eqnl_eval(eqnlist_t *nl, eqn_t e)
102 #ifdef NO_EQUATIONS
103 return e.val;
104 #else
105 float *fp;
106 float res;
107 int r;
108 eqntoken_t *et;
109 int index;
111 if(e.eqn==NULL)return 0.0;
112 for(et=e.eqn;!OP_ISEND(et->op);et=eqntoken_next(et))
114 if((et->op==OPlit) || (et->op==OPlitm))
115 assert(0);
117 if((et->op==OPlitv) || (et->op==OPlitvm))
119 if((index=et->z.lit.ref)==eqn_litref_INIT)
120 assert(0);
122 fp=list_data(&(nl->cache),index);
123 if(fp!=NULL)
124 et->z.lit.cache=*fp;
125 else assert(0);
128 res=0.0;
129 r=eqntok_eval(&res,e.eqn);
130 assert(r==0);
131 return res;
132 #endif
137 any parameter is stored in our cache.
138 here we resolve parameter dependecies
139 and evaluate all parameters.
143 void eqnl_evaldep(eqnlist_t *nl)
145 #ifdef NO_EQUATIONS
146 return;
147 #else
148 eqntoken_t *et;
149 int i,sweep,qleft=0,qdep,index;
150 eqn_t *e;
151 bitlist_t *bl;
153 qleft=list_qty(&(nl->eqnlist));
154 bl=bitlist_new(qleft);
156 for(sweep=0;sweep<32;sweep++) /* limit heirarchy depth to stop cycles */
158 /* now check dependencies of all equations until done */
159 list_iterate(&(nl->eqnlist),i,e)
161 if(!bitlist_test(bl,i)) /* quick check for done */
163 qdep=0;
164 /* go through eqntokens and find dependencies */
165 for(et=e->eqn;!OP_ISEND(et->op);et=eqntoken_next(et))
167 if((et->op==OPlit) || (et->op==OPlitm))
168 assert(0);
170 if((et->op==OPlitv) || (et->op==OPlitvm))
172 if((index=et->z.lit.ref)==eqn_litref_INIT)
173 assert(0);
175 if(bitlist_test(bl,index))
176 { /* dependency is already computed, get its value */
177 float *fp;
179 fp=list_data(&(nl->cache),index);
180 if(fp!=NULL)
181 et->z.lit.cache=*fp;
182 else assert(0);
184 else qdep++; /* indicate dependency not done */
188 if(qdep==0) /* all dependencies resolved, mark as done */
190 int r=100;
191 float *fp;
193 fp=list_data(&(nl->cache),i);
195 if(fp!=NULL) /* compute new value */
197 r=eqntok_eval(fp,e->eqn);
198 D(5,fprintf(stderr,"Evaldep: recomputed equation %i -> %s == %g\n",i,eqnl_lookup(nl,i),*fp));
200 assert(r==0);
201 bitlist_set(bl,i);
202 qleft--;
207 if(qleft==0)break;
209 if(sweep==32)
211 assert(0);
214 bitlist_free(bl);
215 #endif
218 /* do eqntoken_depend looking up unresolved symbols in eqnlist
219 that is, a single predefined list of parameters
222 static eqn_litref_t eqnl_depend_lookup(struct plookup_st *user, char *str)
224 eqn_litref_t r;
225 r=eqnl_find(user->user, str);
226 if(r<0)
228 fprintf(stderr,"eqnl_depend: unresolved symbol %s\n",str);
229 assert(0);
231 return r;
235 void eqnl_depend(eqnlist_t *nl, eqn_t e)
237 plookup_t plu;
238 if(e.eqn==NULL)return;
239 plu.lookup=eqnl_depend_lookup;
240 plu.user=nl;
241 eqntok_depend(e.eqn,&plu);
245 /* do eqnl_depend on all predefined parameters in eqnlist */
246 void eqnl_autodepend(eqnlist_t *nl)
248 int i;
249 eqn_t *e;
251 list_iterate(&(nl->eqnlist),i,e)
253 eqnl_depend(nl,*e);
257 /* check if an entry in our eqn table is undefined,
258 that is it should be defined by the client
259 before it tries to call evaleqns
261 int eqnl_is_undefined(eqnlist_t *nl, int index)
263 eqn_t *ep;
264 ep= list_data(&(nl->eqnlist),index);
265 if(ep==NULL)return -1;
266 return eqn_is_undefined(*ep);
270 int eqnl_define(eqnlist_t *nl, int index, float *valp)
272 eqn_t *ep;
273 ep= list_data(&(nl->eqnlist),index);
274 if(ep==NULL)return -1;
275 eqn_setvalp(ep,valp);
276 return 0;
279 int eqnl_qty(eqnlist_t *nl)
281 int a,b;
282 a=list_qty(&(nl->eqnlist));
283 b=list_qty(&(nl->cache));
284 assert(a==b);
285 return a;
288 char *eqnl_lookup(eqnlist_t *nl, int index)
290 return names_lookup(nl->params,index);