Stefano Zaghi
2013-08-20 15:24:50 UTC
Hi all,
I have some problems with the definition of a character variable inside a procedure (e.g. a function). The problem seems very trivial, but...
I have a huge array (rank 1) in input and I would like to define a (local to the function) character variable with the length equals to the array size (automatic length size).
The pseudo code of the function could be:
function foo(array)
implicit none
integer, intent(IN):: array(1:)
logical:: foo
character(len=size(array,dim=1,kind=8)):: string
"do something with string"
return
endfunction foo
This approach fails if the array is very huge (in particular if the number of its elements is greater than 2^31-1) producing a zero length string. I do not know if the standard (std2003) fix a limit on the character variables length, I only know that the Intel Compiler has the following behavior:
The largest valid value for len ... is 2**31-1 on IA-32 architecture; 2**63-1 on IntelĀ® 64 architecture. Negative values are treated as zero.
This let me suppose that the maximum character length is compiler-dependent.
However a workaround seems to exist, in particular avoiding the use of "size" function into the string definition:
function foo2(n,array)
implicit none
integer(8), intent(IN):: n
integer, intent(IN):: array(1:n)
logical:: foo2
character(len=n):: string
"do something with string"
return
endfunction foo2
This approach works producing a correct length string even if n>2^31-1 (on 64bit architecture of course). This is true only for Intel Compiler, whereas gfortran (4.7) does not work in both cases.
In order to let you to reproduce my problem I have prepared a minimal program:
program test_length
implicit none
integer, parameter:: I8P = selected_int_kind(18)
integer, allocatable:: array(:)
integer(I8P), parameter:: n32=2_I8P**31-1_I8P, n64=2_I8P**31
integer(I8P):: n
character(len=n32):: string32
character(len=n64):: string64
integer:: ierr
print *,'32bit test'
n = n32
allocate(array(1:n),stat=ierr)
print *,'allocate stat: ',ierr
print *,'size : ',size(array,dim=1,kind=I8P)
print *,'len_ok : ',len_ok(n=n)
print *,'len_ko : ',len_ko(array=array)
deallocate(array)
print *
print *,'64bit test'
n = n64
allocate(array(1:n),stat=ierr)
print *,'allocate stat: ',ierr
print *,'size : ',size(array,dim=1,kind=I8P)
print *,'len_ok : ',len_ok(n=n)
print *,'len_ko : ',len_ko(array=array)
deallocate(array)
print *
print *,'Direct len function testing'
print *,'len(string32) : ',len(string32,kind=I8P)
print *,'len(string64) : ',len(string64,kind=I8P)
stop
contains
function len_ko(array)
implicit none
integer, intent(IN):: array(1:)
integer(kind=I8P):: len_ko
character(len=size(array,dim=1,kind=I8P)):: string
len_ko=len(string,kind=I8P)
return
endfunction len_ko
function len_ok(n)
implicit none
integer(kind=I8P), intent(IN):: n
integer(kind=I8P):: len_ok
character(len=n):: string
len_ok=len(string,kind=I8P)
return
endfunction len_ok
endprogram test_length
Running on my workstation (GNU/Linux 3.5.0-18 x86_64 with 24 GB of RAM) I have obtained:
32bit test
allocate stat: 0
size : 2147483647
len_ok : 2147483647
len_ko : 2147483647
64bit test
allocate stat: 0
size : 2147483648
len_ok : 2147483648
len_ko : 0
Direct len function testing
len(string32) : 2147483647
len(string64) : 2147483648
This is true for the Intel Compiler (13.x), whereas, on the same workstation, gfortran (4.7) always fails if n>2^31-1.
Note that the "size" function works properly outside the character definition.
Note also that substituting "size" with "ubound" (for example) into the len_ko string definition does not solve the problem.
Can someone explains the behavior of the above listed code?
Thank you very much for any suggestions,
sincerely
Stefano
I have some problems with the definition of a character variable inside a procedure (e.g. a function). The problem seems very trivial, but...
I have a huge array (rank 1) in input and I would like to define a (local to the function) character variable with the length equals to the array size (automatic length size).
The pseudo code of the function could be:
function foo(array)
implicit none
integer, intent(IN):: array(1:)
logical:: foo
character(len=size(array,dim=1,kind=8)):: string
"do something with string"
return
endfunction foo
This approach fails if the array is very huge (in particular if the number of its elements is greater than 2^31-1) producing a zero length string. I do not know if the standard (std2003) fix a limit on the character variables length, I only know that the Intel Compiler has the following behavior:
The largest valid value for len ... is 2**31-1 on IA-32 architecture; 2**63-1 on IntelĀ® 64 architecture. Negative values are treated as zero.
This let me suppose that the maximum character length is compiler-dependent.
However a workaround seems to exist, in particular avoiding the use of "size" function into the string definition:
function foo2(n,array)
implicit none
integer(8), intent(IN):: n
integer, intent(IN):: array(1:n)
logical:: foo2
character(len=n):: string
"do something with string"
return
endfunction foo2
This approach works producing a correct length string even if n>2^31-1 (on 64bit architecture of course). This is true only for Intel Compiler, whereas gfortran (4.7) does not work in both cases.
In order to let you to reproduce my problem I have prepared a minimal program:
program test_length
implicit none
integer, parameter:: I8P = selected_int_kind(18)
integer, allocatable:: array(:)
integer(I8P), parameter:: n32=2_I8P**31-1_I8P, n64=2_I8P**31
integer(I8P):: n
character(len=n32):: string32
character(len=n64):: string64
integer:: ierr
print *,'32bit test'
n = n32
allocate(array(1:n),stat=ierr)
print *,'allocate stat: ',ierr
print *,'size : ',size(array,dim=1,kind=I8P)
print *,'len_ok : ',len_ok(n=n)
print *,'len_ko : ',len_ko(array=array)
deallocate(array)
print *
print *,'64bit test'
n = n64
allocate(array(1:n),stat=ierr)
print *,'allocate stat: ',ierr
print *,'size : ',size(array,dim=1,kind=I8P)
print *,'len_ok : ',len_ok(n=n)
print *,'len_ko : ',len_ko(array=array)
deallocate(array)
print *
print *,'Direct len function testing'
print *,'len(string32) : ',len(string32,kind=I8P)
print *,'len(string64) : ',len(string64,kind=I8P)
stop
contains
function len_ko(array)
implicit none
integer, intent(IN):: array(1:)
integer(kind=I8P):: len_ko
character(len=size(array,dim=1,kind=I8P)):: string
len_ko=len(string,kind=I8P)
return
endfunction len_ko
function len_ok(n)
implicit none
integer(kind=I8P), intent(IN):: n
integer(kind=I8P):: len_ok
character(len=n):: string
len_ok=len(string,kind=I8P)
return
endfunction len_ok
endprogram test_length
Running on my workstation (GNU/Linux 3.5.0-18 x86_64 with 24 GB of RAM) I have obtained:
32bit test
allocate stat: 0
size : 2147483647
len_ok : 2147483647
len_ko : 2147483647
64bit test
allocate stat: 0
size : 2147483648
len_ok : 2147483648
len_ko : 0
Direct len function testing
len(string32) : 2147483647
len(string64) : 2147483648
This is true for the Intel Compiler (13.x), whereas, on the same workstation, gfortran (4.7) always fails if n>2^31-1.
Note that the "size" function works properly outside the character definition.
Note also that substituting "size" with "ubound" (for example) into the len_ko string definition does not solve the problem.
Can someone explains the behavior of the above listed code?
Thank you very much for any suggestions,
sincerely
Stefano