Version 24 of a tcl script for function value listing based on a fortran expression

Updated 2013-01-28 02:24:44 by RLE

tv

As part of some maxima ramblings, a little script to take a FORTRAN expression, which is used to generate efficiently computed list of function values.

A possible use for this is to generate heavy graphs from mathematica expressions, which can be converted into fortran expressions with the fortran command:

   fortran(diff(sin(x)/x,x));
      COS(x)/x-SIN(x)/x**2

The idea is to have an easy to use C program that calls a little fortran subroutine, and that whole program is invoked by a tcl proc, which also takes care of the combined compilation of the fortran and C function value loop code, and the exec of the resulting executable:

 # Feed this Tcl proc a fortran expression
 proc formake {e} {
   global f
   set t [subst -nocommand {
      subroutine sayhello(x,r)
        real x,r
        r = $e
        return 
      end 
   }]
   set f [open sub.f w]
   puts $f [string trim $t \n]
   close $f
   exec gcc -ffixed-line-length-none -o fm sub.f main.c -lm
   return [exec ./fm]
 }

(DKF: Adapted the above to use subst for greater code clarity.) (TV Isn't there a backward compatibility issue with this ?) (DKF: Certainly not if your version of Tcl is less than 10 years old.)

[TV} (apr 6 '05) I've changed the declaration of the reals; I guess this is correct according to the fortran way...

TV (aug 21 '05) I've added a no line length limitation option to the gcc command, otherwise long lines (like with high accuracy floats) generate errors.

This, or an adapted, C program is needed in the current directory:

 /* This is file: main.c */
 #include<stdio.h>
 #include<math.h>

 extern void sayhello_(float *, float *);

 int main(argc, argv)
 int argc;
 char *argv[];
 {
   float in, out;
   float x, start, stop, incr;

   if (argc == 1) {
      start = -10.0;
      stop = 10.0;
      incr = 2.0;
   } else exit((int) -1);
   for (x=start; x<=stop; x+=incr) {
      in = x;
      sayhello_(&in,&out);
      printf("%f %f\n", x, (float) out);
   }
   return((int) 0);
 }

Calling the formake routine in this case returns a formatted list of 21 X Y values, but it could return more. Of course braces could be added to automatically create a Tcl list as result.

There is nothing against using these methods in Bwise blocks.

Note that this approach assumes running on a linux like or compatible (like maybe cygwin) system, with gcc present with fortran extensions, I tested on RH9, which worked fast.


LV Too bad that critcl couldn't do the FORTRAN compilation...

TV Maybe some day Maxima will on top of a Tk interface also have tcl/expr inteface, or who knowns, maybe somebody has time and vision to replace the LISP based code with tcl code... (wish wish). But Linux and cygwin (for windows) have the gnu compiler which does the job fine and fast.

LV and in fact, critcl makes use of the gnu compiler to do its job - so in theory, the above code could be modified so that the FORTRAN subroutine were somehow passed to critcl to compile. That would seem to eliminate the need for the special C hooks.

[TV} Well, when you have the gnu complier already, it's not hard to do the compilation:

   exec gcc -o fm sub.f main.c -lm

isn't exactly the holy grail in university research...

LV I guess the reference to critcl isn't being understood. What critcl currently allows the developer to do is to put C code in-line in the Tcl program, dynamically create a loadable function, and invoke it, 'transparently' to the developer. No coding of an exec, no main.c, etc. needed. The end result is a Tcl function that can be called as if it were a part of Tcl.

[TV} Well if it runs the essence of gcc anyhow, I'd rather have control and vision on the commands being executed, I guess. Most contemporary machines won't have a space problem with that, so a little cygwin install doesn't hurt and is very useful and insightfull I'm sure.

AM (7 april 2005) I have done some work on getting Critcl to work with Fortran programs :). The tough issue is to automatically combine the Fortran and C compilers. They have to be on "speaking terms."

LV Okay - I've not programmed in FORTRAN for probably 30 yrs. But I thought I had read that use of g77 allowed one to compile both FORTRAN 77 and C code. And I thought I had also read that one of the goals of gfortran was to be able to compile C and FORTRAN 95 (95, right?) code.

I'd assume that by making use of g++, critcl might be able to compile C++ and C code. What I don't know is whether one can just use gcc itself and feed it the files with the appropriate suffixes to get all the appropriate front-ends to work.

TV Well, as te above example does in Tcl script code, that is quite possible (and if you can use the working results quite easy), and the varables can be exchanged, except I don't know about the meaning of the fortran formal procedure declaration method.

AM Re LV: True, g77 and gcc work together, but my ambitions were (and are) to move away from the complete dependency on the Gnu compilers to be present.

And then the FORTRAN77 standard is about 30 years old. We have seen at least two widely used newer standards since then and the latest, Fortran 2003, has been formally approved. Furthermore, there is g95 and gfortran if we merely look at the Gnu family


TV (mar 7 '06) Recently I used these scripts and found ouy that on FC4/64, I needed to replace the compile anove by:

 exec gfortran -ffixed-line-length-none -c sub.f
 exec gcc -o fm sub.o main.c -lm

(Dec 3 '06) On FC5 however, its right the way it was... Also I changed a few small things in the C program.