- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I need to create a elemental function with returning a variable-length string. To do so I use a allocatable object. But the ifort compiler return the error with code 6112 when gfortran do this very well. So is there a way to do this kind of function with ifort ?
Cheers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Depending on the situation, it may be appropriate to wrap the allocatable character object in a derived type, and return that instead.
module m implicit none type :: string character(:), allocatable :: item end type string contains elemental function fun(x) integer, intent(in) :: x type(string) :: fun fun%item = repeat('x', x) end function fun end module m program p use m implicit none type(string), allocatable :: out(:) integer :: i out = fun([1,2,3,4,5]) print "(a)", (out(i)%item, i = 1, size(out)) end program p
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran standard states in C1290, "The result variable of an elemental function shall be scalar, shall not have the POINTER or ALLOCATABLE attribute, and shall not have a type parameter that is defined by an expression that is not a constant expression."
You write, "need to create a element(al) function with returning a variable-length string": is the length of the return string a constant expression of dummy argument(s) which would be INTENT(IN)? Then you can make use of this fact in defining the function result string length.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Depending on the situation, it may be appropriate to wrap the allocatable character object in a derived type, and return that instead.
module m implicit none type :: string character(:), allocatable :: item end type string contains elemental function fun(x) integer, intent(in) :: x type(string) :: fun fun%item = repeat('x', x) end function fun end module m program p use m implicit none type(string), allocatable :: out(:) integer :: i out = fun([1,2,3,4,5]) print "(a)", (out(i)%item, i = 1, size(out)) end program p
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH your solution is interesting but a bit heavy to use because you need to declare your string type every time you need to call the function. And your type string is a hidden character allocatable, so why the compiler do not allow the character allocatable directly ?
FortranFan I try to combine what I understood of your comment into a small example but it compiles find but did not work correctly. So I probably miss-understood. Here is my example:
module test3_mod implicit none contains elemental function leng(args) result(num) implicit none integer, intent(in) :: args integer :: num if (args >=0) then num= args +2 else num= -args +3 endif return end function leng elemental function func(args) result(string) implicit none integer, intent(in) :: args character(len=leng(args)) :: string string=repeat('x',leng(args)) return endfunction func end module test3_mod PROGRAM test3 use test3_mod implicit none integer, parameter :: n=10 print *, 'start' print*, '.'//func( (/1,10/) )//'.' print *, 'normal stop' end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The compiler does not allow the allocatable attribute on an elemental function result because the language does not permit it.
The language does not permit the allocatable attribute on an elemental function result because, conceptually and practically, it does not make sense. Being allocatable implies that characteristics, other than the value, of the function result can vary from call to call of the function, such as the length of the function result in this case. Elemental functions can be invoked as part of setting the value of an array - that is what they are primarily for - and in that context, variation in characteristics, other than the value, from element to element in an array is not permitted.
When the allocatable character thing is made a component of a derived type, then the allocation status of the component and aspects such as the length of the component are then considered part of the value of an object of the derived type (see F2008 4.5.8). From the perspective of objects of the derived type (rather than looking at the component), the function result can no longer potentially differ in type parameters from call to call - there are no type parameters at the level of the derived type to vary.
Wrapping an allocatable/pointer object as a component of a derived type to permit its use in array-like contexts is a very common thing to do in modern Fortran - it is how you implement arrays of pointers, or arrays of arrays, or arrays of polymorphic objects that might differ in dynamic type from element to element.
That version of gfortran has a bug - one that ifort had a few versions ago too. The release of gfortran I have here (6.3.1) correctly rejects the code.
For similar reasons as to why allocatable results are prohibited (plus perhaps to make things a little simpler for implementations), the type parameters of the function result of an elemental function must be specified by constant expressions. The value of a constant expression cannot depend on the value of a dummy argument, and cannot require the execution of a user supplied procedure, but that is what the code in #4 does. Because this is a constraint, ifort should issue a diagnostic for the non-conforming code in #4, the absence of such a diagnostic is a compiler bug. Current versions of gfortran do diagnose the error in the program.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Romain N. wrote:
.. FortranFan I try to combine what I understood of your comment into a small example but it compiles find but did not work correctly. ..
@Romain N,,
Note the constraint C1290 in the Fortran Standard that says, " shall not have a type parameter that is defined by an expression that is not a constant expression". So look in section 7.1.12 of the standard on "Constant Expression" and the limitations of such an expression.
That said, it would appear to me if you were to change the result variable declaration to be something like, say,
.. character(len=abs(args)+2) :: string ..
then it should be Ok per my interpretation of C1290 since ABS is a standard intrinsic elemental function (but note I am more often than not wrong on such matters). Again Intel Fortran compiler compiles such code without complaints but the executable doesn't work as expected; I don't know if the use is list-directed IO or with the elemental function. Note gfortran gives an error with the elemental function, "Dummy argument 'args' not allowed in expression at (1)"
I suggest you follow up further with Intel team on this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@IanH, @FortranFan :
Thanks to your two explanations, I understood why it makes no sense to try directly this kind of implementation. I flag IanH respond as the best reply because it gives a good alternative to do this function using a derived type.
Thank you for your time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I reported the ifort defect of not properly flagging the non-conformant code in post #4 that IanH describes in post #5.
(Internal tracking id: DPD200417031)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page