- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[fortran] MODULE ac_mod CONTAINS FUNCTION make_a(m,l) REAL,ALLOCATABLE :: make_a(:) INTEGER,INTENT(out) :: l, m INTEGER :: n = 4 INTEGER :: k ALLOCATE(make_a(1:n)) make_a = [(REAL(k),k=1,n)] write(*,*) 'in func', make_a l=10 m=20 RETURN END FUNCTION make_a END MODULE ac_mod ! PROGRAM ac USE ac_mod IMPLICIT none REAL,ALLOCATABLE :: a(:) INTEGER :: l, m ! INTEGER :: ios ! ALLOCATE(a, SOURCE = make_a(l,m)) ! <<< case 1 problem line ! ALLOCATE(a, SOURCE = make_a(l,m),STAT=ios) ! <<< case 2 problem line ! ALLOCATE(a(:), SOURCE = make_a(l,m),STAT=ios) ! <<< case 3 problem line ! ALLOCATE(a(*), SOURCE = make_a(l,m),STAT=ios) ! <<< case 4 problem line WRITE(*,*) 'results',a WRITE(*,*) 'returned arguments:',l, m ! WRITE(*,*) 'ios of allocate: ',ios WRITE(*,*) 'status allocated a:',ALLOCATED(a) READ(*,*) END PROGRAM [/fortran]An allocatable array A becomes allocated and filled with the result of the function make_a that is a function with an allocatable array as a function result.
In this form the program runs fine. The results of A are correct. The compiler, however, generates a warning #8199 that a shape specification for a must be supplied in the ALLOCATE statement.
If I add the STAT in the allocate statement, (case 2 line), this warning dissappears. Strange!
I tried an explicit shape specification (case 3 line) but the compiler gives error #6726 telling that an explicit shape specification is incorrect. Finally, if I tryan assumed size array (case 4 line), the compiler gives an internal compiler error.
So, I am afraid thateither I do not understand how to use the ALLOCATE statement in this situation properly, or the compiler lost its way, or both. Who has an idea what happens here?
Robert
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am certainly no standards expert butto myunderstanding of F2003
" stat_variable, source_expr, and errmsg_variable must not be allocated within the ALLOCATE statement in which they appear."
(emphasis mine.)
SoI thinkthat your make_a function cannot appear in the allocate statement.
Les
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is nothing wrong with the allocate in the function itself - that's legal F2003.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is nothing wrong with the allocate in the function itself - that's legal F2003.
Ah, so I misunderstood the F2003 notes on Allocate. :-(
not that I am surprised by that but I thought that because the functionresult was also declared as allocatable then it was non-standard.
I live and learn.
Les
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I forgot to mention that the warning #8199 is solely due to the Fortran 2003 syntax requirement. (/stand:f03) Removing that requirement does the warning disappear. The question remains what should be the proper syntax so that the compiler does not complain.
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In Fortran 2003, constraint C628 says, "An allocate-shape-spec list shall appear if and only if the allocate-object is an array."
In Fortran 2008, the corresponding constraint C633 says, "If allocate-object is an array either allocate-shape-spec-list shall appear or source-expr shall appear and have the same rank as allocate-object. If allocate-object is scalar, allocate-shape-spec-list shall not appear."
What we have here is a change between F03 and F08 where F08 allows the shape to be taken from the SOURCE= expression but F03 does not. You want the F08 behavior, which the compiler does provide. In the current version, restricting diagnostics to extensions to F08 is not yet supported. I note that while it will be supported in a future release, the current development version doesn't suppress the diagnostic here - I will report that. I also notice that if you add STAT=, the diagnostic goes away, which is really weird. I will report that too.
You can either supply the shape for the allocate, add STAT=, or suppress diagnostic 8199 (under Diagnostics > Disable Specific Diagnostics, put in 8199.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
this makes thing very clear to me.
Thanks for yourhelp.
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a follow-up question to this old thread. How would you be able to modify the simple code at the top, given by Robert, to have the returned array "a" start with a lower bound of 0? Just modifying the allocation to "make_a(0:n)" in the function is fine, but how do you keep that lower bound indexing on return into the main program for the allocatable array "a"? When I try to do this by the simple change in the function I get the following error:
Error 1 error #6726: An explicit-shape-spec in an ALLOCATE statement is incorrect.
Amalia
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
amalia.barrios@navy.mil wrote:
I have a follow-up question to this old thread. How would you be able to modify the simple code at the top, given by Robert, to have the returned array "a" start with a lower bound of 0? Just modifying the allocation to "make_a(0:n)" in the function is fine, but how do you keep that lower bound indexing on return into the main program for the allocatable array "a"? When I try to do this by the simple change in the function I get the following error:
Error 1 error #6726: An explicit-shape-spec in an ALLOCATE statement is incorrect.
Amalia
Is this what you're looking for? You can do the specification of lower bound of your array on the caller side.
MODULE m !.. IMPLICIT NONE PRIVATE PUBLIC :: CreateRealArray CONTAINS FUNCTION CreateRealArray(ArrSize) RESULT(NewArray) !.. Argument list INTEGER, INTENT(IN) :: ArrSize !.. Function result REAL, ALLOCATABLE :: NewArray(:) !.. Local Variables INTEGER :: Istat INTEGER :: I IF (ArrSize > 0) THEN ALLOCATE(NewArray(1:ArrSize), SOURCE=[( REAL(I), I = 1, ArrSize )], STAT=Istat) ELSE ALLOCATE(NewArray(1), SOURCE=[( 0.0 )], STAT=Istat) END IF RETURN END FUNCTION CreateRealArray END MODULE m PROGRAM p USE m, ONLY : CreateRealArray IMPLICIT NONE !.. Local variables REAL, ALLOCATABLE :: a(:) INTEGER :: Istat !.. ALLOCATE (a(0:4), SOURCE=CreateRealArray(5), STAT=Istat) IF (Istat == 0) THEN PRINT *, " a = ", a PRINT *, " SIZE of a = ", SIZE(a) PRINT *, " Lower Bound of a = ", LBOUND(a) PRINT *, " Upper Bound of a = ", UBOUND(a) ELSE PRINT *, " Allocation of a failed. STAT = ", Istat END IF STOP END PROGRAM p
The program result is
a = 1.000000 2.000000 3.000000 4.000000 5.000000 SIZE of a = 5 Lower Bound of a = 0 Upper Bound of a = 4 Press any key to continue . . .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The lower bound of the value that results from evaluating an array function result is always one, regardless of the lower bound of the result variable prior to the end of execution of the function.
(The result of evaluating an array function is an array value, array values are always considered to have a lower bound of one, array data objects (array names or array components) are the things that can have bounds other than one).
So if you want the main program to have a different lower bound then you have to specify that in the allocate statement in the main program.
MODULE m IMPLICIT NONE CONTAINS FUNCTION make_a() REAL, ALLOCATABLE :: make_a(:) ALLOCATE(make_a(10)) make_a = 1.0 END FUNCTION make_a END MODULE m PROGRAM p USE m IMPLICIT NONE REAL, ALLOCATABLE :: a(:) ALLOCATE(a(0:9), SOURCE=make_a()) PRINT *, LBOUND(a) END PROGRAM p
On the other hand, if make_a returned an object of derived type with an array component, then the bounds are carried across to the component in the main program. This is because the bounds of a allocatable component are considered part of the value of an object of derived type (versus the bounds of an array value of derived type - which is just a different case of the first paragraph).
MODULE m2 IMPLICIT NONE TYPE btype REAL, ALLOCATABLE :: component(:) END TYPE btype CONTAINS FUNCTION make_b() TYPE(btype) :: make_b ALLOCATE(make_b%component(0:9)) make_b%component = 1.0 END FUNCTION make_b END MODULE m2 PROGRAM p USE m2 IMPLICIT NONE TYPE(btype) :: b b = make_b() PRINT *, LBOUND(b%component) END PROGRAM p
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks FortranFan and IanH for the sample code, however, in your examples it seems that I have to know APRIORI the size of "make_a" before I can declare the array "a" with a lower bound of 0. In the original sample the upper bound is determined within the function itself, so the size carries back to the main program but not the lower bound, apparently. I'm looking to set "a" to the exact size (lower & upper bounds) via the "SOURCE =" attribute, where the size is determined within the function.
Looks like there's no easy way to do this without requiring an explicit interface, but a work around may be the derived type sample, correct?
Amalia
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Consider not using a function - make the thing that you want allocated with particular bounds an actual argument that corresponds to a dummy allocatable array argument with the intent(out) attribute.
As a bit of a guideline (reasonable exceptions exist), if a function is never going to be used for anything bar the right hand side of an assignment statement, then you should reconsider whether the thing that is a function should be a function.
(In the original example, the function modifies its arguments. I consider that an anathema in any context bar C interoperability.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH wrote:
..
As a bit of a guideline (reasonable exceptions exist), if a function is never going to be used for anything bar the right hand side of an assignment statement, then you should reconsider whether the thing that is a function should be a function.
(In the original example, the function modifies its arguments. I consider that an anathema in any context bar C interoperability.)
Different strokes for different folks, I guess! Generally, we only create functions when it is indeed going to be used mainly as the right-hand side of an assignment i.e., to get "formula translation" for:
y = f(x)
IanH wrote:
..
(In the original example, the function modifies its arguments. I consider that an anathema in any context bar C interoperability.)
Agree, so we try to apply PURE attribute to all functions and INTENT(IN) to all its arguments, so we can get slapped when we tried to modify the function arguments.
amalia.barrios@navy.mil wrote:
..
Looks like there's no easy way to do this without requiring an explicit interface, but a work around may be the derived type sample, correct?
Amalia
Amalia,
Not sure what all requirements you have, but from what you've indicated thus far, as suggested by IanH, functions returning a derived type with a zero-based array component or a SUBROUTINE procedure with an INTENT(OUT) allocatable array dummy argument appear to be your best options.

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