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

gfortran read of hex values

211 views
Skip to first unread message

trizzzat

unread,
Dec 4, 2007, 6:06:10 PM12/4/07
to
I am using gfortran 4.2.2 and have the following issue. The following
statement

real, parameter :: cc_pi = ' some_hex_value 'X

does not produce the value of pi. In other compilers this works. Can
someone tell me how to take a hex value of pi and store it into a real
type variable in gfortran.

Steven G. Kargl

unread,
Dec 4, 2007, 6:37:52 PM12/4/07
to

Tobias Burnus

unread,
Dec 4, 2007, 6:38:33 PM12/4/07
to

Well, the easiest is the following:

real, parameter :: M_PI = acos(0.0)*2.0

Note: This is valid Fortran 2003, but acos is not a valid Fortran 95
initialization expression. It works at least with gfortran 4.1.3,
4.2.2 and 4.3.0.

Your
real, parameter :: M2_PI = z'40490FDB'
is not valid in Fortran 95/2003, which means that it is compiler
dependent whether it is accepted and how.

GFortran does the following:
real(int(z'40490FDB'))
which is not what you intended. Other compilers interpret it as
real(z'40490FDB')

The latter two versions are Fortran 2003 BOZ which are not yet
implemented in gfortran.

But why do you want to use BOZ to specify pi ? I can understand why to
use it for INF or NAN, but why not enter pi as:

real, parameter :: pi = 3.1415926535897931

This is much easier to understand!

Tobias

PS: gfortran BOZ bugreports:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18026
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29471

Paul van Delst

unread,
Dec 4, 2007, 6:48:18 PM12/4/07
to

Apart from your syntax issues regarding usage of "X" suffix rather than "Z" prefix, I
couldn't find anything in the standard that said it was o.k. to assign a hex constant to
anything but an integer. And even more, in section "4.3.1.1 Integer type", the f95
standard states

<quote>
In a DATA statement (5.2.10), an unsigned binary, octal, or hexadecimal literal
constant shall correspond to an integer scalar variable.
R407 boz-literal-constant is binary-constant
or octal-constant
or hex-constant
Constraint: A boz-literal-constant may appear only in a DATA statement.
</quote>

The constraint is quite clear.


Then again, the following program worked most of the time in bog standard mode:

program test_hexpi
implicit none
real, parameter :: cc_pi = z'40490FDB'
real :: rpi, zrpi
integer :: ipi, zipi
equivalence (rpi,ipi)
equivalence (zipi,zrpi)
rpi = 3.1415927
zipi = z'40490FDB'
write(*,'(z8)') ipi
write(*,'(f9.7)') zrpi
write(*,'(f9.7)') cc_pi
end program test_hexpi


lnx: lf95 test_hexpi.f90
Encountered 0 errors, 0 warnings in file test_hexpi.f90.
lnx: a.out
40490FDB
3.1415927
3.1415927

lnx: gfortran test_hexpi.f90
lnx: a.out
40490FDB
3.1415927
*********

lnx: g95 test_hexpi.f90
lnx: a.out
40490FDB
3.1415927
3.1415927

lnx: pgf95 test_hexpi.f90
lnx: a.out
40490FDB
3.1415927
3.1415927

m2n6: xlf95 test_hexpi.f90
** test_hexpi === End of Compilation 1 ===
1501-510 Compilation successful for file test_hexpi.f90.
m2n6 : a.out
40490FDB
3.1415927
3.1415927

but when I turned on conformance checking:

lnx: lf95 --f95 test_hexpi.f90
3114-W: "test_hexpi.f90", line 3, column 30: Position of binary, octal, or hexadecimal
literal constant is not standard-conforming.
3114-W: "test_hexpi.f90", line 9, column 10: Position of binary, octal, or hexadecimal
literal constant is not standard-conforming.
Encountered 0 errors, 2 warnings in file test_hexpi.f90.

lnx: g95 -std=f95 test_hexpi.f90
In file test_hexpi.f90:3

real, parameter :: cc_pi = z'40490FDB'
1
Warning (160): BOZ constant conversion at (1) is nonstandard


But interestingly gfortran produces no output message of non-conformance:

lnx: gfortran -std=f95 test_hexpi.f90
lnx: a.out
40490FDB
3.1415927
*********


Despite this it would seem gfortran is doing the right thing. Since the code is
non-conforming, output of "********" would seem to be valid. Annoying, maybe, but valid.

You got lucky with the other compilers. :o)


cheers,

paulv

Richard Maine

unread,
Dec 4, 2007, 6:54:21 PM12/4/07
to
Tobias Burnus <bur...@net-b.de> wrote:

> But why do you want to use BOZ to specify pi ? I can understand why to
> use it for INF or NAN, but why not enter pi as:
>
> real, parameter :: pi = 3.1415926535897931
>
> This is much easier to understand!

not to speak of being standard conforming and portable.

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

trizzzat

unread,
Dec 4, 2007, 8:46:37 PM12/4/07
to

Thank you all for all your answers. I wish things were that easy and
I could change pi to be 3.14159... , but this ported code must remain
intact as much as possible in the porting process so as to maintain
consistency with embedded software elsewhere. Also there are other
places were this initialization scheme is performed for other
variables, to which I have no idea what the values should be. I
already have the -std=legacy option on when I compile in gfortran so
after reading this I will attempt to use the equivalence method
tomorrow and see how things turn out. Thanks a bunch.

glen herrmannsfeldt

unread,
Dec 4, 2007, 9:33:53 PM12/4/07
to
Paul van Delst wrote:

(snip)

> Apart from your syntax issues regarding usage of "X" suffix rather than
> "Z" prefix, I couldn't find anything in the standard that said it was
> o.k. to assign a hex constant to anything but an integer. And even more,
> in section "4.3.1.1 Integer type", the f95 standard states

From Fortran 2003 C410 (R411)

"A boz-literal-constant shall appear only as a data-stmt-constant
in a DATA statement, as the actual argument associated with the
dummy argument A of the numeric intrinsic functions DBLE, REAL or
INT, or as the actual argument associated with the X or Y dummy
argument of the intrinsic function CMPLX."

If the DATA statement part is standard F95, that should be good
enough for the OP, though.

-- glen

James Van Buskirk

unread,
Dec 4, 2007, 10:22:53 PM12/4/07
to
"trizzzat" <dam....@gmail.com> wrote in message
news:bea6f0cf-644f-4441...@s19g2000prg.googlegroups.com...

> Thank you all for all your answers. I wish things were that easy and
> I could change pi to be 3.14159... , but this ported code must remain
> intact as much as possible in the porting process so as to maintain
> consistency with embedded software elsewhere. Also there are other
> places were this initialization scheme is performed for other
> variables, to which I have no idea what the values should be. I
> already have the -std=legacy option on when I compile in gfortran so
> after reading this I will attempt to use the equivalence method
> tomorrow and see how things turn out. Thanks a bunch.

My attitude is that if the compiler abuses you, you should abuse
it right back.

C:\gfortran\clf\bozpi>type bozpi.f90
! File: bozpi.f90
! Public domain 2007 James Van Buskirk
program bozpi
implicit none
integer intpi
real pi1
real pi2
data intpi / Z'40490FDB' /

pi1 = transfer(intpi, pi1)
pi2 = 4*atan(real(1,kind(pi2)))

write(*,*) 'BOZ ', pi1
write(*,*) 'ATAN', pi2
write(*,*) 'DIFF', pi1-pi2
end program bozpi
! End of file: bozpi.f90

C:\gfortran\clf\bozpi>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran -std=f95
-Wall bozpi.f90 -obozpi

C:\gfortran\clf\bozpi>bozpi
BOZ 3.1415927
ATAN 3.1415927
DIFF 0.00000000E+00

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


Steven G. Kargl

unread,
Dec 4, 2007, 11:19:04 PM12/4/07
to
In article <n8Wdnc-U17d3kcva...@comcast.com>,

Ah, no. A BOZ in a DATA statement is an integer with the
kind parameter for largest decimal range (I didn't check
the actually wording in the F95 standard, here; but I'm close).
The OP wants to initialize a REAL with a BOZ. This simply
isn't possible without using TRANSFER. A BOZ is not permitted
in DBLE, REAL, INT, or CMPLX in F95.

--
Steve
http://troutmask.apl.washington.edu/~kargl/

glen herrmannsfeldt

unread,
Dec 5, 2007, 12:31:41 AM12/5/07
to
Steven G. Kargl wrote:

(snip, I wrote)

>>If the DATA statement part is standard F95, that should be good
>>enough for the OP, though.

> Ah, no. A BOZ in a DATA statement is an integer with the
> kind parameter for largest decimal range (I didn't check
> the actually wording in the F95 standard, here; but I'm close).
> The OP wants to initialize a REAL with a BOZ. This simply
> isn't possible without using TRANSFER. A BOZ is not permitted
> in DBLE, REAL, INT, or CMPLX in F95.

I first knew Z constants in OS/360 Fortran, where they were allowed
to initialize REAL variables. VAX/VMS Fortran also had them
(the first of DEC's to support Z), also allowed for REAL variables.
(and where you learn what middle-endian really means.)

There are no BOZ examples in the DATA statement examples in F2003
(with or without INT, REAL, DBLE, or CMPLX).

Hopefully more compilers will soon implement the F2003 form.

-- glen

FX

unread,
Dec 5, 2007, 4:16:28 AM12/5/07
to
> My attitude is that if the compiler abuses you

Abuse by rejecting invalid code? Sounds cruel! :-)

--
FX

FX

unread,
Dec 5, 2007, 4:21:46 AM12/5/07
to
> Despite this it would seem gfortran is doing the right thing. Since the
> code is non-conforming, output of "********" would seem to be valid.
> Annoying, maybe, but valid.

gfortran outputs "********" because the output doesn't fit in your
format. What this code is doing is the same as
real, parameter :: cc_pi = 1078530011
as is demonstrated by the following:

$ cat a.f90

real, parameter :: cc_pi = z'40490FDB'

write(*,*) z'40490FDB', cc_pi
end
taigne /tmp $ gfortran a.f90 && ./a.out
1078530011 1.07853005E+09

I've never been too fond of BOZ but it does look like a logical thing to
do, doesn't it?

--
FX

Jugoslav Dujic

unread,
Dec 5, 2007, 7:51:16 AM12/5/07
to

I agree; other interpretations, as demonstrated by other compilers, belong into
the field of mind reading: "Tis ain't defined, but I suppose you wanted to
transfer bits from the left side to the entity on the right side. Or not,
but I'll give ya that anyway." Slightly more nicely formulated, they violate
the common Fotran approach that interpretation of a literal is not dependent
from
the context.

(compare DOUBLE PRECISION, PARAMETER:: Pi=3.14159265358979323846)

--
Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

trizzzat

unread,
Dec 5, 2007, 1:55:38 PM12/5/07
to
Everything worked out pretty well using the intrinsic transfer
function. The concern that I have is that in doing so I had to remove
the parameter statement which causes the variable to be fix. I've
been thinking of ways to make the variable fixed and still compile
with the right value but gave up. Thanks all.

Steven G. Kargl

unread,
Dec 5, 2007, 2:42:01 PM12/5/07
to
In article <ea4f13f0-9a59-413b...@e10g2000prf.googlegroups.com>,

What's wrong with

real, parameter :: pi = 3.1415926535897931

This has an advantage over TRANSFER when it comes to portable code.

--
Steve
http://troutmask.apl.washington.edu/~kargl/

trizzzat

unread,
Dec 5, 2007, 2:51:06 PM12/5/07
to
On Dec 5, 1:42 pm, ka...@troutmask.apl.washington.edu (Steven G.
Kargl) wrote:
> In article <ea4f13f0-9a59-413b-a8e7-68487969b...@e10g2000prf.googlegroups.com>,

> trizzzat <dam.tr...@gmail.com> writes:
>
> > Everything worked out pretty well using the intrinsic transfer
> > function. The concern that I have is that in doing so I had to remove
> > the parameter statement which causes the variable to be fix. I've
> > been thinking of ways to make the variable fixed and still compile
> > with the right value but gave up. Thanks all.
>
> What's wrong with
>
> real, parameter :: pi = 3.1415926535897931
>
> This has an advantage over TRANSFER when it comes to portable code.
>
> --
> Stevehttp://troutmask.apl.washington.edu/~kargl/

Cannot do this due to the nature of the code I'm porting. When using
the parameter statement it seems that variables cannot be on the right
hand side unless they are fixed constants. Also only intrinsic
operations are allowed on the right hand side.

Trung

trizzzat

unread,
Dec 5, 2007, 2:56:24 PM12/5/07
to
> Trung- Hide quoted text -
>
> - Show quoted text -

Final Solution:

REAL, PARAMETER :: CC_PI=TRANSFER('40490FDB'X,0.0)

This made CC_PI a fixed number and got what I wanted in the value of
CC_PI.

Steven G. Kargl

unread,
Dec 5, 2007, 2:57:44 PM12/5/07
to
In article <5926e0cf-1fca-4a81...@i12g2000prf.googlegroups.com>,

trizzzat <dam....@gmail.com> writes:
> On Dec 5, 1:42 pm, ka...@troutmask.apl.washington.edu (Steven G.
> Kargl) wrote:
>> In article <ea4f13f0-9a59-413b-a8e7-68487969b...@e10g2000prf.googlegroups.com>,
>> trizzzat <dam.tr...@gmail.com> writes:
>>
>> > Everything worked out pretty well using the intrinsic transfer
>> > function. The concern that I have is that in doing so I had to remove
>> > the parameter statement which causes the variable to be fix. I've
>> > been thinking of ways to make the variable fixed and still compile
>> > with the right value but gave up. Thanks all.
>>
>> What's wrong with
>>
>> real, parameter :: pi = 3.1415926535897931
>>
>> This has an advantage over TRANSFER when it comes to portable code.
>>
>
> Cannot do this due to the nature of the code I'm porting. When using
> the parameter statement it seems that variables cannot be on the right
> hand side unless they are fixed constants. Also only intrinsic
> operations are allowed on the right hand side.

Huh, what do you mean right hand side? 3.14... is a literal constant.

Are you coding to some bizarre coding standard?

--
Steve
http://troutmask.apl.washington.edu/~kargl/

John Harper

unread,
Dec 5, 2007, 4:18:11 PM12/5/07
to
In article <ea4f13f0-9a59-413b...@e10g2000prf.googlegroups.com>,

In f2003 you can do it AFAIK, and g95 and Intel both have enough f2003
to make the following compile and run and produce the expected output.

! File: bozpi2.f90 Public domain 2007
! By J F Harper, based on James Van Buskirk's bozpi.f90
program bozpi2
implicit none
integer,parameter:: intpi = int(Z'40490FDB')
real,parameter:: dummy = 0, &
pi1 = transfer(intpi, dummy), &
pi2 = 4*atan(real(1,kind(dummy)))

write(*,*) 'BOZ ', pi1
write(*,*) 'ATAN', pi2
write(*,*) 'DIFF', pi1-pi2

end program bozpi2
! end of file bozpi2.f90

When I tried that program with gfortran, either with or without
the -std=f2003 option, it compiled and ran but I got this output:
BOZ 3.141593
ATAN 3.141593
DIFF -2.0054164E+09
On logging out and in again I got the same values for BOZ and ATAN
but DIFF -2.0051707E+09 with -std=f2003, -2.0054533E+09 without.

Our gfortran-capable machine has an old version: gfortran -v reveals
gcc version 4.1.1 20070105 (Red Hat 4.1.1-52) and I can't update that.
What does up-to-date gfortran do? Is the program valid f2003?

-- 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 5341 fax (+64)(4)463 5045

Tobias Burnus

unread,
Dec 5, 2007, 4:40:14 PM12/5/07
to
> When I tried that program with gfortran, either with or without
> the -std=f2003 option, it compiled and ran but I got this output:
> BOZ 3.141593
> ATAN 3.141593
> DIFF -2.0054164E+09

I do not understand what gfortran 4.1 does for:
write(*,*) 'DIFF', pi1-pi2
however, using
write(*,*) 'DIFF', (pi1-pi2)
prints the desired result.

Alternatively, use gfortran 4.2.x or 4.3, which print the desired 0.0
also without the "( )".

(Seems to be time to recommend 4.2.x or higher instead of 4.1.x or
higher...)

Tobias

James Van Buskirk

unread,
Dec 5, 2007, 4:56:56 PM12/5/07
to
"John Harper" <har...@mcs.vuw.ac.nz> wrote in message
news:11968894...@bats.mcs.vuw.ac.nz...

> Our gfortran-capable machine has an old version: gfortran -v reveals
> gcc version 4.1.1 20070105 (Red Hat 4.1.1-52) and I can't update that.
> What does up-to-date gfortran do? Is the program valid f2003?

C:\gfortran\clf\bozpi>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran -v
Using built-in specs.
Target: x86_64-pc-mingw32
Configured with:
../trunk/configure --prefix=/home/FX/win64 --build=i386-pc-ming
w32 --target=x86_64-pc-mingw32 --enable-languages=c,fortran --with-gmp=/home/FX/
local --disable-werror --disable-nls --enable-threads=win32
Thread model: win32
gcc version 4.3.0 20071130 (experimental) [trunk revision 130537] (GCC)

C:\gfortran\clf\bozpi>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran

bozpi2.f9
0 -std=f2003 -obozpi2

C:\gfortran\clf\bozpi>bozpi2


BOZ 3.1415927
ATAN 3.1415927
DIFF 0.0000000

Yes, I think it's valid f03; the stuff you could do in initialization
expressions was greatly expanded there. ifort 9.1 doesn't like that
ATAN in an initialization expression, though.

John Harper

unread,
Dec 5, 2007, 7:17:32 PM12/5/07
to
In article <mKudnUyYcNE3g8ra...@comcast.com>,

James Van Buskirk <not_...@comcast.net> wrote:
>"John Harper" <har...@mcs.vuw.ac.nz> wrote in message
>news:11968894...@bats.mcs.vuw.ac.nz...
>
>> What does up-to-date gfortran do? Is the program valid f2003?
...

>
>C:\gfortran\clf\bozpi>bozpi2
> BOZ 3.1415927
> ATAN 3.1415927
> DIFF 0.0000000
>
>Yes, I think it's valid f03; the stuff you could do in initialization
>expressions was greatly expanded there. ifort 9.1 doesn't like that
>ATAN in an initialization expression, though.

I was using ifort 10.0, which was happy with it.

Tobias Burnus

unread,
Dec 6, 2007, 5:31:41 PM12/6/07
to
On Dec 5, 12:48 am, Paul van Delst <Paul.vanDe...@noaa.gov> wrote:
> trizzzat wrote:
> > I am using gfortran 4.2.2 and have the following issue. The following
> > statement
> >
> > real, parameter :: cc_pi = ' some_hex_value 'X
> >
> > does not produce the value of pi.

> real, parameter :: cc_pi = z'40490FDB'
> zipi = z'40490FDB'

> But interestingly gfortran produces no output message of non-conformance:
>
> lnx: gfortran -std=f95 test_hexpi.f90
> lnx: a.out
> 40490FDB
> 3.1415927

I just submitted [1] a patch for gfortran, which does the following:

a) Implements Fortran 2003's BOZ in REAL, INT, DBLE, CMPLX

b) Gives an error with -std=f2003/f95 when using a BOZ to initialize
non-integer variables in the DATA statements

c) Rejects with -std=f95 all BOZ outside DATA statements

d) TRANSFERs the bit pattern of the BOZ for real/complex variables in
DATA statements

e) Supports
real :: r = z'boz'
which is treated as "r = real(z'b0')". Note, however, that as
procedure argument or as soon as you have expressions on the right-
hand side ("r = z'b0' + 1"), the boz is regarded as integer (with
maximal supported integer precision).

From an older patch but recent patch:
f) 'boz'z now gives an error for -std=f95/f2005. (The check was there
before but became not active.)

g) x'boz' gives now also an error for -std=f2003 without using -
pedantic.

Tobias

[1] http://gcc.gnu.org/ml/gcc-patches/2007-12/msg00296.html

James Van Buskirk

unread,
Dec 14, 2007, 8:27:19 PM12/14/07
to
"FX" <cou...@alussinan.org> wrote in message
news:fj5q9c$15uc$1...@nef.ens.fr...

>> My attitude is that if the compiler abuses you

> Abuse by rejecting invalid code? Sounds cruel! :-)

Yes, but my counterabuse was the short form, too. The long form:

! File: abuse.f90


! Public domain 2007 James Van Buskirk

module abuse_mod
implicit none
integer, parameter :: ik1 = selected_int_kind(2)
integer, parameter :: ik2 = selected_int_kind(4)
character(8), parameter :: HEX1 = '40490FDB'
integer(ik2), parameter :: q47 = iachar('0')-1, &
q58 = iachar('9')+1, q64 =iachar('A')-1, q91 = iachar('Z')+1, &
q223 = 223, q15 = 15
integer i
integer(ik1), parameter :: MSKa1(len(HEX1)) = iand([(ishft(iand( &
iachar(HEX1(i:i))-q58,q47-iachar(HEX1(i:i))),-8),i=1,len(HEX1) &
)],q15)
integer(ik1), parameter :: MSKb1(len(HEX1)) = iand([(ishft(iand( &
iand(iachar(HEX1(i:i)),q223)-q91,q64-iand(iachar(HEX1(i:i)),q223)) &
,-8),i=1,len(HEX1))],q15)
integer(ik1), parameter :: ARR1(len(HEX1)) = [(iand(iachar( &
HEX1(i:i))-48,MSKa1(i))+iand(iand(iachar(HEX1(i:i)),-33_ik1)-55, &
MSKb1(i)),i=1,len(HEX1))]
integer, parameter :: HFu1 = ((ARR1(1)*16+ARR1(2))*16+ARR1(3))*16+ARR1(4)
integer, parameter :: HFl1 = ((ARR1(5)*16+ARR1(6))*16+ARR1(7))*16+ARR1(8)
real, parameter :: pi = transfer(ishft(HFu1,16)+HFl1, real(1,kind(pi)))
end module abuse_mod

program abuse
use abuse_mod
implicit none
character(len(HEX1)) cpi
real pi1

cpi = HEX1
read(cpi,'(z8)') pi1
write(*,*) pi1
write(*,*) pi
end program abuse
! End of file: abuse.f90

Walter Spector

unread,
Dec 15, 2007, 9:08:55 AM12/15/07
to
James Van Buskirk wrote:
> "FX" <cou...@alussinan.org> wrote in message
> news:fj5q9c$15uc$1...@nef.ens.fr...
>
>>> My attitude is that if the compiler abuses you
>
>> Abuse by rejecting invalid code? Sounds cruel! :-)
>
> Yes, but my counterabuse was the short form, too. The long form:
> ...
That is pretty abusive. Even after changing the square brackets
back to (/ /), only 1 of the 5 compilers I tried would compile it.

W.

James Van Buskirk

unread,
Dec 15, 2007, 9:51:10 AM12/15/07
to
"Walter Spector" <w6ws_xt...@earthlink.net> wrote in message
news:13m7nvp...@corp.supernews.com...

> That is pretty abusive. Even after changing the square brackets
> back to (/ /), only 1 of the 5 compilers I tried would compile it.

Darn, I didn't realize that ifort passes MIL-STD 1753 intrinsics
with mixed KINDs by default. Here is a fix; see if more compilers
like it:

! File: abuse1.f90


! Public domain 2007 James Van Buskirk
module abuse_mod
implicit none
integer, parameter :: ik1 = selected_int_kind(2)
integer, parameter :: ik2 = selected_int_kind(4)
character(8), parameter :: HEX1 = '40490FDB'
integer(ik2), parameter :: q47 = iachar('0')-1, &
q58 = iachar('9')+1, q64 =iachar('A')-1, q91 = iachar('Z')+1, &
q223 = 223, q15 = 15
integer i

integer(ik1), parameter :: MSKa1(len(HEX1)) = iand((/(ishft(iand( &
int(iachar(HEX1(i:i)),ik2)-q58,q47-int(iachar(HEX1(i:i)),ik2)), &
-8), i=1,len(HEX1))/),q15)
integer(ik1), parameter :: MSKb1(len(HEX1)) = iand((/(ishft(iand( &
iand(int(iachar(HEX1(i:i)),ik2),q223)-q91,q64-iand(int(iachar( &
HEX1(i:i)),ik2),q223)),-8),i=1,len(HEX1))/),q15)
integer(ik1), parameter :: ARR1(len(HEX1)) = (/(iand(int(iachar( &
HEX1(i:i))-48,ik1),MSKa1(i))+iand(iand(int(iachar(HEX1(i:i)), &
ik1),-33_ik1)-55_ik1, MSKb1(i)),i=1,len(HEX1))/)
integer, parameter :: HFu1 = ((ARR1(1)*16+ARR1(2))*16+ARR1(3))*16+ &
ARR1(4)
integer, parameter :: HFl1 = ((ARR1(5)*16+ARR1(6))*16+ARR1(7))*16+ &
ARR1(8)
real, parameter :: pi = transfer(ishft(HFu1,16)+HFl1, &


real(1,kind(pi)))
end module abuse_mod
program abuse
use abuse_mod
implicit none
character(len(HEX1)) cpi
real pi1

cpi = HEX1
read(cpi,'(z8)') pi1
write(*,*) pi1
write(*,*) pi
end program abuse

! End of file: abuse1.f90

At least it's a sort of a solution to the problem the O.P. posed
in that it takes a BOZ string and turns it into a REAL PARAMETER.

Walter Spector

unread,
Dec 15, 2007, 11:32:33 AM12/15/07
to
James Van Buskirk wrote:
> "Walter Spector" <w6ws_xt...@earthlink.net> wrote in message
> news:13m7nvp...@corp.supernews.com...
>
>> That is pretty abusive. Even after changing the square brackets
>> back to (/ /), only 1 of the 5 compilers I tried would compile it.
>
> Darn, I didn't realize that ifort passes MIL-STD 1753 intrinsics
> with mixed KINDs by default. Here is a fix; see if more compilers
> like it:

That helps a bit. Yes, ifort compiled and ran both versions. On
the second version:

IRIX f90 (MIPSpro 7.4.4m) does not like the REAL (1, KIND (pi)).
I think, by F95, it has a right to object. (Result of REAL is not
an INTEGER or CHARACTER.) So fixing the initialization
of pi to read the following, works:

integer, parameter :: one = 1.0
integer, parameter :: pi = transfer (ishft (HFu1,16)+HFl1, one)

G95 compiled the (unmodified) second version, but gave a runtime
error when doing the decode in the main program. It doesn't like
using hex conversion into a REAL variable. (Again, I think that
by F95, the RTL has a right to complain.) It works by changing
the main program to:

integer :: ipi1
real :: pi1
equivalence (ipi1, pi1)
...
read(cpi,'(z8)') pi1

Salford loses track of I and whines that it isn't a parameter.
(Simpler cases of using I in an array constructor work OK though.)

And finally gfortran loses track of things when doing the initialization
of ARR1 - which then cascades into errors when initializing HFu1 and HFl1.

Bottom line is that if you fix the two non-Standardisms (by f95), the
success rate goes up to 3 of 5. Salford and gfortran have bugs to fix.

W.

Walter Spector

unread,
Dec 15, 2007, 11:36:35 AM12/15/07
to
Walter Spector wrote:
> ...

> G95 compiled the (unmodified) second version, but gave a runtime
> error when doing the decode in the main program. It doesn't like
> using hex conversion into a REAL variable. (Again, I think that
> by F95, the RTL has a right to complain.) It works by changing
> the main program to:
>
> integer :: ipi1
> real :: pi1
> equivalence (ipi1, pi1)
> ...
> read(cpi,'(z8)') pi1

Oops. I meant:

read (cpi,'(z8)') ipi1

> ...

James Van Buskirk

unread,
Dec 15, 2007, 3:33:15 PM12/15/07
to
"Walter Spector" <w6ws_xt...@earthlink.net> wrote in message
news:13m80d2...@corp.supernews.com...

> IRIX f90 (MIPSpro 7.4.4m) does not like the REAL (1, KIND (pi)).
> I think, by F95, it has a right to object. (Result of REAL is not
> an INTEGER or CHARACTER.) So fixing the initialization
> of pi to read the following, works:

> integer, parameter :: one = 1.0
> integer, parameter :: pi = transfer (ishft (HFu1,16)+HFl1, one)

Yep, that is a pesky one. First off, I take it that your actual
code ran more like:

real, parameter :: one = 1.0

My first attempt was:

integer, parameter :: pi = transfer (ishft (HFu1,16)+HFl1, pi)

but that didn't work because TRANSFER isn't a specification
inquiry, even through its MOLD argument, even in f03. Probably
an act of mercy towards compiler writers. I always forget that
REAL and even LOGICAL were forbidden in f95 initialization
expressions. After all, structure constructors were allowed so

integer, parameter :: dp = selected_real_kind(15,300)
type x
real(kind = dp) x
end type x
type(x), parameter :: y = x(1)

is OK, but

integer, parameter :: dp = selected_real_kind(15,300)
real(dp), parameter :: y = real(1,kind(y))

is not until f03 where the stuff allowed in initialization
expressions is so inclusive that it will break compilers
for decades to come just as it is breaking f95 compilers
through specification expressions right now. Hmmm, neither
ifort of 20061104 with /stand:f95 nor gfortran of 20071130
with -std=f95 can be made to warn about the latter usage.
Do you suppose an interp changed this or are both compilers
being naughty?

> G95 compiled the (unmodified) second version, but gave a runtime
> error when doing the decode in the main program. It doesn't like
> using hex conversion into a REAL variable. (Again, I think that
> by F95, the RTL has a right to complain.) It works by changing
> the main program to:

> integer :: ipi1
> real :: pi1
> equivalence (ipi1, pi1)
> ...
> read(cpi,'(z8)') pi1

The correction to the above from your future post will be noted.
That's dusty-deck FORTRAN for sure so of course it worked quite
smoothly in ifort. This was another case of my being flustered
in that my first attempt was:

read(HEX1,'(z8)') pi

and so I had to fix reading from a named constant to reading
from a variable and didn't check that the ways of the old ones
also were not permitted regarding reading with an INTEGER format
into a REAL variable. Had I read into a HOLLERITH constant I'm
sure everything would have worked out fine. gfortran would have
caught this had it survived the battery of initialization
expressions.

> Salford loses track of I and whines that it isn't a parameter.
> (Simpler cases of using I in an array constructor work OK though.)

> And finally gfortran loses track of things when doing the initialization
> of ARR1 - which then cascades into errors when initializing HFu1 and HFl1.

> Bottom line is that if you fix the two non-Standardisms (by f95), the
> success rate goes up to 3 of 5. Salford and gfortran have bugs to fix.

Thanks for the testing! It's amazing you much nonstandard stuff you
can put in a source file and have it still look completely normal to
the author.

Walter Spector

unread,
Dec 15, 2007, 5:26:35 PM12/15/07
to
James Van Buskirk wrote:
> "Walter Spector" <w6ws_xt...@earthlink.net> wrote in message
> news:13m80d2...@corp.supernews.com...
>> integer, parameter :: one = 1.0
>> integer, parameter :: pi = transfer (ishft (HFu1,16)+HFl1, one)
>
> Yep, that is a pesky one. First off, I take it that your actual
> code ran more like:
>
> real, parameter :: one = 1.0
>
> My first attempt was:
>
> integer, parameter :: pi = transfer (ishft (HFu1,16)+HFl1, pi)

Double typos in the post... Both one and pi should be REAL...

> but that didn't work because TRANSFER isn't a specification
> inquiry, even through its MOLD argument, even in f03. Probably
> an act of mercy towards compiler writers. I always forget that
> REAL and even LOGICAL were forbidden in f95 initialization
> expressions.

The LOGICAL restriction made little sense to me. The REAL (and DP and
COMPLEX) restriction, made somewhat more sense - since, in a compiler
with reasonable QOI, one would want initialization (compile-time)
and run-time expressions to give bit-by-bit identical results to the
extent possible.

> ...


> Hmmm, neither
> ifort of 20061104 with /stand:f95 nor gfortran of 20071130
> with -std=f95 can be made to warn about the latter usage.
> Do you suppose an interp changed this or are both compilers
> being naughty?

No idea. Most of the code I write is pretty well-defined by F95.

W.

James Van Buskirk

unread,
Dec 16, 2007, 1:35:58 AM12/16/07
to
"Walter Spector" <w6ws_xt...@earthlink.net> wrote in message
news:13m8l4s...@corp.supernews.com...

> The LOGICAL restriction made little sense to me. The REAL (and DP and
> COMPLEX) restriction, made somewhat more sense - since, in a compiler
> with reasonable QOI, one would want initialization (compile-time)
> and run-time expressions to give bit-by-bit identical results to the
> extent possible.

Actually I was referring to the intrinsic functions REAL and
LOGICAL, not the data types. Your comments still have validity in
that context anyway. I thought to have a little fun with gfortran
here:

C:\gfortran\clf\abuse>type paramtest.f90
integer, parameter :: ipi = Z'40490fdb'
real pi
parameter(pi=transfer(ipi,pi))
real, parameter :: z = transfer(ipi,z)
real, parameter :: y = real(1,kind(y))

write(*,*) pi, z, y
end

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
paramtest
.f90 -std=f95 -oparamtest

C:\gfortran\clf\abuse>paramtest
3.1415927 3.1415927 1.00000000

All lines with 'parameter' in them should not be valid f95: the
first because the BOZ literal is not in a DATA statement, the second
and third treat transfer as a specification inquiry even thought
that is not permitted even in f03, and the fourth has that pesky
REAL intrinsic, which is not an elemental function of type integer
or character. We can find stuff that gfortran doesn't like:

C:\gfortran\clf\abuse>type paramtest.f90
real, parameter :: pi = Z'40490fdb'
real, parameter :: z = transfer(z,z)
real, parameter :: y = real(pi,kind(y))

write(*,*) pi, z, y
end

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
paramtest
.f90 -std=f95 -oparamtest
paramtest.f90:2.3:

real, parameter :: z = transfer(z,z)
1
Error: Unclassifiable statement at (1)
paramtest.f90:3.25:

real, parameter :: y = real(pi,kind(y))
1
Error: Fortran 2003: Elemental function as initialization expression with
non-in
teger/non-character arguments at (1)

So it still likes the BOZ, although I think the result is not what
the programmer would expect, it errors on the other two lines but
the first error might be rather difficult to interpret if we hadn't
composed that line just to torture the compiler. Just a couple
more:

C:\gfortran\clf\abuse>type paramtest.f90
real, parameter :: pi = Z'40490fdb'
real z
parameter(z = transfer(z,z))
real, parameter :: y = real(Z'deadbeef',kind(y))

write(*,*) pi, z, y
end

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
paramtest
.f90 -std=f95 -oparamtest
paramtest.f90:3.26:

parameter(z = transfer(z,z))
1
Error: Parameter 'z' at (1) has not been declared or is a variable, which
does n
ot reduce to a constant expression

Mmmm... fair enough. How about:

C:\gfortran\clf\abuse>type paramtest.f90
real, parameter :: pi = Z'40490fdb'
real z
! parameter(z = transfer(z,z))
real, parameter :: y = real(Z'deadbeef',kind(y))

write(*,*) pi, z, y
end

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
paramtest
.f90 -std=f95 -oparamtest

C:\gfortran\clf\abuse>paramtest
1.07853005E+09 0.00000000E+00 3.73592858E+09

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran -v


Using built-in specs.
Target: x86_64-pc-mingw32
Configured with:
../trunk/configure --prefix=/home/FX/win64 --build=i386-pc-ming
w32 --target=x86_64-pc-mingw32 --enable-languages=c,fortran --with-gmp=/home/FX/
local --disable-werror --disable-nls --enable-threads=win32
Thread model: win32
gcc version 4.3.0 20071130 (experimental) [trunk revision 130537] (GCC)

So it compiles. The nonstandard usage of BOZ, though not flagged,
leads to the kind of results discussed earlier.

Thomas Koenig

unread,
Dec 16, 2007, 6:26:21 AM12/16/07
to
On 2007-12-16, James Van Buskirk <not_...@comcast.net> wrote:

> C:\gfortran\clf\abuse>type paramtest.f90
> integer, parameter :: ipi = Z'40490fdb'
> real pi
> parameter(pi=transfer(ipi,pi))
> real, parameter :: z = transfer(ipi,z)
> real, parameter :: y = real(1,kind(y))
>
> write(*,*) pi, z, y
> end

With a recent gfortran:

$ cat > foo.f90


integer, parameter :: ipi = Z'40490fdb'
real pi
parameter(pi=transfer(ipi,pi))
real, parameter :: z = transfer(ipi,z)
real, parameter :: y = real(1,kind(y))

write(*,*) pi, z, y
end

$ gfortran -std=f95 -pedantic foo.f90
foo.f90:1.42:

integer, parameter :: ipi = Z'40490fdb'

1
Error: Fortran 2003: BOZ used outside a DATA statement at (1)
foo.f90:3.25:

parameter(pi=transfer(ipi,pi))
1
Error: Parameter 'ipi' at (1) has not been declared or is a variable,
which does not reduce to a constant expression
foo.f90:4.35:

real, parameter :: z = transfer(ipi,z)

1
Error: Parameter 'ipi' at (1) has not been declared or is a variable,
which does not reduce to a constant expression

At least the BOZ case has been fixed. I'll look into the others.

James Van Buskirk

unread,
Dec 16, 2007, 11:10:26 AM12/16/07
to
"Thomas Koenig" <tko...@netcologne.de> wrote in message
news:slrnfma2r2....@meiner.onlinehome.de...

> On 2007-12-16, James Van Buskirk <not_...@comcast.net> wrote:

>> C:\gfortran\clf\abuse>type paramtest.f90
>> integer, parameter :: ipi = Z'40490fdb'
>> real pi
>> parameter(pi=transfer(ipi,pi))
>> real, parameter :: z = transfer(ipi,z)
>> real, parameter :: y = real(1,kind(y))

>> write(*,*) pi, z, y
>> end

> At least the BOZ case has been fixed. I'll look into the others.

I took a look at N1601.pdf and in section 13.7.121 (about TRANSFER)
it says:

"MOLD may be of any type. It may be a scalar or an array. If it
is a variable, it need not be defined."

That last sentence above is new to f03 and makes TRANSFER act sort
of like a specification inquiry through its MOLD argument. Whoops,
wrong again, James. That clause was added in Corrigendum 2, so the
syntax is correct for f95 even. Let's see... the compiler that
didn't like MOLD being undefined was ifort. Suppose we try this
"need not be defined" stuff in a few specification and
initialization expressions:

C:\gfortran\clf\abuse>type test2.f90
module more_stuff
implicit none
contains
recursive subroutine sub(x)
integer, intent(in) :: x
integer i
real pi4
character(0) sv1(int(transfer(x,pi4)))
parameter(pi4 = transfer(3.14159265358979,1.0))

write(*,*) size(sv1)
end subroutine sub
end module more_stuff

program test2
use more_stuff
implicit none
integer, parameter :: ipi = 1078530011
real, parameter :: pi1 = transfer(ipi,pi1)
real :: pi2 = transfer(ipi,pi2)
real pi3
parameter(pi3 = transfer(ipi,pi3))

write(*,*) pi1, pi2, pi3
call sub(ipi)
end program test2

C:\gfortran\clf\abuse>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran

test2.f90
-std=f95 -otest2

C:\gfortran\clf\abuse>test2
3.1415927 3.1415927 3.1415927
3

C:\gfortran\clf\abuse>ifort /stand:f95 test2.f90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

test2.f90(9) : Error: Conflicting attributes or multiple declaration of
name.
[PI4]
parameter(pi4 = transfer(3.14159265358979,1.0))
-------------------^
test2.f90(7) : Error: A specification expression object must be a dummy
argument
, a COMMON block object, or an object accessible through host or use
association
[PI4]
real pi4
--------------^
test2.f90(16) : Error: This module file was not generated by any release of
this
compiler. [MORE_STUFF]
use more_stuff
-------^
test2.f90(19) : Error: A PARAMETER must not be defined in terms of itself.
[PI
1]
real, parameter :: pi1 = transfer(ipi,pi1)
-----------------------------------------^
test2.f90(22) : Error: A PARAMETER must not be defined in terms of itself.
[PI
3]
parameter(pi3 = transfer(ipi,pi3))
--------------------------------^
test2.f90(20) : Error: This symbol must be a defined parameter or an
argument of
an inquiry function that evaluates to a compile-time constant. [PI2]
real :: pi2 = transfer(ipi,pi2)
------------------------------^
test2.f90(20) : Error: This is not a valid initialization expression.
[TRANSFE
R]
real :: pi2 = transfer(ipi,pi2)
-----------------^
compilation aborted for test2.f90 (code 1)

Well, this is an old version of ifort, so maybe it's been fixed. Or
maybe my example is massively invalid. For example, the
documentation for the TRANSFER intrinsic says the MOLD argument need
not be defined if it's a variable, but a parameter is not a variable
so maybe it does have to be defined in this context.

Oh, side note:

character(0) h4(1:minval([(1,i=1,0)],1))

gives an array of huge size (2**31-1) but it doesn't need 1.2 TB
nor even 1.2 GB because each element has zero size.

0 new messages