zador-anthony@CS.YALE.EDU (anthony zador) (09/15/89)
I have functions of the form double f(V,t) double V,t; { return (some math function involving about a line of exp, division, mult and add on V, t) } I use these functions to construct a table: Table(f, table_array) ptr_to_fun f; double_array table_array; { construct table_array by evaluating f[n] } I would like to be able to specify the form of the function f at *run time* (no recompiles). That is, i would like to place a line of math in some file and have the program read it in and evaluate it. For example, my fnct could be 1.6/(1+exp(-0.072*(V-5.0))) or 0.02*(V+8.69)/(exp((V+8.69)/5.36)-1) I have played around with "hoc", the high order calculator described in the Unix Programming Environment by K&P, but that seems like overkill for this task. Is there a simpler way? I'd appreciate any ideas. --Tony Zador zador@yale-sun3-nebula.arpa zador@nebula.sun3.cs.yale.edu
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/15/89)
In article <72603@yale-celray.yale.UUCP> zador-anthony@CS.YALE.EDU (anthony zador) writes: >I would like to be able to specify the form of the function f >at *run time* (no recompiles). That is, i would like >to place a line of math >in some file and have the program read it in and evaluate it. >I have played around with "hoc", the high order calculator >described in the Unix Programming Environment by K&P, but that seems >like overkill for this task. Is there a simpler way? Because C expressions have to be compiled (in most C environments, anyway), there's no way to input C language pieces at run time. You could however construct a source file, invoke the compiler on it, and execute it to get the results (into a file or via IPC), assuming a decent operating system environment. The portable way to do this is to build a language translator/interpretor into your application, much along the lines of the code used in "hoc".
henry@utzoo.uucp (Henry Spencer) (09/15/89)
In article <72603@yale-celray.yale.UUCP> zador-anthony@CS.YALE.EDU (anthony zador) writes: >I would like to be able to specify the form of the function f >at *run time* (no recompiles). That is, i would like >to place a line of math >in some file and have the program read it in and evaluate it. You can't. There is no way that line of math can be *executed* without compiling it (in a very broad sense of the word), so trying to do it with no recompiles is futile. Either you invoke the C compiler, or you write a mini-compiler as part of your program. *Something* has to turn the math notation into an executable/interpretable representation of some kind. -- V7 /bin/mail source: 554 lines.| Henry Spencer at U of Toronto Zoology 1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
mcdonald@uxe.cso.uiuc.edu (09/16/89)
In article <72603@yale-celray.yale.UUCP> zador-anthony@CS.YALE.EDU (anthony zador) writes: >I would like to be able to specify the form of the function f >at *run time* (no recompiles). That is, i would like >to place a line of math >in some file and have the program read it in and evaluate it. Henry Spencer replies: >You can't. There is no way that line of math can be *executed* without >compiling it (in a very broad sense of the word), so trying to do it with >no recompiles is futile. Either you invoke the C compiler, or you write >a mini-compiler as part of your program. *Something* has to turn the math >notation into an executable/interpretable representation of some kind. Or, if you need to do it once or only a couple of times, write an interpreter. An interpreter can be written in portable C. A compiler, of course, can't. You have to know the machine code. But the situation concerning mini-compilers is even worse than non-portability. It is certainly guaranteed possible to write to an array the bits which constitute the necessary code. BUT -- BUT-- due apparently to X3J11 bowing to the concerns of manufacturers of brain-dead computers and operating systems, there is absolutely no guarantee that you can EXECUTE that code. Actually the situation is not too bad on most computers - for example, on MS-DOS or VMS there is no problem at all. There you can just cast a pointer to the data array to a code pointer and go to town. On OS/2 you can't do that - but there is a trivial OS call that will do it for you. There appear to be, however, Unixes that really make it impossible. I am very sensitive to this sort of thing, as my spiffiest programs all depend on in-situ compilation of expressions (though, thank God, not control constructs). Doug McDonald
mccaugh@s.cs.uiuc.edu (09/17/89)
In article <72603@yale-celray.yale.UUCP> zador-anthony@CS.YALE.EDU (Anthony Zador) writes: > I would like to be able to specify the form of the function f > at *run time* (no recompiles). That is, i would like > to place a line of math > in some file and have the program read it in and evaluate it. > ..... As rightly noted by the preceding respondents, the function definition would have to be parsed into some internal form suitable for digestion by an inter- preter. But with a utility as nice as BC (the arbitrary-precision desk calcu- lator), it may not be necessary to "re-invent the wheel" writing your own. Suppose file 'f1' contained your function definitions, say: define u(x) { /* signum function */ if(x<0) return(-1) if(x>0) return(1) return(0) } define t(x) { /* tangent function */ auto z if(x==90) return(572957.8) if(x==270) return(572957.8) /* else convert degrees to radians */ z = 0.0174532*x /* and return tan(x) */ return(s(z)/c(z)) } and your calls to these functions were included in another file, 'f2': /* some sample values */ f(-13.57) /* s/b: -1 */ t(45) /* s/b: +1 */ quit Then your C program could issue the system call: system("cat f1 f2 | bc -l > f3"); and you have your results in file 'f3': -1 .99999167323977094494 This is certainly not an elegant solution, but it does appear feasible and takes advantage of BC's arbitrary-precision capability to boot (and hence is slooow). But it would appear to spare one the need to tool their own interpreter along the lines of 'hoc' (I recall the source for 'hoc' runs to 13 pages in Kernighan & Pike). Scott McCaughrin Dept. of Computer Science University of Illinois
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)
In article <225800223@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
-due apparently to X3J11 bowing to the concerns of manufacturers
-of brain-dead computers and operating systems, there is absolutely
-no guarantee that you can EXECUTE that code.
I consider that an implementation that lets you set the PC to
data space is brain dead.
-Actually the situation is not too bad on most computers - for
-example, on MS-DOS or VMS there is no problem at all. There you
-can just cast a pointer to the data array to a code pointer and
-go to town.
My opinion of VMS just dropped another notch. The VAX architecture
permits enforcement of code/data separation, and one would think it
would be used for tasks resulting from compilation of C source code.
Certainly there are uses for the facility of executing instructions
out of data space. The bit-blit code for some of the Blit family
of terminals works like that, for example. But for most applications,
the added safety check is much more useful than the ability to execute
out of data space. And as we've pointed out before, some environments
require the separation.
henry@utzoo.uucp (Henry Spencer) (09/17/89)
In article <225800223@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes: >>You can't. There is no way that line of math can be *executed* without >>compiling it (in a very broad sense of the word), so trying to do it with >>no recompiles is futile. Either you invoke the C compiler, or you write >>a mini-compiler as part of your program... > >Or, if you need to do it once or only a couple of times, write >an interpreter. An interpreter can be written in portable C. >A compiler, of course, can't. You have to know the machine code. You are assuming a very narrow definition of "compiler". Note the phrase "in a very broad sense of the word". Not all translators referred to as "compilers" generate machine code. -- "Where is D.D. Harriman now, | Henry Spencer at U of Toronto Zoology when we really *need* him?" | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
jeenglis@nunki.usc.edu (Joe English) (09/17/89)
zador-anthony@CS.YALE.EDU (anthony zador) writes: >I would like to be able to specify the form of the function f >at *run time* (no recompiles). That is, i would like >to place a line of math >in some file and have the program read it in and evaluate it. How about writing a set of math interface functions that take, instead of a fixed set of parameters, an argv/argc pair? I'm doing something like that right now in a report generator I'm writing: enum valuetype { vInt, vFloat, vString ... }; typedef struct { enum valuetype tag; union { int ival; double fval; char *sval; ... } datum; } value; Then for the interface function: value somefunc(int argc,value *argv) { /* use argc parameters from the argv array. Type-checking of arguments is done by the parser & function lookup table. */ } If you don't need full generality, you can use 'double *argv'. --Joe English jeenglis@nunki.usc.edu