Bug in adjustl in gfortran when applied to an allocatable string - fortran

I am modifying a program developed using ifort to work with gfortran as well, and I am running into an issue with calling adjustl on an allocatable string. The following program will produce unexpected output when compiled with gfortran:
program compilercheck
implicit none
character(len=:), allocatable :: string
string = " Hi" !Note leading space
string = adjustl(string(2:))
if(string == "Hi") then
write(*,*) "You compiled with ifort"
else
write(*,*) "You compiled with gfortran"
endif
end program compilercheck
Instead of string becoming "Hi" as expected (and when compiling with ifort) it ends up as "H". The bug can be worked around by changing the call to adjustl(...) into adjustl(trim(...)), but it seems very strange that that would affect the result (no trailing spaces). Is there a bug in gfortran or is the code doing something beyond the fortran specifications that ifort allows? I am using gfortran version 7.5.0 for reference.

It is sad to see that the bug is apparently not reported.
Here is a workaround wrapper, for those, who stuck with gfrotran-8 or below. Also it doesn't require trim().
function adjustlFIX(str) result(res)
character(len=*), intent(in) :: str
character(:),allocatable :: res
res = adjustl(str)
end function adjustlFIX

Related

How to write the values in files with different extensions by using the below code?

subroutine iswap (file,b)
implicit none
integer b,m
character*(*) file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
open(1, File = file(1:m),form='formatted')
write (1,*) b
close(1)
end
subroutine iswap1 (file,b1,c1)
implicit none
integer m,b1,c1
character*6 file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
call iswap(file(1:m)//'.jk',b1)
call iswap(file(1:m)//'.bk',c1)
end
program callex
implicit none
character*6 unit
call iswap1(unit,2,3)
end
I'm trying to write the code that generates two files ".jk" and ".bk", each containing the value 2 and 3. The code I wrote is not not creating any file. Could you please guide me in correcting this code keeping the code format same? The main program calls "iswap1" subroutine, which then calls "iswap2" subroutine that writes values to files with the extension mentioned in "iswap1" subroutine. Thanks!
Here's the code roughly written in idiomatic modern Fortran:
program callex
implicit none
character(len=80) :: fname = "thefile"
call iswap1(fname,2,3)
contains
subroutine iswap (file,b)
implicit none
integer, intent(in) :: b
character(len=*), intent(in) :: file
integer :: unit
open(newunit=unit, File = file ,form='formatted')
write (unit,*) b
close(unit)
end subroutine iswap
subroutine iswap1 (file,b1,c1)
implicit none
integer, intent(in) :: b1,c1
character(len=*), intent(in) :: file
call iswap(trim(file)//'.jk',b1)
call iswap(trim(file)//'.bk',c1)
end subroutine iswap1
end program callex
Some notable changes from your original version:
Use contained procedures to get argument checking.
character variables declared with length per modern syntax.
Initial character variable, fname initialized (and made a bit longer because why not). Also I initialized fname to a non-empty string because otherwise on Unix type systems the generated files will be hidden as the name would start with ..
Dummy character variables declared with len=* meaning they get the length from the caller.
Declare intent for dummy arguments.
Use trim instead of a loop to get rid of trailing spaces.
Use NEWUNIT= when opening units rather than manually allocating unit numbers.

What 'language' is this written in? (from 1994) - Is it Fortran? [duplicate]

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.

End of Record error when saving a variable

I'm having a runtime error when I run a code that works without problems using a different computer.
I'm wondering if the problem is the Fortran compiler of this machine (GCC 4.9.2) since the former computer used a previous version.
The issue comes when defining a variable like this:
In a module I define
character(30),allocatable,save :: sceneclass(:)
Then in the subroutine sceneclass is defined according to
character(30) surf, frac, scene
allocate(sceneclass(10))
do i=1,10
write(sceneclass(i),*) trim(scene)//trim(surf)//'_'//trim(frac)
enddo
In the first iteration I get the "End of record". But I don't know where is the problem. It seems to work fine in other computers.
You are probably writing a string to sceneclass(i) that is longer then the 30 chars you specified.
I can reproduce this with
program test
implicit none
character(10),allocatable :: sceneclass(:)
integer :: i
allocate( sceneclass(10) )
do i=1,10
write(sceneclass(i),*) 10**i
enddo
print *, ( trim(sceneclass(i)), i=1,10 )
end program
gfortran fails with
Fortran runtime error: End of record
while ifort reports the error correctly:
output statement overflows record, unit -5, file Internal List-Directed Write
Increasing the string length to 12 solves the issue in this case. You can (and should) use iostat within the write statement to capture this.
One thing to be aware of, when you specify a list directed * write of a character string, the compiler always(?) adds an extra lead blank, so the effective length of the string you can write is one less than you might expect.
To remedy that (and of course assuming you don't want the lead blank anyway ) use a string edit descriptor:
write(sceneclass(i),'(a)')...
Interestingly ifort (linux 11.1) actually allows you to overrun by one character:
character*5 c
write(c,*)'12345' ! result: " 1234"
which I would consider a bug. It seems they forgot to count the blank too.. ( gfortran throws the above error on this, and ifort balks if you add one more character )
see here if you wonder why the blank.. Are Fortran control characters (carriage control) still implemented in compilers?
and now I'm curious if some compiler somewhere didn't do that for an internal list write, or maybe your code was previously compiled with a flag to disable the "printer control" code

What is error in this fortran program?

I am writing following fortran 90 program and compiling with GNU Fortran Compiler. However, I am getting some errors that I can't resolve. Can someone explain me where I am going wrong?
PROGRAM FILE1
IMPLICIT NONE
INTEGER:: status,a,b,c,i,j
a=5
b=6
c=1
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
ALLOCATE (arr1(a,b))
DO i=1,a,1
DO j=1,b,1
arr1(i,j)=c
c=c+1
END DO
END DO
DO i=1,a,1
DO j=1,b,1
WRITE (*,100,ADVANCE=NO) arr1(i,j)
100 FORMAT (1X,I4.1)
END DO
WRITE (*,110)
110 FORMAT ('',/)
END DO
DEALLOCATE(arr1)
END PROGRAM
I got several errors, e.g. in statement REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1 Error: Unexpected data declaration statement at (1). I checked syntax from several sources, but no luck. There is error in statement WRITE (*,100,ADVANCE=NO) arr1(i,j) too. Can someone comment?
The posted code has a couple of issues:
you need to define all your variables before you execute any other statement.
a=5
b=6
c=1
should come after your last variable definition:
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
You need to quote NO in the WRITE statement:
WRITE (*,100,ADVANCE="NO") arr1(i,j)
Since you are writing a REAL value, you need to give a floating point format in such as f or g
100 FORMAT (1X,f7.3)
The working code would be:
PROGRAM FILE1
IMPLICIT NONE
INTEGER:: status,a,b,c,i,j
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
a=5
b=6
c=1
ALLOCATE (arr1(a,b))
DO i=1,a,1
DO j=1,b,1
arr1(i,j)=c
c=c+1
END DO
END DO
DO i=1,a,1
DO j=1,b,1
WRITE (*,100,ADVANCE="NO") arr1(i,j)
100 FORMAT (1X,f7.3)
END DO
WRITE (*,110)
110 FORMAT ('',/)
END DO
DEALLOCATE(arr1)
END PROGRAM

Simplest Fortran Code Still Has an Error

I'm learning Fortran for a new job and started writing some very, very basic programs. To compile, I'm using gcc version 4.6.2, and I'm working on Linux Suse OS (if that matters at all). I believe the version of Fortran I'm using is F90 or F95. The code is written using the VIM text editor.
Here is the program I've written
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
That's it! Oh, and the lines are indented, They start on column 8, so indentation isn't an issue.
UPDATE 1
I have tried doing this like so:
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
I also tried adding the IMPLICIT NONE statement to all of that and didn't get a change in the error.
END UPDATE 1
I save, quit, and compile. The compiler returns this error:
Error: Unexpected end of file in 'practice1.f'
Anyone know what the problem is? I've even tried removing the print statement and just having the variable declarations but the same error occurs. It's keeping me from practicing Fortran at all!
Your first version
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
is NOT a valid Fortran program. Every valid program ends with the end statement. A 'program' without an end statement is not syntactically correct. Keep reading your introductory tutorial.
I suggest you get into the habit of starting your programs with a program statement, with a name, such as
program myprog
and ending them with
end program myprog
Strictly, neither the program statement nor a program name is necessary but they do make things look a bit more comprehensible.
Oh, and while I'm writing ... don't get into the habit of starting lines at column 8, that smacks of the now out-dated fixed-form source. If you are using a reasonable compiler (such as gcc) give your filenames the .f90 suffix and let your source code run free. All the while observing good habits of indentation of course.
EDIT in response to OP's edits
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
and
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
END
are both syntactically correct. Both gfortran (v4.1.2) and Intel Fortran (v13.0.1) compile both correctly and produce executables which execute.