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

Format syntax for a defined number of values on a line

Adrian_F_1
Beginner
848 Views

Back in my day this was legal:

        write(52,'(a,<nc>e20.10)') '  Recombined_Comp  :', (Recombined_Comp(i), i=1,nc)

It still works but I get:

warning #6923: Fortran 2008 does not allow an expression to be used as part of the format list.   [NC]

How is this done these days?

0 Kudos
18 Replies
mecej4
Honored Contributor III
848 Views

It was legal if you had a good lawyer on your side.

Variable Format Expressions is a vendor extension. You probably have specified /stand:f03 as a compiler option somewhere, causing such extensions to be disallowed. 

0 Kudos
Adrian_F_1
Beginner
848 Views

So how does Fortran 2008 handle it?

0 Kudos
mecej4
Honored Contributor III
848 Views

The Fortran standard does not specify non-standard extensions. The vendors do, at their pleasure and their customer's request. Therefore, if you want to use an extension, don't specify that the compiler should check for standard-compliance, at least for those source files that do use such extensions.

0 Kudos
Adrian_F_1
Beginner
848 Views

Yes I understand this.  That isn't my question.  I was wondering if the Fortran 2008 standard allows for variable format length, perhaps with a different format.  eg "$" has been replaced with "advance='no'"

0 Kudos
mecej4
Honored Contributor III
848 Views

The standard way of doing what you want is to create or alter the format string before using that format to output to an external file.

For example, you could do:

character(len=12) :: fmtstr = '(a,nce20.10)'
..
write(fmtstr(4:),'(I2)') nc
..
write(52,fmtstr) ' Recombined_Comp  :', (Recombined_Comp(i), i=1,nc)

Note, however, that you are not required to use an internal WRITE as I did. You can build up the format string as a character expression in any convenient way, including reading it from an input file.

If the repeated edit specification is the last item in the format, you could simply use a large enough repeat prefix. For example, if you know that nc will never exceed 15, you could write 15E20.10. If, at the time the format is used, nc is smaller, the extra instances of E20.10 would just get ignored.

0 Kudos
Adrian_F_1
Beginner
848 Views

Yes although <nc> is more elegant, maybe that will get into the standard one day...

0 Kudos
Steven_L_Intel1
Employee
848 Views

Fortran 2008 handles this case as follows:

write(52,'(a,*(e20.10))') '  Recombined_Comp  :', (Recombined_Comp(i), i=1,nc)

 

0 Kudos
Adrian_F_1
Beginner
848 Views

Wow excellent, I didn't know this.

0 Kudos
mecej4
Honored Contributor III
848 Views

Nice to know; I checked, and find that the feature was available even in the 14.0 compiler. 

0 Kudos
netphilou31
New Contributor II
848 Views

Hi,

Thanks Steve for the clarification. However, what happen if there are several implicit loops ? How the compiler is identifying which part of the format to use? does it use the type of the variables or does it analyzes the content of the expression to print ?

what happen in such a case ?

    write(52,'(a,*(i2),*(a),*(1pg13.6))') 'Indexes, names, composition : ', &
                                          (Ind(i), i=1,nc), (name(i),i=1,nc), (x(i),i=1,nc)
   
 

Best regards,

0 Kudos
mecej4
Honored Contributor III
848 Views

There are no rules to associate format edit descriptors with I/O list items grouped by implied loops in the latter. If there were such rules, your problem would be solved if the edit descriptors and list items were perfectly matched, but formatted I/O would become severely restricted otherwise. Rather, think of the I/O list being expanded completely by repeating the implied loops. Only after the list has been expanded in this way to a simple serial list is the I/O conversion performed under control of the format items.

I do not see any way to resolve the issue that you raised other than by breaking up the WRITE statements using ADVANCE='NO' clauses, or to output the pieces to an array or list of character variables using internal writes, followed by writing out those character variables. 

I wonder if the following idea would work: the colon format descriptor has been available in Fortran for a long time and is part of the standard. Its effect is to discard the remainder of the format list, if any, and immediately terminate output if all the items in the I/O list have been processed. Its meaning/effect could be extended by specifying that when a colon descriptor appears within an unlimited-format-item, output control moves to the next item in the format string, if any.

0 Kudos
jimdempseyatthecove
Honored Contributor III
848 Views

I'd like to offer some sense, or nonsense, on this subject.

From my understanding the purpose of the * formatting is to provide a means of indicating that at compile time it is unknown as to the number of instances of a type that will be required. The argument(s) list for say *(i2) could be:

(Ind(i), i=1,nc)
Ind(1:nc)
Ind(:)
9

Or other construct where one expression/value fulfills the *. Although in the case of the 9 above, you know the count of integers and then you would not use * formatting.

Using this rule, quote #11 would work. As to if his is how it is implemented, I cannot say.

More complex expressions for a single * could be written using an array constructor.

Jim Demspey

 

0 Kudos
mecej4
Honored Contributor III
848 Views

Jim, here is the explanation from F2008 (draft):

The effect of an unlimited-format-item is as if its enclosed list were preceded by a very large repeat count.
There is no file positioning implied by unlimited-format-item reversion. This may be used to write what is
commonly called a comma separated value record.

For example, WRITE( 10, '( "IARRAY =", *( I0, :, ","))') IARRAY produces a single record with a header and a comma separated list of integer values.

If there are items in the I/O list that come after the preceding items that were intended to be used with the *(...) format, and their type is unsuitable for the edit descriptors in the unlimited-format-item, a run time error would occur. I don't see how the standard allows anything other than control items and character strings to come after a *() group. In other words, there can only be a single *() item in a format string, and that one cannot be followed by other edit descriptors, if my reading of the standard is not mistaken.

Incidentally, note the use of the colon in the example (from the standard, quoted above) to prevent a terminal comma from being output to the CSV file.

0 Kudos
Steven_L_Intel1
Employee
848 Views

mecej4 has it right. It isn't called "unlimited format item" for nothing. It isn't a universal replacement for variable format expressions, but it does the job for the majority of uses. For the cases it doesn't work, the standard solution, one that goes back to F77, is to write the format to a character variable, with the count inserted for the repeat count, and then use the variable as the format.

0 Kudos
mecej4
Honored Contributor III
848 Views

Steve, can you enlighten us on why VFE-s did not eventually find a place in the Fortran standard? Using chevrons (angle-brackets) as they do, they do not clash with any other Fortran feature, and provide a nice solution to a common problem.

0 Kudos
jimdempseyatthecove
Honored Contributor III
848 Views

Mecej4,

If you look at the example given in your #14, there is a single *, and a single "expression" that is substitutable for an array constructor. This leaves the question as to which would you prefer:

WRITE( 10, '( "DATA =", *( I0, :, ","))') IARRAY, JARRAY

or

WRITE( 10, '( "DATA =", *( I0, ","), *( I0, :, ","))') IARRAY, JARRAY

If your predilection is to only use one type then the former would be preferred. However, consider ramification for the latter and:

WRITE( 10, '( "DATA =", *( I0, ","), *( F0, :, ","))') IARRAY, ARRAY

This is what post #11 was querying about.

Jim Dempsey

0 Kudos
mecej4
Honored Contributor III
848 Views

The compiler confirms the suspicions that I expressed in #14:

chkio.f90(4): error #8416: Unlimited format item shall be specified ONLY once.   [,*]
WRITE( 10, '( "DATA =", *( I0, ","), *( F0, :, ","))') IARRAY, ARRAY
-----------------------------------^

Since you are not allowed to use more than one UFI (unlimited format item) in a format string, there is no need to discuss how two UFIs should be interpreted.

0 Kudos
Steven_L_Intel1
Employee
848 Views

V FEs are universally detested by implementors - the semantics are exceedlingly strange for Fortran. I don't think anyone ever considered making them standard. We don't particularly care for them ourselves, and we invented them! (Back in the DEC PDP-11 days, before my time.)

0 Kudos
Reply