Distinguishing between a variable and a constant - fortran

Okay, before I start: I know this is really bad. I'm asking for a hack for a situation that wouldn't have eventuated if there had been a design agreement that everyone followed. But here is my problem.
I have an enormous Fortran code base with an error reporting routine. The error reporting routine is only called if something weird happened, and it has an integer input: ErrorCode. Positive values mean errors and abort, negative values mean warnings and continue.
Here's my problem:
Some people have taken to call the error reporting function like this:
ErrorCode = -5
call error_report(ErrorCode)
if (ErrorCode /= 0) stop "Hey, you were supposed to reset ErrorCode"
I don't know whether there is any call to that error_report that actually expects a negative ErrorCode to be reset to 0. All I know is that the current implementation of error_report does this, and I don't want to change any functionality.
And other people make it easier on themselves:
call error_report(-5)
At the moment, in the routine, ErrorCode is not declared with any INTENT, just so that the code compiles. But of course this only means that whenever a warning is called in the second way, instead of displaying the warning and keeping working, the program segfaults.
I have neither the time nor the authority at the moment to clean up the code properly (normally I'd just set it to INTENT(INOUT) and then let the compiler tell me where I need to make changes. But this is not an option at the moment for a variety of reasons.)
Is there any way in which I could write a routine error_report that would satisfy both versions? Procedure Overloading? Some method to distinguish between a variable and a constant? Anything?

Here is an idea that should work on any *nix system... The main idea is that constant literals are compiled into the binary as symbols, whereas variables are not.
So if you are using ld for linking, it will insert a symbol _end at the final position (for both static and dynamic linking).
This you can (ab)use to check whether a given dummy argument has an address before or after _end. In case of a lower address, the actual argument is a constant, otherwise it is a (temporary) variable.
This, however requires some C code:
addr.c
int isConstant(int *x){
extern void *_end;
if ( (void *)x > (void *)&_end ) {
return 1; // Variable
} else {
return 0; // Constant
}
}
test.F90
program test
use,intrinsic :: ISO_C_Binding
interface
integer(C_INT) function isConstant(a) bind(C, name="isConstant")
use,intrinsic :: ISO_C_Binding
integer(C_INT), intent(in) :: a
end function
end interface
integer :: i
integer,parameter :: ii=2
i = 1
print *,isConstant(i)
print *,isConstant(1)
print *,isConstant((i))
print *,isConstant(ii)
end program
Compile it as
gfortran -Wall -Wextra test.F90 addr.c
It will give you:
./a.out
1
0
1
0
Note that I did not test this with Windows Tested on Windows using mingw. Use at your own risk.
Please note that the constant expression (i) is not definable as per Standard. However, it is created at runtime, and therefore not a symbol. This is apparent in the output.
However, in the context of the OP, I did not get a segfault when trying to assign it a value.

Related

Are interface blocks ever required to compile Fortran?

I'm trying to teach myself Fortran, and have been messing around with linking multiple files together. Following examples, I have been writing programs in one file, functions in another, and using interface blocks in my main program to refer to the external function.
I was testing how much information was needed in the interface block and realised that I can remove it entirely.
My program:
program test
implicit none
real :: x, y, func
x = 3
y = func(x)
print *, y
end program test
And the function file:
function func(x)
implicit none
real :: x, func
func = x**3
end function func
I then compile it using gfortran -o test test.f90 func.f90 and the code works as expected. My question is, why do I not need to include an interface block in my program file? Is it simply a matter of good practice, or does defining func as a real variable serve as shorthand? I am on Windows, having installed gfortran through minGW.
As an aside/related question, if I instead use a subroutine:
subroutine func(x,y)
implicit none
real :: x,y
y = x**3
end subroutine func
And change the line y = func(x) to call func(x,y) then the code will work fine without any interface block or declaration. Why is this?
The declaration real :: func in the main program here declares func to be a function with (default) real result. This function has an interface in the main program as a result, so it is legitimate to reference that function with y = func(x).
The interface in this case is implicit. In this way, the main program knows exactly three things about func:
it is a function (with that name);
it has the external attribute;
it has real result.
The reference to the function is compatible with that knowledge. Further, how you reference the function matches precisely the properties of the function itself.
Equally, in the case of the subroutine, a call func(x,y) tells the main program exactly three things, again with the implicit interface:
it is a subroutine (with that name);
it has the external attribute;
it takes two real arguments.
Those three things again match the subroutine's definition, so things are fine.
Loosely, then, you don't need an interface block in these cases because the implicit interfaces are good enough.
There are times when an explicit interface is required and in most (nearly all) cases an explicit interface is better. As you can see in other questions and answers, there are usually better ways to provide an explicit interface than using an interface block.
Why do I not need to include an interface block in my program file?
Since Fortran 90, the recommended way to define reusable functions and subroutines is to use modules.
module func_m
contains
function func(x)
implicit none
real :: x, func
func = x**3
end function func
end module func_m
Then write use func_m in the main program, before implicit none: gfortran -c func_m.f90, gfortran -c test.f90 and gfortran -o test test.o func_m.o.
When you use modules, the compiler will check the type of the arguments of the functions. You also do not need to declare real :: func as the declarations are taken from the module.
When you compile as a "simple" object file, the compiler will simply call whatever function is named func without verification, as long as such a function is given in an object file.
The interface block is a kind of "in between". In your case, you could add one in the program file. This would force you to follow that declaration in the program. But it will not prevent linking to wrong functions at link time: there is no guarantee that the interface is right. It is mostly useful if you need to call C or FORTRAN 77 code from someone else, for which you couldn't use modules.
And change the line y = func(x) to call func(x,y) then the code will
work fine without any interface block or declaration. Why is this?
The interface issue is orthogonal to the function vs subroutine issue.
There are some cases where interface blocks are needed. For example if the called subroutine uses a pointer, allocatable or assumed shape arrays (this list is not complete, see the standard for more):
integer, pointer :: x(:,:) ! pointer attribute
integer, allocatable :: x(:,:) ! pointer attribute
integer :: a(:,:) ! assumed shape array
The pointer/allocatable have the advantage that the called subroutine can allocate it for the calling function. Assumed shape arrays automatically transfer the dimensions to the called subroutine.
If you use any of this your program will crash without explicit interface. Easiest solution is like said in the other answer: use modules to have the interface automtically correct. We use a perl script automatically extracting interfaces to have interface check without rewriting the code to modules (and avoid long compile times until all compilers reliably support Fortran 2008 submodules...)

SAVE attribute needed for Fortran variables when only the C_LOC address is returned to a C program?

Normally, the SAVE attribute is used in Fortran type declarations so that the variable retains its value at the end of a subprogram, such as described by the answers to the SO question here. However, I recently gave an example at another question for how a Fortran function can be written that returns only the C address of an allocatable character string constant to a C calling program, with the C_LOC intrinsic and other ISO_C_BINDING features of F2003. Should the SAVE attribute be used on the Fortran allocatable string constant to avoid potential issues?
Although I didn't use SAVE, the function worked as intended: the C program uses a char* to point at the address returned by the Fortran function, which could then be used as normal (e.g., for printing and with strlen()). No warnings/errors were generated. Also, this seems consistent with how I have seen C_F_POINTER used in the compiler docs and the examples at a related SO question (that is, the target values did not have the SAVE attr).
Particularly since the Fortran function was called from C, it's not clear to me whether this process exhibits the expected behavior, or if it could/should have failed, or if this is a vendor-specific implementation detail. The Intel Fortran 17 documentation for SAVE (here) seems to indicate that a string constant (allocatable or not?) is saved by default, but I am not sure if I'm reading this right, or how/if this info holds up in the current context. Am I performing this process in a portable, correct manner?
Although I linked to the code already, here are the important bits:
! f_string.f90: returns the C address to an allocatable string constant:
function get_string() bind(c, name='get_string')
use, intrinsic :: iso_c_binding
implicit none
type(C_PTR) :: get_string
character(len=:), allocatable, target :: fortstring ! <- Include SAVE?
fortstring = "Hello StackOverflow" // C_NULL_CHAR ! <- NULL-terminated string constant
get_string = C_LOC(fortstring)
end function get_string
// c_string.c: uses a char* to point at the address returned by 'get_string'
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *get_string(void); // <- Fortran fcn signature
int main(){
char *mycharptr;
mycharptr = get_string();
printf("String from Fortran: %s\n", mycharptr);
printf("len = %d\n", strlen(mycharptr));
return 0;
}
Compiled as ifort /c f_string.f90, icl c_string /link f_string.obj.
That is correct. Save is necessary.
All allocatable entities are deallocated when the procedure exits unless they are save.
You can use pointer instead of allocatable and the target will not be automatically deallocated. I find it better than save because of possible multiple calls to the procedure.
Your program probably "worked" because although the memory block was deallocated, it was not overwritten. So the C procedure still found meaningful data, but at address it was not allowed to access. But this access is not always checked by the OS memory protection.

error: 'x' argument pf 'dtime' intrinsic at <1> must be of kind 4

My understanding of programming is very limited so I hope I am making sense.
I made a change to a fixed variable in a program (the program is called NAFnoise; I was using the .exe but it came with the source code and I made the change there). The program is written in Fortran and is in multiple files. I am using gfortran to compile it and most of the files works without a problem. One file, however, is giving me trouble. And I didn't even make changes to it. It is giving error messages that is like this:
error: 'x' argument pf 'dtime' intrinsic at <1> must be of kind 4
The same message appears for etime. The only times those (I am guessing they are) functions and variables inside them are referenced as shown below:
IMPLICIT NONE
! Local variables.
INTEGER(4) :: klo,khi,i,n_in,nvar,nj,j1,j2,ivar,nok,nbad
REAL(DbKi) :: kk2, Isumwell, Isum, Itot,eps,h1,hmin
REAL(DbKi) :: ys1,ys2,poverall,phipot
REAL(DbKi) :: bigben(2),bigben2(2),dtime,etime
REAL(DbKi) :: phif(10)
COMPLEX(DbKi) :: value,dval1,dval2,dval11,dval12,dval22
COMPLEX(DbKi) :: btrans,btrans1,btrans2,btrans11,btrans12,btrans22
COMPLEX(DbKi) :: bbb,bbb1,bbb2
and
write(*,*) etime(bigben2),dtime(bigben)
and
write(*,*) etime(bigben2),dtime(bigben)
I am guessing the program was found when the author included it in the source folder, so I am not sure what went wrong. The variable I change should have nothing to do with this. Does it have something to do with the compiler? How can it be fixed?
DTIME is a non-standard GNU function described in the manual https://gcc.gnu.org/onlinedocs/gfortran/DTIME.html. It requires an argument to be of kind 4. That is the single precision under the default settingd for gfortran.
Probably, DbKi means double precision instead for you. Change
REAL(DbKi) :: bigben(2),bigben2(2),dtime,etime
to
REAL :: bigben(2),bigben2(2)
(or real(4)) if you use the GNU intrinsic extension.
If you actually want to call some your own external dtime, you must declare an interface block for it.
The same holds for etime from https://gcc.gnu.org/onlinedocs/gfortran/ETIME.html

Is it possible to load built-in functions with a USE statement?

I'm currently toying around with passing functions as arguments.
In the program below I use the built-in function EXP as an argument for
the integral function. My compiler gives me the following error:
integrate1.f90:22.26:
r = integral(-1.0,1.0,EXP,1000);
1
Error: Expected a procedure for argument 'f' at (1)
If I uncomment the usage of EXP on the declaration of the variable r I don't get this error.
So it seems that if I don't use a built-in function I cannot use it as an argument
which is kind of weird, cause "built-in" kind of suggests the function is loaded no matter what.
How can I prevent this error without explicitly using the EXP function? Do I need to use the USE statement to load built-in's? If there is no other way around this, I would be interested to know if this is due to the Fortran specification or a compiler issue?
I am using GNU Fortran (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3.
Example:
MODULE MINTEGRATE
CONTAINS
FUNCTION integral(from,to,f,n)
INTERFACE
FUNCTION f(y); REAL, INTENT(IN) :: y; END FUNCTION
END INTERFACE
REAL :: from,to,integral,width;
INTEGER :: n;
width=ABS(to-from)/n;
integral = 0.0;
DO i=0,n
integral = integral+f(from+width*i)*width;
END DO
END
END
PROGRAM INTEGRATE
USE MINTEGRATE;
!PROCEDURE(EXP), POINTER :: f => EXP; ! using the variable f below works without error
REAL :: r!=EXP(0.0);
r = integral(-1.0,1.0,EXP,1000);
WRITE(*,*) r;
END
"When an intrinsic function is passed as an actual argument to a procedure, its specific name must be used, and when called, its arguments must be scalar. Not all specific intrinsic functions can appear as actual arguments. (For more information, see Intrinsic Functions Not Allowed as Actual Arguments)." From Intel Fortran manual.
You were lucky, because the specific name of the generic exp for single precision real is also exp, but otherwise be careful and pass the right specific function, or write own wrapper calling the generic name. For example, if you wanted default real logarithm, you would have to use alog.
You can inform the compiler that you mean the intrisic function exp by:
intrinsic exp
placed among the declarations in the main program.

Use function inside subroutine in FORTRAN77

I am updating legacy code and I need to use a simple mathematical function inside a subroutine. I cannot figure out how to do this. I have a function that works when called from a test program. What do I need to do differently for a subroutine?
example:
subroutine foo(i,j,k)
i = bar(j,k)
stuff = otherstuff
return
end
other info:
bar is an erf approximation.
I am using the PGF90 compiler.
I am new to FORTRAN from C.
thanks!
Basically, calling from a program or a subroutine shouldn't differ. Does the code really look like this, without any declarations? This means all variables will have implicit types: variables with names starting with the letters i-n will be integer, all others real; this also holds for function return values. The code you show, tries to assign a real (bar()) to an integer (i).
If you're writing new code, always start programs and procedures with IMPLICIT NONE. This forces you to explicitly include type declarations for all variables and function return values, greatly reducing errors.