- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If an array is allocated with another array as the source, the bounds of the source array are used for the bounds of the allocated array. This works fine for regular arrays. But the Intel compiler comes in trouble if the source is not a regular array but a function result. In that case, the size of the allocated array is correct, but the lower bound of the result array is set to 1. And that seems incorrect to me. (See MFE ed 2018, section 15.4.4) Our gfortran friends present the correct result.
I have added a reproducer
Robert
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Robert_van_Amerongen , if you have support subscription, please also submit a support request at Intel OSC (https://supporttickets.intel.com/servicecenter?lang=en-US) to get Intel Fortran team's direct attention and their response to your situation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here's my 2 cents' worth: per the Fortran standard, effectively the LBOUND along each dimension of a function result that is an array is always 1. In your reproducer, that the variable of rank-1 array corresponding to the function result in the function subprogram has been defined therein with a lower bound of -5 is only relevant in that subprogram, the standard in essence states the lower bound not be retained once the function result is returned from the subprogram.
It's gfortran that appears not to conform to the standard in this case.
Note section 15.4.4 of "MFE" does not allude to the function result case. Regardless, it's the standard that is ultimately the arbiter on such matters.
So I suggest you follow up with Intel Fortran team to get their feedback on this, especially with respect to what I state above. Also, please consider a support request toward gfortran at GCC Bugzilla: https://gcc.gnu.org/bugzilla/ and you can link this comment to help that discussion.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In effect, the standard implies you should pursue other options for what you seek such as a subroutine subprogram perhaps:
MODULE ta_mod
IMPLICIT none
PRIVATE
!
PUBLIC :: subta
!
CONTAINS
!
subroutine subta( a )
REAL,ALLOCATABLE, intent(out) :: a(:)
!
ALLOCATE(a(-5:+5))
a = 567.0
!
write(*,*) 'bounds of a after ALLOCATE', LBOUND(a, DIM=1), UBOUND(a, DIM=1)
RETURN
END subroutine subta
!
END MODULE ta_mod
!
!======================================
!
PROGRAM ta
USE ta_mod, ONLY : subta
IMPLICIT none
!
REAL,ALLOCATABLE :: c(:)
!
call subta( c )
write(*,*) 'bounds of c after ALLOCATE', LBOUND(c, DIM=1), UBOUND(c, DIM=1)
!
STOP
END PROGRAM ta
C:\temp>ifort /standard-semantics ta.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:ta.exe
-subsystem:console
ta.obj
C:\temp>ta.exe
bounds of a after ALLOCATE -5 5
bounds of c after ALLOCATE -5 5
C:\temp>
Separately, do note if you wish to work with lower bounds other than unity in your Fortran program(s), that is feasible but it does take effort and require very careful management across all your subprograms.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Separately, do note if you wish to work with lower bounds other than unity in your Fortran program(s), that is feasible but it does take effort and require very careful management across all your subprograms.
Indeed it is for such reasons that I pretty much never have anything other than the 1 lower bound and mange my data representations/problem formulation accordingly. None the less, the inconsistency between a function return and a subroutine return in the examples shown is quite disturbing as it is counter intuitive. I would guess the standards writers were looking to avoid some other consequences (or complication) but if anyone knows the answer I would be interested to know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A function result is an expression. If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel writes:
.. If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1.
Re: "If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1," it is not correct.
There is a lot of convoluted logic vis-a-vis the wording in the standard that comes into play here.
In essence, what it boils down to is whether the source-expr is a whole array or not. Following tortuous paths through the standard verbiage and several leaps with mind-numbing logic, one is forced to arrive at a point where the standard supposedly stipulates the lower bound of a source-expr is 1 unless the operand of a source-expr is a whole array in which it is the LBOUND intrinsic result of that whole array. And given how a whole array is defined in the standard, a function result that is an array is not a whole array.
Consider the code below:
module m
integer, allocatable :: dat(:)
contains
function func() result(r)
integer, allocatable :: r(:)
allocate( r, source=dat )
end function
end module
use m
integer, allocatable :: x(:), y(:)
allocate( dat(-1:1) ) ; dat = 0
allocate( x, source=dat ) !<-- Here, source-expr is an array expression
print *, "lbound(x) = ", lbound(x, dim=1)
allocate( y, source=func() ) !<-- Here too, source-expr is an array expression
print *, "lbound(y) = ", lbound(y, dim=1)
end
C:\temp>ifort /standard-semantics c.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:c.exe
-subsystem:console
c.obj
C:\temp>c.exe
lbound(x) = -1
lbound(y) = 1
C:\temp>
The whole situation is so effed up with both the wordings in the standard and the compiler implementations there may be only compiler that can claim conformance to the standard now! And that is IFORT! This is because an Intel Fortran team rep had requested clarification a couple of years ago in a standard discussion context which had then led to a change in subsequent versions of IFORT.
There is likely only one person, the editor of the standard, who can convincingly claim accuracy in the standardese here and who can then make the leaps in "logic" required to arrive at the above point. And this editor also happens to be the main developer of a commercial transpiler that itself does NOT conform to the standard in this case. It too gives the same output as gfortran. And with similar situations, there are other Fortran compilers that have nonconforming behavior . Go figure!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, @FortranFan , I don't quite agree with you regarding my earlier statement. Perhaps I was insufficiently precise, and I fully agree that this is one of the more mind-numbingly obscure parts of the language.
You are correct to point to the description of LBOUND as the definition of what the lower bound should be here. The key wording is the definition of "whole array" which is "array component or array name without further qualification (9.5.2)" A function result does not qualify.
The point of difference is that an expression can simply be a variable, in which case its lower bounds are preserved. But if it's anything more complex than that, which is what I meant when I wrote "expression", then the lower bounds are always 1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, what does (supposed to) the following return for lbound of y?
program test
real, allocatable :: y(:)
y = foo(1.2)
print *,lbound(y)
contains
function foo(x) result(r)
real:: x,r(-1:1)
r = x
end function foo
end program test
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1, as it does. The lower bounds of an array-valued non-pointer function return are always 1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you all for your feedback. First, I found this example in a c-style environment and wanted to know how Fortran handles such a case. Based on my intuition, I expected the lower bound to be -5. If I am correct, Andrew feels the same.
But I am afraid that in this situation I must follow the advice here to use a subroutine in stead of a function (result) as FortranFan mentioned. And the fact that the two leading compilers in the field yield different result is an extra reason.
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Indeed Robert, you have reached the same conclusions as to how to deal with this (i.e. avoid it!) as I did at some point in history!

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page