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

Letter to the standards committee about bounds of ordinary, assumed-rank arrays

325 views
Skip to first unread message

John Donners

unread,
May 4, 2017, 5:02:59 PM5/4/17
to
Hi all,

I'll send a letter to the standards committee about a feature that I've been playing with for a while now: the bounds of an array is passed to an assumed-rank dummy array in a subroutine, even if the dummy array is not allocatable, nor pointer.

This feature is found in the draft 2015 standard and has been implemented by Cray, Intel and IBM in their latest compilers. I would like to see this feature being continued in the final standard, but I'm also quite curious about your opinion for this particular feature.

You can test it yourself with a simple example:

program assumedrank
implicit none
real,dimension(:,:,:),allocatable :: bb
real,dimension(3:9,10:15,16:32) :: c

allocate(bb(3:9,10:15,16:32))
print*, 'Actual argument, allocatable, lbound=',lbound(bb)
call p(bb)
print*, 'Actual argument, ordinary, lbound=',lbound(c)
call p(c)

contains

subroutine p(a)
real,dimension(..) :: a
print*,'Dummy argument, lbound=',lbound(a)

end subroutine p

end


------------------------

Dear Committee members,

I would like to thank you for your efforts to bring the Fortran standard
forward with many new functionalities, while keeping the strengths of
the language. I would like to discuss one particular feature that was
introduced in the Fortran 2015 language standard: the bounds of ordinary,
assumed-rank arrays.

TS 29113 introduces the notion of the assumed rank array in section 5.2
Section 6.3 defines that the bounds of the assumed rank array are implied
from the actual argument for allocatable and pointer arrays.

The Draft Fortran 2015 standard modifies this behaviour in
section 12.5.2.4 ('Ordinary dummy variables'), clause 15:

"An actual argument of any rank may correspond to an assumed-rank dummy
argument. The rank and shape of the dummy argument are the rank and shape
of the corresponding actual argument. If the rank is nonzero, the lower
and upper bounds of the dummy argument are those that would be given by
the intrinsic functions LBOUND and UBOUND respectively if applied to the
actual argument, except that when the actual argument is assumed-size,
the upper bound of the last dimension of the dummy argument is 2 less
than the lower bound of that dimension."

So the bounds of ordinary dummy variables are also implied from their actual
argument, not only for allocatable or pointer arrays. I plea to keep this
functionality in the final Fortran 2015 standard.

A defining feature of fortran is that the definition of bounds belong
to the array. It underlines its use
in scientific computing where an array index always has an actual meaning
and, since that meaning is not always counted starting from 0 or 1, is
more than just a pointer to an element. This frees the programmer from
always explicitly translating his meaningful index to a pointer index
(mentally and in the code itself). So this nice feature should be further
solidified in the new standard by passing the bounds to the dummy assumed-rank array.

I think that this functionality is important and that it doesn't interfere
with other dummy array types.

Many Fortran applications use the variable lower bound of an array, but
need to use different methods to pass these bounds between routines:
-define the bounds in a module, common block or include file (FLASH)
-define the array in a module, common block or include file (AFiD)
-define the array as member of a user-defined structure
-bounds remapping (FLASH, WRF)
Bounds remapping is not applicable to assumed-rank arrays. The
other options require some application-specific knowledge in a subroutine
to use the full power of the Fortran array syntax.
The definition of ordinary, assumed-rank dummy arrays as described in
the current draft would allow for independent libraries that use the
full power of Fortran arrays.

The assumed-rank array can be combined with the generic TYPE(*) to allow for
fully general arguments. A single routine can handle any basic type of any rank,
removing the need for an interface of routines that do the same, except for
their different argument types and ranks. The generic part of the routine will
have access to little information about the actual argument, in which
case the array bounds can be quite useful.

Since the actual data of the assumed-rank array can only be indexed through
explicit SELECT RANK (if adapted) and SELECT TYPE statements, there is little cause for confusion. The programmer has to use the UBOUND and LBOUND functions to access the array bounds of an assumed-rank dummy argument in the generic
part of the code (outside the SELECT .. statements). This is quite different
from other dummy arrays, where the programmer can explicitly write out the indices.

My conclusion is that it would be a powerful addition to the language, where independent libraries can be written in Fortran, without losing a defining feature of the language.

jfh

unread,
May 4, 2017, 8:17:50 PM5/4/17
to
Both gfortran and ifort compile and run that program but the outputs differ:

gfortran 6.3.1 20170109:

Actual argument, allocatable, lbound= 3 10 16
Dummy argument, lbound= 1 1 1
Actual argument, ordinary, lbound= 3 10 16
Dummy argument, lbound= 1 1 1

ifort 17.0.0.098 Build 20160721:

Actual argument, allocatable, lbound= 3 10 16
Dummy argument, lbound= 3 10 16
Actual argument, ordinary, lbound= 3 10 16
Dummy argument, lbound= 3 10 16

Stefano Zaghi

unread,
May 5, 2017, 4:39:14 AM5/5/17
to
Dear John,

thank you very much for sharing your thoughts. This topic is very interesting for me and I like to share with you my (bad) idea.

Il giorno giovedì 4 maggio 2017 23:02:59 UTC+2, John Donners ha scritto:
> Dear Committee members,
>
> I would like to thank you for your efforts to bring the Fortran standard
> forward with many new functionalities, while keeping the strengths of
> the language.

I totally agree :-)

> I would like to discuss one particular feature that was
> introduced in the Fortran 2015 language standard: the bounds of ordinary,
> assumed-rank arrays.

Partially off topic: how you consider assumed-rank arrays, do you think to them mainly for C-interp or also for generic programming?

My interest is mainly in generic programming and assumed-rank arrays sound very interesting, but others more experienced drive me to think this feature is mainly useful for only C-interp.

Aside, basing on your own experience, the assumed-rank arrays are "well" implemented in the GNU and Intel compilers? I mean, are you aware about compilers bug concerning assumed-rank arrays? I am currently a bit reluctant to "put my heart" on new features...

>... A defining feature of fortran is that the definition of bounds belong
> to the array. It underlines its use
> in scientific computing where an array index always has an actual meaning
> and, since that meaning is not always counted starting from 0 or 1, is
> more than just a pointer to an element. This frees the programmer from
> always explicitly translating his meaningful index to a pointer index
> (mentally and in the code itself). So this nice feature should be further
> solidified in the new standard by passing the bounds to the dummy assumed-rank array.

I agree. In my applications often the bounds are plenty of meaning, e.g. often negative lower bounds indicate "ghost cells" where boundary conditions are to be imposed.

> I think that this functionality is important and that it doesn't interfere
> with other dummy array types.
>
> Many Fortran applications use the variable lower bound of an array, but
> need to use different methods to pass these bounds between routines:
> -define the bounds in a module, common block or include file (FLASH)
> -define the array in a module, common block or include file (AFiD)
> -define the array as member of a user-defined structure
> -bounds remapping (FLASH, WRF)

I often use something along the following lines

---assumed shape preserving bounds meaning---

subroutine example(object, array)
class(my_object), intent(in) :: object
type(another_object), intent(inout) :: array(1-object%gc : ) ! "gc" is the number of ghost cells used
...
endsubroutine example

---end assumed shape preserving bounds meaning---

I have to check what the standard imposes about assumed-shape arrays, but often with some (all?) compilers I had used the assumed-shape arrays are remapped to start from 1 if the lower bound is not defined, thus I currently adopt the above approach.

> Bounds remapping is not applicable to assumed-rank arrays. The
> other options require some application-specific knowledge in a subroutine
> to use the full power of the Fortran array syntax.

Yes, this is what I have to do, rely on the application-specific knowledge, no generic programming at all :-(

> The definition of ordinary, assumed-rank dummy arrays as described in
> the current draft would allow for independent libraries that use the
> full power of Fortran arrays.

This sounds exciting, can you provide examples?


> The assumed-rank array can be combined with the generic TYPE(*) to allow for
> fully general arguments. A single routine can handle any basic type of any rank,
> removing the need for an interface of routines that do the same, except for
> their different argument types and ranks. The generic part of the routine will
> have access to little information about the actual argument, in which
> case the array bounds can be quite useful.

Even more exciting, can you provide examples? I am not aware about good usage of "type(*)", is it well supported by compiler vendors?

> Since the actual data of the assumed-rank array can only be indexed through
> explicit SELECT RANK (if adapted) and SELECT TYPE statements, there is little cause for confusion. The programmer has to use the UBOUND and LBOUND functions to access the array bounds of an assumed-rank dummy argument in the generic
> part of the code (outside the SELECT .. statements). This is quite different
> from other dummy arrays, where the programmer can explicitly write out the indices.

In your experience, the necessity of "select rank" surrounding introduces relevant overhead with respect an assumed-shape array equivalent?

> My conclusion is that it would be a powerful addition to the language, where independent libraries can be written in Fortran, without losing a defining feature of the language.

I agree, this could be a very nice feature.

Thank you very much for your effort.

My best regards.

John Donners

unread,
May 6, 2017, 4:08:34 AM5/6/17
to
Hello jfh,

indeed gfortran doesn't implement this at the moment. I reported it:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67894

gfortran seems to have had it in an earlier version, but I'm not sure. Shouldn't be too hard to fix, though (although I didn't manage 2 years ago..)

The IBM XL and Cray compilers support it as well.

John Donners

unread,
May 7, 2017, 3:24:37 PM5/7/17
to
On Friday, May 5, 2017 at 10:39:14 AM UTC+2, Stefano Zaghi wrote:
> Dear John,
>
> thank you very much for sharing your thoughts. This topic is very interesting for me and I like to share with you my (bad) idea.
>
> Il giorno giovedì 4 maggio 2017 23:02:59 UTC+2, John Donners ha scritto:
> > Dear Committee members,
> >
> > I would like to thank you for your efforts to bring the Fortran standard
> > forward with many new functionalities, while keeping the strengths of
> > the language.
>
> I totally agree :-)
>
> > I would like to discuss one particular feature that was
> > introduced in the Fortran 2015 language standard: the bounds of ordinary,
> > assumed-rank arrays.
>
> Partially off topic: how you consider assumed-rank arrays, do you think to them mainly for C-interp or also for generic programming?

I do consider them for generic programming. It's a weird idea that a typical Fortran feature would be meant for C.

>
> My interest is mainly in generic programming and assumed-rank arrays sound very interesting, but others more experienced drive me to think this feature is mainly useful for only C-interp.
>
> Aside, basing on your own experience, the assumed-rank arrays are "well" implemented in the GNU and Intel compilers? I mean, are you aware about compilers bug concerning assumed-rank arrays? I am currently a bit reluctant to "put my heart" on new features...

Cray already implemented it according to the draft years ago, Intel and IBM fixed their compilers after a few reports. I use allocatable dummy arrays for gfortran as a workaround. I'm confident that gfortran can be 'fixed' as well. Fact is that the largest drive behind the assumed-rank arrays is MPI-3, so I'm confident it's here to stay.
Check https://github.com/jdonners/gabriel, it's written around this idea. It is a library that 'stitches' together arrays on different MPI ranks based on their indices. It can automatically communicate halos, or transform one set of arrays to another (e.g. columns to rows). The configure script checks the compiler to see if it supports assumed-rank arrays and if it interprets the bounds according to the draft.

You can find a paper about it here: https://surfdrive.surf.nl/files/index.php/s/niuyknHHNyEvE6j . PRACE should put it on the website soon.

>
>
> > The assumed-rank array can be combined with the generic TYPE(*) to allow for
> > fully general arguments. A single routine can handle any basic type of any rank,
> > removing the need for an interface of routines that do the same, except for
> > their different argument types and ranks. The generic part of the routine will
> > have access to little information about the actual argument, in which
> > case the array bounds can be quite useful.
>
> Even more exciting, can you provide examples? I am not aware about good usage of "type(*)", is it well supported by compiler vendors?

Hmm, that would be one of the next steps to implement, but again it's driven by MPI-3, so I'm confident it'll be supported.

>
> > Since the actual data of the assumed-rank array can only be indexed through
> > explicit SELECT RANK (if adapted) and SELECT TYPE statements, there is little cause for confusion. The programmer has to use the UBOUND and LBOUND functions to access the array bounds of an assumed-rank dummy argument in the generic
> > part of the code (outside the SELECT .. statements). This is quite different
> > from other dummy arrays, where the programmer can explicitly write out the indices.
>
> In your experience, the necessity of "select rank" surrounding introduces relevant overhead with respect an assumed-shape array equivalent?

I don't think that any compiler has implemented this, it is just an idea so far..

John Donners

unread,
May 11, 2017, 8:43:03 AM5/11/17
to
Let me know if you'd like to co-sign the letter. I plan to send it at the end of this week.

Cheers,
John

Stefano Zaghi

unread,
May 11, 2017, 9:33:20 AM5/11/17
to
Dear John,

I would like to co-sign, also you could consider to get the attention of the GitHub group (where other Fortraners more distinguished than me could add their voices to yours).

My best regards.

P.S. I had followed Gabriel from its born, but I was not conscious you were exploiting assumed rank, very interesting!

FortranFan

unread,
May 11, 2017, 11:19:08 AM5/11/17
to
On Thursday, May 4, 2017 at 5:02:59 PM UTC-4, John Donners wrote:

> ..
>
> I'll send a letter to the standards committee about a feature that I've been playing with for a while now: the bounds of an array is passed to an assumed-rank dummy array in a subroutine, even if the dummy array is not allocatable, nor pointer.
>
> This feature is found in the draft 2015 standard and has been implemented by Cray, Intel and IBM in their latest compilers. I would like to see this feature being continued in the final standard, but I'm also quite curious about your opinion for this particular feature.
>
> ..

@John Donners,

Ref : "I'm also quite curious about your opinion for this particular feature"

FWIW, my own opinion is that the feature you are proposing be included in the final standard can "mess things up" and cause confusion among quite a few users of Fortran UNLESS it is accompanied by an enhancement to the assumed shape functionality but which is entirely unlikely given the risk of 'breaking' existing codebases.

I will be the first to admit I know very little about the fundamental aspects of language syntax, semantics, and taxonomy and how these come into play when one tries to introduce improvements that extent and expand forward in a way that is *consistent* with the existing core constructs of a language.

All I notice is that the draft standard and the implementations in Cray, IBM, and Intel compilers do NOT seem to flow with whatever little intuition I have which informs me the ASSUMED RANK facility should *build upon* the ASSUMED SHAPE functionality ala the inheritance concept of object-oriented (OO) design but only bring in the polymorphism involving the RANK of the object. That is, unless what I perceive as the base 'class' i.e., the ASSUMED SHAPE feature is also revised to provide the information pertaining to the bounds of an array, the assumed rank dummy arguments that are neither ALLOCATABLE nor POINTER should only provide the rank information but when cased within SELECT RANK constructs they should effectively reduce to the equivalent ASSUMED SHAPE objects and provide the commensurate SHAPE information.

To understand better my concerns, please consider this example:

-- begin code --
program p
use, intrinsic :: iso_fortran_env, only : compiler_version
implicit none
integer :: foo(0:1)
print *, "Compiler Version: ", compiler_version()
call assumed_shape( foo )
call assumed_rank( foo )
contains
subroutine assumed_shape( foo )
integer, intent(in) :: foo(:)
print *, "assumed_shape sub: lbound(foo) = ", lbound(foo)
end subroutine
subroutine assumed_rank( foo )
integer, intent(in) :: foo(..)
print *, "assumed_rank sub: rank(foo) = ", rank(foo)
print *, "assumed_rank sub: lbound(foo) = ", lbound(foo)
end subroutine
end program p

-- end code --

Upon execution, the output with 2 different compilers are as follows:

-- begin Intel compiler output --
Compiler Version:
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 18.0.0.065 Beta Build 20170320

assumed_shape sub: lbound(foo) = 1
assumed_rank sub: rank(foo) = 1
assumed_rank sub: lbound(foo) = 0
-- end Intel compiler output --

-- begin gfortran output --
Compiler Version: GCC version 8.0.0 20170430 (experimental)
assumed_shape sub: lbound(foo) = 1
assumed_rank sub: rank(foo) = 1
assumed_rank sub: lbound(foo) = 1
-- end gfortran output --

I find the gfortran implementation of the assumed rank feature (or lack thereof in fully conformance with the draft standard!) to be more intuitive and consistent with what I would have expected, especially given how 'modern' aspects have been arranged with the assumed shape feature since the introduction of Fortran 90.

Now I can understand when the assumed rank dummy argument has either the ALLOCATABLE or POINTER attribute then for the standard to stipulate the bounds information be provided; note this will only be consistent then what is included with assumed shape arrays currently.

But the notion that when a coder uses ':' for rank-1 objects or ':,:' for rank-2 and so forth, the bounds information is unavailable even though the ranks are clearly indicated, but when the horizontal counterpart of '..' is employed, some sort of miracle occurs whereby not only the rank but also the bounds become all known seems like a big jump, a violation of some sort with respect to language design and possibly prone to misuse, if not outright abuse. Hence I would urge the standards committee to think through the implications of this in conjunction with their experience with many of them having been involved with several standard revisions.

Perhaps this view of mine of looking at consistency with assumed shape dummy objects in entirely misplaced and a lone voice of dissent that will be readily ignored. But this is how I see it and I wanted to share it in case it turns to be a growing and sizeable minority among those who have not throught this through.

Best wishes,

John Donners

unread,
May 12, 2017, 5:49:02 AM5/12/17
to
Hi FortranFan,

thanks for sharing your thoughts. I can see your point that it could cause confusion with the assumed-shape functionality. Maybe an extra dummy array property like 'PASSBOUNDS' for assumed-shape and assumed-rank arrays would help?

Cheers,
John

FortranFan

unread,
May 12, 2017, 9:06:54 AM5/12/17
to
On Friday, May 12, 2017 at 5:49:02 AM UTC-4, John Donners wrote:

>..
>
> Hi FortranFan,
>
> thanks for sharing your thoughts. I can see your point that it could cause confusion with the assumed-shape functionality. Maybe an extra dummy array property like 'PASSBOUNDS' for assumed-shape and assumed-rank arrays would help?
>
> ..

Hello John,

Thanks much for reviewing my opinion.

Yes, what you are suggesting is a good way to proceed. Please note I was indeed thinking along the same lines over the last few days and I was leaning toward the standard including the requirement that the bounds be passed when the TARGET attribute is applied on the dummy i.e., in addition to the current stipulation that bounds be available when the dummy has the ALLOCATABLE or POINTER attributes. So my thought is as explained in the code snippet below:

-- begin code --
program p
use, intrinsic :: iso_fortran_env, only : compiler_version
implicit none
integer :: foo(0:1)
print *, "Compiler Version: ", compiler_version()
call assumed_shape( foo )
call assumed_rank( foo )
contains
subroutine assumed_shape( foo )
integer, intent(in), TARGET :: foo(:) !<-- Note the TARGET attribute
print *, "assumed_shape sub: lbound(foo) = ", lbound(foo)
! because of TARGET attribute, bound shall be that of actual argument
end subroutine
subroutine assumed_rank( foo )
integer, intent(in), TARGET :: foo(..) !<-- Note the TARGET attribute
print *, "assumed_rank sub: rank(foo) = ", rank(foo)
print *, "assumed_rank sub: lbound(foo) = ", lbound(foo)
! because of TARGET attribute, bound shall be that of actual argument
end subroutine
end program p

On the plus side, I figure this will be better than introducing a NEW KEYWORD such as PASSBOUNDS in the standard which might then make things much easier for the standard writers and compiler implementations and users.

But I was also somewhat wary about this because I was unsure if this introduces any further complexities with respect to any existing properties or constraints with the TARGET attribute. And I had not the chance to go through the implications of this.

However you and the readers can also review this alternative and see if this can be the path forward or if your new keyword suggestion will be better.

Best Regards,

Richard Maine

unread,
May 12, 2017, 10:01:39 AM5/12/17
to
John Donners <j.do...@gmail.com> wrote:

> Maybe an extra dummy array property like 'PASSBOUNDS' for assumed-shape
> and assumed-rank arrays would help?

Just a trivial comment that ASSUMEBOUNDS would seem to be more
consistent in terminology. I also think it makes sense in that it is a
property of the dummy. The dummy is doing the assuming, while the actual
is doing the passing.

--
Richard Maine
email: last name at domain . net
domain: summer-triangle

herrman...@gmail.com

unread,
May 12, 2017, 11:36:48 AM5/12/17
to
On Friday, May 12, 2017 at 7:01:39 AM UTC-7, Richard Maine wrote:

(snip)

> Just a trivial comment that ASSUMEBOUNDS would seem to be more
> consistent in terminology. I also think it makes sense in that it is a
> property of the dummy. The dummy is doing the assuming, while the actual
> is doing the passing.

This reminds me that it took me a long time to understand
the meaning of assumed size and assumed shape, I believe
relating to who was doing the assuming.

That is, I understood the two, but kept forgetting which
one was which, and what was assumed.

Ron Shepard

unread,
May 12, 2017, 12:28:02 PM5/12/17
to
On 5/12/17 8:06 AM, FortranFan wrote:
> Please note I was indeed thinking along the same lines over the last few days and I was leaning toward the standard including the requirement that the bounds be passed when the TARGET attribute is applied on the dummy i.e., in addition to the current stipulation that bounds be available when the dummy has the ALLOCATABLE or POINTER attributes.

Unfortunately, I do not have any good suggestions to address or to solve
the overall problem. I would just point out that if TARGET is used for
this purpose, an undesirable side effect would be to suppress
optimizations that would otherwise be allowed because of aliasing
possibilities.

It would also change the meaning of existing codes, right? That kind of
backward incompatibility is usually a dead end for language features.

I have always thought that this feature regarding lower bounds in
ALLOCATABLE and POINTER arrays was a programming trap. Most times, you
do want the lower bounds to be remapped during subroutine calls. But
other times you don't, and then it sometimes seems like a lot of extra
effort is required to pass the bounds explicitly. However, if the lower
bounds are constants, then it isn't much of a problem, and that is how I
mostly use this feature in my codes. The ALLOCATABLE and POINTER
attributes of course limit the types of actual arguments that can be
used, so that is not a universal workaround.

I have wondered about the possibility of adding a feature to remap the
bounds at runtime. Would this cause compiler writers headaches?

All in all, this seems like a complicated issue, with tradeoffs between
programming ease, execution efficiency, and functionality. I don't know
of a good overall solution.

$.02 -Ron Shepard

Ron Shepard

unread,
May 12, 2017, 12:50:57 PM5/12/17
to
There are two meanings for the word "assume". The most common meaning is
to suppose without proof or to take on a default. That is not what the
word means in the assumed shape and rank contexts. In fact it is almost
the opposite because it is NOT taking a default. The second meaning is
to accept or to take on or to take over as in assuming a responsibility
or assuming a debt. That is the meaning in these contexts. The dummy
argument accepts the bounds or the shape or the rank from the actual
argument.

With assumed size arrays however, the word "assume" is the first
meaning. In this case, the dummy array is assumed to be unkknown and to
have no upper bound, and the programmer is responsible for not exceeding
the unknown actual array size.

Except for character lengths, in which case assumed size has the second
meaning. The LEN() intrinsic will take the assumed size character string
and tell you the length that was assumed (taken on) from the actual
argument.

I think some of the confusion about the meaning of assumed shape or
assumed rank is because of those two meanings of the word "assume." If
the first meaning is assumed (ok, that is ironic) in all situations,
then confusion will follow. Fortran uses that word in both ways.

$.02 -Ron Shepard

Richard Maine

unread,
May 12, 2017, 8:57:37 PM5/12/17
to
Ron Shepard <nos...@nowhere.org> wrote:

> There are two meanings for the word "assume". The most common meaning is
> to suppose without proof or to take on a default.
...
> With assumed size arrays however, the word "assume" is the first
> meaning. In this case, the dummy array is assumed to be unkknown and to
> have no upper bound, and the programmer is responsible for not exceeding
> the unknown actual array size.

That's not the way I interpret it. I interpret "assumed size" to use the
same meaning of "assumed" as does "assumed shape" - that is the size is
taken from the actual argument.

The bit about the programmer being responsable for not exceeding it is
no different than for any other array, as far as the standard is
concerned. The programmer is always responsible for not exceeding the
bounds of any array. There are no cases where the standard mandates that
a compiler be able to diagnose bounds errors. It is common practice for
compilers to at least have such an option, but that is a quality of
implementation issue - not a specification of the standard. It just so
happens that most implementations don't have a handy way to do that for
assumed-size arrays (though some do).

From the perspective of the standard (wherefrom the term comes), an
assumed-size array does have a size. It is just that the standard
doesn't (for historical reasons) presume that the compiler will know the
size, and thus things that would require the compiler to know the size
are forbidden. But it still has a size and the restrictions on the user
are just the same; that size is assumed from the actual argument.

To my knowledge, all uses of "assumed" in the standard use the same
meanng.

herrman...@gmail.com

unread,
May 12, 2017, 9:34:53 PM5/12/17
to
On Friday, May 12, 2017 at 5:57:37 PM UTC-7, Richard Maine wrote:

(snip)

> From the perspective of the standard (wherefrom the term comes), an
> assumed-size array does have a size. It is just that the standard
> doesn't (for historical reasons) presume that the compiler will know the
> size, and thus things that would require the compiler to know the size
> are forbidden. But it still has a size and the restrictions on the user
> are just the same; that size is assumed from the actual argument.

Yes, the compiler doesn't know the size, so it assumes that you
know the size, and use it appropriately.

Richard Maine

unread,
May 12, 2017, 9:45:01 PM5/12/17
to
Correction: the compiler *might* not know the size. Although it is not
the most common case, there exist compilers that do know the size, and
this is allowed by the standard. In particular, there exist compilers
that can diagnose (at run-time) exceeding the bounds of an assumed-size
array. I think I recall that Salford at least used to have an option for
that, though I'll not guarantee my memory is correct on that detail.

Ron Shepard

unread,
May 13, 2017, 4:12:10 AM5/13/17
to
On 5/12/17 7:57 PM, Richard Maine wrote:
> Ron Shepard<nos...@nowhere.org> wrote:
>
>> There are two meanings for the word "assume". The most common meaning is
>> to suppose without proof or to take on a default.
> ...
>> With assumed size arrays however, the word "assume" is the first
>> meaning. In this case, the dummy array is assumed to be unkknown and to
>> have no upper bound, and the programmer is responsible for not exceeding
>> the unknown actual array size.
> That's not the way I interpret it. I interpret "assumed size" to use the
> same meaning of "assumed" as does "assumed shape" - that is the size is
> taken from the actual argument.

I think I understand your point, but I still disagree. The assumed size
array declaration

integer array(*)

tells the compiler it MUST IGNORE any of the actual argument shape and
size values and to take a default lower bound of 1 and a default size of
unknown. As you say, things like ubound(array) or size(array) do not
work because the declaration explicitly tells the compiler to NOT assume
(take on) those attributes from the actual argument but rather to take
"without proof" a different default behavior for that declaration. The
actual argument might well be a multidimensional array, for example
ACTUAL(M,N), and that dummy array declaration above works correctly
through storage sequence association to allow the entire array to be
referenced through a single subscript. It is up to the programmer to
ensure that the single subscript does not exceed the size of the actual
array argument (e.g. M*N in the 2D example). Nothing is assumed (taken
on) from the actual argument by the compiler, not M, not N, not the
product M*N, and there is no (standard) way to inquire about these
values from within the subroutine through the dummy array.

On the other hand, the assumed size character declaration

character(len=*) c

tells the compiler to assume (to take on) the attributes of the actual
argument. Things like len(c) work in this case because the length is one
of the attributes that are assumed (taken on) from the actual argument.
Both of the above declarations are called "assumed size," but the first
array declaration has a different meaning from the second character
length declaration.

Things like assumed shape and the newer assumed rank (which I have not
yet actually used) are further examples of how the dummy arguments
assume (take on) information from the actual arguments, and the compiler
is required to use that information and to make it available through the
dummy argument.

The two meanings of "assume" are almost opposite in these two cases. One
tells the compiler it MUST IGNORE the characteristics of the actual
argument, while the other requires that certain information MUST BE
PASSED ON to the dummy argument and made available through the dummy
argument. Those attributes include some or all of size(), shape(),
lbound(), and ubound(), depending on the other details of the
declaration. Given the similar terminology but the opposite meanings, it
is no surprise that programmers might sometimes confuse the functionality.

$.02 -Ron Shepard

Thomas Koenig

unread,
May 13, 2017, 7:00:23 AM5/13/17
to
Ron Shepard <nos...@nowhere.org> schrieb:

> I think I understand your point, but I still disagree. The assumed size
> array declaration
>
> integer array(*)

[...]

> On the other hand, the assumed size character declaration
>
> character(len=*) c
>
> tells the compiler to assume (to take on) the attributes of the actual
> argument.

[...]

> The two meanings of "assume" are almost opposite in these two cases.

> Given the similar terminology but the opposite meanings, it
> is no surprise that programmers might sometimes confuse the functionality.

I have to admit that I among the people who often get confused.
I have to keep looking up which is which.

I assume that [pun intended], at the time of F90, a better
terminology could have been chosen. But that is water long
under the bridge by now.

Richard Maine

unread,
May 13, 2017, 9:57:55 AM5/13/17
to
Ron Shepard <nos...@nowhere.org> wrote:

> On 5/12/17 7:57 PM, Richard Maine wrote:

> > That's not the way I interpret it. I interpret "assumed size" to use the
> > same meaning of "assumed" as does "assumed shape" - that is the size is
> > taken from the actual argument.
>
> I think I understand your point, but I still disagree. The assumed size
> array declaration
>
> integer array(*)
>
> tells the compiler it MUST IGNORE any of the actual argument shape and
> size values and to take a default lower bound of 1 and a default size of
> unknown.

That's not what the standard says. From f2008 5.3.8.5.

" An assumed-size array is a dummy argument array whose size is assumed
from that of its effective argument....

The size of an assumed-size array is determined as follows [details
omitted]"

That seems pretty explicit (not to be confused wih explicit shape :-))
to me. Nothing there about having a size of unknown. It has a specific
size and the standard specifies how that size is computed. Oh, and the
syntax allows lower bound to be specified by declarations like

integer array(0:*)

or for that matter like

integer array(3:7,0:5,42:*)

While 1-D assumed size arrays are the most common case, they are not the
only case allowed.

spectrum

unread,
May 13, 2017, 10:31:30 AM5/13/17
to

> > > That's not the way I interpret it. I interpret "assumed size" to use the
> > > same meaning of "assumed" as does "assumed shape" - that is the size is
> > > taken from the actual argument.
> >
> > I think I understand your point, but I still disagree. The assumed size
> > array declaration
> >
> > integer array(*)
> >
> > tells the compiler it MUST IGNORE any of the actual argument shape and
> > size values and to take a default lower bound of 1 and a default size of
> > unknown.
>
> That's not what the standard says. From f2008 5.3.8.5.
>
> " An assumed-size array is a dummy argument array whose size is assumed
> from that of its effective argument....


Is this a new specification introduced as of F2008 (and does not exist
up to F2003)? As far as I experienced, I cannot get the size of an actual
array argument (= the number of elements) by applying size() to the corresponding
dummy array in a subroutine declared with (*) (<-- e.g., integer :: a(*)).

Richard Maine

unread,
May 13, 2017, 11:16:29 AM5/13/17
to
spectrum <septc...@gmail.com> wrote:

> > That's not what the standard says. From f2008 5.3.8.5.
> >
> > " An assumed-size array is a dummy argument array whose size is assumed
> > from that of its effective argument....
>
>
> Is this a new specification introduced as of F2008 (and does not exist up
> to F2003)? As far as I experienced, I cannot get the size of an actual
> array argument (= the number of elements) by applying size() to the
> corresponding dummy array in a subroutine declared with (*) (<-- e.g.,
> integer :: a(*)).

No. Nothing of substance here changed since the introduction of assumed
size in f77.

The array has a size, but you are not allowed to inquire about it. As
noted elsewhere, in the most common implementations the compiler does
not "know" the size. In order to accomodate such implementations, the
standard specifically forbids inquiring about the size. That doesn't
mean the array doesn't have a size - just that you can't inquire about
it. You also can't inquire about the upper bound of the last dimension;
again, it has one, but you can't inquire about it. An assumed-size array
does not have a shape.

Ron Shepard

unread,
May 13, 2017, 4:04:54 PM5/13/17
to
Here is an online dictionary definition of the word "assume".

as·sume
əˈso͞om/Submit
verb
1.
suppose to be the case, without proof.
"you're afraid of what people are going to assume about me"
synonyms: presume, suppose, take it (as given), take for granted, take
as read, conjecture, surmise, conclude, deduce, infer, reckon, reason,
think, fancy, believe, understand, gather, figure
"I assumed he wanted me to keep the book"
2.
take or begin to have (power or responsibility)
"he assumed full responsibility for all organizational work"
synonyms: accept, shoulder, bear, undertake, take on/up, manage, handle,
deal with
"they are to assume more responsibility"

I am not saying that the standard does not use the word "assume," I am
saying that in some cases that word means the first definition (take
without proof) while in other cases the word means the second definition
(to take on).

On 5/13/17 8:57 AM, Richard Maine wrote:
> Ron Shepard <nos...@nowhere.org> wrote:
>
>> On 5/12/17 7:57 PM, Richard Maine wrote:
>
>>> That's not the way I interpret it. I interpret "assumed size" to use the
>>> same meaning of "assumed" as does "assumed shape" - that is the size is
>>> taken from the actual argument.
>>
>> I think I understand your point, but I still disagree. The assumed size
>> array declaration
>>
>> integer array(*)
>>
>> tells the compiler it MUST IGNORE any of the actual argument shape and
>> size values and to take a default lower bound of 1 and a default size of
>> unknown.
>
> That's not what the standard says. From f2008 5.3.8.5.
>
> " An assumed-size array is a dummy argument array whose size is assumed
> from that of its effective argument....
>
> The size of an assumed-size array is determined as follows [details
> omitted]"

This use of "assume" means to "take without proof". It does not assume
(take on, take from, inherit) the characteristics of the actual
argument. The dummy argument has the new characteristics from that point
on "without proof" from the actual argument characteristics. Even the
standard in this case uses the term "effective argument" rather than
"actual actual" I would assume :) to emphasize this point. I would say
that a better phrasing for that sentence in the standard might be

"...whose size is implicitly limited by that of its effective argument..."

But the standard used the word "assumed," so we are stuck with the
ambiguity of that word.

The explanation of the actual size of the array is given so that the
programmer can stay within the limits of the actual argument array, not
because the compiler is required to assume (take on) characteristics
from the actual argument and to be able to report them to the
programmer. Those characteristics of the actual argument MUST BE IGNORED
by the compiler with this declaration rather than assumed (taken on). I
previously mentioned how a rank-2 actual argument could become a rank-1
dummy argument to demonstrate this. The programmer must stay within the
size constraints of the actual argument, and the compiler can assume
(without proof) that the programmer has done so.

> That seems pretty explicit (not to be confused wih explicit shape :-))
> to me. Nothing there about having a size of unknown. It has a specific
> size and the standard specifies how that size is computed.

It is unknown to the compiler through the dummy argument, and the
standard is specific that shape(), size(), and ubound() inquiries are
not allowed for these array declarations. In the case of ubound(), it is
specifically the last dimension specified by * that is prohibited. The
size must be known to the programmer who is required to know the actual
argument characteristics and to avoid exceeding that size. The compiler
is allowed to assume (without proof) that the programmer has conformed
to these size requirements. If the programmer does not do his part, then
it is not the compiler's fault, and further, the compiler is not
required to report this error because it is not required to assume (take
on) the actual argument characteristics necessary to report this error.

> Oh, and the
> syntax allows lower bound to be specified by declarations like
>
> integer array(0:*)
>
> or for that matter like
>
> integer array(3:7,0:5,42:*)
>
> While 1-D assumed size arrays are the most common case, they are not the
> only case allowed.

Yes, I actually use these forms, and have done so since f77 compilers
became available. But these declarations also take the dummy array rank
and bounds from the dummy array declaration (without proof) rather than
assuming (taking on, taking from) them from the actual argument. The
rank and bounds information from the actual arguments MUST BE IGNORED
with these definitions. For example, if the declaration

integer array(:,:,*)

were allowed, then this might declare a rank 3 array in which the actual
argument characteristics are assumed (taken from) the first two
dimensions, and the characteristics of the last dimension are assumed
(without proof) from the dummy declaration while ignoring the actual
argument characteristics. The actual argument might be a rank 4 or
higher array, for example. This would clearly mix the two different
definitions of the word "assume" in a single array declaration. Of
course, this declaration is not allowed, so I'm just using it here as an
example that shows the two distinct meanings of "assume."

Here is an example that is legal fortran that does pretty clearly mix
the two definitions of the word "assume."

program chartest
character(len=4) c(5)
call sub1(c)
call sub2(c)
contains
subroutine sub1(c)
character(len=*) c(*)
write(*,*) 'len=', len(c) ! size(c) is not allowed.
return
end subroutine sub1
subroutine sub2(c)
character(len=*) c(:)
write(*,*) 'len=', len(c), ' size=', size(c)
return
end subroutine sub2
end program chartest

In sub1() there is an assumed size array of assumed size character
strings. You can inquire about the length of the character string, but
you cannot inquire about the size of the array. That is because assumed
size character strings use the second definition (take from) of the word
"assume" while the assumed size array uses the first definition (without
proof).

In sub2(), there is an assumed shape array of assumed size character
strings. It is legal to inquire about both the length of the character
string and the size of the array. In this case, both definitions use the
second meaning (take from) of the word "assume". Both characteristics
are taken from the actual argument.

When executed, this program prints

len= 4
len= 4 size= 5

Because sub1() is a contained subroutine, the compiler clearly knows
what is the size of the actual argument, both at compile time and at run
time. However, it is still illegal to inquire about that size, size(c),
because within sub1() the compiler is effectively REQUIRED TO IGNORE
that characteristic of the actual argument.

So let's follow this just a little further. Consider adding the line

call sub2(c(1:2))

to sub1(). This is still legal because the programmer has followed the
rules and stayed within the size of the actual argument in the main
program. Now, the program prints out

len= 4
len= 4 size= 2
len= 4 size= 5

as expected. The size() inquiry is still allowed in sub2() because it
assumes (takes from, inherits) this from the actual argument.

There are several other ways in which to make size() allowed. Within
sub1() one could declare c(5) as explicit shape. Or, one could use

size(c(1:5))

and still be legal. But in these cases, the size() of the array is being
determined locally within sub1(), using the "without proof" definition
of assume, rather than the "take from" definition.

$.02 -Ron Shepard

Richard Maine

unread,
May 13, 2017, 9:01:37 PM5/13/17
to
Ron Shepard <nos...@nowhere.org> wrote:

> Even the
> standard in this case uses the term "effective argument" rather than
> "actual actual" I would assume :) to emphasize this point.

The "effective argument" bit has nothing to do with this question. If I
recall correctly (though I don't feel like looking it up), that's for
the case where a pointer appears in the actual argument list; the
effective argument is then the target of the pointer. That has nothing
in particular to do with assumed size, but is the same for all sorts of
dummy arguments.

I still disagree with you on the rest, but I'll stop debating the point.

spectrum

unread,
May 14, 2017, 11:33:23 AM5/14/17
to
Dear Richard,

Thank you very much for your information. Hmm, it does seem like the word
"assume" is confusing... (in my country, the "assumed-shape" is translated
to something like "shape-inheriting" array or something in introductory Fortran
books :-)

Richard Maine

unread,
May 14, 2017, 10:11:38 PM5/14/17
to
spectrum <septc...@gmail.com> wrote:

> Thank you very much for your information. Hmm, it does seem like the word
> "assume" is confusing... (in my country, the "assumed-shape" is translated
> to something like "shape-inheriting" array or something in introductory
> Fortran books :-)

I'd consider that a decent translation. It works in English as well.
"Inherited" might have been as good (or perhaps better) a word, but it's
a bit late to change that now.

John Donners

unread,
May 15, 2017, 5:53:02 AM5/15/17
to
On Thursday, May 4, 2017 at 11:02:59 PM UTC+2, John Donners wrote:
> Hi all,
>
> I'll send a letter to the standards committee about a feature that I've been playing with for a while now: the bounds of an array is passed to an assumed-rank dummy array in a subroutine, even if the dummy array is not allocatable, nor pointer.
>
> This feature is found in the draft 2015 standard and has been implemented by Cray, Intel and IBM in their latest compilers. I would like to see this feature being continued in the final standard, but I'm also quite curious about your opinion for this particular feature.
>
Hi,

thanks for your comments. I'll add a paragraph to the letter with the alternative that was discussed:

"
An alternative could be the introduction of a new characteristic for dummy arrays,
which would indicate that the dummy assumes the bounds of the actual argument.
This would have some advantages:
-it can be introduced for assumed-rank, assumed-shape and assumed-size arrays
-older codes would not be broken
-programmers can choose when to assume bounds
"

Personally, I like the ASSUMEBOUNDS suggestion, but I'll leave it out of the text. The suggestion to use TARGET would cause confusion and incompatibilities, especially since that keyword is already used quite frequently in production codes.

FortranFan

unread,
May 15, 2017, 10:48:41 AM5/15/17
to
On Monday, May 15, 2017 at 5:53:02 AM UTC-4, John Donners wrote:

> ..
>
> Hi,
>
> thanks for your comments. I'll add a paragraph to the letter with the alternative that was discussed:
>
> "
> An alternative could be the introduction of a new characteristic for dummy arrays,
> which would indicate that the dummy assumes the bounds of the actual argument.
> This would have some advantages:
> -it can be introduced for assumed-rank, assumed-shape and assumed-size arrays
> -older codes would not be broken
> -programmers can choose when to assume bounds
> "
>
> Personally, I like the ASSUMEBOUNDS suggestion, ..

Hello John,

Thanks for your summary.

I suggest you include this comp.lang.fortran thread also in your letter, so the interested committee numbers can peruse it if they feel inclined to understand the opinions.

Also, everyone interested in Fortran will have to take a pause and ponder over the ensuing verbosity in the language - note some code might read in the future:

-- begin code snippet --
..
subroutine foo(.., x, ..)
<type>, dimension(..), codimension[..], ASSUMEBOUNDS, contiguous, target, optional, intent(..) :: x ! plus whatever other attributes that can be piled on or might get added in the future!
..
-- end snippet --

It is NOT that I'm complaining:

* I personally prefer such verbosity (though I tend to drop *dimension attributes to make the lines shorter; instead I prefer to apply the array syntax on the right next to the dummy argument names e.g., x(..)[..] ). Compared to extreme terseness in some other languages which tend to make a lot of use of symbols and their combinations which I find utterly non-intuitive (I greatly struggle with C++), the verbally-explicit nature of Fortran has its positives.

* I'm only bringing this up for awareness and in case some brilliant minds out there can think of even better ways to work out the language syntax.
0 new messages