I know that in Fortran 90 the symbol for greater than (for example) has been changed from .gt. to >. Is this the case also for other logical expressions like .and. and .or.? Are there equivalent symbolic expressions for these as well?
No there are no such symbols nor have I noticed any interest or need from anyone who would call for such symbols before reading your question. So no, there are none in Fortran 90, none in Fortran 2018 and there are no plans for them for future Fortran AFAIK.
With I fort there is == and /= but many will point to 'non standard' as a rebuttal.
I use them routinely.
Related
I'm very new at Fortran. I'm trying to compile this Fortran, I think 90??? Code. I'm using visual studio with the intel compiler.
The following code is giving me an error 5082. I have absolutely no idea why. Like literally no clue. Please, please help.
integer function Dub(n)
integer n
Dub = 2*n
return
end
program Subroutines
implicit none
! Variables
integer n
n = 5
! Body of Subroutines
write(*,*) n
Dub(n)
write(*,*) 'Press Enter to Exit'
read(*,*)
stop
end program Subroutines
In Fortran a call to a function, or a subroutine, must be part of a statement (or an initialization expression, but that's more advanced). name(argument[s]) by itself is not a statement, unlike some other languages such as C, C++ and Java. A function call must be in an expression, and a subroutine call must use the call keyword. See https://en.wikibooks.org/wiki/Fortran/Fortran_procedures_and_functions for examples.
Changing that line of your program to n = Dub(n) would make it legal, but rather useless. That function does nothing except return a value, and your main program does nothing useful with the value returned. Generally you call a function because you want either a side effect from executing the function, or to use the returned value, or both.
I'm new to Fortran. I was given a file that is supposed to be in Fortran 90, but written to be compiled with the Lahey Fujitsu compiler (the sparse documentation states that it should be compiled with lf95 filename.f -out compiled_name #imsllf95.cmd). However, some lines are commented with c, which as I understand was the way to comment in Fortran 77. Also, matrices are declared like REAL*8, DIMENSION(23,8) :: xxx19, which again I think is from Fortran 77.
For the most part, I can compile the file with gfortran or ifort except for a section that requires the computation of a matrix inverse. Apparently, in the LF95 compiler (using a propietary module IMSLF90), a matrix inverse was computed with .i.. If I delete those inversions, the file compiles and runs with no problem (apart from the fact that it gives the wrong result).
I'm trying to find the version of Fortran this code is written in, so that I can then search for some code written in that same version so that I can invert the matrices in the code.
EDIT: The file has extension .f, even though the compiling instructions seem to imply that it is Fortran 95.
Here I have some sections of the code:
PROGRAM estimate_group
implicit none
INTEGER :: i,j,k,full,group1
REAL*8, DIMENSION(500) :: theta_start,theta_input
OPEN(68, STATUS="REPLACE",file='fit_measures.txt')
c OPEN(68, file='fit_measures.txt')
REWIND(68)
DO full=1,1
PRINT *, "=================================="
PRINT *, "FULL LOOP #: ", full
PRINT *, "=================================="
WRITE(68, *) "=================================="
WRITE(68, *) "FULL LOOP #: ", full
WRITE(68, *) "=================================="
DO group1=2,28
c Additional If statement to focus on top level and scale
c IF ( ((group1>=22) .AND. (group1<=28)) .OR. (group1==2)) THEN
IF ( group1==2) THEN
c READING IN THETA VECTOR FROM PREVIOUS ITERATIONS
c (starting values taken from prior runs theta output)
c ====================================================
IF ((group1==2) .AND. (full==1)) THEN
theta_input=0.0*theta_input
OPEN(67, file='theta_input1.txt')
REWIND(67)
DO i=1,500
READ(67,*) theta_input(i)
END DO
ELSE
theta_input=0.0*theta_input
OPEN(66,file='theta_input.txt')
REWIND(66)
DO i=1,500
READ(66,*) theta_input(i)
END DO
END IF
SUBROUTINE estimate(group1, theta_start)
INTEGER, INTENT(IN) :: group1
REAL*8, INTENT(IN), DIMENSION(500) :: theta_start
c Variable Declarations:\
INTEGER :: i,j,k,m,l,t0,i0,improve,max_m
REAL*8, DIMENSION(23,8) :: xxx19
xxx19(1:23,1) = (/554.0,541.1,583.3,593.2,615.8,582.0,582.5,546.5,
& 538.4,494.1,503.3,494.1,486.9,478.6,432.6,439.6,
& 380.4,355.4,305.9,271.8,254.6,208.8,202.8/)
Real*8 is not part of Fortran, and has never been part of Fortran. So the strict answer to your question is it is not Fortran of any vintage.
However going on what you have shown apart from Real*8 it is Fortran 90 or later. Fixed source form is still part of the language (though I would fail any students I have for using it) so it not an indicator of the vintage of the code. However after a quick look at the above I can see the following features which came into the standard language in Fortran 90:
Mixed case (outside character variables and constants)
Underscore in symbol name
Implicit None
:: in variable declarations and comma separated attribute lists
Variable names longer than 6 characters
Double inverted commas (") to delimit character strings
Do ... End Do (I assume you have missed out the End Do for some reason as otherwise the fragments above make no sense whatsoever)
== to test equality
Intent for dummy arguments
Array sections
Array constructors
There may be others.
I kind of know the behaviour of the data statement in fortran. However I don't know if there is any situation where it is prefered or it should be avoided
I personally like data statement when the initialization of my variables would be more clear with it than by normal assignment. For example:
type gene
character :: gene
integer :: depth
integer :: delta
end type
type(gene) :: pool(8)
! initializing in a data statement looks nicer in this case
data pool%gene / '#', 'U', 'R', '+', '-', '*', '/', '^'/
data pool%depth / 0 , 0 , 1 , 2 , 2 , 2 , 2 , 2 /
data pool%delta / 1 , 1 , 0 , -1 , -1 , -1 , -1 , -1 /
The data statement is not obsolescent. However, its use amongst executable statements has been obsolescent since Fortran 95. Appendix B of the latest Fortran standard gives details of obsolescent features.
B.3.5 DATA statements among executables. The statement ordering
rules allow DATA statements to appear anywhere in a program unit after
the specification statements. The ability to position DATA
statements amongst executable statements is very rarely
used, unnecessary, and a potential source of error.
On page 140 of Modern Fortran Explained (the green edition from 2011, not the newer red edition, which I don't have), Metcalf, Cohen & Reid write
We recommend using the type declaration statement rather than the data
statement, but the data statement must be employed when only part of
a variable is to be initialised.
Given that two of the authors are members of the WG5 (which is responsible for the development of Fortran --- actually maybe all three authors are members; I'm not sure about Michael Metcalf), we can say with a fair degree of certainty that the data statement should be avoided unless initialising part of a variable, before the executable statements in a program unit.
This works just fine:
program main
integer,parameter,dimension(3) :: x = [1,2,3]
print*,x
end program main
As does this:
program main
integer,parameter,dimension(3) :: x = (/1,2,3/)
print*,x
end program main
Is there a reason to think that one form should be preferred over the other (e.g. backward compatibility)?
The square bracket form was added to the language in Fortran 2003. If you are writing to Fortran 90 (as per the tag on the question) then the square bracket form is a syntax error (square brackets are not in the Fortran 90 character set).
Beyond language standard it a question of personal preference and style.
I need a portable function/subroutine to locate the position of the last non-blank character in a string. I've found two options: LEN_TRIM and LNBLNK. However, different compilers seem to have different standards. The official documentation for the following compilers suggests that LEN_TRIM is part of the Fortran 95 standard on the following platforms:
IBM: LEN_TRIM
Intel: LNBLNK and LEN_TRIM
gfortran: LNBLNK and LEN_TRIM
PGI: LEN_TRIM
However, it appears that nothing is guaranteed on compilers released before the F95 standard. My experience has been that older compilers might specify either LEN_TRIM or LNBLNK, but not necessarily both. My solution has been to use preprocessor conditionals:
#ifdef USE_LEN_TRIM
iNameLen = LEN_TRIM(cabase)
iExtLen = LEN_TRIM(caext)
#else
iNameLen = LNBLNK(cabase)
iExtLen = LNBLNK(caext)
#endif
and then pass -DUSE_LEN_TRIM to the preprocessor. However, I am not a big fan of preprocessor conditionals & extra compile-time flags. Do you have any suggestions for a portable (before the Fortran 95 standard) function that locate the position of the last non-blank character in a string?
LEN_TRIM is part of the Fortran 95 standard. I am not aware of any simple combination of intrinsics in Fortran 77 that could tackle this (TRIM also appeared with Fortran 95, and wasn't available in Fortran 77). But you can use a simple user function to perform that task if you really want to be portable without relying on compiler intrinsics and preprocessor:
function lentrim(s)
implicit none
character(len=*) :: s
integer lentrim
do lentrim = len(s), 1, -1
if (s(lentrim:lentrim) .ne. ' ') return
end do
end function lentrim
(tested with g77 and gfortran; use option -ffree-form to compile free-form source like this).
Before the standard, I would say no. I've seen the len_trim function implemented by hand on F77 codes. If you want to be standard toward old compilers, then you will have to provide your own implementation as a failsafe, and use a preprocessor conditional to pick what you need.
I'm stuck trying to find if this is a pre-Fortran 95 or not, but does
len(trim(s))
work?