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

exponentiation

69 views
Skip to first unread message

Eugene

unread,
Jan 12, 2009, 5:56:56 PM1/12/09
to
Hi
Does the following expression make difference?
2.D0**2
2.D0**2.
2.D0**2.D0
Thanks a lot.

glen herrmannsfeldt

unread,
Jan 12, 2009, 7:01:03 PM1/12/09
to
Eugene <yjy...@gmail.com> wrote:

> Does the following expression make difference?
> 2.D0**2
> 2.D0**2.
> 2.D0**2.D0

yes.

-- glen

George

unread,
Jan 12, 2009, 7:17:59 PM1/12/09
to

I rarely find d0 useful, because if you need double precision, then you're
going to want it in a form that you can use in an initialization
expression.

The above will give 4.0, but you'll want to assign that value to something
that you've declared dp as well.

Might as well have dp defined in a form you can use portably:

integer, parameter :: dp = selected_real_kind(15)
real(kind=dp):: x,y,z

If what you're doing is squaring a real, the exponent is best just the
integer 2 :

x=2.0_dp**2

Cheers,
--
George

I believe in the transformational power of liberty. I believe that the free
Iraq is in this nation's interests. I believe a free Afghanistan is in this
nation's interest.
George W. Bush

Picture of the Day http://apod.nasa.gov/apod/

jwm

unread,
Jan 12, 2009, 11:25:55 PM1/12/09
to

In theory, "2.D0**2" can be evaluated as "2.D0*2.D0", but for
"2.D0**2." and "2.D0**2.D0" the compiler might have to do a little
more effort (e.g., some logarithmic rule, depending on how
"intelligent" the compiler is).

In the examples you posted, it really makes no difference since the
effort occurs during compilation (not at runtime).

Richard Maine

unread,
Jan 13, 2009, 12:09:37 AM1/13/09
to
jwm <jwmw...@gmail.com> wrote:

Yes. The literal examples posted are just "silly" in that it would be
far better to just write 4.0d0 than any of them. But when you
extrapolate to more realistic cases, things get very different. Among
other things, x**2. and x**2.d0 are both illegal if the value of x is
negative, whereas x**2 is perfectly fine.

Some compilers might happen to quietly "fix" such an error for you, but
it would still technically be an error.

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

michael...@compuserve.com

unread,
Jan 13, 2009, 1:18:19 AM1/13/09
to
On Jan 13, 5:25 am, jwm <jwmwal...@gmail.com> wrote:
> On Jan 12, 3:56 pm, Eugene <yjyi...@gmail.com> wrote:
>
>In theory, "2.D0**2" can be evaluated as "2.D0*2.D0",

... not according to the rules of Fortran ("Fortran 95/2003
Explained", Table 3.2).

Regards,

Mike Metcalf

James Van Buskirk

unread,
Jan 13, 2009, 1:36:17 AM1/13/09
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1itg7xr.1acwkhh72elnmN%nos...@see.signature...

> jwm <jwmw...@gmail.com> wrote:

>> On Jan 12, 3:56 pm, Eugene <yjyi...@gmail.com> wrote:
>> > Hi
>> > Does the following expression make difference?
>> > 2.D0**2
>> > 2.D0**2.
>> > 2.D0**2.D0
>> > Thanks a lot.

>> In theory, "2.D0**2" can be evaluated as "2.D0*2.D0", but for
>> "2.D0**2." and "2.D0**2.D0" the compiler might have to do a little
>> more effort (e.g., some logarithmic rule, depending on how
>> "intelligent" the compiler is).

>> In the examples you posted, it really makes no difference since the
>> effort occurs during compilation (not at runtime).

> Yes. The literal examples posted are just "silly" in that it would be
> far better to just write 4.0d0 than any of them. But when you
> extrapolate to more realistic cases, things get very different. Among
> other things, x**2. and x**2.d0 are both illegal if the value of x is
> negative, whereas x**2 is perfectly fine.

> Some compilers might happen to quietly "fix" such an error for you, but
> it would still technically be an error.

In f95 the expressions

2.D0**2

and

2.D0**2.

are semantically different and are required by the standard to
produce distinct results for programs that are appropriately
designed.

Here we go:

C:\gfortran\clf\exponent_test>type exponent_test.f90
module funcs
implicit none
contains
recursive function initialization(x) result(f)
logical f
integer x
integer z(0*transfer(2.D0**2,1)+2)
save

z = 0
if(x > 0) then
z = 1
f = initialization(x-1)
end if
f = z(1) == 0
end function initialization

recursive function non_initialization(x) result(f)
logical f
integer x
integer z(0*transfer(2.D0**2.,1)+2)
save

z = 0
if(x > 0) then
z = 1
f = initialization(x-1)
end if
f = z(1) == 0
end function non_initialization
end module funcs

program exponent_test
use funcs
implicit none

write(*,*) initialization(1), non_initialization(1)
end program exponent_test

C:\gfortran\clf\exponent_test>gfortran -std=f95
exponent_test.f90 -oexponent_tes
t
f951.exe: internal compiler error: in gfc_target_encode_expr, at
fortran/target-
memory.c:244
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

C:\gfortran\clf\exponent_test>ifort /stand:f95 exponent_test.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.

exponent_test.f90(21) : Warning: Fortran 95 requires an INTEGER data type in
thi
s context. [2.]
integer z(0*transfer(2.D0**2.,1)+2)
------------------------------------^
Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.

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

C:\gfortran\clf\exponent_test>exponent_test
T F

At least ifort 9.1 gets the semantic distinction, although its
warning message is incorrect. ISO/IEC 1539-1:1997(E) section 7.1.6.1
says:

"An initialization expression is a constant expression in which the
exponentiation operation is permitted only with an integer power, and
each primary is
...
(5) A reference to one of the transformational functions REPEAT,
RESHAPE, SELECTED_INT_KIND, SELECTED_REAL_KIND, TRANSFER, or TRIM,
where each argument is an initialization expression."

so

integer z(0*transfer(2.D0**2.,1)+2)

has a shape which is not an initialization expression, but section
7.1.6.2 says:

"A restricted expression is an expression in which each operation
is intrinsic and each primary is
...
(8) A reference to any other intrinsic function defined in this
standard where each argument is a restricted expression"

so z is an automatic data object, therefore the empty SAVE does
not apply to it. ifort's warning message is incorrect (I don't know
whether this has been fixed in later versions) but it generates
correct code nonetheless: 2.D0**2 really is different from 2.D0**2.
as we can see because the former expression results in .TRUE. while
the latter yields .FALSE. when the question is put: "is this an f95
initialization expression?"

The latest build of gfortran by www.equation.com didn't seem to make
a useful compiler so I can't report results more recent than a month
ago for that compiler which is unfortunate because some work was done
in this area just recently.

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


kar...@comcast.net

unread,
Jan 13, 2009, 1:44:34 AM1/13/09
to
On Jan 12, 9:09 pm, nos...@see.signature (Richard Maine) wrote:

> jwm <jwmwal...@gmail.com> wrote:
> > On Jan 12, 3:56 pm, Eugene <yjyi...@gmail.com> wrote:
> > > Hi
> > > Does the following expression make difference?
> > > 2.D0**2
> > > 2.D0**2.
> > > 2.D0**2.D0
> > > Thanks a lot.
>
> > In theory, "2.D0**2" can be evaluated as "2.D0*2.D0", but for
> > "2.D0**2." and "2.D0**2.D0" the compiler might have to do a little
> > more effort (e.g., some logarithmic rule, depending on how
> > "intelligent" the compiler is).
>
> > In the examples you posted, it really makes no difference since the
> > effort occurs during compilation (not at runtime).
>
> Yes. The literal examples posted are just "silly" in that it would be
> far better to just write 4.0d0 than any of them. But when you
> extrapolate to more realistic cases, things get very different. Among
> other things, x**2. and x**2.d0 are both illegal if the value of x is
> negative, whereas x**2 is perfectly fine.
>
> Some compilers might happen to quietly "fix" such an error for you, but
> it would still technically be an error.
>

I've searched the pdf files of the final-committee drafts for F95 and
F2003
for the string "**" and the string "exponent". I cannot find any text
that
states x**2. or x**2.d0 is illegal if x is negative. A Fortran
processor
can determine that 2. and 2.d0, so one does not need to resort to exp
(2.*log(x))
to compute the expression. I will agree that for portability these
expressions
should be avoided. Can you point me to the relevant text?

--
steve

Richard Maine

unread,
Jan 13, 2009, 2:07:07 AM1/13/09
to
<kar...@comcast.net> wrote:

> On Jan 12, 9:09 pm, nos...@see.signature (Richard Maine) wrote:

> > other things, x**2. and x**2.d0 are both illegal if the value of x is
> > negative, whereas x**2 is perfectly fine.
> >
> > Some compilers might happen to quietly "fix" such an error for you, but
> > it would still technically be an error.
>
> I've searched the pdf files of the final-committee drafts for F95 and
> F2003 for the string "**" and the string "exponent". I cannot find any

> text that states x**2. or x**2.d0 is illegal if x is negative... Can you


> point me to the relevant text?

Yes, I can. In f2003 (you can find the same thing in all the other
versions, I'm quite sure, but f2003 is most readily at hand for me right
now), the second sentence of the second para of 7.1.8, "Evaluation of
Operations".

"Raising a negative-valued primary of type real to a real power is
prohibitted."

It is had to be more explicit than that. That it might be easier to find
the restriction, I agree, but that's a different matter. I'll not bother
with explaining why this restriction exists; just the facts will do for
now.

This is not a constraint or anything else that a compiler is required to
diagnose. Thus it is allowed for a compiler to do anything with such
code. Specifically, it is certainly allowed for a compiler to do what
some probably do, which is to essentially evaluate x**2.0 as x**2
instead. It is also allowed for the compiler to throw an error on it.

In any case, the above citation makes it quite explicit that such code
is illegal, or to be more precise, in violation of the Fortran standard.

kar...@comcast.net

unread,
Jan 13, 2009, 2:25:06 AM1/13/09
to
On Jan 12, 11:07 pm, nos...@see.signature (Richard Maine) wrote:
> <kar...@comcast.net> wrote:
> > On Jan 12, 9:09 pm, nos...@see.signature (Richard Maine) wrote:
> > > other things, x**2. and x**2.d0 are both illegal if the value of x is
> > > negative, whereas x**2 is perfectly fine.
>
> > > Some compilers might happen to quietly "fix" such an error for you, but
> > > it would still technically be an error.
>
> > I've searched the pdf files of the final-committee drafts for F95 and
> > F2003 for the string "**" and the string "exponent".  I cannot find any
> > text that states x**2. or x**2.d0 is illegal if x is negative...  Can you
> > point me to the relevant text?
>
> Yes, I can. In f2003 (you can find the same thing in all the other
> versions, I'm quite sure, but f2003 is most readily at hand for me right
> now), the second sentence of the second para of 7.1.8, "Evaluation of
> Operations".
>
>   "Raising a negative-valued primary of type real to a real power is
> prohibitted."
>
> It is had to be more explicit than that. That it might be easier to find
> the restriction, I agree, but that's a different matter. I'll not bother
> with explaining why this restriction exists; just the facts will do for
> now.

Thanks! I would not have found that sentence.

gfortran gets this wrong in its constant folding. I'll fix it soon.
REMOVE:kargl[254] cat g.f
program a
x = (-2.)**2.
print *, x
end program a
REMOVE:kargl[255] gfc4x -o z g.f
REMOVE:kargl[256] ./z
4.0000000

--
steve

Terence

unread,
Jan 13, 2009, 5:47:18 AM1/13/09
to

If the general case were x**integer, then
if x is also an integer, this requests a repeated multiplication,
which is usually done as such, with some tricks to improve speed,
else by exponentiation rules if x is a "real" value.

But if the general case were

x**y

Then if y is not an integer, we enter a different realm of
mathematics, even if y is a ratio of two integers i / j.
This is because the value of y can be represented by an integer plus a
real part with value less than 1.0.
Then any value of x less than exactly zero is illegal since it
requires complex numbers.

When x is positive the calculation is in two parts, one of which
requires fractional roots.
So the shown cases all mean 4.0D0, but the implied general cas falls
into three different situations, and one case is illegal

robin

unread,
Jan 13, 2009, 9:46:41 AM1/13/09
to
"Eugene" <yjy...@gmail.com> wrote in message
news:2dff7b8e-d91a-4605...@d36g2000prf.googlegroups.com...

As an example of a general exponentiation A**2, the first is best,
and it's the clearest and simplest.
The second and third could be far less efficient.
If it's a constant, 4.D0 or similar is best.

In a general exponentiation, using a non-integer after the ** operator
can cause a different exponentiation library routine to be invoked --
one that will take longer than the simpler form.

For A**2, compilers can reduce that to A*A, which is relatively quick.


Michael Prager

unread,
Jan 13, 2009, 11:36:50 AM1/13/09
to
Eugene <yjy...@gmail.com> wrote:

Others have answered your question. However, there is a similar
case that i didn't see mentioned and that can trap beginners:

5.0**(1./3.)

vs.

5.0**(1/3)

Note that (1/3) is an integer operation, so the two expressions
have quite different answers.


--
Mike Prager, NOAA, Beaufort, NC
Address spam-trapped; remove color to reply.
* Opinions expressed are personal and not represented otherwise.
* Any use of tradenames does not constitute a NOAA endorsement.

Ron Shepard

unread,
Jan 13, 2009, 11:58:35 AM1/13/09
to
In article
<b500b05c-f38b-4ce8...@p2g2000prf.googlegroups.com>,
michael...@compuserve.com wrote:

I don't have your book handy, could you elaborate on this?

The "usual" algorithm for computing X**J consists of extracting the
binary bits of the integer J and using those to accumulate the
appropriate products of powers. In the simple case of J=2, where J has
only the second bit set, this would result in a single multiplication,
and X**2 would be evaluated as X*X. Whether the compiler treats this as
a special case or uses the general bit extraction algorithm is a matter
of optimization, but in any case the result would be evaluated as the
simple product X*X. When you say that this is not allowed, it seems to
imply that this algorithm cannot be used. If X**2 cannot be evaluated
as X*X, then how exactly can it be evaluated legally?

$.02 -Ron Shepard

michael...@compuserve.com

unread,
Jan 13, 2009, 12:10:58 PM1/13/09
to
On Jan 13, 5:58 pm, Ron Shepard <ron-shep...@NOSPAM.comcast.net>
wrote:
> In article
> <b500b05c-f38b-4ce8-8b52-c5b1d6be0...@p2g2000prf.googlegroups.com>,

Sorry, I read "2.D0*2.D0" as "2.D0**2.D0", hence my remark.

Mea culpa

Mike Metcalf


robert....@sun.com

unread,
Jan 13, 2009, 6:23:13 PM1/13/09
to


Did you mean to say that "2D0**2" cannot be evaluated as
"2D0**2D0"?

Bob Corbett

James Van Buskirk

unread,
Jan 13, 2009, 9:47:57 PM1/13/09
to
"James Van Buskirk" <not_...@comcast.net> wrote in message
news:gkhcp2$kll$1...@news.motzarella.org...

> recursive function non_initialization(x) result(f)
> logical f
> integer x
> integer z(0*transfer(2.D0**2.,1)+2)
> save
>
> z = 0
> if(x > 0) then
> z = 1
> f = initialization(x-1)
> end if
> f = z(1) == 0
> end function non_initialization

When Tobias Burnus reported in

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38822

that several compilers got the right answer, I knew that I must have
made some kind of error in coding. The error lay in the line

> f = initialization(x-1)

which is not a recursive invocation of non_initialization.
The correction:

C:\gfortran\clf\exponent_test>type exponent_test.f90
module funcs
implicit none
contains
recursive function initialization(x) result(f)
logical f
integer x
integer z(0*transfer(2.D0**2,1)+2)
save

z = 0
if(x > 0) then
z = 1
f = initialization(x-1)
end if
f = z(1) == 0
end function initialization

recursive function non_initialization(x) result(f)
logical f
integer x
integer z(0*transfer(2.D0**2.,1)+2)
save

z = 0
if(x > 0) then
z = 1

f = non_initialization(x-1)


end if
f = z(1) == 0
end function non_initialization
end module funcs

program exponent_test
use funcs
implicit none

write(*,*) initialization(1), non_initialization(1)
end program exponent_test

C:\gfortran\clf\exponent_test>ifort /stand:f95 exponent_test.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.

exponent_test.f90(21) : Warning: Fortran 95 requires an INTEGER data type in
thi
s context. [2.]
integer z(0*transfer(2.D0**2.,1)+2)
------------------------------------^
Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.

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

C:\gfortran\clf\exponent_test>exponent_test

T T

As can be seen, now ifort 9.1 coughs up the wrong result ( T F is
still correct) as was originally anticipated. Probably most if not
all other compilers will do the wrong thing as well.

michael...@compuserve.com

unread,
Jan 14, 2009, 12:30:03 PM1/14/09
to
On Jan 14, 12:23 am, robert.corb...@sun.com wrote:
>
> Did you mean to say that "2D0**2" cannot be evaluated as
> "2D0**2D0"?
>
> Bob Corbett

Yes.

Mike

Dick Hendrickson

unread,
Jan 20, 2009, 2:48:05 PM1/20/09
to
I'll bite. Why not. They look mathematically equivalent to me.

X**2 can't, in general, be evaluated as x**2D0, but I think it's
OK for constants.

Dick Hendrickson

kar...@comcast.net

unread,
Jan 20, 2009, 3:36:51 PM1/20/09
to
On Jan 12, 10:36 pm, "James Van Buskirk" <not_va...@comcast.net>
wrote:

> At least ifort 9.1 gets the semantic distinction, although its
> warning message is incorrect.  ISO/IEC 1539-1:1997(E) section 7.1.6.1
> says:
>
> "An initialization expression is a constant expression in which the
> exponentiation operation is permitted only with an integer power, and
> each primary is
> ...
> (5) A reference to one of the transformational functions REPEAT,
> RESHAPE, SELECTED_INT_KIND, SELECTED_REAL_KIND, TRANSFER, or TRIM,
> where each argument is an initialization expression."
>
> so
>
>          integer z(0*transfer(2.D0**2.,1)+2)
>
> has a shape which is not an initialization expression, but section
> 7.1.6.2 says:
>
> "A restricted expression is an expression in which each operation
> is intrinsic and each primary is
> ...
> (8) A reference to any other intrinsic function defined in this
> standard where each argument is a restricted expression"
>
> so z is an automatic data object, therefore the empty SAVE does
> not apply to it.

James,

Can you explain again why z is an automatic data object? I must be
missing something because the Fortran 95 says:

The specification-expr (7.1.6.2) of a char-len-param-value (5.1.1.5)
or an array-spec (5.1.2.4) may be a nonconstant expression provided
the specification expression is in an interface body (12.3.2.1), the
specification part of a subprogram, or the type-spec of a FUNCTION
statement (12.5.2.2). If a specification-expr involves a reference
to a specification function (7.1.6.2), the expression is considered
to be a nonconstant expression. If the data object being declared
depends on the value of such a nonconstant expression and is not a
dummy argument, such an object is called an automatic data object.

In 'integer z(0*transfer(2.D0**2.,1)+2)' we have an array-spec, but
0*transfer(2.D0**2.,1)+2 appears to be a constant expression. So,
z is not an automatic data object.

One also finds in 5.1.2.4.1,

An automatic array is an explicit-shape array that is declared in a
subprogram, is not a dummy argument, and has bounds that are
nonconstant specification expressions.

The word 'nonconstant' again appears, so z is not an automatic array.

I freely admit I could be missing something.

--
steve

Dick Hendrickson

unread,
Jan 20, 2009, 4:41:41 PM1/20/09
to

I think you're missing the part about exponentiation only to
an INTEGER power in James' first 3 quoted lines.

Dick Hendrickson

kar...@comcast.net

unread,
Jan 20, 2009, 5:28:27 PM1/20/09
to

I know you understand the standard better than I, but AFAICT a
specification expression is not defined in terms of an initialization
expression. The requirement of integer exponents only applies to
an initialization expression. F95 contains

A constant specification expression is a specification expression
that is also a constant expression.

R734 specification-expr is scalar-int-expr

Constraint: The scalar-int-expr shall be a restricted expression.

A restricted expression is an expression in which each operation
is intrinsic and each primary is

(1) A constant or subobject of a constant,
....


(8) A reference to any other intrinsic function defined in this
standard

where each argument is a restricted expression,

In 0*transfer(2.D0**2.,1)+2 , I think we'll agree that 0, 2.D0, 1 and
2 are
constants and satisfies (1). transfer() satisfies (8) and it also
satisfies (5)
under the definition of a constant expression on page 93. I think
we'll also
agree that + is an intrinsic operation. That leaves us with **.
Neither the
definition for a constant expression nor the definition of a
restricted expression
state that the exponent in ** must be an integer.

Richard Maine

unread,
Jan 20, 2009, 6:03:17 PM1/20/09
to
<kar...@comcast.net> wrote:

> On Jan 20, 1:41 pm, Dick Hendrickson <dick.hendrick...@att.net> wrote:
> > kar...@comcast.net wrote:

> > > Can you explain again why z is an automatic data object?

...


> > I think you're missing the part about exponentiation only to
> > an INTEGER power in James' first 3 quoted lines.

..


> I know you understand the standard better than I, but AFAICT a
> specification expression is not defined in terms of an initialization
> expression. The requirement of integer exponents only applies to

> an initialization expression....

Correct. No go back and look at the question under discussion. I have
retained it above. The question was not anything about whether this was
a specification expression. The question was about whether z was an
automatic data object. That question, in turn, depends on whether the
expression is an initialization expression. Thus the requirements for
initialization expressions are exactly what are relevant.

I think perhaps you got sidetracked onto the question of whether the
declataion of z was legal at all. That would indeed be a question about
whether the expression was valid as a specification expression. But
that's not the question at hand.

kar...@comcast.net

unread,
Jan 20, 2009, 7:24:21 PM1/20/09
to
On Jan 20, 3:03 pm, nos...@see.signature (Richard Maine) wrote:
> <kar...@comcast.net> wrote:
> > On Jan 20, 1:41 pm, Dick Hendrickson <dick.hendrick...@att.net> wrote:
> > > kar...@comcast.net wrote:
> > > > Can you explain again why z is an automatic data object?
> ...
> > > I think you're missing the part about exponentiation only to
> > > an INTEGER power in James' first 3 quoted lines.
> ..
> > I know you understand the standard better than I, but AFAICT a
> > specification expression is not defined in terms of an initialization
> > expression.  The requirement of integer exponents only applies to
> > an initialization expression....
>
> Correct. No go back and look at the question under discussion. I have
> retained it above. The question was not anything about whether this was
> a specification expression. The question was about whether z was an
> automatic data object. That question, in turn, depends on whether the
> expression is an initialization expression. Thus the requirements for
> initialization expressions are exactly what are relevant.
>

Well, obviously I'm confused because neither the definition for an
automatic data object nor an automatic array discuss initialization
expressions. For an automatic array (page 54 of F95 standard):

An automatic array is an explicit-shape array that is declared

in a subprogram, is not a dummy argument, and has bounds that
are nonconstant specification expressions.

Here's James' function with the non-essential guts removed:

recursive function non_initialization(x) result(f)
logical f
integer x
integer z(0*transfer(2.D0**2.,1)+2)
save

end function non_initialization

z is declared in a subprogram. z is not a dummy argument.
z has bounds that are *constant specification expressions*.
The lower bound is implicitly 1 and the upper bound is 2.
z is not an automatic array. There is no reference to an
initialization expression in the definition of an automatic
array or the definition of a specification expressions.

If I go through the definition of an automatic data objection,
I reach the same conclusion. So, how exactly does the
definition of an initialization expression enter into the
determination of an automatic data object.

Richard Maine

unread,
Jan 20, 2009, 7:49:23 PM1/20/09
to
<kar...@comcast.net> wrote:

> On Jan 20, 3:03 pm, nos...@see.signature (Richard Maine) wrote:

> > The question was about whether z was an
> > automatic data object. That question, in turn, depends on whether the

> > expression is an initialization expression...


>
> Well, obviously I'm confused because neither the definition for an
> automatic data object nor an automatic array discuss initialization
> expressions. For an automatic array (page 54 of F95 standard):
>
> An automatic array is an explicit-shape array that is declared
> in a subprogram, is not a dummy argument, and has bounds that
> are nonconstant specification expressions.

Ah. That's where the confusion came from. It's that term "nonconstant".
That term is "problematic".

If you'll look at the coresponding f2003 text, you will find that the
wording has been changed to (in 5.1.2.5.1)

"An automatic array is an explicit-shape array that is declared in a

subprogram, is not a dummy argument, and has bounds that are not
initialization expressions."

I forget exactly when that change was made. I think it might have been
in an interp to f95 because the term "nonconstant" was, at best,
confusing. F95 did have "constant expressions". (I had to go check
whether those were still in f95 or not; looks like they were). One
possible interpretation of "nonconstant" would be "not a constant
expression". I don't actually recall whether that was the interpretation
or not. I think I recall some discussion of the subject, but I don't
recall the details, including whether or not it was a formal interp.

kar...@comcast.net

unread,
Jan 20, 2009, 8:19:18 PM1/20/09
to

Thanks for whacking me with a clue stick.

Fortran 95 Corrigendum 1 is loaded with replacement text that
removes many uses of nonconstant.

--
steve

James Van Buskirk

unread,
Jan 20, 2009, 8:36:39 PM1/20/09
to
<kar...@comcast.net> wrote in message
news:a35a4e27-666f-4105...@g3g2000pre.googlegroups.com...

> On Jan 12, 10:36 pm, "James Van Buskirk" <not_va...@comcast.net>
> wrote:

> > integer z(0*transfer(2.D0**2.,1)+2)

> James,

> Can you explain again why z is an automatic data object? I must be
> missing something because the Fortran 95 says:

> The specification-expr (7.1.6.2) of a char-len-param-value (5.1.1.5)
> or an array-spec (5.1.2.4) may be a nonconstant expression provided
> the specification expression is in an interface body (12.3.2.1), the
> specification part of a subprogram, or the type-spec of a FUNCTION
> statement (12.5.2.2). If a specification-expr involves a reference
> to a specification function (7.1.6.2), the expression is considered
> to be a nonconstant expression. If the data object being declared
> depends on the value of such a nonconstant expression and is not a
> dummy argument, such an object is called an automatic data object.

> In 'integer z(0*transfer(2.D0**2.,1)+2)' we have an array-spec, but
> 0*transfer(2.D0**2.,1)+2 appears to be a constant expression. So,
> z is not an automatic data object.

> An automatic array is an explicit-shape array that is declared in a


> subprogram, is not a dummy argument, and has bounds that are
> nonconstant specification expressions.

> The word 'nonconstant' again appears, so z is not an automatic array.

> I freely admit I could be missing something.

Steve,

First of all I have observed what you have been doing with
initialization expressions as in:

http://gcc.gnu.org/ml/fortran/2009-01/msg00231.html

and I applaud your efforts. I'll give you a little more encouragement
later on in this message.

The problem that is shooting you down has also left bullet holes in
my back. Once I came up with a beautiful example of how constant
expressions were inconsistent in the f95 standard, posted it on my
web site, and bragged about it in this forum. However, someone, it
may have been Steve Lionel, pointed out that Corregendum 1 to f95
invalidated my example. Indeed, if you look in N1421.pdf you will
find that constant expressions are excised from the standard not by
eliminating their definition in section 7.1.6.1 of ISO/IEC
1539-1:1997(E) but by removing their effect everywhere else in the
standard. Thus N1421.pdf says:

"Subclause 5.1

In the fina paragraph of Page 48, replace: 'may be a nonconstant
expression provided the specification expression' with 'shall be an
initialization expression unless it'.

In the first paragraph of page 49:

(i) delete the sentence: 'If a ... nonconstant expression.'.

(ii) replace 'such a nonconstant expression' with 'a specification-
expr that is not an initialization expression'.

In the first paragraph following NOTE 5.3, replace: 'a nonconstant
expression' with 'an expression that is not an initialization
expression'."

So let's rewrite the above-quoted passage with edits:

"The specification-expr (7.1.6.2) of a char-len-param-value (5.1.1.5)

or an array-spec (5.1.2.4) shall be an initialization expression unless
it is in an interface body (12.3.2.1), the specification part of a
subprogram, or the type-spec of a FUNCTION statement (12.5.2.2). If the
data object being declared depends on the value of a specification-expr
that is not an initialization expression and is not a dummy argument,


such an object is called an automatic data object."

Again going back to N1421.pdf:

"Subclause 5.1.2.4.1

In the constraint, replace: 'nonconstant expressions' with
'expressions that are not initialization expressions'.

In line 2 after the constraint, replace 'nonconstant specification'
with not initialization'.

In line 3 after the constraint, replace 'nonconstant specification'
with 'not initialization'.

In lines 5 and 6 after the constraint, replace the sentence by 'The
bounds of such an array are unaffected by the redefinition or
undefinition of any variable during execution of the procedure.'."

The quoted paragraph then becomes:

"An automatic array is an explicit-shpe array that is declared in a
subprogram, is not a dummy argument, and has bounds that are not
initialization expressions."

These edits are not isolated occurrences. Rather if you go through
the standard you will find that all the effects of constant
expressions have been elided, except for the SIZE of the SHAPE
argument to the RESHAPE intrinsic, and maybe some others, which I
think is just an omission. For example, the SIZE of the SHAPE is
still constant in f03, but there are no constant expression there,
so what does this mean? This has indeed been fixed in the f08
draft.

It may prove worthwhile to examine the error statements that any
compiler emits and change any that refer to constant expressions.

Wiping out constant expressions was a good thing because not only
were they inconsistent, but all the kinds of expressions complicate
the standard greatly: if you want to test whether your compiler can
handle some expression, you have to test it as an ordinary expression,
an initialization expression, and as a specification expression. A
fourth kind of expressions makes it just that much harder to test.
Well, specification expressions in elemental functions are technically
a fourth kind, but we don't have to worry about them unless we are
writing a compiler. Given current context this means that we do in
fact have to worry about them.

Now for the encouragement: when gfortran tries to evaluate a constant
expression and doesn't find the available tools, the result is an ICE.
It seems to me that the path you are trying to drive gfortran towards
will avoid the ICE an many situations because the expression will be
recognized as not being an initialization expression according to the
standard in question (f95, f2003, or gnu) and so will be deferred to
run-time and its result will be marked as not being an initialization
expression so problems won't propagate to dependent expressions.
Removal of all that ICE potential has to be a good thing independent
of the fact that it will result in standard-conforming code perhaps
uniquely among compilers.

A technical comment:

program z
real x(0*transfer(2.e0**3.e0, 1) + 2)
end program z

does not provide the stress test that you want. Automatic data
objects are not permitted in a main program nor in the speicification-
part of a module (see that passages quoted above), so you are going to
have to write a separate subroutine (or function) to prove your point.

Again, thanks for your efforts on this problem in particular and
gfortran in general.

glen herrmannsfeldt

unread,
Jan 20, 2009, 8:48:03 PM1/20/09
to
kar...@comcast.net wrote:

> Well, obviously I'm confused because neither the definition for an
> automatic data object nor an automatic array discuss initialization
> expressions. For an automatic array (page 54 of F95 standard):

> An automatic array is an explicit-shape array that is declared
> in a subprogram, is not a dummy argument, and has bounds that
> are nonconstant specification expressions.

This sounds a little strange to me.

A static array has to have constant (known at compile time)
bounds, but I don't see that an automatic array can't
have constant bounds.

-- glen

Richard Maine

unread,
Jan 20, 2009, 10:02:04 PM1/20/09
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

Nonetheless, that's the definition.

How else would it be defined? Yes, I understand that one could have a
keyword to specify it explicitly. In fact, I'd be in favor of such a
thing. But lacking that, how else would one distinguish an automatic
from a nonautomatic array when both had constant (or in f2003,
initialization expression) bounds?

The difference *DOES* matter; there are things in the standard that
depend on it. (See upthread). Thus, you can't just say that the compiler
can decide. This isn't just a question of implementation decision, but
of standard specification.

And when you come up with a scheme to tell the difference other than
with an explicit keyword, don't forget to make it compatible with prior
standards.

But that's all a bit moot, as the above *IS* the definition (modulo the
interps mentioned in other posts, but those seem orthogonal to this
question).

glen herrmannsfeldt

unread,
Jan 21, 2009, 1:03:16 AM1/21/09
to
Richard Maine <nos...@see.signature> wrote:
(snip, I wrote)


>> A static array has to have constant (known at compile time)
>> bounds, but I don't see that an automatic array can't
>> have constant bounds.

> Nonetheless, that's the definition.

> How else would it be defined? Yes, I understand that one could have a
> keyword to specify it explicitly. In fact, I'd be in favor of such a
> thing. But lacking that, how else would one distinguish an automatic
> from a nonautomatic array when both had constant (or in f2003,
> initialization expression) bounds?

Declare the routine RECURSIVE? It seems a little unusual,
but it should work.


> The difference *DOES* matter; there are things in the standard that
> depend on it. (See upthread). Thus, you can't just say that the compiler
> can decide. This isn't just a question of implementation decision, but
> of standard specification.

> And when you come up with a scheme to tell the difference other than
> with an explicit keyword, don't forget to make it compatible with prior
> standards.

C has the auto keyword, and PL/I the AUTOMATIC attribute, both
rarely used as it is normally the default. In C all functions
are recursive.


> But that's all a bit moot, as the above *IS* the definition (modulo the
> interps mentioned in other posts, but those seem orthogonal to this
> question).

RECURSIVE doesn't seem to use the work automatic, but...

"Each instance has an independent sequence of execution and an
independent set of dummy arguments and local unsaved data objects."

That sounds like automatic without using the word.

-- glen

Richard Maine

unread,
Jan 21, 2009, 2:12:28 AM1/21/09
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Richard Maine <nos...@see.signature> wrote:
> (snip, I wrote)
>
> >> A static array has to have constant (known at compile time)
> >> bounds, but I don't see that an automatic array can't
> >> have constant bounds.
>
> > Nonetheless, that's the definition.
>
> > How else would it be defined? Yes, I understand that one could have a
> > keyword to specify it explicitly.

..

> Declare the routine RECURSIVE? It seems a little unusual,
> but it should work.

And you thought the existing definition was nonobvious?

Plus, that seems like a pretty blunt hammer, as it applies to a whole
routine rather than a specific data object.

> C has the auto keyword...

Yes, I mentioned the explicit keyword possibility.

> RECURSIVE doesn't seem to use the work automatic, but...
>
> "Each instance has an independent sequence of execution and an
> independent set of dummy arguments and local unsaved data objects."
>
> That sounds like automatic without using the word.

Sound like it though it might, as you say, it doesn't use the word and
thus isn't automatic. I'm moderately sure there are contexts where the
difference matters.

kar...@comcast.net

unread,
Jan 24, 2009, 4:46:08 PM1/24/09
to
On Jan 20, 5:36 pm, "James Van Buskirk" <not_va...@comcast.net> wrote:

James,

Thanks for the long, thoughtful reply. I've written up a small
program
below. If I now understand initializiation expression, specifications
expressions, and the effect of a blank save, then it appears your
second
program has found an incompatibility between F95 and F2003. Is my
analysis
still flawed.

> Now for the encouragement: when gfortran tries to evaluate a constant
> expression and doesn't find the available tools, the result is an ICE.

Correct.

> It seems to me that the path you are trying to drive gfortran towards
> will avoid the ICE an many situations because the expression will be
> recognized as not being an initialization expression according to the
> standard in question (f95, f2003, or gnu) and so will be deferred to
> run-time and its result will be marked as not being an initialization
> expression so problems won't propagate to dependent expressions.

No, I'm driving in the direction that you probably want.

This is a case of 1 step forward and 2 steps backwards. I've removed
code that only allows constant folding of exponentation with only
integer
powers. This allows gfortran to now issue an error for (-1.0)**1.9.

> Removal of all that ICE potential has to be a good thing independent
> of the fact that it will result in standard-conforming code perhaps
> uniquely among compilers.

The problem is gfortran inherited its code from g95 where it appears
that
Andy wrote the specification expression and initialization expression
parsing in accord with Fortran 95 without Corrigendum 1 and 2. Until
you
brought up this issue, none of the gfortran developers had reason to
review this code.

Of greater importance, and if I understand the following correctly,
it
appears that J3 may have inadvertently introduced an incompatibility
between F95+Corrigendum 1 and F2003.

!
! Fortran 95 + Corrigendum 1 and Fortran 2003:
!
! An automatic array is an explicit-shape array that is declared in
a
! subprogram, is not a dummy argument, and has bounds that are not
! initialization expressions.
!
! Fortran 95 + Corrigendum 1:
!
! An initialization expression is a constant expression in which the
! exponentiation operation is permitted only with an integer power,
! and each primary is
!
! (1) A constant or subobject of a constant,
! ...
! (5) A reference to one of the transformational functions REPEAT,
RESHAPE,
! SELECTED_INT_KIND, SELECTED_REAL_KIND, TRANSFER, or TRIM,
where each
! argument is an initialization expression,
!
! '0 * transfer(2.e0**2, 1.e0) + 2' is an initialization
expression.
! '0 * transfer(2.e0**2.e0, 1.e0) + 2' is not an initialization
expression.
!
! A specification expression is an expression with limitations that
make
! it suitable for use in specifications such as character lengths
(R510)
! and array bounds (R515, R516). A constant specification
expression is
! a specification expression that is also a constant expression.
!
! R734 specification-expr is scalar-int-expr
!
! Constraint: The scalar-int-expr shall be a restricted expression.
!
! A restricted expression is an expression in which each operation
is
! intrinsic and each primary is
!
! (1) A constant or subobject of a constant,
! ...
! (8) A reference to any other intrinsic function defined in this
standard
! where each argument is a restricted expression,
!
! In the following, z1 and z2 are specification expression, but z1 is
not
! an automatic array and z2 is an automatic array.
!
! Fortran 2003:
!
! An initialization expression is an expression with limitations
that make
! it suitable for use as a kind type parameter, initializer, or
named
! constant. It is an expression in which each operation is
intrinsic,
! and each primary is
!
! (1) A constant or subobject of a constant,
! ...
! (5) A reference to a transformational standard intrinsic function
other
! than NULL, where each argument is an initialization
expression,
!
! '0 * transfer(2.e0**2, 1.e0) + 2' is an initialization
expression.
! '0 * transfer(2.e0**2.e0, 1.e0) + 2' is an initialization
expression.
!
! The definition of specification in Fortran 2003 is substantially the
! same as Fortran 95 + Corrigendum 1. z1 and z2 are specification
! expressions and both are initialization expressions; thus, z1 and z2
! are not automatic arrays.
!
! Fortran 95 + Corrigendum 1:
!
! Constraint: The SAVE attribute shall not be specified for an
object that
! is in a common block, a dummy argument, a procedure, a function
result,
! an automatic data object, or an object with the PARAMETER
attribute.
!
! NOTE 5.3
! An automatic object shall neither appear in a SAVE or DATA
statement
! nor be declared with a SAVE attribute nor be initially defined
by an
! initialization.
!
! Fortran 2003:
!
! C517 (R501) The SAVE attribute shall not be specified for an
object that
! is in a common block, a dummy argument, a procedure, a function
result,
! an automatic data object, or an object with the PARAMETER
attribute.
!
! NOTE 5.3
! Same as above.
!
! Thus, Fortran 2003 has changed the semantics of a standard
conforming
! Fortran 95 + Corrigendum 1 program.
!
program a
implicit none
integer i, j, k
do i = 1, 5
call sub1(i, j)
call sub2(i, k)
end do
print *, j, k
end program a

subroutine sub1(i, j)
implicit none
integer i, j
integer z1(0 * transfer(2.e0**2, 1.e0) + 2)
save
if (i == 1) then
z1 = 10
end if
z1 = z1 + i
j = z1(1)
end subroutine sub1

subroutine sub2(i, j)
implicit none
integer i, j
integer z2(0 * transfer(2.e0**2.e0, 1.e0) + 2)
save
if (i == 1) then
z2 = 10
end if
z2 = z2 + i
j = z2(1)
end subroutine sub2

kar...@comcast.net

unread,
Jan 24, 2009, 4:49:49 PM1/24/09
to
Damn, I grabbed the wrong code.

>

> subroutine sub1(i, j)
>   implicit none
>   integer i, j
>   integer z1(0 * transfer(2.e0**2, 1.e0) + 2)

Should be 1 instead of 1.e0.

>   save
>   if (i == 1) then
>      z1 = 10
>   end if
>   z1 = z1 + i
>   j = z1(1)
> end subroutine sub1
>
> subroutine sub2(i, j)
>   implicit none
>   integer i, j
>   integer z2(0 * transfer(2.e0**2.e0, 1.e0) + 2)

Ditto.

0 new messages