Porting FMINUIT

Compilation, Porting and Compatibility of FMINUIT

Fminuit is a minimization program written in C and linked to the Fortran 77 subroutines of MINUIT, running under Matlab (or a clone) as a dynamic or relocatable executable.
Building Fminuit therefore requires C and a Fortran 77 compilers generating linker-compatible objects. Compatibility of the Fminuit code "as is" is further restricted by the calling convention of Fortran subroutines from a C program, which is compiler-dependent. At present, Fortran compilers with a supported Fortran-to-C calling convention are:

  1. The native VMS compilers by Digital Equipment Corporation ® (DEC) for Vax/Alpha VMS (where Fminuit was originally developed);
  2. Fortran compilers for Unix/Linux systems, including GNU g77 and the f2c Fortran-to-C translator, and many others. The calling convention of these compilers basically consists in that:
    • a Fortran subroutine name corresponds to a lowercase C name with a trailing underscore appended, and
    • for any string argument, an extra integer (the string length) is appended to the C argument list. This convention is a de-facto standard over the Unix world.
    Fortunately, f2c and the accompanying runtime library libf2c are available for virtually any operating system, which ensures portability to any platform.
    The port for Windows is based on f2c, and works fine.
    Compiling Fminuit with a non-Unix and non-VMS Fortran compiler would at least require to modify the calls of the Minuit APIs in the Fminuit code according to the current Fortran-to-C calling convention.

    In order to run Fminuit in a windowed Matlab/Scilab shell (e.g. Matlab under Windows and X-Window, Scilab under X-window), however, the following points are also to be considered.

    Calls to I/O functions must be wrapped

    In a windowed environment, standard input and standard output of the C library, as well as READ and WRITE statements from/to the Fortran units 5 and 6, do not work properly or do not work at all. For instance, if you start a windowed Matlab or Scilab session from the command line under Unix/Linux, a standard printf would cause output to be issued in the Xterm you started Matlab (Scilab) from, rather than in the program window.
    A similar malfunction occurs for stdin with terminal-based versions of Matlab under Unix/Linux. The only platform where I found the standard runtime library working properly is VMS.

    For stdout within C code, this problem can be solved by calling the mex API mexPrintf as a replacement for the standard printf. There is no mexGetchar or mexFgets API to read standard input, however.
    The difficulty is even more serious with Fortran (Minuit code). WRITE and READ are statements, not functions, and therefore they cannot be replaced while preserving their invocation syntax.
    I devised two different approaches to cope with these problems:

    1. If the problem is with stdin only, a workaround can be enabled at a user-program level by compiling Fminuit with BROKENSTDIN defined. This causes calls to the Minuit API mnintr to be replaced by calls to the local subroutine mnintr_workaround. The latter reads an input line by a callback to Matlab, parses input, and calls mnexec. Minuit internal mode is set batch, which disables the execution of READ statements from unit 5. Some interactive features of Minuit (e.g. SAVE) are therefore unavailable.
    2. A more powerful workaround, suitable for both broken stdin and stdout, although probably only possible with Unix compilers (f2c included), can be implemented at a Fortran library level, by replacing reference to the basic I/O functions (fgetc, fungetc, fputc, fputs, fprintf) in the Fortran library with references to suitable wrappers. All I/O of libf2c and libg2c (compiled with NON_UNIX_STDIO defined, which is default even under Linux) is based on the above C-library function

    3. The I/O wrappers (enclosed in the Fminuit distribution) behave as the standard I/O functions if the opened file is none of stdin, stdout, stderr; they print or get I/O to/from the main window by means of calls to the Matlab/Scilab APIs (or callbacks to Matlab) otherwise.
      If source code of the Fortran library is available, as with libf2c, wrapping can be obviously implemented by recompiling the library with fgetc, fputc, ... redefined. On systems with a GNU ld linker (e.g. Linux), wrapping is also possible with the binary library without recompilation, by linking with the --wrap option: see Makefiles in the Fminuit directory for details.
    I have no experience with non-Unix Fortran compilers except the Vax one. If both stdin and stdout do not work in the Matlab window (so that the approach a) is not viable) there is a high probability that such compilers are useless, unless their runtime library is based on stdio.h functions and the binary utilities coming with the compiler allow wrapping and similar manipulations of the object code.

    Fminuit for Scilab (Linux and other Unix with GNU compilers)

    Building Fminuit for Scilab
    (up to version 4.x) under Linux requires further attention. The Scilab executable scilex exports all its symbols. Therefore, all the subroutines and commons making up Scilab are accessible to a Scilab mex program. This provides the user with plenty of (undocumented) APIs, which could be exploited in the dirty work of having Fminuit running under earlier Scilab versions. The danger with this, however, is a high probability of name collision. This was actually the case with Minuit code. Since Scilab is mostly written in Fortran, the scilex executable incorporates most of the Fortran library code. There is therefore a big chance that, when a mex program based on Fortran code is dynamically linked (loaded) to Scilab, references to functions of the Fortran runtime library (e.g. s_wsle) are resolved to the subroutine code built-in with scilex, rather than to the library passed as argument to the linker. As explained above, the Fortran-library subroutines built-in with Scilab (coming from a standard version of the library) do not produced working input/output.
    In order to prevent name conflict and have undefined references to the Fortran library resolved to a working version of libf2c/libg2c - with wrappped calls to I/O C-library functions - one has to proceed along the following steps:

    1. partial linking (ld -r) of Minuit with a wrapped Fortran library;
    2. localization of ALL libf2c/libg2c defined symbols by means of the binary utility objcopy - this makes all libf2c/libg2c symbols invisible to the linker in a subsequent linking step, thus ensuring that Minuit undefined symbols are actually resolved to the wrapped libf2c/libg2c;
    3. linking of the resulting object with fminuit.o, I/O wrappers, and the other objects.
    See Makefile.scilab.* for details.


Giuseppe.Allodi@fis.unipr.it
© Copyright by G. Allodi 1996 - 2010.
 
 
 
 
  
 
 
Intro
Main
Building
Porting
Download