views:

56

answers:

4

I am linking some fortran code (f90) from matlab using mex and I am having matlab freeze occasionally.

In the past, I had freezing happening due to mismatch between data types (say integer*4 vs integer*8).

The code I am linking has many implicitly defined variables, so I am wondering if there is a hidden data type conflict that only occurs occasionally.

To rule out data type mismatch as the cause of the freeze, I would like to have the compiler requiring all variables to be explicitly declared.

Questions:

  1. How do I get gfortran to require all variables to be explicitly declared at compile time? Failing that, is there any way to at least get warnings?

  2. Is a "real" data type interpreted by gfortran as a specific kind in all architectures? If so, which one is it (real*4, real*8, ...)?

  3. Is there anyway to force gfortran to interpret the "real" data type as a specific kind, say "real*4"?

  4. Any ideas on what makes the fortran code to freeze when called from a mex compiled routine in matlab (other than data type mismatches)?

Thanks for any help.

Until I figure this out I will be going through many lines of codes trying to list all implicitly defined variables. Needless to say, I will be tremendously grateful to anyone who frees me from such a boring task...

Best,

G.

A: 

One of these works with most compilers, since Fortran 77:

implicit none

or

implicit undefined(a-z)

Real is architecture dependent; the default size is usually modifiable by a command line option.

I don't have any experience linking with Matlab.

wallyk
Thanks for the speedy reply.
Guilherme Rocha
A: 
  1. You can require all variables to be explicitly declared by adding implicit none.
  2. I believe the default "real" data type is a real*4.
  3. You can use a command-line flag -fdefault-real-8 to force all variables declared as real to be interpreted as a real*8

Note (for writing more code, not necessarily trying to solve the current bug): If you're using Fortran 90 code, you can use real(kind=4) or real(kind=8) with gfortran rather than the real*4 or real*8 syntaxes. I've moved away from setting the real or integer size using command-line flags and instead use an integer, parameter :: REAL_SIZE variable to hold the appropriate number (I typically go for 4 or 8 because all the compilers I use support them, but if you want to be very portable you should use the selected_real_kind routine)

Tim Whitcomb
Thanks a lot, especially for the tip on the -fdefault-real-8 flag. Do you know whether there is a -fdefault-real-4 flag as well? I tried it on gfortran but it did not seem to work...
Guilherme Rocha
I don't believe so, as that would be just the default.
Tim Whitcomb
So the default for real is not architecture dependent then?
Guilherme Rocha
No. It is architecture dependent. And be aware of the fact that real kind /= number of bytes to store the value!
kemiisto
+1  A: 

As already stated, in your source code, you can use implicit none. The advantage is that this is portable to all compilers.

With gfortran, you can use the compiler option -fimplicit-none. This advantage is that this will catch variables that you forgot to explicitly type even if you forgot to include implicit none. Most other compilers have a similar option.

Both are highly recommended -- implicit typing is pernicious, and allows the mistake of typos creating unintended variables.

What a plain "real" means is up to the compiler -- if you have specific requirements, it is best to use a more specific declaration. The best way is to define a parameter with the selected real kind intrinsic and use that -- for a similar discussion see http://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind4

M. S. B.
Thanks a lot, especially for the tip on the -fimplicit-none flag
Guilherme Rocha
+1 especially for the compiler option.
kemiisto
+1  A: 

IMPLICIT NONE and compiler option already mentioned.

Let's talk about floating point arithmetic. The problem is that (ss mentioned here) MATLAB constructs both the double-precision (or double) and the single-precision (or single) data types according to IEEE® Standard 754 but Fortran standard doesn't require it's default and double precision real's to conform this standard. As you can see the standard document even use another name (default real, not single-precision).

MODULE kinds

  IMPLICIT NONE

  INTEGER, PARAMETER :: fortran_default = kind(0.0)
  INTEGER, PARAMETER :: fortran_double = kind(0.0D0)
  INTEGER, PARAMETER :: ieee_single = selected_real_kind(7, 38)
  INTEGER, PARAMETER :: ieee_double = selected_real_kind(15, 307)

END MODULE kinds

Here in the first two strings of my kinds specification I've used convenient way to obtain kinds for default real and double precision real. The next two kinds correspond to mentioned IEEE standard.

PROGRAM main

  USE kinds

  IMPLICIT NONE

  REAL(kind=ieee_single) :: is
  REAL(kind=ieee_double) :: id
  REAL(kind=fortran_default) :: fs
  REAL(kind=fortran_double) :: fd

  PRINT *, kind(is), precision(is), range(is)
  PRINT *, kind(id), precision(id), range(id)
  PRINT *, kind(fs), precision(fs), range(fs)
  PRINT *, kind(fd), precision(fd), range(fd)

END PROGRAM main 

The output on my machine (Mac OS X 10.6, gfortran 4.5.1) is:

   8          15         307
   8          15         307
   4           6          37
   8          15         307

So Fortran's default real kind is not equal to IEEE standard single-precision float kind.

So it might be the source of bugs. The precision is lost somewhere, some variable becomes equal to 0.0 instead of being slightly bigger/smaller the 0.0 and then you divide by this value (which is exactly 0.0). Well, it can freeze the program.

kemiisto
Observation >> Speculation - very nice.
Tim Whitcomb
Technically selected_real_kind(7, 38) provides at least 7 digits precision -- it could supply many more if the compiler chooses, so this is not guaranteed to select an IEEE type. If you absolutely must have a IEEE type, there are the new IEEE modules of Fortran 2003 -- but there are not yet commonly supported.
M. S. B.
@ M. S. B.: Your comment is perfectly valid. The idea is to have in Fortran code floating-point numbers with precision at least as IEEE single- and double-precision.
kemiisto