- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
In our software i am using quite a lot of allocatable arrays which i have to "reallocate" to runtime for increasing or decreasing. (static arrays are not an option :) )
- Marcas:
- Intel® Fortran Compiler
Link copiado
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
module reallocate
interface realloc
module procedure realloc_int1d
module procedure realloc_real1d
...
end interface realloc
contains
subroutine realloc_int1d( array, newsize )
integer, dimension(:), allocatable:: array
include "actual_realloc_code.f90"
endsubroutine
subroutine realloc_real1d( array, newsize )
real, dimension(:), allocatable :: array
include "actual_realloc_code.f90"
endsubroutine
...
end module
Via the INCLUDE statement you canrepeat the boilerplate code.
With derived types you can even put the declarations in such an
INCLUDE file, but I do not have the time at the moment to elaborate
on that.
Note that F2003's move_alloc routine makes life very much simpler.
(No more copying needed)
Regards,
Arjen
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
But i do have to write all subroutines for special types and bind them to the interface, which is quite the main "problem" i have.
Not that i am not know what i am doing hehe...but life would be SO much easier by using only 1 simple subroutine for all cases.
never heard about that but sounds interessing....think i cant use it actually if the whole software is written in F90 can i? (fortran compiler 11 by the way)
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
newsize = oldsize + increment
allocate (temp(newsize), stat=ierr)
if (ierr == 0) then
temp(1:oldsize) = array
call move_alloc(temp, array)
oldsize = newsize
endif
Les
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
If your version of the compiler supports the /assume:realloc_lhs flag, reallocating an array of any type can be done during the assignment, say:
[fortran]implicit none real, allocatable :: a(:) allocate (a(1:0)) !empty array print *, "0 entries:", a a = [a, 1.] !increase size print *, "1 entry:", a a = [a, 2., 3., 4.] !increase size print *, "4 entries:", a a(:) = [1., 2., 3., 5.] !no reallocation print *, "4 entries:", a a = a(:3) !decrease size print *, "3 entries:", a a = a(:0) !make empty print *, "0 entries:", a end [/fortran]
With /assume:realloc_lhs, you'll have to use (:) for the cases when you want to avoid reallocation, as shown in the example.
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
Especially cause F90 is not object orientated...for what i read about it.
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
F90's transfer intrinsic can be used to "type cast" the value of a variable of arbitrary type to a value of another type. The programmer needs to ensure that the "another type" (which can be an array) is large enough to accomodate the size in memory of the original variable, or you will not be able to reverse the type cast. Typically a 1D array of integers is used (perhaps an 1D array of INTEGER(1) under ifort) - so your typecastedArray would need to be a 2D array.
Fortran 2003 introduces a number of other possibilities (CLASS(*) may help), but if you have limited yourself to F90 (seriously??? Its pretty hard to justify that sort of restriction today) then obviously you will be missing out F2003's "cool features".
(Note that allocatable arguments, allocatable function results and allocatable derived type components are all not available in F90.)
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
The problem is that you keep mentioning "reallocation", and for that you can rely on reallocating the array during assignment (which I showed in my previous post), which is a Fortran 2003 feature. Because it's part of the language, it works the same regardless of whether you have an array of intrinsic (logical, integer, real, character) or derived type.
Even though you mentioned that you're restricting yourself to F90, it seems to be a relative restriction for you ---since the ALLOCATABLE attribute for function/subroutine arguments is a Fortran 2003 feature.
Other than the TRANSFER intrinsic, there is no typecasting in Fortran. As IanH suggested, you could use CLASS(*) combined with type-guards (yet another Fortran 2003 feature), but besides being more complex than reallocate on assignment, it's not yet supported by Intel Fortran ---i.e., the CLASS(*) feature still doesn't work well with arrays.
The following should, in theory, be close to what you want (although the code doesn't even compile, so it might not be valid):
[fortran]program test implicit none integer, allocatable :: a(:) character(5), allocatable :: b(:) allocate (a(1), b(2)) a = 1 b = 'two' print *, 'a, before:',a call reallocate(a, [2, 2]) print *, 'a, after:',a print *, 'b, before:',b call reallocate(b, [character(5) :: 'three', 'three', 'three']) print *, 'b, after:',b contains subroutine reallocate (array, increment) class(*), allocatable, intent(INOUT) :: array(:) class(*), intent(IN) :: increment(:) integer, allocatable :: auxi(:) character(5), allocatable :: auxc(:) select type (array) type is (integer) select type (increment) type is (integer) call MOVE_ALLOC(array, auxi) allocate (integer :: array(SIZE(auxi) + SIZE(increment))) array(:SIZE(auxi)) = auxi array(SIZE(auxi)+1:) = increment class default stop 'type not supported' end select type is (character(*)) select type (increment) type is (character(*)) call MOVE_ALLOC(array, auxc) allocate (character(5) :: array(SIZE(auxc) + SIZE(increment))) array(:SIZE(auxc)) = auxc array(SIZE(auxc)+1:) = increment class default stop 'type not supported' end selectclass default stop 'type not supported' end select end subroutine end program test[/fortran]
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
Using the Fortran Preprocessor, you might be able to reduce this to 1 or 2 lines.
Jim Dempsey
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
- Subscrever fonte RSS
- Marcar tópico como novo
- Marcar tópico como lido
- Flutuar este Tópico para o utilizador atual
- Marcador
- Subscrever
- Página amigável para impressora