Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CMPLX and constant folding

0 views
Skip to first unread message

James Van Buskirk

unread,
May 9, 2008, 5:11:11 AM5/9/08
to
gfortran does constant folding so aggressively that one has to be
careful when testing it. I have seen several instances lately
where it yields the correct answer if its constant folding
mechanism can come into play, but will be tripped up if not.
Another case in point:

C:\gfortran\james\cmplx>type test0.f90
module mykinds
implicit none
integer, parameter :: sp = selected_real_kind(6,37)
integer, parameter :: dp = selected_real_kind(15,307)
integer, parameter :: ep = selected_real_kind(18,4931)
integer, parameter :: qp_preferred = selected_real_kind(33,4931)
integer, parameter :: qp = (1+sign(1,qp_preferred))/2*qp_preferred+ &
(1-sign(1,qp_preferred))/2*ep
end module mykinds

subroutine sub(x1) ! constant folding permitted
!subroutine sub(x) ! constant folding forbidden
use mykinds
implicit none
integer x1 ! constant folding permitted
integer, parameter :: x = 1 ! constant folding permitted
! integer x ! constant folding forbidden

call xfinit
write(*,*) real(b'01000000001010010101001111111101',sp)
write(*,*) real(o'10012251775',sp)
write(*,*) real(z'402953FD',sp)
write(*,*) real(b'010000000000010100101010011111111010100&
&1110100101111100011101010',dp)
write(*,*) real(o'0400051247765164574352',dp)
write(*,*) real(z'40052A7FA9D2F8EA',dp)
write(*,*) real(b'010000000000000010101001010100111111110&
&10100111010010111110001110100110110111100',qp)
write(*,*) real(o'100001245237724722761646674',qp)
write(*,*) real(z'4000A953FD4E97C74DBC',qp)
write(*,*) cmplx(b'01000000001010010101001111111101',KIND=sp)
write(*,*) cmplx(o'10012251775',KIND=sp)
write(*,*) cmplx(z'402953FD',KIND=sp)
write(*,*) cmplx(b'01000000000001010010101001111111101010&
&01110100101111100011101010',KIND=dp)
write(*,*) cmplx(o'0400051247765164574352',KIND=dp)
write(*,*) cmplx(z'40052A7FA9D2F8EA',KIND=dp)
write(*,*) cmplx(b'01000000000000001010100101010011111111&
&010100111010010111110001110100110110111100',KIND=qp)
write(*,*) cmplx(o'100001245237724722761646674',KIND=qp)
write(*,*) cmplx(z'4000A953FD4E97C74DBC',KIND=qp)
write(*,*) cmplx(b'01000000001010010101001111111101',x,sp)
write(*,*) cmplx(o'10012251775',x,sp)
write(*,*) cmplx(z'402953FD',x,sp)
write(*,*) cmplx(b'01000000000001010010101001111111101010&
&01110100101111100011101010',x,dp)
write(*,*) cmplx(o'0400051247765164574352',x,dp)
write(*,*) cmplx(z'40052A7FA9D2F8EA',x,dp)
write(*,*) cmplx(b'01000000000000001010100101010011111111&
&010100111010010111110001110100110110111100',x,qp)
write(*,*) cmplx(o'100001245237724722761646674',x,qp)
write(*,*) cmplx(z'4000A953FD4E97C74DBC',x,qp)
write(*,*) cmplx(x,b'01000000001010010101001111111101',sp)
write(*,*) cmplx(x,o'10012251775',sp)
write(*,*) cmplx(x,z'402953FD',sp)
write(*,*) cmplx(x,b'0100000000000101001010100111111110101&
&001110100101111100011101010',dp)
write(*,*) cmplx(x,o'0400051247765164574352',dp)
write(*,*) cmplx(x,z'40052A7FA9D2F8EA',dp)
write(*,*) cmplx(x,b'0100000000000000101010010101001111111&
&1010100111010010111110001110100110110111100',qp)
write(*,*) cmplx(x,o'100001245237724722761646674',qp)
write(*,*) cmplx(x,z'4000A953FD4E97C74DBC',qp)
end subroutine sub

program test0
implicit none
integer x

x = 1
call sub(x)
end program test0

C:\gfortran\james\cmplx>gfortran test0.f90 finit.s -otest0

C:\gfortran\james\cmplx>test0
2.6457512
2.6457512
2.6457512
2.6457513110645907
2.6457513110645907
2.6457513110645907
2.6457513110645905904
2.6457513110645905904
2.6457513110645905904
( 2.6457512 , 0.0000000 )
( 2.6457512 , 0.0000000 )
( 2.6457512 , 0.0000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 2.6457512 , 1.00000000 )
( 2.6457512 , 1.00000000 )
( 2.6457512 , 1.00000000 )
( 2.6457513110645907 , 1.00000000000000000 )
( 2.6457513110645907 , 1.00000000000000000 )
( 2.6457513110645907 , 1.00000000000000000 )
( 2.6457513110645905904 , 1.00000000000000000000 )
( 2.6457513110645905904 , 1.00000000000000000000 )
( 2.6457513110645905904 , 1.00000000000000000000 )
( 1.00000000 , 2.6457512 )
( 1.00000000 , 2.6457512 )
( 1.00000000 , 2.6457512 )
( 1.00000000000000000 , 2.6457513110645907 )
( 1.00000000000000000 , 2.6457513110645907 )
( 1.00000000000000000 , 2.6457513110645907 )
( 1.00000000000000000000 , 2.6457513110645905904 )
( 1.00000000000000000000 , 2.6457513110645905904 )
( 1.00000000000000000000 , 2.6457513110645905904 )

So all is well, right? But if we comment out the lines that
say 'constant folding permitted' and uncomment the lines that
say 'constant folding forbidden', as in:

!subroutine sub(x1) ! constant folding permitted
subroutine sub(x) ! constant folding forbidden
use mykinds
implicit none
! integer x1 ! constant folding permitted
! integer, parameter :: x = 1 ! constant folding permitted
integer x ! constant folding forbidden

C:\gfortran\james\cmplx>gfortran test0.f90 finit.s -otest0

C:\gfortran\james\cmplx>test0
2.6457512
2.6457512
2.6457512
2.6457513110645907
2.6457513110645907
2.6457513110645907
2.6457513110645905904
2.6457513110645905904
2.6457513110645905904
( 2.6457512 , 0.0000000 )
( 2.6457512 , 0.0000000 )
( 2.6457512 , 0.0000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645907 , 0.0000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 2.6457513110645905904 , 0.0000000000000000000 )
( 1.07645030E+09, 1.00000000 )
( 1.07645030E+09, 1.00000000 )
( 1.07645030E+09, 1.00000000 )
( 4.61314012110932990E+018, 1.00000000000000000 )
( 4.61314012110932990E+018, 1.00000000000000000 )
( 4.61314012110932990E+018, 1.00000000000000000 )
( 3.02243656277986766270E+0023, 1.00000000000000000000 )
( 3.02243656277986766270E+0023, 1.00000000000000000000 )
( 3.02243656277986766270E+0023, 1.00000000000000000000 )
( 1.00000000 , 1.07645030E+09)
( 1.00000000 , 1.07645030E+09)
( 1.00000000 , 1.07645030E+09)
( 1.00000000000000000 , 4.61314012110932990E+018)
( 1.00000000000000000 , 4.61314012110932990E+018)
( 1.00000000000000000 , 4.61314012110932990E+018)
( 1.00000000000000000000 , 3.02243656277986766270E+0023)
( 1.00000000000000000000 , 3.02243656277986766270E+0023)
( 1.00000000000000000000 , 3.02243656277986766270E+0023)

We see that gfortran in this case has treated the BOZ literals as
integers and then converted the integers to reals. This incorrect
behavior can only be seen when gfortran can't do constant folding.
CMPLX has so many effective specific functions that you just knew
you could trip it up somewhere!

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


FX

unread,
May 9, 2008, 5:43:00 AM5/9/08
to
> We see that gfortran in this case has treated the BOZ literals as
> integers and then converted the integers to reals. This incorrect
> behavior can only be seen when gfortran can't do constant folding.

This is now know as PR36186
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36186).

> CMPLX has so many effective specific functions that you just knew you
> could trip it up somewhere!

The real issue is that all other intrinsics (DBLE, REAL, etc.) are
simplified when they have a BOZ as argument, while in complex you can
prevent that by putting a nonconstant second arg. This might have been
overlooked during the BOZ design.

--
FX

glen herrmannsfeldt

unread,
May 9, 2008, 8:29:15 AM5/9/08
to
FX wrote:
(snip)

> The real issue is that all other intrinsics (DBLE, REAL, etc.) are
> simplified when they have a BOZ as argument, while in complex you can
> prevent that by putting a nonconstant second arg. This might have been
> overlooked during the BOZ design.

Fortran 2003 13.7.20:

"CMPLX (X, Y, KIND) has the complex value whose real
part is REAL (X, KIND) and whose imaginary part is
REAL (Y, KIND)."

Since CMPLX is defined in terms of REAL, the effect should be
the same as applying REAL to each argument separately.
If one is BOZ then it seems the usual BOZ rules should apply.

-- glen

FX

unread,
May 9, 2008, 9:12:01 AM5/9/08
to
>> This might have been overlooked during the BOZ design.
>
> If one is BOZ then it seems the usual BOZ rules should apply.

Oops, sorry I wasn't clear, I'm not talking about the description of BOZ
in the standard, only about their implementation in gfortran.

--
FX

James Van Buskirk

unread,
May 9, 2008, 12:02:22 PM5/9/08
to
"FX" <cou...@alussinan.org> wrote in message
news:g01ij1$11gf$1...@nef.ens.fr...

> Oops, sorry I wasn't clear, I'm not talking about the description of BOZ
> in the standard, only about their implementation in gfortran.

There is a buglet in the description of CMPLX in the standard:

"If X is complex, it is as if X were real with the value REAL(X,KIND)
and Y were present with the value AIMAG(X,KIND)."

Nice concise prose, but AIMAG doesn't take a KIND optional agument.
Maybe REAL(AIMAG(X),KIND) ?

James Van Buskirk

unread,
May 9, 2008, 8:24:04 PM5/9/08
to
"FX" <cou...@alussinan.org> wrote in message
news:g016b4$2bbj$1...@nef.ens.fr...

> The real issue is that all other intrinsics (DBLE, REAL, etc.) are
> simplified when they have a BOZ as argument, while in complex you can
> prevent that by putting a nonconstant second arg. This might have been
> overlooked during the BOZ design.

Well, there are also DCMPLX and COMPLEX. I didn't realize that
gfortran for Win64 already supports INTEGER*16. Interesting...

C:\gfortran\james\cmplx>type test2.f90
program test2
implicit none
real(4) x4
real(8) x8
real(10) x10
real(4), parameter :: p4 = 1.795195802051310421978653361874_4
real(8), parameter :: p8 = 1.795195802051310421978653361874_8
real(10), parameter :: p10 = 1.795195802051310421978653361874_10

x4 = 1.795195802051310421978653361874_4
x8 = 1.795195802051310421978653361874_8
x10 = 1.795195802051310421978653361874_10
write(*,*) complex(x4,z'40052A7FA9D2F8EA')
write(*,*) complex(p10,z'40052A7FA9D2F8EA')
write(*,*) dcmplx(x8,z'40052A7FA9D2F8EA')
write(*,*) dcmplx(p8,z'40052A7FA9D2F8EA')
write(*,*) kind(z'1')
write(*,*) 12345678901234567890_16
end program test2
C:\gfortran\james\cmplx>gfortran test2.f90 -otest2

C:\gfortran\james\cmplx>test2
( 1.7951958 , 4.61314012E+18)
( 1.7951958020513104000 , 0.0000000000000-(00000E-4933)
( 1.7951958020513104 , 4.61314012110932990E+018)
( 1.7951958020513104 , 2.6457513110645907 )
16
12345678901234567890

Notice that extra parenthesis in the second line of output. Design
or bug?

FX

unread,
May 11, 2008, 1:16:41 PM5/11/08
to
>> We see that gfortran in this case has treated the BOZ literals as
>> integers and then converted the integers to reals. This incorrect
>> behavior can only be seen when gfortran can't do constant folding.
>
> This is now know as PR36186
> (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36186).

A fix is ready, it'll be committed soon and will show up in your next
builds. Thanks for reporting this issue.

(Still sure you don't want to open a http://gcc.gnu.org/bugzilla
account?)

--
FX

John Harper

unread,
May 11, 2008, 8:33:33 PM5/11/08
to
In article <E9udndyVTK4S6LnV...@comcast.com>,

James Van Buskirk <not_...@comcast.net> wrote:
>"FX" <cou...@alussinan.org> wrote in message
>news:g01ij1$11gf$1...@nef.ens.fr...
>
>There is a buglet in the description of CMPLX in the standard:
>
>"If X is complex, it is as if X were real with the value REAL(X,KIND)
>and Y were present with the value AIMAG(X,KIND)."
>
>Nice concise prose, but AIMAG doesn't take a KIND optional agument.
>Maybe REAL(AIMAG(X),KIND) ?

That buglet seemed to have been squashed in the f95 standard Working
Draft of October 21, 1997, which says AIMAG(X), but it reappeared in
the f2003 Working Draft of May 10, 2004 and in the f2008 Working Draft
of 5th January 2007 :-(

But AIMAG has another problem: it is both generic and specific, but the
specific version is a default real function of a default complex
argument only. Pity there isn't a specific DAIMAG intrinsic function,
not to mention DCABS, DCCOS, DCEXP, DCLOG, DCONJ, DCSIN, DCSQRT.

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington 6140, New Zealand
e-mail john....@vuw.ac.nz phone (+64)(4)463 6780 fax (+64)(4)463 5045

Richard Maine

unread,
May 11, 2008, 8:55:07 PM5/11/08
to
John Harper <har...@mcs.vuw.ac.nz> wrote:

> But AIMAG has another problem: it is both generic and specific, but the
> specific version is a default real function of a default complex
> argument only. Pity there isn't a specific DAIMAG intrinsic function,
> not to mention DCABS, DCCOS, DCEXP, DCLOG, DCONJ, DCSIN, DCSQRT.

This "problem" is pretty much universal to all the intrinsics. You won't
find *ANY* new specifics for them. The number of specific names required
would be huge, not to speak of the fact that even what specifics were
appropriate would be compiler-dependent (because the number of kinds is
compiler dependent, and it would be problematic if changing kinds meant
that you no longer had a specific).

Sorry... (well, not very), but specific intrinsics have been on the way
out since f77. Using specific intrinsic names is basically an f66
practice. Adding zillions of new specific intrinsics just to support f66
styles isn't realistically going to happen. The number of places where
one actually needs a specific name for an intrinsic is miniscule to the
point of being essentially nonexistant. How many times do you actually
pass an intrinsic as an actual argument? Well, somehow I might believe a
non-zero answer from one or two people here, but if so, they are in a
pretty small minority.

And if you happen to have such an exceedingly rare case, it is usually
easy enough to work around by making a user-written specific procedure
as a wrapper. The number of cases where that workaround isn't viable
(because user procedures can't do some of the things that intrinsic ones
can) is even more rare. If you have such an unusual rarity, I'm afraid
that the cost benefit of throwing a zillion specifics into the standard
just isn't there.

For the most part, the answer is "don't do that."

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain

James Van Buskirk

unread,
May 11, 2008, 11:56:46 PM5/11/08
to
"FX" <cou...@alussinan.org> wrote in message
news:g079lo$2ur$1...@nef.ens.fr...

> A fix is ready, it'll be committed soon and will show up in your next
> builds. Thanks for reporting this issue.

Cool. Thanks.

> (Still sure you don't want to open a http://gcc.gnu.org/bugzilla
> account?)

I was on the cusp of doing that at one point in time but there was
something that was a showstopper for me, although I can't remember
what it was just off the top of my head.

In http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36214 I noticed
that if you print out rd, you get 0000000040295400 with the r
line in force, but 00000000402953FD with it commented out. If
the high and low dwords are reversed you get 402953FD00000000 in
both cases. It might have something to do with rd being denormal
as well as being BOZ.

0 new messages