/[ascend]/trunk/base/generic/compiler/extfunc.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/extfunc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 707 - (show annotations) (download) (as text)
Tue Jun 27 05:49:11 2006 UTC (18 years ago) by johnpye
File MIME type: text/x-csrc
File size: 13263 byte(s)
Lots of tidying up in instantiate.c.
Fixed up some GPL headers.
Changed from 'solver_var' to 'factor' in extfntest.a4c.
Added test for AtomAssigned in extfunc.c.
1 /*
2 ASCEND modelling environment
3 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly, Kirk Andre Abbott
4 Copyright (C) 2006 Carnegie Mellon University
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, or (at your option)
9 any later version.
10
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.
15
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,
19 Boston, MA 02111-1307, USA.
20 *//*
21 by Kirk Andre Abbott
22 Created: July 4, 1994.
23 Last in CVS: $Revision: 1.8 $ $Date: 1998/02/05 22:23:26 $ $Author: ballan $
24 */
25
26 #include <utilities/ascConfig.h>
27 #include <utilities/ascMalloc.h>
28 #include <utilities/ascPanic.h>
29 #include <general/hashpjw.h>
30 #include <general/list.h>
31 #include <general/table.h>
32 #include <general/dstring.h>
33 #include "compiler.h"
34 #include "symtab.h"
35 #include "instance_enum.h"
36 #include "instance_io.h"
37 #include "extfunc.h"
38 #include "extcall.h"
39
40 /*------------------------------------------------------------------------------
41 forward decls and typedefs etc
42 */
43
44 #define EXTFUNCHASHSIZE 31
45
46 static struct Table *ExternalFuncLibrary = NULL;
47
48 /*-----------------------------------------------------------------------------
49 BLACK BOX STUFF
50 */
51
52 int CreateUserFunctionBlackBox(CONST char *name,
53 ExtBBoxInitFunc *init,
54 ExtBBoxFunc *value,
55 ExtBBoxFunc *deriv,
56 ExtBBoxFunc *deriv2,
57 ExtBBoxInitFunc *final,
58 CONST unsigned long n_inputs,
59 CONST unsigned long n_outputs,
60 CONST char *help)
61 {
62 struct ExternalFunc *efunc;
63 int isNew = 0;
64 if (name == NULL) {
65 return 1;
66 }
67 efunc = LookupExtFunc(name);
68 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
69 isNew = 0;
70 } else {
71 isNew = 1;
72 efunc = ASC_NEW(struct ExternalFunc);
73 asc_assert(efunc!=NULL);
74 efunc->help = NULL;
75 efunc->name = ascstrdup(SCP(AddSymbol(name)));
76 /* add or find name in symbol table */
77 /* the main symtab owns the string */
78 }
79
80 efunc->etype = efunc_BlackBox;
81 efunc->n_inputs = n_inputs;
82 efunc->n_outputs = n_outputs;
83 efunc->u.black.initial = init;
84 efunc->u.black.value = value;
85 efunc->u.black.deriv = deriv;
86 efunc->u.black.deriv2 = deriv2;
87 efunc->u.black.final = final;
88 if (help) {
89 if (efunc->help) ascfree((char *)efunc->help);
90 efunc->help = ascstrdup(help);
91 } else {
92 efunc->help = NULL;
93 }
94
95 if (isNew) {
96 (void)AddExternalFunc(efunc,1);
97 }
98 return 0;
99 }
100
101 double blackbox_evaluate_residual(struct relation *r){
102 struct ExtCallNode *ext;
103 struct ExternalFunc *efunc;
104 int i,n;
105 char *tmp;
106 struct Instance *inst;
107 double *in;
108 double *out;
109
110 CONSOLE_DEBUG("...");
111
112 n = NumberVariables(r);
113
114 asc_assert(r!=NULL);
115 asc_assert(r->share!=NULL);
116 asc_assert(r->share->bbox.ext!=NULL);
117 ext = r->share->bbox.ext;
118 efunc = ext->efunc;
119 asc_assert(efunc!=NULL);
120 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"ABOUT TO EVALUATE %s",efunc->name);
121
122 asc_assert(efunc->etype==efunc_BlackBox);
123
124 ExtBBoxFunc *valfnptr = efunc->u.black.value;
125 asc_assert(valfnptr!=NULL);
126
127 CONSOLE_DEBUG("vars=%d, inputs=%d, outputs=%d",n
128 ,NumberInputArgs(efunc)
129 ,NumberOutputArgs(efunc)
130 );
131
132 /* list all the variables associated with this black box */
133 for(i=1;i <= n; ++i){
134 inst = RelationVariable(r,i);
135 tmp = WriteInstanceNameString(inst, NULL);
136 if(i<=NumberInputArgs(efunc)){
137 CONSOLE_DEBUG("Input %d: '%s'", i, tmp);
138 }else{
139 CONSOLE_DEBUG("Output %d: '%s'", i-NumberInputArgs(efunc), tmp);
140 }
141 ASC_FREE(tmp);
142 }
143
144 in = ASC_NEW_ARRAY(double,NumberInputArgs(efunc));
145 out = ASC_NEW_ARRAY(double,NumberOutputArgs(efunc));
146
147 for(i=0; i < NumberInputArgs(efunc); ++i){
148 inst = RelationVariable(r,i+1);
149 tmp = WriteInstanceNameString(inst,NULL);
150 if(!AtomAssigned(inst)){
151 CONSOLE_DEBUG("Var %d ('%s') has not been assigned yet!",i+1,tmp);
152 in[i]=-1;
153 }else{
154 in[i] = RealAtomValue(inst);
155 }
156 CONSOLE_DEBUG("Set var %d ('%s') to '%f'",i+1,tmp,in[i]);
157 ASC_FREE(tmp);
158 }
159
160 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Blackbox not implemented, returning -1");
161 return -1;
162 }
163
164
165 ExtBBoxInitFunc * GetInitFunc(struct ExternalFunc *efunc)
166 {
167 asc_assert(efunc!=NULL);
168 /* return (ExtBBoxInitFunc*)efunc->u.black.init; */
169 return efunc->u.black.initial;
170 }
171
172 ExtBBoxInitFunc * GetFinalFunc(struct ExternalFunc *efunc)
173 {
174 asc_assert(efunc!=NULL);
175 return efunc->u.black.final;
176 }
177
178 ExtBBoxFunc *GetValueFunc(struct ExternalFunc *efunc)
179 {
180 asc_assert(efunc!=NULL);
181 asc_assert(efunc->etype == efunc_BlackBox);
182 /* return (ExtBBoxFunc *)efunc->value; */
183 return efunc->u.black.value;
184 }
185
186
187 ExtBBoxFunc *GetDerivFunc(struct ExternalFunc *efunc)
188 {
189 asc_assert(efunc!=NULL);
190 asc_assert(efunc->etype == efunc_BlackBox);
191 return efunc->u.black.deriv;
192 }
193
194 ExtBBoxFunc *GetDeriv2Func(struct ExternalFunc *efunc)
195 {
196 asc_assert(efunc!=NULL);
197 asc_assert(efunc->etype == efunc_BlackBox);
198 return efunc->u.black.deriv2;
199 }
200
201 /*------------------------------------------------------------------------------
202 GLASS BOX STUFF
203 */
204
205 int CreateUserFunctionGlassBox(CONST char *name,
206 ExtEvalFunc *init,
207 ExtEvalFunc **value,
208 ExtEvalFunc **deriv,
209 ExtEvalFunc **deriv2,
210 ExtEvalFunc *final,
211 CONST unsigned long n_inputs,
212 CONST unsigned long n_outputs,
213 CONST char *help)
214 {
215 struct ExternalFunc *efunc;
216 int isNew = 0;
217 if (name == NULL) {
218 return 1;
219 }
220 efunc = LookupExtFunc(name);
221 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
222 isNew = 0;
223 } else {
224 isNew = 1;
225 efunc = ASC_NEW(struct ExternalFunc);
226 asc_assert(efunc!=NULL);
227 efunc->help = NULL;
228 efunc->name = ascstrdup(SCP(AddSymbol(name)));
229 /* add or find name in symbol table */
230 /* the main symtab owns the string */
231 }
232
233 efunc->etype = efunc_GlassBox;
234 efunc->n_inputs = n_inputs;
235 efunc->n_outputs = n_outputs;
236 efunc->u.glass.initial = init;
237 efunc->u.glass.value = value;
238 efunc->u.glass.deriv = deriv;
239 efunc->u.glass.deriv2 = deriv2;
240 efunc->u.glass.final = final;
241 if (help) {
242 if (efunc->help) ascfree((char *)efunc->help);
243 efunc->help = ascstrdup(help);
244 } else {
245 efunc->help = NULL;
246 }
247
248 if (isNew) {
249 (void)AddExternalFunc(efunc,1);
250 }
251 return 0;
252 }
253
254
255 /*
256 * GlassBox relations in particular register not just
257 * a single function but rather a pointer to a jump table
258 * of functions. There will be a jump table ptr for each
259 * of value, deriv, deriv2.
260 */
261
262 /*
263 * The following means:
264 * GetValue is a function that returning pointer to array[] of
265 * pointer to functions, which take args and return an int.
266 *
267 * int (*(*GetValueJumpTable(struct ExternalFunc *efunc))[])(args)
268 */
269
270 ExtEvalFunc **GetValueJumpTable(struct ExternalFunc *efunc)
271 {
272 asc_assert(efunc!=NULL);
273 asc_assert(efunc->etype == efunc_GlassBox);
274 return efunc->u.glass.value;
275 }
276
277 ExtEvalFunc **GetDerivJumpTable(struct ExternalFunc *efunc)
278 {
279 asc_assert(efunc!=NULL);
280 asc_assert(efunc->etype == efunc_GlassBox);
281 return efunc->u.glass.deriv;
282 }
283
284 ExtEvalFunc **GetDeriv2JumpTable(struct ExternalFunc *efunc)
285 {
286 asc_assert(efunc!=NULL);
287 asc_assert(efunc->etype == efunc_GlassBox);
288 return efunc->u.glass.deriv2;
289 }
290
291 /*------------------------------------------------------------------------------
292 EXTERNAL METHOD STUFF
293 */
294
295 int CreateUserFunctionMethod(CONST char *name,
296 /* ExtMethodInit *init, */
297 ExtMethodRun *run,
298 /* ExtMethodInitEvalFunc *final, */
299 CONST long n_args,
300 /* CONST unsigned long n_outputs, */
301 CONST char *help)
302 {
303 struct ExternalFunc *efunc;
304 int isNew = 1;
305 if (name == NULL) {
306 return 1;
307 }
308 efunc = LookupExtFunc(name);
309 if (efunc != NULL) {
310 isNew = 0;
311 /* name was pre-loaded -- just update the info. This may cause user
312 insanity if it wasn't a reload of the same thing. */
313 } else {
314 isNew = 1;
315 efunc = ASC_NEW(struct ExternalFunc);
316 asc_assert(efunc!=NULL);
317 efunc->help = NULL;
318 efunc->name = ascstrdup(SCP(AddSymbol(name)));
319 /* add or find name in symbol table, and copy because */
320 /* the main symtab owns the string */
321 }
322 efunc->etype = efunc_Method;
323 efunc->n_inputs = n_args;
324 efunc->n_outputs = 0;
325 efunc->u.method.run = run;
326 #if 0
327 efunc->u.method.initial = init;
328 efunc->u.method.final = final;
329 #endif
330 if (help) {
331 if (efunc->help) { ascfree((char *)efunc->help); }
332 efunc->help = ascstrdup(help);
333 } else {
334 efunc->help = NULL;
335 }
336
337 if (isNew ) {
338 (void)AddExternalFunc(efunc,1);
339 }
340 return 0;
341 }
342
343
344
345 ExtMethodRun *GetExtMethodRun(struct ExternalFunc *efunc)
346 {
347 asc_assert(efunc!=NULL);
348 asc_assert(efunc->etype == efunc_Method);
349 return efunc->u.method.run;
350 }
351
352 /*------------------------------------------------------------------------------
353 REGISTRATION AND LOOKUP FUNCTIONS
354 */
355
356 void DestroyExternalFunc(struct ExternalFunc *efunc)
357 {
358 struct ExternalFunc *tmp;
359 if (efunc) {
360 tmp = efunc;
361 if (tmp->name ) ascfree((char *)(tmp->name)); /* we own the string */
362 if (tmp->help) ascfree((char *)(tmp->help)); /* we own the string */
363 tmp->name = NULL;
364 tmp->help = NULL;
365 /* might want to set null pointers here depending on etype. */
366 tmp->etype = efunc_ERR;
367 ascfree((char *)tmp);
368 }
369 }
370
371 CONST char *ExternalFuncName(CONST struct ExternalFunc *efunc)
372 {
373 asc_assert(efunc!=NULL);
374 return efunc->name;
375 }
376
377 unsigned long NumberInputArgs(CONST struct ExternalFunc *efunc)
378 {
379 asc_assert(efunc!=NULL);
380 return efunc->n_inputs;
381 }
382
383 unsigned long NumberOutputArgs(CONST struct ExternalFunc *efunc)
384 {
385 asc_assert(efunc!=NULL);
386 return efunc->n_outputs;
387 }
388
389 /*
390 * These are the table management routines.
391 */
392
393 void InitExternalFuncLibrary(void)
394 {
395 struct Table *result;
396 result = CreateTable(EXTFUNCHASHSIZE); /* this isn't destroyed at end. fix.*/
397 ExternalFuncLibrary = result;
398 }
399
400 int AddExternalFunc(struct ExternalFunc *efunc, int force)
401 {
402
403 struct ExternalFunc *found, *tmp;
404 char *name;
405
406 asc_assert(efunc!=NULL);
407 name = (char *)efunc->name;
408 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,name);
409 if (found) { /* function name already exists */
410 if (force==0) {
411 return 0;
412 } else { /* need to update information */
413 tmp = (struct ExternalFunc *)RemoveTableData(ExternalFuncLibrary,name);
414 DestroyExternalFunc(tmp);
415 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
416 return 1;
417 }
418 }
419 else{ /* need to add function to library */
420 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
421 return 1;
422 }
423 }
424
425 struct ExternalFunc *LookupExtFunc(CONST char *funcname)
426 {
427 struct ExternalFunc *found;
428 if (!funcname) {
429 return NULL;
430 }
431 found = (struct ExternalFunc *)
432 LookupTableData(ExternalFuncLibrary,funcname);
433 if (found) {
434 return found;
435 } else {
436 return NULL; /* name not found */
437 }
438 }
439
440 struct ExternalFunc *RemoveExternalFunc(char *funcname)
441 {
442 struct ExternalFunc *found;
443 if (!funcname)
444 return NULL;
445 found = (struct ExternalFunc *)
446 RemoveTableData(ExternalFuncLibrary,funcname);
447 return found;
448 }
449
450
451 static
452 void ExternalFuncDestroyFunc(void *efunc)
453 {
454 struct ExternalFunc *local;
455 local = (struct ExternalFunc *)efunc;
456 if (local)
457 DestroyExternalFunc(local);
458 }
459
460 void DestroyExtFuncLibrary(void)
461 {
462 TableApplyAll(ExternalFuncLibrary,
463 (TableIteratorOne)ExternalFuncDestroyFunc);
464 DestroyTable(ExternalFuncLibrary,0);
465 ExternalFuncLibrary = NULL;
466 }
467
468 static
469 void PrintExtFuncLibraryFunc(void *efunc, void *fp)
470 {
471 struct ExternalFunc *local_efunc = (struct ExternalFunc *)efunc;
472
473 if (local_efunc!=NULL) {
474 FPRINTF(fp,"%s\n",ExternalFuncName(local_efunc));
475 if (local_efunc->help) {
476 FPRINTF(fp,"%s\n",local_efunc->help);
477 } else {
478 FPRINTF(fp,"No help information available for this function\n");
479 }
480 }
481 }
482
483 void PrintExtFuncLibrary(FILE *fp)
484 {
485 if (!fp) {
486 FPRINTF(ASCERR,"Invalid file handle in PrintExtFuncLibrary\n");
487 return;
488 }
489 TableApplyAllTwo(ExternalFuncLibrary, PrintExtFuncLibraryFunc,
490 (void *)fp);
491 }
492
493 static
494 void WriteExtFuncString(struct ExternalFunc *efunc, Asc_DString *dsPtr)
495 {
496 if (efunc!=NULL) {
497 Asc_DStringAppend(dsPtr,"{{",2);
498 Asc_DStringAppend(dsPtr,ExternalFuncName(efunc),-1);
499 Asc_DStringAppend(dsPtr,"} {",3);
500 if (efunc->help!=NULL) {
501 Asc_DStringAppend(dsPtr,efunc->help,-1);
502 } else {
503 Asc_DStringAppend(dsPtr,"No help available.",18);
504 }
505 Asc_DStringAppend(dsPtr,"}} ",3);
506 }
507 }
508
509 char *WriteExtFuncLibraryString(void)
510 {
511 char *result;
512 Asc_DString ds, *dsPtr;
513 dsPtr = &ds;
514 Asc_DStringInit(dsPtr);
515 TableApplyAllTwo(ExternalFuncLibrary,(TableIteratorTwo)WriteExtFuncString,
516 (void *) dsPtr);
517 result = Asc_DStringResult(dsPtr);
518 return result;
519 }
520
521 void
522 TraverseExtFuncLibrary(void (*func)(void *,void *), void *secondparam){
523 TableApplyAllTwo(ExternalFuncLibrary, func, secondparam);
524 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22