Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fortran format specifier for complex number

Can I specify a format specifier for a complex number in fortran? I have a simple program.

program complx1
implicit none
complex :: var1
var1 = (10,20)
write (*,*) var1
write (*,'(F0.0)') var1
write (*,'(F0.0,A,F0.0)') real(var1), ' + i ' , aimag(var1)
end program complx1

Output:

 (  10.0000000    ,  20.0000000    )
10.
20.
10. + i 20.

I wanted to use inbuilt format for a+bi with some format specifier, instead of one did manually (second last line of program). Obviously F0.0 did not work. Any ideas?

EDIT: I don't think this is a duplicate of post: writing complex matrix in fortran, which says to use REAL and AIMAG functions. I already used those functions and wondering whether there is an inbuilt format that can do the work.

like image 906
343_458 Avatar asked May 17 '15 19:05

343_458


2 Answers

There is no distinct complex edit descriptor. In Fortran 2008, 10.7.2.3.6 we see

A complex datum consists of a pair of separate real data. The editing of a scalar datum of complex type is specified by two edit descriptors each of which specifies the editing of real data.

In your second example, which you say "did not work", you see this formatting in action. Because the format had only one descriptor with no repeat count the values are output in distinct records (format reversion).

The first of your three cases is a very special one: it uses list-directed output. The rules for the output are

Complex constants are enclosed in parentheses with a separator between the real and imaginary parts

There is another useful part of the first rule mentioned:

Control and character string edit descriptors may be processed between the edit descriptor for the real part and the edit descriptor for the imaginary part.

You could happily adapt your second attempt, as we note that your "not working" wasn't because of the use of the complex variable itself (rather than the real and imaginary components)

write (*, '(F0.0,"+i",F0.0)') var1

This, though, isn't right when you have potentially negative complex part. You'll need to change the sign in the middle. This is possible, using a character variable format (rather than literal) with a conditional, but it perhaps isn't worth the effort. See another answer for details of another approach, similar to your third option but more robust.

Another option is to write a function which returns a correctly written character representation of your complex variable. That's like your third option. It is also the least messy approach when you want to write out many complex variables.

Finally, if you do have to worry about negative complex parts but want a simple specification of the variable list, there is the truly ugly

write(*,'(F0.0,"+i*(",F0.0,")")') var1

or the imaginative

character(19) fmt
fmt = '(F0.0,"+",F0.0,"i")'
fmt(8:8) = MERGE('+',' ',var1%im.gt.0)
write(*,fmt) var1

or the even better use of the SP control edit descriptor as given by High Performance Mark's answer which temporarily (for the duration of the output statement) sets the sign mode of the transfer to PLUS which forces the printing of the otherwise optional "+" sign. [Alternatively, this can be set for the connection itself in an open with the sign='plus' specifier.]

All this is because the simple answer is: no, there is no in-built complex edit descriptor.

like image 29
francescalus Avatar answered Sep 18 '22 12:09

francescalus


An addendum to @francescalus' existing, and mostly satisfactory, answer. A format string such as

fmt = '(F0.0,SP,F0.0,"i")'

should result in a complex number being displayed with the correct sign between real and imaginary parts; no need to fiddle around with strings to get a plus sign in there.

like image 113
High Performance Mark Avatar answered Sep 19 '22 12:09

High Performance Mark