1 /****************************************************************
2 Copyright (C) 1997-2001 Lucent Technologies
3 All Rights Reserved
4 
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name of Lucent or any of its entities
11 not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior
13 permission.
14 
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 THIS SOFTWARE.
23 ****************************************************************/
24 
25 #ifndef FUNCADD_H_INCLUDED
26 #define FUNCADD_H_INCLUDED
27 #include "stdio1.h"	/* for ANSI and any printing */
28 
29 #ifndef VA_LIST
30 #define VA_LIST va_list
31 #endif
32 
33 #ifdef _WIN32
34 #define Stdio_redefs
35 #endif
36 
37  typedef struct cryptblock cryptblock;
38 
39 #ifdef __cplusplus
40 #undef KR_headers
41 extern "C" {
42 #endif
43 
44 #ifndef real
45 typedef double real;
46 #endif
47 typedef struct arglist arglist;
48 typedef struct function function;
49 typedef struct TVA TVA;
50 typedef struct AmplExports AmplExports;
51 typedef struct AuxInfo AuxInfo;
52 typedef struct TableInfo TableInfo;
53 typedef struct TMInfo TMInfo;
54 
55 #ifndef No_arglist_def
56 
57 #undef Const
58 #ifdef KR_headers
59 #define Const /* nothing */
60 #else
61 #define Const const
62 #endif
63 
64  struct
65 arglist {			/* Information sent to user-defined functions */
66 	int n;			/* number of args */
67 	int nr;			/* number of real input args */
68 	int *at;		/* argument types -- see DISCUSSION below */
69 	real *ra;		/* pure real args (IN, OUT, and INOUT) */
70 	Const char **sa;	/* symbolic IN args */
71 	real *derivs;		/* for partial derivatives (if nonzero) */
72 	real *hes;		/* for second partials (if nonzero) */
73 	char *dig;		/* if (dig && dig[i]) { partials w.r.t.	*/
74 				/*	ra[i] will not be used }	*/
75 	Char *funcinfo;		/* for use by the function (if desired) */
76 	AmplExports *AE;	/* functions made visible (via #defines below) */
77 	function *f;		/* for internal use by AMPL */
78 	TVA *tva;		/* for internal use by AMPL */
79 	char *Errmsg;		/* To indicate an error, set this to a */
80 				/* description of the error.  When derivs */
81 				/* is nonzero and the error is that first */
82 				/* derivatives cannot or are not computed, */
83 				/* a single quote character (') should be */
84 				/* the first character in the text assigned */
85 				/* to Errmsg, followed by the actual error */
86 				/* message.  Similarly, if hes is nonzero */
87 				/* and the error is that second derivatives */
88 				/* are not or cannot be computed, a double */
89 				/* quote character (") should be the first */
90 				/* character in Errmsg, followed by the */
91 				/* actual error message text. */
92 	TMInfo *TMI;		/* used in Tempmem calls */
93 	Char *Private;
94 				/* The following fields are relevant */
95 				/* only when imported functions are called */
96 				/* by AMPL commands (not declarations). */
97 
98 	int nin;		/* number of input (IN and INOUT) args */
99 	int nout;		/* number of output (OUT and INOUT) args */
100 	int nsin;		/* number of symbolic input arguments */
101 	int nsout;		/* number of symbolic OUT and INOUT args */
102 	};
103 
104 typedef real (*rfunc) ANSI((arglist *));
105 typedef real (ufunc) ANSI((arglist *));
106 
107 #endif /* No_arglist_def */
108 
109  enum AMPLFUNC_AT_BITS {	/* Intrepretation of at[i] when the type */
110 				/* arg to addfunc has the */
111 				/* FUNCADD_OUTPUT_ARGS bit on.*/
112 	AMPLFUNC_INARG  = 1,	/* IN or INOUT */
113 	AMPLFUNC_OUTARG = 2,	/* OUT or INOUT */
114 	AMPLFUNC_STRING = 4,	/* Input value is a string (sa[i]) */
115 	AMPLFUNC_STROUT = 8	/* String output value allowed */
116 	};
117 
118  enum FUNCADD_TYPE {			/* bits in "type" arg to addfunc */
119 
120 		/* The type arg to addfunc should consist of one of the */
121 		/* following values ... */
122 
123 	FUNCADD_REAL_VALUED = 0,	/* real (double) valued function */
124 	FUNCADD_STRING_VALUED = 2,	/* char* valued function (AMPL only) */
125 	FUNCADD_RANDOM_VALUED = 4,	/* real random valued */
126 	FUNCADD_012ARGS = 6,		/* Special case: real random valued */
127 					/* with 0 <= nargs <= 2 arguments */
128 					/* passed directly, rather than in */
129 					/* an arglist structure (AMPL only). */
130 
131 		/* possibly or-ed with the following... */
132 
133 	FUNCADD_STRING_ARGS = 1,	/* allow string args */
134 	FUNCADD_OUTPUT_ARGS = 16,	/* allow output args (AMPL only) */
135 	FUNCADD_TUPLE_VALUED = 32,	/* not yet allowed */
136 
137 		/* internal use */
138 	FUNCADD_NO_ARGLIST = 8,
139 	FUNCADD_NO_DUPWARN = 64,	/* no complaint if already defined */
140 	FUNCADD_NONRAND_BUILTIN = 128	/* mean, variance, moment, etc. */
141 	};
142 
143 /* If a constraint involves an imported function and presolve fixes all
144  * the arguments of the function, AMPL may later need to ask the
145  * function for its partial derivatives -- even though the solver had
146  * no reason to call the function.  If so, it will pass an arglist *al
147  * with al->derivs nonzero, and it will expect the function to set
148  * al->derivs[i] to the partial derivative of the function with respect
149  * to al->ra[i].  Solvers that need to evaluate an imported function
150  * work the same way -- they set al->derivs to a nonzero value if they
151  * require both the function value and its first derivatives.  Solvers
152  * that expect Hessians to be supplied to them also set al->hes to a
153  * nonzero value if they require second derivatives at the current
154  * argument.  In this case, the function should set
155  * al->hes[i + j*(j+1)/2] to the partial derivative of the function with
156  * respect to al->ra[i] and al->ra[j] for all 0 <= i <= j < al->nr.
157  */
158 
159 typedef void AddFunc ANSI((
160 		const char *name,
161 		rfunc f,	/* cast f to (rfunc) if it returns char* */
162 		int type,	/* see FUNCADD_TYPE above */
163 		int nargs,	/* >=  0 ==> exactly that many args
164 				 * <= -1 ==> at least -(nargs+1) args
165 				 */
166 		void *funcinfo,	/* for use by the function (if desired) */
167 		AmplExports *ae
168 		));
169 
170 typedef void AddRand ANSI((
171 		const char *name,
172 		rfunc f,	/* assumed to be a random function */
173 		rfunc icdf,	/* inverse CDF */
174 		int type,	/* FUNCADD_STRING_ARGS or 0 */
175 		int nargs,	/* >=  0 ==> exactly that many args
176 				 * <= -1 ==> at least -(nargs+1) args
177 				 */
178 		void *funcinfo,	/* for use by the function (if desired) */
179 		AmplExports *ae
180 		));
181 
182 typedef void (*RandSeedSetter) ANSI((void*, unsigned long));
183 typedef void AddRandInit ANSI((AmplExports *ae, RandSeedSetter, void*));
184 typedef void Exitfunc ANSI((void*));
185 
186  struct
187 AuxInfo {
188 	AuxInfo *next;
189 	char *auxname;
190 	void *v;
191 	void (*f) ANSI((AmplExports*, void*, ...));
192 	};
193 
194  struct
195 AmplExports {
196 	FILE *StdErr;
197 	AddFunc *Addfunc;
198 	long ASLdate;
199 	int (*FprintF)  ANSI((FILE*, const char*, ...));
200 	int (*PrintF)   ANSI((const char*, ...));
201 	int (*SprintF)  ANSI((char*, const char*, ...));
202 	int (*VfprintF) ANSI((FILE*, const char*, VA_LIST));
203 	int (*VsprintF) ANSI((char*, const char*, VA_LIST));
204 	double (*Strtod) ANSI((const char*, char**));
205 	cryptblock *(*Crypto) ANSI((char *key, size_t scrbytes));
206 	Char *asl;
207 	void (*AtExit)  ANSI((AmplExports *ae, Exitfunc*, void*));
208 	void (*AtReset) ANSI((AmplExports *ae, Exitfunc*, void*));
209 	Char *(*Tempmem) ANSI((TMInfo*, size_t));
210 	void (*Add_table_handler) ANSI((
211 		int (*DbRead) (AmplExports *ae, TableInfo *TI),
212 		int (*DbWrite)(AmplExports *ae, TableInfo *TI),
213 		char *handler_info,
214 		int flags,
215 		void *Vinfo
216 		));
217 	Char *Private;
218 	void (*Qsortv) ANSI((void*, size_t, size_t, int(*)(const void*,const void*,void*), void*));
219 
220 	/* More stuff for stdio in DLLs... */
221 
222 	FILE	*StdIn;
223 	FILE	*StdOut;
224 	void	(*Clearerr)	ANSI((FILE*));
225 	int	(*Fclose)	ANSI((FILE*));
226 	FILE*	(*Fdopen)	ANSI((int, const char*));
227 	int	(*Feof)		ANSI((FILE*));
228 	int	(*Ferror)	ANSI((FILE*));
229 	int	(*Fflush)	ANSI((FILE*));
230 	int	(*Fgetc)	ANSI((FILE*));
231 	char*	(*Fgets)	ANSI((char*, int, FILE*));
232 	int	(*Fileno)	ANSI((FILE*));
233 	FILE*	(*Fopen)	ANSI((const char*, const char*));
234 	int	(*Fputc)	ANSI((int, FILE*));
235 	int	(*Fputs)	ANSI((const char*, FILE*));
236 	size_t	(*Fread)	ANSI((void*, size_t, size_t, FILE*));
237 	FILE*	(*Freopen)	ANSI((const char*, const char*, FILE*));
238 	int	(*Fscanf)	ANSI((FILE*, const char*, ...));
239 	int	(*Fseek)	ANSI((FILE*, long, int));
240 	long	(*Ftell)	ANSI((FILE*));
241 	size_t	(*Fwrite)	ANSI((const void*, size_t, size_t, FILE*));
242 	int	(*Pclose)	ANSI((FILE*));
243 	void	(*Perror)	ANSI((const char*));
244 	FILE*	(*Popen)	ANSI((const char*, const char*));
245 	int	(*Puts)		ANSI((const char*));
246 	void	(*Rewind)	ANSI((FILE*));
247 	int	(*Scanf)	ANSI((const char*, ...));
248 	void	(*Setbuf)	ANSI((FILE*, char*));
249 	int	(*Setvbuf)	ANSI((FILE*, char*, int, size_t));
250 	int	(*Sscanf)	ANSI((const char*, const char*, ...));
251 	char*	(*Tempnam)	ANSI((const char*, const char*));
252 	FILE*	(*Tmpfile)	ANSI((void));
253 	char*	(*Tmpnam)	ANSI((char*));
254 	int	(*Ungetc)	ANSI((int, FILE*));
255 	AuxInfo *AI;
256 	char*	(*Getenv)	ANSI((const char*));
257 	void	(*Breakfunc)	ANSI((int,void*));
258 	Char	*Breakarg;
259 	/* Items available with ASLdate >= 20020501 start here. */
260 	int (*SnprintF) ANSI((char*, size_t, const char*, ...));
261 	int (*VsnprintF) ANSI((char*, size_t, const char*, VA_LIST));
262 
263 	AddRand *Addrand;	/* for random function/inverse CDF pairs */
264 	AddRandInit *Addrandinit; /* for adding a function to receive a new random seed */
265 	};
266 
267 extern const char *i_option_ASL, *ix_details_ASL[];
268 
269 #define funcadd funcadd_ASL
270 
271 #if defined(_WIN32) && !defined(__MINGW32__)
272 __declspec(dllexport)
273 #endif
274 extern void funcadd ANSI((AmplExports*));	/* dynamically linked */
275 extern void af_libnamesave_ASL ANSI((AmplExports*, const char *fullname, const char *name, int nlen));
276 extern void note_libuse_ASL ANSI((void));	/* If funcadd() does not provide any imported */
277 						/* functions, it can call note_libuse_ASL() to */
278 						/* keep the library loaded; note_libuse_ASL() is */
279 						/* called, e.g., by the tableproxy table handler. */
280 
281 #ifdef __cplusplus
282 	}
283 #endif
284 
285  typedef struct
286 DbCol {
287 	real	*dval;
288 	char	**sval;
289 	} DbCol;
290 
291  struct
292 TableInfo {
293 	int (*AddRows) ANSI((TableInfo *TI, DbCol *cols, long nrows));
294 	char *tname;	/* name of this table */
295 	char **strings;
296 	char **colnames;
297 	DbCol *cols;
298 	char *Missing;
299 	char *Errmsg;
300 	void *Vinfo;
301 	TMInfo *TMI;
302 	int nstrings;
303 	int arity;
304 	int ncols;
305 	int flags;
306 	long nrows;
307 	void *Private;
308 	int (*Lookup) ANSI((real*, char**, TableInfo*));
309 	long (*AdjustMaxrows) ANSI((TableInfo*, long new_maxrows));
310 	void *(*ColAlloc) ANSI((TableInfo*, int ncol, int sval));
311 	long maxrows;
312 	};
313 
314 enum {	/* return values from (*DbRead)(...) and (*DbWrite)(...) */
315 	DB_Done = 0,	/* Table read or written. */
316 	DB_Refuse = 1,	/* Refuse to handle this table. */
317 	DB_Error = 2	/* Error reading or writing table. */
318 	};
319 
320 enum {	/* bits in flags field of TableInfo */
321 	DBTI_flags_IN = 1,	/* table has IN  or INOUT entities */
322 	DBTI_flags_OUT = 2,	/* table has OUT or INOUT entities */
323 	DBTI_flags_INSET = 4	/* table has "in set" phrase: */
324 				/* DbRead could omit rows for */
325 				/* which Lookup(...) == -1; AMPL */
326 				/* will ignore such rows if DbRead */
327 				/* offers them. */
328 	};
329 
330 #endif /* FUNCADD_H_INCLUDED */
331 
332 #ifndef No_AE_redefs
333 /* Assume "{extern|static} AmplExports *ae;" is given elsewhere. */
334 #undef Stderr
335 #undef addfunc
336 #undef fprintf
337 #undef getenv
338 #undef printf
339 #undef sprintf
340 #undef snprintf
341 #undef strtod
342 #undef vfprintf
343 #undef vsprintf
344 #undef vsnprintf
345 #define Stderr (ae->StdErr)
346 #define addfunc(a,b,c,d,e) (*ae->Addfunc)(a,b,c,d,e,ae)
347 #define addrand(a,b,c,d,e,f) (*ae->Addrand)(a,b,c,d,e,f,ae)
348 #define addrandinit(a,b) (*ae->Addrandinit)(ae,a,b)
349 #define printf	(*ae->PrintF)
350 #define fprintf (*ae->FprintF)
351 #define snprintf (*ae->SnprintF)
352 #define sprintf (*ae->SprintF)
353 #define strtod  (*ae->Strtod)
354 #define vfprintf (*ae->VfprintF)
355 #define vsprintf (*ae->VsprintF)
356 #define vsnprintf (*ae->VsnprintF)
357 #define TempMem(x,y) (*ae->Tempmem)(x,y)
358 #define at_exit(x,y) (*ae->AtExit)(ae,x,y)
359 #define at_reset(x,y) (*ae->AtReset)(ae,x,y)
360 #define add_table_handler(a,b,c,d,e) (*ae->Add_table_handler)(a,b,c,d,e)
361 #define qsortv(a,b,c,d,e) (*ae->Qsortv)(a,b,c,d,e)
362 #define getenv(x) (*ae->Getenv)(x)
363 #ifdef Stdio_redefs
364 #undef clearerr
365 #undef fclose
366 #undef fdopen
367 #undef feof
368 #undef ferror
369 #undef fflush
370 #undef fgetc
371 #undef fgets
372 #undef fileno
373 #undef fopen
374 #undef fputc
375 #undef fputs
376 #undef fread
377 #undef freopen
378 #undef fscanf
379 #undef fseek
380 #undef ftell
381 #undef fwrite
382 #undef getc
383 #undef getchar
384 #undef gets
385 #undef pclose
386 #undef perror
387 #undef popen
388 #undef putc
389 #undef putchar
390 #undef puts
391 #undef rewind
392 #undef scanf
393 #undef setbuf
394 #undef setvbuf
395 #undef sscanf
396 #undef tempnam
397 #undef tmpfile
398 #undef tmpnam
399 #undef ungetc
400 #undef vprintf
401 #define clearerr	(*ae->Clearerr)
402 #define fclose		(*ae->Fclose)
403 #define fdopen		(*ae->Fdopen)
404 #define feof		(*ae->Feof)
405 #define ferror		(*ae->Ferror)
406 #define fflush		(*ae->Fflush)
407 #define fgetc		(*ae->Fgetc)
408 #define fgets		(*ae->Fgets)
409 #define fileno		(*ae->Fileno)
410 #define fopen		(*ae->Fopen)
411 #define fputc		(*ae->Fputc)
412 #define fputs		(*ae->Fputs)
413 #define fread		(*ae->Fread)
414 #define freopen		(*ae->Freopen)
415 #define fscanf		(*ae->Fscanf)
416 #define fseek		(*ae->Fseek)
417 #define ftell		(*ae->Ftell)
418 #define fwrite		(*ae->Fwrite)
419 #define getc		(*ae->Fgetc)
420 #define getchar()	(*ae->Getc)(ae->StdIn)
421 #define gets		Error - use "fgets" rather than "gets"
422 #define pclose		(*ae->Pclose)
423 #define perror		(*ae->Perror)
424 #define popen		(*ae->Popen)
425 #define putc		(*ae->Fputc)
426 #define putchar(x)	(*ae->Fputc)(ae->StdOut,(x))
427 #define puts		(*ae->Puts)
428 #define rewind		(*ae->Rewind)
429 #define scanf		(*ae->Scanf)
430 #define setbuf		(*ae->Setbuf)
431 #define setvbuf		(*ae->Setvbuf)
432 #define sscanf		(*ae->Sscanf)
433 #define tempnam		(*ae->Tempnam)
434 #define tmpfile		(*ae->Tmpfile)
435 #define tmpnam		(*ae->Tmpnam)
436 #define ungetc		(*ae->Ungetc)
437 #define vprintf(x,y)	(*ae->VfprintF)(ae->StdOut,(x),(y))
438 #define Stdin		(ae->StdIn)
439 #define Stdout		(ae->StdOut)
440 #ifndef No_std_FILE_redefs	/* may elicit compiler warnings */
441 #undef stdin
442 #undef stdout
443 #undef stderr
444 #define stdin		(ae->StdIn)
445 #define stdout		(ae->StdOut)
446 #define stderr		(ae->StdErr)
447 #endif /* No_std_FILE_redefs */
448 #endif /* Stdio_redefs */
449 #endif /* ifndef No_AE_redefs */
450 
451 /* DISCUSSION: the "at" field of an arglist...
452  *
453  * OUT and INOUT arguments are only permitted in AMPL commands,
454  * such as "let" and "call" commands (and not in declarations, e.g.,
455  * of constraints and variables).
456  *
457  * When addfunc was called with type <= 6 (so there can be no OUT or
458  * INOUT arguments), for 0 <= i < n,
459  *		at[i] >= 0 ==> arg i is ra[at[i]]
460  *		at[i] <  0 ==> arg i is sa[-(at[i]+1)].
461  *
462  * When addfunc was called with type & FUNCADD_OUTPUT_ARGS on (permitting
463  * OUT and INOUT arguments), arg i is in ra[i] or sa[i] (as explained
464  * below), derivs and hes are both null, and at[i] is the union of bits
465  * that describe arg i:
466  *	AMPLFUNC_INARG  = 1 ==> input arg;
467  *	AMPLFUNC_OUTARG = 2 ==> output arg;
468  *	AMPLFUNC_STRING = 4 ==> input is sa[i]
469  *	AMPLFUNC_STROUT = 8 ==> can be assigned a string value.
470  *
471  * INOUT args have both the AMPLFUNC_INARG and the AMPLFUNC_OUTARG bits
472  * are on, i.e., (at[i] & 3) == 3.
473  *
474  * Symbolic OUT and INOUT arguments are a bit complicated.  They can only
475  * correspond to symbolic parameters in AMPL, which may have either a
476  * string or a numeric value.  Thus there is provision for specifying
477  * output values to be either numbers or strings.  For simplicity, when
478  * the function accepts output arguments, ra[i] and sa[i] together describe
479  * argument i.  In general (whentype & FUNCADD_OUTPUT_ARGS is nonzero in
480  * the addfunc call), the incoming value of argument i is ra[i]
481  * (a numeric value) if sa[i] is null and is otherwise sa[i].
482  * To assign a value to argument i, either assign a numeric value to
483  * ra[i] and set sa[i] = 0, or assign a non-null value to sa[i]
484  * (in which case ra[i] will be ignored).  A value assigned to argument
485  * i is ignored unless at[i] & AMPLFUNC_OUTARG is nonzero; if so
486  * and if (at[i] & AMPLFUNC_STROUT) == 0, string values cause an error
487  * message.
488  */
489