I wanted to ask some Fortran gurus about this issues I have with an up to date version of the Cray Compiler. I have several warnings that although they do not affect correctness, they will probably do for performance. The warning is:
This argument produces a copy in to a temporary variable.
Here is one of the situations where I get this warning. Within the same file (fem.f90) and module:
call fem( array_local( i, : ), pcor, arcol, inder, &
^
ftn-1438 crayftn: CAUTION FFEM, File = fem.f90, Line = 676, Column = 31
This argument produces a copy in to a temporary variable.
The routine FFEM from where array_local is called looks like:
--------------------------
subroutine ffem( alow, pcor, arcol, inder, iflag )
integer , intent( in ) :: alow(3), pcor(3)
real, intent( in ) :: inder,arcol
integer, intent( out ) :: iflag
integer:: array_local(5,3)
! within in a loop
call fem( array_local( i, : ), pcor, arcol, inder, &
..........
--------------------------
And here is fem subroutine:
--------------------------
subroutine fem (ac, pc, rc, id, flag )
integer, intent( in ) :: ac(3)
.......
--------------------------
I cannot find the way to get rid of that copy in which will definitely slow down my code. I was wondering, does anyone know why this happen, and how can I fix it?
If array_local must be defined as it is and you cannot define it as (5,3) as brady shows, you can consider an assumed shape dummy argument
subroutine fem (ac, pc, rc, id, flag )
integer, intent( in ) :: ac(:)
array passed there can be non-contiguous and still there is no copy, ac will be non-contiguous (strided) too.
You need explicit interfaces for that. That is best achieved by placing the subroutines in a module.
The feasibility of this change depends on your use of array_local elsewhere, but you could swap the order:
integer:: array_local(3,5)
and then call fem:
call fem( array_local( :, i ), pcor, arcol, inder, &
This will allow the compiler to simply send a reference to the appropriate part of the array_local array since columns are ordered contiguously in memory.
Related
I have the following code which is producing a segmentation fault. It does complain that
forrtl: severe (408): fort: (7): Attempt to use pointer TT when it is not associated with a target
Now I am pretty sure what the reason is, namely, it is trying to access my copy assignment routine, while I am just trying to initialise the object.
By commenting out generic :: assignment(=) => copy it works fine!
I am compiling the code as follows : (IFORT version 19.0.3)
ifort -O0 -debug full -check all -traceback -g -C -CB -CU -CA -fpp filaname.f90
and running by ./a.out
module md
implicit none
type T_TEST
integer :: ii
contains
procedure, pass(this) :: COPY
generic :: assignment(=) => copy
end type
interface t_test
module procedure init
end interface t_test
type(t_test) , allocatable :: tt
contains
function init( size )
integer, intent(in) :: size
type(t_test) , allocatable :: init
allocate( init )
init% ii = size
end function
subroutine copy(this, old )
class(t_test), intent(out) ::this
type(t_test), intent(in) :: old
this% ii = old% ii
end subroutine
end module md
program t_Testprogram
use md
implicit none
tt = t_test( 100 )
end program t_Testprogram
The reason is that the overloaded assignment copy does not support allocatable left hand sides. So when the value of this is used in this% ii = old% ii , it actually does not exist and a null pointer is used. But I do agree the Intel's error message is confusing or even incorrect.
The automatic left hand side (re-)allocation only applies to intrisic assignments, not to user defined ones. In user-defined ones you must program yourself the exact behaviour. And you did not specify anything for not-allocated left hand sides.
This works for me:
type T_TEST
integer :: ii
end type
interface assignment(=)
procedure copy
end interface
subroutine copy(this, old )
class(t_test), allocatable, intent(out) ::this
type(t_test), intent(in) :: old
if (.not.allocated(this)) allocate(this)
this% ii = old% ii
end subroutine
Or you can just allocate the object first (that is what I would do here because gfortran seems to not like generic resolution based on the allocatable attribute - a F08 feature).
allocate(tt)
tt = t_test( 100 )
It seems that you are thinking that just because the constructor has its result variable "marked" allocatable, it will allocate the left hand side of the assignment for you. It is not so. The only thing it does it that it allocates its own result as a temporary variable. This result is then assigned in tt = t_test() and then deallocated automatically.
Remember, the result variable is not the same as the left hand side of the assignment. The result can be used in an expression of many different types, not just in an assignment. It can be passed to a subroutine, it can be used in an arithmetic expression, it can be printed...
Your constructor can be just
function init( size )
integer, intent(in) :: size
type(t_test) :: init
init% ii = size
end function
and the result will be exactly the same. There is no reason to make it allocatable, it just complicates it, but does not change the result in the slightest.
Maybe what you are trying to follow some C++ RAII principles, but remember, C++ is simply not Fortran.
I am new to Fortran and I am trying on the common block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power is by default a single precision variable, but why declaring power as double precision in the function is not enough? And why writing real * 8 power in main would not work either?
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program and also is not part of any module, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p will be default real type (in your compiler, it is real(4)). As you declared the function result as real*8, that your compiler interpret as real(8) (see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable, optional, pointer, target, asynchronous, volatile or value; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental and, if pure, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify an interface for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program, after contains. This is recommended only if you don't plan to reuse this function in other program units. #IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8 is non-standard and should be avoided.
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian#eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian#eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian#eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian#eris:~/work/stackoverflow$
In fortran, we can define default arguments. However, if an optional argument is not present, it can also not be set. When using arguments as keyword arguments with default values, this leads to awkward constructs like
PROGRAM PDEFAULT
CALL SUB
CALL SUB(3)
CONTAINS
SUBROUTINE SUB(VAL)
INTEGER, OPTIONAL :: VAL
INTEGER :: AVAL ! short for "actual val"
IF(PRESENT(VAL)) THEN
AVAL = VAL
ELSE
AVAL = -1 ! default value
END IF
WRITE(*,'("AVAL is ", I0)') AVAL
END SUBROUTINE SUB
END PROGRAM PDEFAULT
Personally, I often ran into the problem of accidentially typing VAL instead of AVAL, i.e. the disconnect between the variable name in the interface, and the initialized value used in the code can introduce runtime bugs – let alone that this manner of initialization is rather verbose.
Is there some more elegant way of using optional arguments with a default value?
Example It would feel more natural to write something like
IF(NOT(PRESENT(VAL))) VAL = -1
because it avoids the VAL vs AVAL confusion. But it isn't valid, presumably because Fortran passes arguments by reference and thus if VAL is not present in the CALL statement, no memory is associated with VAL and VAL = -1 would cause a segfault.
You described the situation rather well. There is no other way I am aware off and that is standard conforming. The pattern with a local variable named similarly is what people often use. The other option is to just put if (present()) else everywhere, but that is awkward.
The point is that they are optional arguments, not default arguments. Fortran doesn't have default arguments. The may have been better, but that is not what the committee members have chosen in the 80s when preparing Fortran 90.
While also looking into this, I found out that you can in fact do something like the proposed example using the OPTIONAL and VALUE attributes (at least with gfortran, not sure how different compilers might handle it). E.g.:
PROGRAM PDEFAULT
CALL SUB
CALL SUB(3)
CONTAINS
SUBROUTINE SUB(VAL)
INTEGER, OPTIONAL,VALUE :: VAL
IF(.NOT. PRESENT(VAL)) VAL = -1 ! default value
WRITE(*,'("VAL is ", I0)') VAL
END SUBROUTINE SUB
END PROGRAM PDEFAULT
This was implemented in version 4.9 of gfortran. And here's the relevant explanation in the documentation for argument passing conventions:
For OPTIONAL dummy arguments, an absent argument is denoted by a NULL
pointer, except for scalar dummy arguments of type INTEGER, LOGICAL,
REAL and COMPLEX which have the VALUE attribute. For those, a hidden
Boolean argument (logical(kind=C_bool),value) is used to indicate
whether the argument is present.
I also found this discussion interesting as historical context.
Maybe somebody more knowledgeable might have comments on whether doing this is a bad idea (aside from being compiler dependent), but at least at face value it seems like a nice workaround.
Note that this behavior is not part of the Fortran standard, and depends on the implementation of a given compiler. For example, the example code segfaults when using ifort (version 16.0.2).
The Fortran standard lib (https://github.com/fortran-lang/stdlib) provides a function called optval that is used in stdlib_logger for example:
subroutine add_log_file( self, filename, unit, action, position, status, stat )
...
character(*), intent(in), optional :: action
...
character(16) :: aaction
...
aaction = optval(action, 'write')
...
end subroutine add_log_file
So their way of representing the "actual" value is a prepended a.
IMHO, I like the option with an appended _, since the optional values are visually marked as such in the call signature.
Whilst I certainly wouldn't advocate doing so in most situations (and indeed you can't in some situations), one may sometimes use an interface to provide a single entry point for multiple routines with different required arguments rather than using an optional argument. For example your code could be written like
MODULE subs
implicit none
public :: sub
interface sub
module procedure sub_default
module procedure sub_arg
end interface
contains
SUBROUTINE SUB_arg(VAL)
INTEGER :: VAL
WRITE(*,'("VAL is ", I0)') VAL
END SUBROUTINE SUB_arg
SUBROUTINE SUB_default
integer, parameter :: default = 3
CALL SUB_arg(default)
END SUBROUTINE SUB_default
END MODULE SUBS
PROGRAM test
use subs, only: sub
call sub
call sub(5)
END PROGRAM TEST
Again, I don't recommend this approach, but I thought I should include it anyway as an alternative way of providing something that looks like a default.
Another possibility is to use an associate block which associates the local variable name with a variable of the same name as the optional argument eg.
SUBROUTINE SUB(VAL)
INTEGER, OPTIONAL :: VAL
INTEGER :: AVAL ! short for "actual val"
IF (PRESENT(VAL)) THEN
AVAL = VAL
ELSE
AVAL = -1 ! default value
END IF
ASSOCIATE (VAL => AVAL)
WRITE(*,'("VAL is ", I0)') VAL
END ASSOCIATE
END SUBROUTINE SUB
Not ideal but allows you to use the same variable name for the argument and in the body of the routine. I shudder to think of the amount of untidy code I've written coping with the lack of default values for optional arguments - roll on F202X.
I hope Fortran to support a popular syntax like
subroutine mysub( x, val = -1 )
integer, optional :: val
or in a more Fortran style
subroutine mysub( x, val )
integer, optional :: val = -1 !! not SAVE attribute intended
but this seems not supported (as of 2016). So some workaround needs to be done by the users' side...
In my case, after trial-and-errors, I settled down to attaching one underscore to the optional dummy argument, so doing something like (*)
subroutine mysub( x, val_)
integer, optional :: val_
integer val
Other people seem to like the opposite pattern (i.e., dummy variable => sep, local variable => sep_, see split() in StringiFor, for example). As seen in this line, the shortest way to set the default value is
val = -1 ; if (present(val_)) val = val_
But because even this line is somewhat verbose, I usually define a macro like
#define optval(x,opt,val) x = val; if (present(opt)) x = opt
in a common header file and use it as
subroutine mysub( x, val_, eps_ )
integer :: x
integer, optional :: val_
real, optional :: eps_
integer val
real eps
optval( val, val_, -1 )
optval( eps, eps_, 1.0e-5 )
print *, "x=", x, "val=", val, "eps=", eps
endsubroutine
...
call mysub( 100 )
call mysub( 100, val_= 3 )
call mysub( 100, val_= 3, eps_= 1.0e-8 )
However, I believe this is still far from elegant and no more than an effort to make it slightly less error-prone (by using the desired variable name in the body of the subroutine).
Another workaround for a very "big" subroutine might be to pass a derived type that contains all the remaining keyword arguments. For example,
#define getkey(T) type(T), optional :: key_; type(T) key; if (present(key_)) key = key_
module mymod
implicit none
type mysub_k
integer :: val = -1
real :: eps = 1.0e-3
endtype
contains
subroutine mysub( x, seed_, key_ )
integer :: x
integer, optional :: seed_
integer :: seed
getkey(mysub_k) !! for all the remaining keyword arguments
optval( seed, seed_, 100 )
print *, x, seed, key% val, key% eps
endsubroutine
endmodule
program main
use mymod, key => mysub_k
call mysub( 10 )
call mysub( 20, key_= key( val = 3 ) )
call mysub( 30, seed_=200, key_= key( eps = 1.0e-8 ) ) ! ugly...
endprogram
This might be a bit close to what is done by some dynamic languages under the hood, but this is again far from elegant in the above form...
(*) I know it is often considered ugly to use CPP macros, but IMO it depends on how they are used; if they are restricted to limited extensions of Fortran syntax, I feel it is reasonable to use (because there is no metaprogramming facility in Fortran); on the other hand, defining program-dependent constants or branches should probably be avoided. Also, I guess it would be more powerful to use Python etc to make more flexible preprocessors (e.g., PreForM.py and fypp and so on), e.g., to allow a syntax like subroutine sub( val = -1 )
Here is an elegant (i.e., short, clear, standard-conforming) solution:
subroutine sub(val)
integer, optional :: val
write(*,'("aval is ", i0)') val_or_default(val, default=-1)
end subroutine
integer function val_or_default(val, default)
integer, optional, intent(in) :: val
integer, intent(in) :: default
if (present(val)) then ! False if `val` is is not present in `sub`.
val_or_default = val
else
val_or_default = default
endif
end function
This uses the fact that optional arguments can still be passed to a function, even when they are not present,
so long as the corresponding dummy argument is also optional.
There is at least one generic implementation of val_or_default on GitHub
for all intrinsic data types.
(They call it optval.)
I was doing an svd decomposition of a square matrix A, with A=U S Vdag, and in the fortran code, the line reads
lwork = -1
call zgesvd( 'A', 'A', A%d, A%d, A%m, A%d, S, U%m, U%d, Vdag%m, Vdag%d,work, lwork, rwork, info )
lwork = int(work(1));deallocate(work); allocate(work(lwork))
call zgesvd( 'A', 'A', A%d, A%d, A%m, A%d, S, U%m, U%d, Vdag%m, Vdag%d,work, lwork, rwork, info )
When I compiled with gfortran, it went through with no error or warning. However when I run the program, it shows error with message:
" ** On entry to ZGESVD parameter number 11 had an illegal value "
I could not figure out what went wrong.
For reference, the definitions of the parameters:
type cmatrix
integer(4) d
complex(8), allocatable :: m(:,:)
end type
type (cmatrix) A,U,Vdag
allocate(A%m(dim,dim),U%m(dim,dim),Vdag%m(dim,dim))
A%d = dim; U%m = dim; Vdag%d = dim
real(8) S(dim)
Thanks in advance!
Xiaoyu
p.s. It should be mentioned that such a program runs smoothly when compiled with ifort, but gfortran gives an runtime error as shown above
--- Problem solved!
It seems that the issue lies in how ifortran and gfortran allocates memory. I defined in the code USV type which:
type USV
integer is_alloc
type (cmatrix) U,V
real(8), allocatable :: S(:)
end USV
When initializing by
type(USV) Test_usv(:)
allocate(Test_usv(3)),
the value of is_alloc is 0 using intel fortran compiler, while arbitrary number for gfortran. I need to use this value as a criterion for allocating U V matrices:
if (is_alloc.eq.0) then
allocate(U%m(dim,dim))
end if
The fundamental problem is not a difference between ifort and gfortran. Your approach to the initialization of the variables isn't valid Fortran. Unless you initialize a variable with a declaration, assignment statement, etc., its value is undefined. One way to fix this would be to add a default initialization to the type definition:
type USV
integer is_alloc = 0
type (cmatrix) U,V
real(8), allocatable :: S(:)
end USV
Another approach would be to not track the allocation status yourself and to rely upon the intrinsic function that Fortran provides for this purpose:
if (.NOT. allocated (U%m) ) allocate(U%m(dim,dim))
P.S. Best practice is not to rely upon specific numeric values for kinds. The kind values are arbitrary and are not necessarily the number of bytes of the type. Some compilers use the number of bytes, others don't. One method to specify the number of bytes and to have portable code is to use types provided by the ISO Fortran environment:
use, intrinsic :: ISO_FORTRAN_ENV
integer(int32) :: d
real(real64), allocatable :: S(:)
The types are named after the number of bits. A list of the available types is in the "Intrinsic Modules" chapter of the gfortran manual.
I'm sorry if this is a trivial question. My fortran-fu is poor.
Is there a way in Fortran to pass the array length? Using common (which, from what I gather is equivalent to global) is an option as well. What I want is in the main program to call a function with an array. For example (This is typed in, not copy pasted from anywhere)
program prog
integer num
double precision x(num),v
double precision test
....
v=test(x,num)
....
function test(x,num)
double precision test
integer num
double precision x(num)
test=0.0d0
....
return
end
This won't compile since num is not a constant. The important thing is to know what the array size I'm passing is.
Edit: I'm using the GNU Fortran 95 compiler.
Edit2: I tried High Performance Mark's solution without luck:
program prog
integer v
parameter (v=10)
double precision x(v),test,k
k=test(x)
write (*,*) size(x)
stop
end
function test(x)
double precision, dimension(:),intent(in) :: x
double precision test
write (*,*) size(x)
test = 0.0d0
return
end
The output should be two lines where 10 is written. Instead I got this:
/scpc:niels: #$ f95 err.f
/scpc:niels: #$ ./a.out
0
10
/scpc:niels: #$
Fortran arrays 'know' how long they are, you shouldn't need to pass the array and its length as different arguments. (Unless, that is, you are interfacing with old Fortran codes.) Today you'd write something like this
function test(arr)
real, dimension(:), intent(in) :: arr
...
integer :: arrsize
...
arrsize = size(arr)
...
If you have to interface to old code in which array sizes are passed you can make calls like this
call old_fortran_subr(array, size(array, 1), other_arguments)
Oh, and while I'm writing, have nothing to do with common in any code you write from scratch, it's a (rightly) deprecated feature from the 70's and earlier. Instead use module variables.
OK, there's a lot going on here, especially as the Fortran style you are using is a little archaic. Let's do it by steps ...
Firstly make sure you always use implicit none
Secondly if you know the size of the array a priori you can use a symbolic constant to denote its size. You do this via a parameter:
Program prog
Implicit None ! ALWAYS USE THIS
Integer, Parameter :: num = 36
Double Precision x( num )
Double Precision test
Double Precision v
Call Random_number( x )
v = test( x, num )
Write( *, * ) v
End Program prog
Function test( x, num )
Implicit None ! ALWAYS USE THIS
Double Precision test
Integer num
Double Precision x( num )
Integer i
test = 0.0d0
Do i = 1, num
test = test + x( i ) * x( i )
End Do
End Function test
[luser#cromer stackoverflow]$ gfortran -O -std=f95 -Wall -Wextra -pedantic func.f90
[luser#cromer stackoverflow]$ ./a.out
12.129812171430215
Note how num is set to be 36, but the parameter bit means I can not change its value - it is a constant and so can be used to set the size of arrays.
And that is how things stood until 1990. Then a number of things came into the language which change the answer. Most directly connected to your question are allocatable arrays, which allow you to specify the size of the array at run time, and assumed shape arrays, which make passing arrays to subprograms simpler. However a whole slew of other things came in and I suggest you have a look in a book to learn about them - the new language is much more expressive and safer than the old. As an example I would write the above nowadays as something like
[luser#cromer stackoverflow]$ cat func.f90
Module numbers_module
Integer, Parameter :: wp = Selected_real_kind( 12, 70 )
End Module numbers_module
Module funcs_module
Use numbers_module
Implicit None
Public :: test
Private
Contains
Function test( x ) Result( sum_sq )
Implicit None ! ALWAYS USE THIS
Real( wp ) :: sum_sq
Real( wp ), Dimension( : ), Intent( In ) :: x
sum_sq = Sum( x * x )
End Function test
End Module funcs_module
Program prog
Use numbers_module
Use funcs_module
Implicit None ! ALWAYS USE THIS
Real( wp ), Dimension( : ), Allocatable :: x
Real( wp ) :: v
Integer :: num
Write( *, * ) 'How many elements ?'
Read ( *, * ) num
Allocate( x( 1:num ) )
Call Random_number( x )
v = test( x )
Write( *, * ) v
End Program prog
[luser#cromer stackoverflow]$ gfortran -O -std=f95 -Wall -Wextra -pedantic func.f90
[luser#cromer stackoverflow]$ ./a.out
How many elements ?
39
14.151818513394156
If you decide to go this way make sure you understand why to use this method an interface to test needs to be in scope at the calling point - and to do this read a book.
Oh. Common. Just Say No.
Implicit variable declaration was used in earlier versions of Fortran. By this method of variable could simply be used without declaring it explicitly. One statement such as IMPLICIT REAL(A-H, O-Z ) would declare all real variables beginning with letters A-H and O-Z. This is now considered to be too loose and explicit type declaration such as is required by the more powerful language C is to be preferred. My first language was FORTRAN IV but the second language I learned was QBasic which like C requires that all variables be declared explicitly before use.