Is my local variable getting overwritten to garbage? - fortran

If I call my function like this:
t = calcMonth(month)
and the corresponding function is
real function calcMonth(m)
real b, m
b = 10
calcMonth = b*m
Does my variable m get overwritten to garbage value?

Responding to your comment
i thought by declaring the variable 'm' locally it gets rid of the passed value of 'm'
When you say (cut down for clarity)
real function calcMonth(m)
real m
end function
you are not declaring a local variable m in the function. Instead you are declaring the type of the dummy argument m. Indeed, doing this declaration is the only sane way to declare types and attributes of dummy arguments. [Discussion of sanity outside the scope of this answer.]
Whilst reusing an identifier for a local variable can obscure other externally defined objects, it simply isn't allowed for dummy arguments.
I'd be very scared of a language tutorial which didn't make these features clear, but I'll speculate as to why there may be some confusion.
It may be that when one has
real function calcMonth(m)
calcMonth = 10*m ! Oh look, we are using the dummy m
end function
this looks very different from
real function calcMonth(m)
real m ! Hmmm, a local m
calcMonth = 10*m ! Oh noes, which m am I using?
end function
These are potentially different, but the only difference is that in the first m - the dummy argument - is being implicitly typed, in the second m - still the dummy argument - is being explicitly typed. [With the default implicit typing rules m would be integer, so this is the potential difference alluded to before.]
Some languages allow one to specify types and attributes (or equivalent) like
real function calcMonth(integer m)
but Fortran isn't one of those. Crucially, also, the type of the dummy argument doesn't come from the actual argument.
integer month
call calcMonth(month)
end
real function calcMonth(m)
real m
calcMonth = 10*m ! Still the dummy m
end function
is still not declaring a local variable m - with the thought that the dummy m is previously declared an integer, or somehow is the actual argument month, and so the type mismatch means it must be a new variable - and most likely at run-time something unwanted will happen.

Related

Equivalence between declaring a function with data type or inside its body [duplicate]

Below is a sample code that addresses the problem I am having. The error message I am getting is
Function result 'sample' at (1) has no IMPLICIT type.
I label where line (1) is below.
I tried to follow this other question, however I wasn't able to figure it out. This function is within a module in my program and I made sure that the module has contains and I end the module after this function.
I also use implicit none in this function so I'm not sure why I get this message. How can I fix this error message?
Adding Real or Complex in front of function works, but I don't really get why. Shouldn't I only be able to use complex since the arrays are complex inside the function? Which is more suitable for my actual function? Both yield no compilation errors.
real function Sample(func) !this is line (1)
!complex function Sample(func)
implicit none
integer :: n,m
real :: x,y
complex, dimension(-9:9,-9:9), intent(in) :: func
complex, dimension(-9:9,-9:9) :: LocalF
LocalF = func
do n=-9,9
do m=-9,9
x = real(n)*0.2
y = real(m)*0.2
LocalF(n,m)= cmplx(z1(x,y),z2(x,y)) !assume z1,z2 are well defined
end do
end do
end function Sample
In Fortran every function has a result. If you like you can think of the result as a value returned by the function. Like every other value in a Fortran program a function result has a type, and a kind and a rank too.
By default the function result has the same name as the function itself, and its declaration is prepended to the function declaration. For example, here
integer function add(m,n)
integer, intent(in) :: a,b
add = a+b
end function
the function is called add and you can see (a) that the result is of type integer (and of default kind and scalar) and (b) that the result is formed by adding the two arguments together.
For functions returning arrays this syntax is not available, so you couldn't write something like
integer(1:4) add_vec(m1,m2)
In such cases you have to explicitly define the name (and later type and kind) of the result variable. Sticking with the simple example, something like
function add(m,n) result(addvec)
integer, intent(in) :: a(4),b(4)
integer, dimension(4) :: addvec
....
end function
Notice that you don't define the intent of the result.
In OP's case sample is, I think, intended to return a rank-2 array of complex values. I think OP needs to replace
function Sample(func) !this is line (1)
with
function Sample(func) result(LocalF)
and see how that goes. Here, if it is not evident already, you learn that the result name doesn't have to be the same as the name of the function.
Furthermore ... Adding Real or Complex in front of function works, but I don't really get why.
It might work in the sense of compiling, but executing it will lead to tears. By telling the compiler that the function result is either a real or complex value you satisfy the syntactical requirements for a function definition. But without assigning a (real or complex as declared) value to the result variable (called Sample in OP's code) the function will, at best, return junk.
To be as clear as I can ... in OP's original code there were two serious mistakes:
The function (result) was not given an explicit type, which lead to the compiler message shown.
The function did not include setting the value of the result variable, i.e. the variable with the same name as the function (in the absence of the result clause).
Procedures in Fortran come in two types: functions and subroutines. This question is about functions, so I'll consider just those.
What was missing in the first revision, giving the error about the implicit type of the function result1, was the result type.
Adding real function ... or complex function ..., etc., resolves that problem by explicitly giving the type of the function result. The linked documentation gives other ways of doing that.
The function's result is used when the function is referenced. When we have a reference like
func0 = Sample(func)
in the main program, the function Sample is invoked and the function result is defined in its execution. At the end of the function's execution its result is placed in the expression of the reference.
So, if you declare
real function Sample(func)
or
complex function Sample(func)
what you are saying is that the function result is either a real or complex entity. And when the function is evaluated, whatever value Sample had at the end is used in the expression (here assignment).
As a consequence of the function result being returned through Sample (in this case) we need to define its value. The important thing to note for the question, then, is that LocalF is a variable local to the function. If you mean it to be the result of the function you need to use the function result.
You have a number of options:
function Sample(func)
<type>, <attributes> :: sample ! Instead of LocalF
... :: func
end function
or
function Sample(func) result(LocalF)
<type>, <attributes> :: LocalF
... :: func
end function
You can even have
<type> function Sample(func)
<attribute statements for Sample>
... func
end function
but I really suggest you avoid that last one.
1 Note the error here is about type for the function result; in the linked question simply about the function when referenced.

variable declaration (implicit and explicit and advantages & disadvantages)

"What are explicit declaration & implicit declaration of variables in programming language concepts and their advantages and disadvantages?"
An explicit declaration is when you start making the variable by order it first.
ex: String name; name="yourname";
the advantages is you be able to fill your variable with any algorithm or math logic to make a value. the disadvantages is when you use it as a material without fill the value of your variable ,there will be an error.
An implicit declaration is when you make a variable directly without order it first. ex : String name="yourname";
the advantages : it is a practically treatment at some condition.
.
Explicit means declaring variable like in c.
Implicit declaration in variable declaration in python.
In Explicit we should cast.
In implicit no need of casting.
Explicit variable declaration means that the type of the variable is declared before or when the variable is set. Implicit variable declaration means the type of the variable is assumed by the operators, but any data can be put in it.
In C,
int x = 5; printf(x-5); x = "test"; printf(x-5);
returns a compile time error when you set x to test
but in Python,
x = 5; print(x-5); x = "test"; print(x-5);
will "compile" (python doesn't compile, but it will run the program) and give you a runt time error when you try to subtract from the string.
One advantage of Implicit variables is that it makes it easier to write code without worrying about the behind the scenes data type, the compiler should pick the appropriate one based on its future usage.
Another advantage is that you can flexibly type a variable to hold different things that may not even share a parent class. Doing this is risky, as you have no guarantees that the objects will be interpreted correctly by following code.
One disadvantage is that Implicit variables have no guarantees of what they are. A function that computes the difference between two numbers will not return an compile time error if the variables have strings in them. You passed in two variables, it is up to you to ensure they are the right type. It also makes reading code harder in some ways. var nextLocation = LeftHandedSmokeShifter(3.3) is completely legitimate code, but You have to look up the function to even guess what it is doing. string nextLocation = LeftHandedSmokeShifter(3.3) at least tells me that I should be using the output for mathematical operations.
Type heavy languages are always explicitly declared and typed, but type weak languages are mostly implicitly typed. If you can set a variable to "Var" it is likely an implicitly typed language.

How are quantities referenced in Fortran?

I was told a long time ago that in FORTRAN, everything is passed by value. Therefore I would need to do this (provided mySubroutine is suitably defined elsewhere):
double precision :: myArray(2)
myArray(1:2) = (/ 2.3d0, 1.5d0 /)
CALL mySubroutine(myArray)
However, I also found that the program compiles and runs as expected if I do this
CALL mySubroutine((/ 2.3d0, 1.5d0 /))
without needing to define an intermediary array myArray. I thought that I was passing myArray into mySubroutine by reference. What is going on under the hood in the second version? Is the compiler unpacking the subroutine call, declaring a temporary variable only to pass it by reference?
To a large extent, trying to classify Fortran procedure calling with pass-by-reference and pass-by-value is not too helpful. You can find more detail on that in response to questions like this one and this one.
In short, generally procedure references are such that changes to a variable in a procedure are reflected in the variable where the procedure was referenced. In some cases a compiler may choose to do copy-in/copy-out, and in others it effectively must. Equally, the value attribute of a dummy argument specifies that an anonymous copy be made.
Where this question adds something a little different is in the use of an expression such as in
call mySubroutine([2.3d0, 1.5d0]) ! Using F2003 array constructor syntax
Is the compiler creating a temporary variable?
Admittedly, this is perhaps just a looseness in terminology but it's worth saying that there is certainly no variable involved. [2.3d0, 1.5d0] is an expression, not a variable. Crucially this means that it cannot be modified (appear in a variable definition context) in the procedure. Restrictions that apply in the case using an expression rather than a (temporary) variable include:
the dummy argument associated with an expression may not have the intent(inout) or the intent(out) attribute;
if the dummy argument hasn't an intent attribute then that argument may not be modified if the associated actual argument is an expression.
Now, if the dummy argument has the value attribute the effect of the procedure is the same whichever way it is referenced.
To conclude, the program may work just as well with an expression instead of an intermediate variable. If it doesn't that's because of violation of some aspect of Fortran. How it works is a problem for the compiler not the programmer.

What's the difference between a named constant and a static (SAVE) variable, apart from being guaranteed immutable?

Comparing
INTEGER, SAVE :: foo = 3
to
INTEGER, PARAMETER :: foo = 3
in what ways do they behave different? Obviously the latter will trigger a compiler error when somebody attempts to mutate foo, but is this just like the const keyword in C / C++ or does it also imply something about storage location etc.?
The parameter attribute is used to denote a named constant that is set at compile-time and cannot be changed at run-time. As such, it is similar to the const keyword. To cite the Fortran 2008 Standard, Cl. 5.3.13 "PARAMETER attribute":
1 The PARAMETER attribute specifies that an entity is a named constant. The entity has the value specified by its constant-expr , converted, if necessary, to the type, type parameters and shape of the entity.
[...]
2 A named constant shall not be referenced unless it has been defined previously in the same statement, defined in
a prior statement, or made accessible by use or host association.
The save attribute causes a variable to keep state after it gets out of scope, e.g. between consecutive calls to a subroutine or inside a module. Other than that, it behaves like a normal variable and can be changed at run-time. The Fortran 2008 Standard, Cl. 5.3.16 "SAVE attribute" states that
1 The SAVE attribute specifies that a local variable of a program unit or subprogram retains its association status, allocation status, definition status, and value after execution of a RETURN or END statement unless it is a
pointer and its target becomes undefined (16.5.2.5(5)). If it is a local variable of a subprogram it is shared by all instances (12.6.2.4) of the subprogram.
A constant is not a variable in the first place. It does not have any storage (conceptually). You cannot ask for its address. You cannot put it in context where a variable is required. You cannot point pointers at it. You can only use it in expressions.
For example consider
INTEGER, SAVE :: foo = 3
INTEGER, PARAMETER :: bar = 3
then
call sub(foo)
passes the variable foo to the subroutine, while
call sub(bar)
computes an expression (rather simple one), stores its value somewhere, and passes it to the subroutine.
You can also do
INTEGER, PARAMETER :: bar = 3
INTEGER, SAVE :: foo = bar
while
INTEGER, SAVE :: foo = 3
INTEGER, PARAMETER :: bar = foo
won't work. A constant value requires a constant expression.

Can the shape of an array in an interface match multiple fixed array size?

I have multiple subroutines with a parameter p which is an array of explicit size like
subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo
subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar
I'd like to call these two functions through an indirect call, but could not find a way to declare an interface that matches both foo and bar signature...
Using an assumed array size in the interface for example does not work:
subroutine indirect(f,p)
integer,dimension(*),intent(in):p
interface
subroutine f(p)
integer,dimension(*),intent(in) :: p
end subroutine f
end interface
call f(p)
end subroutine indirect
When I invoke foo or bar thru indirect, the compiler (gfortran 4.9.2) complains about shape mismatch for first argument p of f...
integer,dimension(2) :: pfoo
integer,dimension(3) :: pbar
pfoo = (/ 0,1 /)
pbar = (/ 1,2,3 /)
call foo(pfoo) ! direct call is OK
call bar(pbar)
call indirect(foo,pfoo) ! compiler complains about foo signature
call indirect(bar,pbar) ! same for bar...
Compiler error is something like:
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'
Of course, I could modify foo and bar signature to use assumed array size (*) instead of fixed array size, but
it's like I'm loosing some information just for making the compiler
happy without adding any kind of security
foo and bar are not my code and I'd rather not change them...
I've found a workaround, but it consist of writing an assumed size wrapper for each subroutine foo and bar
call indirect(foo_wrapper,pfoo) ! compiler complains about foo signature
call indirect(bar_wrapper,pbar) ! same for bar...
subroutine foo_wrapper(p)
integer,dimension(*),intent(in) ::p
call foo(p)
end subroutine foo_wrapper
subroutine bar_wrapper(p)
integer,dimension(*),intent(in) ::p
call bar(p)
end subroutine bar_wrapper
or eventually, replacing all assumed size by deferred size in indirect and wrapper, so as to give a chance to runtime checks, also works, but that's not the point...
The point is, since I have many such foo/bar isn't there a way to declare the interface properly (I mean without wrappers or other artefacts).
I couldn't decipher the standard (I used http://www.j3-fortran.org/doc/year/10/10-007.pdf - I presume it's around 12.5.2.9 Actual arguments associated with dummy procedure entities ยง2), so I don't know if it's a limitation of gfortran. Right now i haven't any other compiler available, but I'd like to know if some other compiler would compile (intel? - I'm on windows 7 64 bits).
I'll look at whether gfortran is correct to complain and, regardless, what options there are to work around the complaint. References are to Fortran 2008.
12.5.2.9 is indeed important.
If the interface of a dummy procedure is explicit, its characteristics as a procedure (12.3.1) shall be the same as those of its effective argument, except that [inapplicable things]
f in indirect is a dummy procedure with an explicit interface (through the interface block; 12.4.2.1). Looking at the reference 12.3.1 we see
The characteristics of a procedure are .. , the characteristics of its dummy arguments, ..
foo, bar and f are all procedures with a single dummy argument (all called p, by coincidence). So, if foo wants to be the effective argument associated with f then foo's p must match the characteristics of f's p. Each p is a dummy data object, so 12.3.2.2 becomes relevant:
The characteristics of a dummy data object are its type, its type parameters (if any), its shape, ... If a shape, size, or type parameter is assumed or deferred, it is a characteristic.
We have that the type and type parameters match. However, p in f has its size assumed. p in foo does not have this matching characteristic. It is, then, not allowed to associate foo with f in the call to indirect. The same holds for bar.
This requirement for matching characteristics of the dummy data objects to have the same shape also leads naturally to another conclusion: foo and bar don't have matching characteristics as procedures. For a third procedure to match both the shape characteristic must be ignored.
Using a wrapper subroutine is possible, but I'd also think about whether I could change the various subroutines to take assumed-shape arguments. This is much better than assumed-size. But, as you say, I'd also be reluctant to change that code.
For the subroutines foo and bar as you have them, there is another available option. Nothing about those subroutines requires a caller to have an explicit interface for them available (12.4.2.2). So, in indirect you could just scrap the interface block: the rules about matching are much more relaxed (other parts of 12.5.2.9). For other procedures this may not be possible, though.
All that said, ifort appears to happily compile and run the code as you have it...