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
21 /* eqnlist.c, routines for equation dependency lists, part of package eqn
35 int __debug_eqnlist__
=1;
37 #ifndef STRIP_DEBUGGING
38 #define D(level,a) do { if(__debug_eqnlist__>(level)) a; } while(0)
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
)
59 ind
=names_check(nl
->params
,str
);
63 eqn_t
eqnl_eqn(eqnlist_t
*nl
, int index
)
66 ep
=list_data(&(nl
->eqnlist
),index
);
73 int eqnl_add(eqnlist_t
*nl
, eqn_t e
, char *str
)
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
));
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
)
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
))
117 if((et
->op
==OPlitv
) || (et
->op
==OPlitvm
))
119 if((index
=et
->z
.lit
.ref
)==eqn_litref_INIT
)
122 fp
=list_data(&(nl
->cache
),index
);
129 r
=eqntok_eval(&res
,e
.eqn
);
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
)
149 int i
,sweep
,qleft
=0,qdep
,index
;
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 */
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
))
170 if((et
->op
==OPlitv
) || (et
->op
==OPlitvm
))
172 if((index
=et
->z
.lit
.ref
)==eqn_litref_INIT
)
175 if(bitlist_test(bl
,index
))
176 { /* dependency is already computed, get its value */
179 fp
=list_data(&(nl
->cache
),index
);
184 else qdep
++; /* indicate dependency not done */
188 if(qdep
==0) /* all dependencies resolved, mark as done */
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
));
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
)
225 r
=eqnl_find(user
->user
, str
);
228 fprintf(stderr
,"eqnl_depend: unresolved symbol %s\n",str
);
235 void eqnl_depend(eqnlist_t
*nl
, eqn_t e
)
238 if(e
.eqn
==NULL
)return;
239 plu
.lookup
=eqnl_depend_lookup
;
241 eqntok_depend(e
.eqn
,&plu
);
245 /* do eqnl_depend on all predefined parameters in eqnlist */
246 void eqnl_autodepend(eqnlist_t
*nl
)
251 list_iterate(&(nl
->eqnlist
),i
,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
)
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
)
273 ep
= list_data(&(nl
->eqnlist
),index
);
274 if(ep
==NULL
)return -1;
275 eqn_setvalp(ep
,valp
);
279 int eqnl_qty(eqnlist_t
*nl
)
282 a
=list_qty(&(nl
->eqnlist
));
283 b
=list_qty(&(nl
->cache
));
288 char *eqnl_lookup(eqnlist_t
*nl
, int index
)
290 return names_lookup(nl
->params
,index
);