Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28178 Discussions

ifort and zero repeat specifications

ur
New Contributor II
1,180 Views
program testzero
implicit none
character(len=:),allocatable :: line(:), input
integer :: ints(3), i, j, k, l, m, n, iostat
namelist /nml/ i,j,k,l,m,n
character(len=256) :: iomsg
! zero data-repeat-specification allows for a zero
data ints/ 1*-10,0*-20,2*-30 /
   write(*,*)ints
   !  list-directed input does something different with each compiler
   !  but gfortran stops saying not allowed
   input='1*10,0*20,2*30'
   read(input,*,iostat=iostat,iomsg=iomsg)i,j,k
   if(iostat.ne.0)write(*,*)trim(iomsg)
   write(*,*)i,j,k

   read(input,*,iostat=iostat,iomsg=iomsg)ints
   if(iostat.ne.0)write(*,*)trim(iomsg)
   write(*,*)ints
   ! ifort does something weird, which gets weirder
   i=-10;j=-20;k=-30;l=-40;m=-50;n=-60
   read(input,*,iostat=iostat,iomsg=iomsg)i,j,k,l,m,n
   if(iostat.ne.0)write(*,*)'TOO MANY:'//trim(iomsg)//':'//input
   write(*,*)i,j,k,l,m,n
   ! repeat specification is supposed to be "positive"
   !write(*,'(2("A",i0:,1x),0("B",i0:,1x),3("C",i0:,1x))') 1,2,3,4,5

   ! namelist input
   i=-1;j=-2;k=-3;l=-4;m=-5;n=-6
   line=[character(len=80) :: '&nml', 'i=11,j=22,k=33,l=44,m=55,n=66', '/']
   read(line,nml=nml,iostat=iostat,iomsg=iomsg)
   if(iostat.ne.0)write(*,'(" > ",a)') 'NAMELIST:'//trim(iomsg)//':',line
   write(*,*)i,j,k,l,m,n
   write(*,nml=nml)
end program testzero

I was testing repeat specifiers, and as part of that was looking at where zero was allowed as a repeat count, as it is definitely allowed in a DATA statement.  If not allowed I was expecting an error, or expecting it to act as a zero.  I did not get errors with ifort, and got very unexpected results with the following test code:

 

ifort testzero.f90
(base) urbanjs@venus:~/github/fun/weird_io/app$ ./a.out
-10 -30 -30
10 20 20
10 20 20
10 20 20 20 20 20
11 22 33 44 55 66
&NML
I = 11,
J = 22,
K = 33,
L = 44,
M = 55,
N = 66
/

 

There were other issues when I added 0 as a repeat specifier in NAMELIST input not shown.

I found one line in the f2018 standard for one case saying the repeat count had to be "positive" which might be implying non-zero; but only the DATA statement  specifically said zero was allowed.

Either way, I would expect these to work as if zero meant no repeat of the following value, or to generate an error. Neither occurs.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 Kudos
1 Solution
Ron_Green
Moderator
991 Views

bug ID CMPLRLIBS-34183

 

 

View solution in original post

0 Kudos
15 Replies
JohnNichols
Valued Contributor III
1,144 Views

This behaves as if all values are ten on a read, it is indeed interesting, but data statements are so not cool. 

input='0*10,0*20,3*30'

 

0 Kudos
ur
New Contributor II
1,125 Views

Repeat specifiers appear in Fortran in several circumstances. One would hope that they behave consistently. The DATA statement clearly describes the behavior and specifically states a repeat count of zero is allowed. In other locations in the standard for NAMELIST groups, list-directed I/O,  FORMAT declarations, and so on I did not find any descriptions as clear. Some did not appear to state what was allowed, and others said the value should be positive, but were not as clear about whether a positive zero was considered positive or not.

The actual case of interest is actually FORMATs that are generated on the fly where the repeat required is calculated and written into a string to be used as a FORMAT, but the general question was is zero allowed in that case, and more generally what is the behavior in all the cases where repeats are allowed?

Some compilers gave error messages, some gave segfaults, etc ... . The ifort compiler did not generate an error, but did also not act correctly if zero is allowed.  So I am not sure if an error should be produced, or if zero should be allowed; but the above test case shows no errors in several cases but also does not behave as if zero is allowed, but appears to produce very unexpected results; including returning more non-zero values than are present in the input, and unexpected values.  So either way I think those are bugs; but not sure what to report until it is determined what the standard behavior should be.

 

Although DATA statements are superior in many ways for easily declaring arrays in row-column order, partially declaring values, and so on I have not added on in years; although I use a lot of code that has DATA statements in them. It is referenced here because it is one of the statements that allows repeat specifiers and also has the clearest specification in the standard, and clearly states zero repeats are allowed, and is the one case where ifort behaved as expected.

0 Kudos
FortranFan
Honored Contributor II
1,116 Views

@ur,

The standard document for Fortran suggests only the DATA statement allows a zero datat-stmt-repeat value.

The standard requires the list-directed IO as well as NAMELIST to have a nonzero, nonsigned int-literal-constant as the repeat value in the "r*c" form allowed for the statement.  Thus your code does not conform.  There are no numbered constraints indicated in the standard thus it is the programmer's responsibility to conform to the standard, the compiler is not required to detect and report nonconformance and the program behavior can be anything.

As to the DATA statement with a zero repeat, two compilers I tried appear to process it alright:

   integer :: x
   data x / 0 * 1, 42 / !<-- first listing should get ignored
   print *, "x = ", x, "; expected is 42"
end
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.33.31630.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\temp>p.exe
 x =  42 ; expected is 42
C:\temp>gfortran p.f90 -o gcc-p.exe

C:\temp>gcc-p.exe
 x =           42 ; expected is 42
0 Kudos
JohnNichols
Valued Contributor III
1,083 Views

@FortranFan, there is a subtle difference between your code and @ur code, that code generates a problem on the read from data with a read statement. The read statement stops at the first 0*1 - I agree with @ur it is a bit annoying, I still think data statements are a lousy way to incorporate constants into a program, they can get buried deep in the code and you do not realize their significance.   Very easy to introduce an incorrectly typed number, the recent prestressed program I played with had such a problem.  

In terms of 0 repeater on the format, it should throw an error.  

 

Just my humble Sunday morning opinion. 

0 Kudos
jimdempseyatthecove
Black Belt
1,058 Views

When you use an internal I/O character variable that may contain a "0*nnn," (with or without ","), prior to use, remove the 0*nnn  (with or without ",").

 

Jim Dempsey

0 Kudos
Ron_Green
Moderator
1,029 Views

This is probably worth a feature request to print an error message.  I'll talk to the runtime library gurus today with this example.

 

but a comment in the code has me confused.  your comment states

 10    !  list-directed input does something different with each compiler
 11    !  but gfortran stops saying not allowed

I'm not seeing that behavior of stopping with gfortran 12.0.1 on linux:

$ gfortran -o testzero testzero.f90 
rwgreen@orcsle153:~/quad$ ./testzero
         -10         -30         -30
 Zero repeat count in item 2 of list input
          10  -706010880           0
 Zero repeat count in item 2 of list input
          10         -30         -30
 TOO MANY:Zero repeat count in item 2 of list input:1*10,0*20,2*30
          10         -20         -30         -40         -50         -60
          11          22          33          44          55          66
&NML
 I=11         ,
 J=22         ,
 K=33         ,
 L=44         ,
 M=55         ,
 N=66         ,
 /

 

gfortran --version

GNU Fortran (GCC) 12.0.1 20220413 (Red Hat 12.0.1-0)

Copyright (C) 2022 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

0 Kudos
Steve_Lionel
Black Belt Retired Employee
1,026 Views

Here's what NAG Fortran 7.1 outputs:

-10 -30 -30
Zero repeat factor in list-directed input
10 0 0
Zero repeat factor in list-directed input
10 -30 -30
TOO MANY:Zero repeat factor in list-directed input:1*10,0*20,2*30
10 -20 -30 -40 -50 -60
11 22 33 44 55 66
&NML I = 11, J = 22, K = 33, L = 44, M = 55, N = 66/

 

0 Kudos
JohnNichols
Valued Contributor III
1,021 Views

I was reading my steel design manual last night.  Light reading after a day fixing the ethernet cables placed in house upon construction.  I finally got round to connecting them up.  Two longest runs had open circuits, both in very hard to reach attic corners.   One I could pull, the other I kept cutting and trying till it was not open and then attached another good cable.  Now all the white cables snaking through the house are gone.  

So the steel manual suggests if you have two independent variables if they are 1:1000 each the odds of both simultaneously is 1 in a million, so @ur has found an odd combinations with data and read and format.  

I am sure most old timers, anyone who thinks Die Hard is the best Christmas movie and who graduated Middle School between 1965 and 1972, would not try this combination.  

The reason for allowing zeros in data is clearly to allow the list to be amended quickly, it should not be allowed,  and the lack of a warning on zero format should be an error, IMHO.  

Now I will be told why I am wrong.  Plus why read from a data statement you can use = to do the same thing can you not and it is a lot clearer, so reading from a data statement is verbotten. 

 

My two penny's worth.  

Thought for the day, if you take a nation, let us call it Old Blighty, and it now has a GDP that is 70% of what it was six years ago, is the political decision that made that change a good one.  LOL

0 Kudos
Ron_Green
Moderator
1,017 Views

It appears our RTL is taking the 0* as an infinite repeat count.  I modified the test thusly to get more clarity:

 

 

 

program testzero
implicit none
character(len=:),allocatable :: line(:), input
integer :: ints(3), i, j, k, l, m, n, iostat
namelist /nml/ i,j,k,l,m,n
character(len=256) :: iomsg
! zero data-repeat-specification allows for a zero
data ints/ 1*-10,0*-20,2*-30 /

   write(*,*) "test 1: data statement data ints/ 1*-10,0*-20,2*-30 /"
   write(*,*) "ints array contains: ", ints
   write(*,*) ""

   !  list-directed input 
   input='1*10,0*20,2*30'
   write(*,*) "test 2: internal read to uninit i,j,k of input: ", input
   write(*,*) "read(input,*,iostat=iostat,iomsg=iomsg)i,j,k"
   read(input,*,iostat=iostat,iomsg=iomsg)i,j,k
     write(*,*) "iostat is ", iostat
     if (iostat /= 0) write(*,*) "iomsg  is ", trim(iomsg)
     write(*,*) "i, j, k after read: ", i,j,k
     write(*,*) ""

   write(*,*) "test 3: internal read to existing 3 elements of ints of input: ", input
   write(*,*) "read(input,*,iostat=iostat,iomsg=iomsg) ints"
   read(input,*,iostat=iostat,iomsg=iomsg) ints
     write(*,*) "iostat is ", iostat
     if (iostat /= 0) write(*,*) "iomsg  is ", trim(iomsg)
     write(*,*) "ints(3) after read: ", ints 
     write(*,*) ""

   write(*,*) "test 4: initialize i=-10;j=-20;k=-30;l=-40;m=-50;n=-60"
   write(*,*) "then read just 3 elements of input: ", input
   write(*,*) "read(input,*,iostat=iostat,iomsg=iomsg)i,j,k,l,m,n"
   i=-10;j=-20;k=-30;l=-40;m=-50;n=-60
   read(input,*,iostat=iostat,iomsg=iomsg)i,j,k,l,m,n
     write(*,*) "iostat is ", iostat
     if (iostat /= 0) write(*,*) "iomsg  is ", trim(iomsg)
     write(*,*) "i,j,k,l,m,n after read: ",i,j,k,l,m,n
     write(*,*) ""

end program testzero

 

 

note that I removed the namelist since that seems to work.  I could/should remove the data statement test as well.  

Our output with IFX and IFORT (same RTL) is:

./testzero
 test 1: data statement data ints/ 1*-10,0*-20,2*-30 /
 ints array contains:          -10         -30         -30
 
 test 2: internal read to uninit i,j,k of input: 1*10,0*20,2*30
 read(input,*,iostat=iostat,iomsg=iomsg)i,j,k
 iostat is            0
 i, j, k after read:           10          20          20
 
 test 3: internal read to existing 3 elements of ints of input: 1*10,0*20,2*30
 read(input,*,iostat=iostat,iomsg=iomsg) ints
 iostat is            0
 ints(3) after read:           10          20          20
 
 test 4: initialize i=-10;j=-20;k=-30;l=-40;m=-50;n=-60
 then read just 3 elements of input: 1*10,0*20,2*30
 read(input,*,iostat=iostat,iomsg=iomsg)i,j,k,l,m,n
 iostat is            0
 i,j,k,l,m,n after read:           10          20          20          20
          20          20

I am in talks with our RTL team.  Since the code does not conform it may be a feature request as opposed to a bug.  

0 Kudos
Ron_Green
Moderator
1,008 Views

it's a bug.  I'll write it up and we'll get a warning message similar to NAG's and Gfortran's messages

0 Kudos
JohnNichols
Valued Contributor III
1,002 Views
0 Kudos
ur
New Contributor II
938 Views

Thanks everyone for going farther than expected. I was only hoping for clarification on whether a zero repeat specifier was allowed/supported anywhere other than in a DATA statement, and got that and far more.  So everyone agrees there is not

support for zero repeaters in anything else  (NAMELIST groups, list-directed I/O, VFE extension, ...)?   Thanks for the fix on the

infinite read, and for the enhancements that will make programming with ifort more robust.  If it is possible to make the error

you get with VFE use of a zero repeater  (it errors out on use, but note not on presence ) that would be less confusing as well.

Thanks to everyone for the responses;  several are solutions to different parts of this.  Note the NAMELIST placeholder does cause errors with a zero repeater as well, the example just does not use one in the posted example; which was in process when the infinite read showed up which really got confusing.

 

program demo_vfe
implicit none
character(len=*),parameter :: template="(1x, <left>('<',i0:,1x), <middle>('@',i0:,1x), <right>('>',i0:,1x))"
integer,allocatable :: vector(:)
integer :: left, middle, right, i
integer :: iostat
character(len=256) :: iomsg
! test extension

left=3
middle=4
right=5
vector=[1,2,3,4,5,6,7,8,9,10,11,12]

write(*, template,iostat=iostat,iomsg=iomsg) vector
if(iostat.ne.0)write(*,*)'*iomsg*:'//trim(iomsg)

left=0
middle=0
right=12
vector=[1,2,3,4,5,6,7,8,9,10,11,12]

write(*, template,iostat=iostat,iomsg=iomsg) vector
if(iostat.ne.0)write(*,*)'*iomsg*:'//trim(iomsg)

left=12
middle=0
right=0
vector=[1,2,3,4,5,6,7,8,9,10,11,12]

write(*, template,iostat=iostat,iomsg=iomsg) vector
if(iostat.ne.0)write(*,*)'*iomsg*:'//trim(iomsg)

end program demo_vfe

0 Kudos
Ron_Green
Moderator
992 Views

bug ID CMPLRLIBS-34183

 

 

0 Kudos
Steve_Lionel
Black Belt Retired Employee
990 Views

Note that NAG and gfortran don't emit messages - those in the output come from the program.

0 Kudos
Ron_Green
Moderator
617 Views

the zero repeat error was fixed and is in the 2023.0 compilers.

 

 

0 Kudos
Reply